コード例 #1
0
ファイル: interface_draw.c プロジェクト: Eibriel/kiriblender
void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti)
{
	Scopes *scopes = (Scopes *)but->poin;
	rctf rect;
	int i, c;
	float w, w3, h, alpha, yofs;
	GLint scissor[4];
	float colors[3][3] = MAT3_UNITY;
	float colorsycc[3][3] = {{1, 0, 1}, {1, 1, 0}, {0, 1, 1}};
	float colors_alpha[3][3], colorsycc_alpha[3][3]; /* colors  pre multiplied by alpha for speed up */
	float min, max;
	
	if (scopes == NULL) return;
	
	rect.xmin = (float)recti->xmin + 1;
	rect.xmax = (float)recti->xmax - 1;
	rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2;
	rect.ymax = (float)recti->ymax - 1;

	if (scopes->wavefrm_yfac < 0.5f)
		scopes->wavefrm_yfac = 0.98f;
	w = BLI_rctf_size_x(&rect) - 7;
	h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac;
	yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) / 2.0f;
	w3 = w / 3.0f;
	
	/* log scale for alpha */
	alpha = scopes->wavefrm_alpha * scopes->wavefrm_alpha;
	
	for (c = 0; c < 3; c++) {
		for (i = 0; i < 3; i++) {
			colors_alpha[c][i] = colors[c][i] * alpha;
			colorsycc_alpha[c][i] = colorsycc[c][i] * alpha;
		}
	}
			
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	
	glColor4f(0.f, 0.f, 0.f, 0.3f);
	uiSetRoundBox(UI_CNR_ALL);
	uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
	

	/* need scissor test, waveform can draw outside of boundary */
	glGetIntegerv(GL_VIEWPORT, scissor);
	glScissor(ar->winrct.xmin + (rect.xmin - 1),
	          ar->winrct.ymin + (rect.ymin - 1),
	          (rect.xmax + 1) - (rect.xmin - 1),
	          (rect.ymax + 1) - (rect.ymin - 1));

	glColor4f(1.f, 1.f, 1.f, 0.08f);
	/* draw grid lines here */
	for (i = 0; i < 6; i++) {
		char str[4];
		BLI_snprintf(str, sizeof(str), "%-3d", i * 20);
		str[3] = '\0';
		fdrawline(rect.xmin + 22, yofs + (i / 5.f) * h, rect.xmax + 1, yofs + (i / 5.f) * h);
		BLF_draw_default(rect.xmin + 1, yofs - 5 + (i / 5.f) * h, 0, str, sizeof(str) - 1);
		/* in the loop because blf_draw reset it */
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	}
	/* 3 vertical separation */
	if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) {
		for (i = 1; i < 3; i++) {
			fdrawline(rect.xmin + i * w3, rect.ymin, rect.xmin + i * w3, rect.ymax);
		}
	}
	
	/* separate min max zone on the right */
	fdrawline(rect.xmin + w, rect.ymin, rect.xmin + w, rect.ymax);
	/* 16-235-240 level in case of ITU-R BT601/709 */
	glColor4f(1.f, 0.4f, 0.f, 0.2f);
	if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)) {
		fdrawline(rect.xmin + 22, yofs + h * 16.0f / 255.0f, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
		fdrawline(rect.xmin + 22, yofs + h * 235.0f / 255.0f, rect.xmin + w3, yofs + h * 235.0f / 255.0f);
		fdrawline(rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f, rect.xmax + 1, yofs + h * 235.0f / 255.0f);
		fdrawline(rect.xmin + w3, yofs + h * 240.0f / 255.0f, rect.xmax + 1, yofs + h * 240.0f / 255.0f);
	}
	/* 7.5 IRE black point level for NTSC */
	if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA)
		fdrawline(rect.xmin, yofs + h * 0.075f, rect.xmax + 1, yofs + h * 0.075f);

	if (scopes->ok && scopes->waveform_1 != NULL) {
		
		/* LUMA (1 channel) */
		glBlendFunc(GL_ONE, GL_ONE);
		glColor3f(alpha, alpha, alpha);
		if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {

			glBlendFunc(GL_ONE, GL_ONE);
			
			glPushMatrix();
			glEnableClientState(GL_VERTEX_ARRAY);
			
			glTranslatef(rect.xmin, yofs, 0.f);
			glScalef(w, h, 0.f);
			glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1);
			glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
					
			glDisableClientState(GL_VERTEX_ARRAY);
			glPopMatrix();

			/* min max */
			glColor3f(0.5f, 0.5f, 0.5f);
			min = yofs + scopes->minmax[0][0] * h;
			max = yofs + scopes->minmax[0][1] * h;
			CLAMP(min, rect.ymin, rect.ymax);
			CLAMP(max, rect.ymin, rect.ymax);
			fdrawline(rect.xmax - 3, min, rect.xmax - 3, max);
		}

		/* RGB / YCC (3 channels) */
		else if (ELEM4(scopes->wavefrm_mode,
		               SCOPES_WAVEFRM_RGB,
		               SCOPES_WAVEFRM_YCC_601,
		               SCOPES_WAVEFRM_YCC_709,
		               SCOPES_WAVEFRM_YCC_JPEG))
		{
			int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB);
			
			glBlendFunc(GL_ONE, GL_ONE);
			
			glPushMatrix();
			glEnableClientState(GL_VERTEX_ARRAY);
			
			glTranslatef(rect.xmin, yofs, 0.f);
			glScalef(w3, h, 0.f);
			
			glColor3fv((rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
			glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1);
			glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);

			glTranslatef(1.f, 0.f, 0.f);
			glColor3fv((rgb) ? colors_alpha[1] : colorsycc_alpha[1]);
			glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2);
			glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
			
			glTranslatef(1.f, 0.f, 0.f);
			glColor3fv((rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
			glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3);
			glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
			
			glDisableClientState(GL_VERTEX_ARRAY);
			glPopMatrix();

			
			/* min max */
			for (c = 0; c < 3; c++) {
				if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB)
					glColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f);
				else
					glColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f);
				min = yofs + scopes->minmax[c][0] * h;
				max = yofs + scopes->minmax[c][1] * h;
				CLAMP(min, rect.ymin, rect.ymax);
				CLAMP(max, rect.ymin, rect.ymax);
				fdrawline(rect.xmin + w + 2 + c * 2, min, rect.xmin + w + 2 + c * 2, max);
			}
		}
		
	}
	
	/* outline, scale gripper */
	draw_scope_end(&rect, scissor);
}
コード例 #2
0
static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, short selectmode)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;

	KeyframeEditData ked;
	KeyframeEditFunc ok_cb, select_cb;
	View2D *v2d = &ac->ar->v2d;
	rctf rectf;
	float ymin = 0, ymax = (float)(-ACHANNEL_HEIGHT_HALF(ac));

	/* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
	UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin + 2, &rectf.xmin, &rectf.ymin);
	UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax - 2, &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);

	/* get beztriple editing/validation funcs  */
	select_cb = ANIM_editkeyframes_select(selectmode);

	if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS))
		ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
	else
		ok_cb = NULL;

	/* init editing data */
	memset(&ked, 0, sizeof(KeyframeEditData));

	/* loop over data, doing border select */
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);

		/* get new vertical minimum extent of channel */
		ymin = ymax - ACHANNEL_STEP(ac);

		/* set horizontal range (if applicable) */
		if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) {
			/* if channel is mapped in NLA, apply correction */
			if (adt) {
				ked.iterflags &= ~(KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP);
				ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
				ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
			}
			else {
				ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
				ked.f1 = rectf.xmin;
				ked.f2 = rectf.xmax;
			}
		}

		/* perform vertical suitability check (if applicable) */
		if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) ||
		    !((ymax < rectf.ymin) || (ymin > rectf.ymax)))
		{
			/* loop over data selecting */
			switch (ale->type) {
#if 0 /* XXX: Keyframes are not currently shown here */
				case ANIMTYPE_GPDATABLOCK:
				{
					bGPdata *gpd = ale->data;
					bGPDlayer *gpl;
					for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
						ED_gplayer_frames_select_border(gpl, rectf.xmin, rectf.xmax, selectmode);
					}
					break;
				}
#endif
				case ANIMTYPE_GPLAYER:
					ED_gplayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
					break;
				case ANIMTYPE_MASKDATABLOCK:
				{
					Mask *mask = ale->data;
					MaskLayer *masklay;
					for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
						ED_masklayer_frames_select_border(masklay, rectf.xmin, rectf.xmax, selectmode);
					}
					break;
				}
				case ANIMTYPE_MASKLAYER:
					ED_masklayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
					break;
				default:
					ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
					break;
			}
		}

		/* set minimum extent to be the maximum of the next channel */
		ymax = ymin;
	}

	/* cleanup */
	ANIM_animdata_freelist(&anim_data);
}
コード例 #3
0
/* Deselects keyframes in the action editor
 * - This is called by the deselect all operator, as well as other ones!
 *
 * - test: check if select or deselect all
 * - sel: how to select keyframes (SELECT_*)
 */
static void deselect_action_keys(bAnimContext *ac, short test, short sel)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;

	KeyframeEditData ked = {{NULL}};
	KeyframeEditFunc test_cb, sel_cb;

	/* determine type-based settings */
	if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
	else
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);

	/* filter data */
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);

	/* init BezTriple looping data */
	test_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);

	/* See if we should be selecting or deselecting */
	if (test) {
		for (ale = anim_data.first; ale; ale = ale->next) {
			if (ale->type == ANIMTYPE_GPLAYER) {
				if (ED_gplayer_frame_select_check(ale->data)) {
					sel = SELECT_SUBTRACT;
					break;
				}
			}
			else if (ale->type == ANIMTYPE_MASKLAYER) {
				if (ED_masklayer_frame_select_check(ale->data)) {
					sel = SELECT_SUBTRACT;
					break;
				}
			}
			else {
				if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
					sel = SELECT_SUBTRACT;
					break;
				}
			}
		}
	}

	/* convert sel to selectmode, and use that to get editor */
	sel_cb = ANIM_editkeyframes_select(sel);

	/* Now set the flags */
	for (ale = anim_data.first; ale; ale = ale->next) {
		if (ale->type == ANIMTYPE_GPLAYER)
			ED_gplayer_frame_select_set(ale->data, sel);
		else if (ale->type == ANIMTYPE_MASKLAYER)
			ED_masklayer_frame_select_set(ale->data, sel);
		else
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
	}

	/* Cleanup */
	ANIM_animdata_freelist(&anim_data);
}
コード例 #4
0
ファイル: keyframes_general.c プロジェクト: Moguri/blender
// TODO: introduce scaling factor for weighting falloff
void smooth_fcurve(FCurve *fcu)
{
	BezTriple *bezt;
	int i, x, totSel = 0;

	if (fcu->bezt == NULL) {
		return;
	}

	/* first loop through - count how many verts are selected */
	bezt = fcu->bezt;
	for (i = 0; i < fcu->totvert; i++, bezt++) {
		if (BEZT_ISSEL_ANY(bezt))
			totSel++;
	}
	
	/* if any points were selected, allocate tSmooth_Bezt points to work on */
	if (totSel >= 3) {
		tSmooth_Bezt *tarray, *tsb;
		
		/* allocate memory in one go */
		tsb = tarray = MEM_callocN(totSel * sizeof(tSmooth_Bezt), "tSmooth_Bezt Array");
		
		/* populate tarray with data of selected points */
		bezt = fcu->bezt;
		for (i = 0, x = 0; (i < fcu->totvert) && (x < totSel); i++, bezt++) {
			if (BEZT_ISSEL_ANY(bezt)) {
				/* tsb simply needs pointer to vec, and index */
				tsb->h1 = &bezt->vec[0][1];
				tsb->h2 = &bezt->vec[1][1];
				tsb->h3 = &bezt->vec[2][1];
				
				/* advance to the next tsb to populate */
				if (x < totSel - 1)
					tsb++;
				else
					break;
			}
		}
			
		/* calculate the new smoothed F-Curve's with weighted averages:
		 *	- this is done with two passes to avoid progressive corruption errors
		 *	- uses 5 points for each operation (which stores in the relevant handles)
		 *	-   previous: w/a ratio = 3:5:2:1:1
		 *	-   next: w/a ratio = 1:1:2:5:3
		 */
		
		/* round 1: calculate smoothing deltas and new values */ 
		tsb = tarray;
		for (i = 0; i < totSel; i++, tsb++) {
			/* don't touch end points (otherwise, curves slowly explode, as we don't have enough data there) */
			if (ELEM(i, 0, (totSel - 1)) == 0) {
				const tSmooth_Bezt *tP1 = tsb - 1;
				const tSmooth_Bezt *tP2 = (i - 2 > 0) ? (tsb - 2) : (NULL);
				const tSmooth_Bezt *tN1 = tsb + 1;
				const tSmooth_Bezt *tN2 = (i + 2 < totSel) ? (tsb + 2) : (NULL);
				
				const float p1 = *tP1->h2;
				const float p2 = (tP2) ? (*tP2->h2) : (*tP1->h2);
				const float c1 = *tsb->h2;
				const float n1 = *tN1->h2;
				const float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2);
				
				/* calculate previous and next, then new position by averaging these */
				tsb->y1 = (3 * p2 + 5 * p1 + 2 * c1 + n1 + n2) / 12;
				tsb->y3 = (p2 + p1 + 2 * c1 + 5 * n1 + 3 * n2) / 12;
				
				tsb->y2 = (tsb->y1 + tsb->y3) / 2;
			}
		}
		
		/* round 2: apply new values */
		tsb = tarray;
		for (i = 0; i < totSel; i++, tsb++) {
			/* don't touch end points, as their values weren't touched above */
			if (ELEM(i, 0, (totSel - 1)) == 0) {
				/* y2 takes the average of the 2 points */
				*tsb->h2 = tsb->y2;
				
				/* handles are weighted between their original values and the averaged values */
				*tsb->h1 = ((*tsb->h1) * 0.7f) + (tsb->y1 * 0.3f); 
				*tsb->h3 = ((*tsb->h3) * 0.7f) + (tsb->y3 * 0.3f);
			}
		}
		
		/* free memory required for tarray */
		MEM_freeN(tarray);
	}
	
	/* recalculate handles */
	calchandles_fcurve(fcu);
}
コード例 #5
0
static void actkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;

	KeyframeEditFunc ok_cb, select_cb;
	KeyframeEditData ked = {{NULL}};
	Scene *scene = ac->scene;

	/* if select mode is replace, deselect all keyframes (and channels) first */
	if (select_mode == SELECT_REPLACE) {
		select_mode = SELECT_ADD;

		/* - deselect all other keyframes, so that just the newly selected remain
		 * - channels aren't deselected, since we don't re-select any as a consequence
		 */
		deselect_action_keys(ac, 0, SELECT_SUBTRACT);
	}

	/* set callbacks and editing data */
	ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
	select_cb = ANIM_editkeyframes_select(select_mode);

	if (leftright == ACTKEYS_LRSEL_LEFT) {
		ked.f1 = MINAFRAMEF;
		ked.f2 = (float)(CFRA + 0.1f);
	}
	else {
		ked.f1 = (float)(CFRA - 0.1f);
		ked.f2 = MAXFRAMEF;
	}

	/* filter data */
	if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
	else
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);

	/* select keys */
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);

		if (adt) {
			ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
			ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
		}
		else if (ale->type == ANIMTYPE_GPLAYER)
			ED_gplayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode);
		else if (ale->type == ANIMTYPE_MASKLAYER)
			ED_masklayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode);
		else
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
	}

	/* Sync marker support */
	if (select_mode == SELECT_ADD) {
		SpaceAction *saction = (SpaceAction *)ac->sl;

		if ((saction) && (saction->flag & SACTION_MARKERS_MOVE)) {
			ListBase *markers = ED_animcontext_get_markers(ac);
			TimeMarker *marker;

			for (marker = markers->first; marker; marker = marker->next) {
				if (((leftright == ACTKEYS_LRSEL_LEFT)  && (marker->frame <  CFRA)) ||
				    ((leftright == ACTKEYS_LRSEL_RIGHT) && (marker->frame >= CFRA)))
				{
					marker->flag |= SELECT;
				}
				else {
					marker->flag &= ~SELECT;
				}
			}
		}
	}

	/* Cleanup */
	ANIM_animdata_freelist(&anim_data);
}
コード例 #6
0
/* Setup motion paths for the given data
 * - Only used when explicitly calculating paths on bones which may/may not be consider already
 *
 * < scene: current scene (for frame ranges, etc.)
 * < ob: object to add paths for (must be provided)
 * < pchan: posechannel to add paths for (optional; if not provided, object-paths are assumed)
 */
bMotionPath *animviz_verify_motionpaths(ReportList *reports, Scene *scene, Object *ob, bPoseChannel *pchan)
{
	bAnimVizSettings *avs;
	bMotionPath *mpath, **dst;
	
	/* sanity checks */
	if (ELEM(NULL, scene, ob))
		return NULL;
		
	/* get destination data */
	if (pchan) {
		/* paths for posechannel - assume that posechannel belongs to the object */
		avs= &ob->pose->avs;
		dst= &pchan->mpath;
	}
	else {
		/* paths for object */
		avs= &ob->avs;
		dst= &ob->mpath;
	}

	/* avoid 0 size allocs */
	if (avs->path_sf >= avs->path_ef) {
		BKE_reportf(reports, RPT_ERROR,
					"Motion Path frame extents invalid for %s (%d to %d).%s\n",
					(pchan)? pchan->name : ob->id.name,
					avs->path_sf, avs->path_ef,
					(avs->path_sf == avs->path_ef)? " Cannot have single-frame paths." : "");
		return NULL;
	}

	/* if there is already a motionpath, just return that,
	 * provided it's settings are ok (saves extra free+alloc)
	 */
	if (*dst != NULL) {
		int expected_length = avs->path_ef - avs->path_sf;
		
		mpath= *dst;
		
		/* path is "valid" if length is valid, but must also be of the same length as is being requested */
		if ((mpath->start_frame != mpath->end_frame) && (mpath->length > 0)) {
			/* outer check ensures that we have some curve data for this path */
			if (mpath->length == expected_length) {
				/* return/use this as it is already valid length */
				return mpath;
			}
			else {
				/* clear the existing path (as the range has changed), and reallocate below */
				animviz_free_motionpath_cache(mpath);
			}
		}
	}
	else {
		/* create a new motionpath, and assign it */
		mpath= MEM_callocN(sizeof(bMotionPath), "bMotionPath");
		*dst= mpath;
	}
	
	/* set settings from the viz settings */
	mpath->start_frame= avs->path_sf;
	mpath->end_frame= avs->path_ef;
	
	mpath->length= mpath->end_frame - mpath->start_frame;
	
	if (avs->path_bakeflag & MOTIONPATH_BAKE_HEADS)
		mpath->flag |= MOTIONPATH_FLAG_BHEAD;
	else
		mpath->flag &= ~MOTIONPATH_FLAG_BHEAD;
	
	/* allocate a cache */
	mpath->points= MEM_callocN(sizeof(bMotionPathVert)*mpath->length, "bMotionPathVerts");
	
	/* tag viz settings as currently having some path(s) which use it */
	avs->path_bakeflag |= MOTIONPATH_BAKE_HAS_PATHS;
	
	/* return it */
	return mpath;
}
コード例 #7
0
static char *rna_ColorRampElement_path(PointerRNA *ptr)
{
	PointerRNA ramp_ptr;
	PropertyRNA *prop;
	char *path = NULL;
	int index;
	
	/* helper macro for use here to try and get the path
	 *	- this calls the standard code for getting a path to a texture...
	 */

#define COLRAMP_GETPATH                                                       \
{                                                                             \
	prop = RNA_struct_find_property(&ramp_ptr, "elements");                   \
	if (prop) {                                                               \
		index = RNA_property_collection_lookup_index(&ramp_ptr, prop, ptr);   \
		if (index != -1) {                                                    \
			char *texture_path = rna_ColorRamp_path(&ramp_ptr);               \
			path = BLI_sprintfN("%s.elements[%d]", texture_path, index);      \
			MEM_freeN(texture_path);                                          \
		}                                                                     \
	}                                                                         \
} (void)0

	/* determine the path from the ID-block to the ramp */
	/* FIXME: this is a very slow way to do it, but it will have to suffice... */
	if (ptr->id.data) {
		ID *id = ptr->id.data;
		
		switch (GS(id->name)) {
			case ID_MA: /* 2 cases for material - diffuse and spec */
			{
				Material *ma = (Material *)id;
				
				/* try diffuse first */
				if (ma->ramp_col) {
					RNA_pointer_create(id, &RNA_ColorRamp, ma->ramp_col, &ramp_ptr);
					COLRAMP_GETPATH;
				}
				/* try specular if not diffuse */
				if (!path && ma->ramp_spec) {
					RNA_pointer_create(id, &RNA_ColorRamp, ma->ramp_spec, &ramp_ptr);
					COLRAMP_GETPATH;
				}
				break;
			}
			case ID_NT:
			{
				bNodeTree *ntree = (bNodeTree *)id;
				bNode *node;
				
				for (node = ntree->nodes.first; node; node = node->next) {
					if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
						RNA_pointer_create(id, &RNA_ColorRamp, node->storage, &ramp_ptr);
						COLRAMP_GETPATH;
					}
				}
				break;
			}
			case ID_LS:
			{
				ListBase listbase;
				LinkData *link;

				BKE_linestyle_modifier_list_color_ramps((FreestyleLineStyle *)id, &listbase);
				for (link = (LinkData *)listbase.first; link; link = link->next) {
					RNA_pointer_create(id, &RNA_ColorRamp, link->data, &ramp_ptr);
					COLRAMP_GETPATH;
				}
				BLI_freelistN(&listbase);
				break;
			}

			default: /* everything else should have a "color_ramp" property */
			{
				/* create pointer to the ID block, and try to resolve "color_ramp" pointer */
				RNA_id_pointer_create(id, &ramp_ptr);
				if (RNA_path_resolve(&ramp_ptr, "color_ramp", &ramp_ptr, &prop)) {
					COLRAMP_GETPATH;
				}
				break;
			}
		}
	}
	
	/* cleanup the macro we defined */
#undef COLRAMP_GETPATH
	
	return path;
}
コード例 #8
0
ファイル: parser.c プロジェクト: Adamantinus/Eternal-Lands
bp_Book * bp_parseBook(bp_Context * context, xmlNodePtr node) {
	bp_Book * result = malloc(sizeof(bp_Book));
	bp_Node * const parent = &result->node;
	bp_Node * page;
	xmlAttrPtr attr;
	xmlNodePtr child;
	bp_Page ** pages;
	st_data * fontSym;

	context->blockOutside = (void *) &bp_defaultBlockOutsideAttributes;
	context->blockBorder  = (void *) &bp_defaultBlockBorderAttributes;
	context->blockInside  = (void *) &bp_defaultBlockInsideAttributes;
	context->inlineAttr      = (void *) &bp_defaultInlineAttributes;

	bp_pushBlockOutside(context);
	bp_pushBlockBorder(context);
	bp_pushBlockInside(context);
	bp_pushInline(context);

	bp_initNode(&result->node, BPE_BOOK);
	result->width = 528;
	result->height = 320;
	result->background = load_texture_cache_deferred("textures/book1.bmp",0);
	fontSym = st_lookup (bp_fonts, "default");
	if (fontSym != NULL) {
		result->fontFace = fontSym->num;
	} else {
		LOG_ERROR("FATAL: default font missing in font symbol table\n");
		exit(1);
	}
	result->layout = BPL_BOOK;
	result->blockProgression = BPD_DOWN;
	result->inlineProgression = BPD_RIGHT;
	result->pages = NULL;
	result->nPages = 0;

	for (attr = node->properties; attr; attr = attr->next) {
		bp_parseBlockOutsideAttribute(context, context->blockOutside, attr);
		bp_parseBlockBorderAttribute(context, context->blockBorder, attr);
		bp_parseBlockInsideAttribute(context, context->blockInside, attr);
		bp_parseInlineAttribute(context, context->inlineAttr, attr);
	}

	for (child = node->children; child; child = child->next) {
		switch(ELEM(child)) {
			case BPE_PAGE:
				result->nPages++;
				ADD(bp_parsePage(context, child));
				break;
			default:
				DISCARD(child);
		}
	}

	bp_popBlockOutside(context);
	bp_popBlockBorder(context);
	bp_popBlockInside(context);
	bp_popInline(context);

	/* create page index */
	pages = calloc(result->nPages, sizeof(bp_Page *));
	result->pages = pages;
	for (page = parent->children; page; page = page->next) {
		*pages++ = (bp_Page *) page;
	}
	
	return result;
}
コード例 #9
0
ファイル: parser.c プロジェクト: Adamantinus/Eternal-Lands
bp_Page * bp_parsePage(bp_Context * context, xmlNodePtr node) {
	bp_Page * result = malloc(sizeof(bp_Page));
	bp_Node * const parent = &result->node;
	xmlAttrPtr attr;
	xmlNodePtr child;

	bp_pushBlockOutside(context);
	bp_pushBlockBorder(context);
	bp_pushBlockInside(context);
	bp_pushInline(context);

	bp_initNode(&result->node, BPE_PAGE);
	result->title = NULL;

	for (attr = node->properties; attr; attr = attr->next) {
		bp_parseBlockOutsideAttribute(context, context->blockOutside, attr);
		bp_parseBlockBorderAttribute(context, context->blockBorder, attr);
		bp_parseBlockInsideAttribute(context, context->blockInside, attr);
		bp_parseInlineAttribute(context, context->inlineAttr, attr);
	}

	for (child = node->children; child; child = child->next) {
		switch(ELEM(child)) {
			case BPE_TITLE:
				if (!result->title) {
					xmlNodePtr grandchild = child->children;
					if (ELEM(grandchild) == BPE_TEXT) {
						int len = strlen(grandchild->content);
						char * title_string = malloc(++len);
						memcpy(title_string, grandchild->content, len);
						result->title = title_string;
					} else {
						DISCARD(grandchild);
					}
				} else {
					DISCARD(child);
				}
				break;
			case BPE_REF:
				bp_parseNavRef(context, child, result);
				break;
			case BPE_BLOCK:
				ADD(bp_parseBlock(context, child));
				break;
			case BPE_IMAGE:
				ADD(bp_parseImage(context, child));
				break;
			case BPE_TABLE:
				ADD(bp_parseTable(context, child));
				break;
			case BPE_LABEL:
				ADD(bp_parseLabel(context, child));
				break;
			default:
				DISCARD(child);
		}
	}

	bp_popBlockOutside(context);
	bp_popBlockBorder(context);
	bp_popBlockInside(context);
	bp_popInline(context);

	return result;
}
コード例 #10
0
ファイル: armature_edit.c プロジェクト: Ichthyostega/blender
/* bone adding between selected joints */
static int armature_fill_bones_exec(bContext *C, wmOperator *op)
{
	Object *obedit = CTX_data_edit_object(C);
	bArmature *arm = (obedit) ? obedit->data : NULL;
	Scene *scene = CTX_data_scene(C);
	View3D *v3d = CTX_wm_view3d(C);
	ListBase points = {NULL, NULL};
	EditBone *newbone = NULL;
	int count;

	/* sanity checks */
	if (ELEM(NULL, obedit, arm))
		return OPERATOR_CANCELLED;

	/* loop over all bones, and only consider if visible */
	CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
	{
		if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL))
			fill_add_joint(ebone, 0, &points);
		if (ebone->flag & BONE_TIPSEL)
			fill_add_joint(ebone, 1, &points);
	}
	CTX_DATA_END;

	/* the number of joints determines how we fill:
	 *  1) between joint and cursor (joint=head, cursor=tail)
	 *  2) between the two joints (order is dependent on active-bone/hierarchy)
	 *  3+) error (a smarter method involving finding chains needs to be worked out
	 */
	count = BLI_listbase_count(&points);

	if (count == 0) {
		BKE_report(op->reports, RPT_ERROR, "No joints selected");
		return OPERATOR_CANCELLED;
	}
	else if (count == 1) {
		EditBonePoint *ebp;
		float curs[3];

		/* Get Points - selected joint */
		ebp = points.first;

		/* Get points - cursor (tail) */
		invert_m4_m4(obedit->imat, obedit->obmat);
		mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));

		/* Create a bone */
		newbone = add_points_bone(obedit, ebp->vec, curs);
	}
	else if (count == 2) {
		EditBonePoint *ebp_a, *ebp_b;
		float head[3], tail[3];
		short headtail = 0;

		/* check that the points don't belong to the same bone */
		ebp_a = (EditBonePoint *)points.first;
		ebp_b = ebp_a->next;

		if (((ebp_a->head_owner == ebp_b->tail_owner) && (ebp_a->head_owner != NULL)) ||
		    ((ebp_a->tail_owner == ebp_b->head_owner) && (ebp_a->tail_owner != NULL)))
		{
			BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
			BLI_freelistN(&points);
			return OPERATOR_CANCELLED;
		}

		/* find which one should be the 'head' */
		if ((ebp_a->head_owner && ebp_b->head_owner) || (ebp_a->tail_owner && ebp_b->tail_owner)) {
			/* use active, nice predictable */
			if (arm->act_edbone && ELEM(arm->act_edbone, ebp_a->head_owner, ebp_a->tail_owner)) {
				headtail = 1;
			}
			else if (arm->act_edbone && ELEM(arm->act_edbone, ebp_b->head_owner, ebp_b->tail_owner)) {
				headtail = 2;
			}
			else {
				/* rule: whichever one is closer to 3d-cursor */
				float curs[3];
				float dist_sq_a, dist_sq_b;

				/* get cursor location */
				invert_m4_m4(obedit->imat, obedit->obmat);
				mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));

				/* get distances */
				dist_sq_a = len_squared_v3v3(ebp_a->vec, curs);
				dist_sq_b = len_squared_v3v3(ebp_b->vec, curs);

				/* compare distances - closer one therefore acts as direction for bone to go */
				headtail = (dist_sq_a < dist_sq_b) ? 2 : 1;
			}
		}
		else if (ebp_a->head_owner) {
			headtail = 1;
		}
		else if (ebp_b->head_owner) {
			headtail = 2;
		}

		/* assign head/tail combinations */
		if (headtail == 2) {
			copy_v3_v3(head, ebp_a->vec);
			copy_v3_v3(tail, ebp_b->vec);
		}
		else if (headtail == 1) {
			copy_v3_v3(head, ebp_b->vec);
			copy_v3_v3(tail, ebp_a->vec);
		}

		/* add new bone and parent it to the appropriate end */
		if (headtail) {
			newbone = add_points_bone(obedit, head, tail);

			/* do parenting (will need to set connected flag too) */
			if (headtail == 2) {
				/* ebp tail or head - tail gets priority */
				if (ebp_a->tail_owner)
					newbone->parent = ebp_a->tail_owner;
				else
					newbone->parent = ebp_a->head_owner;
			}
			else {
				/* ebp_b tail or head - tail gets priority */
				if (ebp_b->tail_owner)
					newbone->parent = ebp_b->tail_owner;
				else
					newbone->parent = ebp_b->head_owner;
			}

			/* don't set for bone connecting two head points of bones */
			if (ebp_a->tail_owner || ebp_b->tail_owner) {
				newbone->flag |= BONE_CONNECTED;
			}
		}
	}
	else {
		/* FIXME.. figure out a method for multiple bones */
		BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d", count);
		BLI_freelistN(&points);
		return OPERATOR_CANCELLED;
	}

	if (newbone) {
		ED_armature_edit_deselect_all(obedit);
		arm->act_edbone = newbone;
		newbone->flag |= BONE_TIPSEL;
	}

	/* updates */
	WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);

	/* free points */
	BLI_freelistN(&points);

	return OPERATOR_FINISHED;
}
コード例 #11
0
ファイル: armature_edit.c プロジェクト: Ichthyostega/blender
static int armature_merge_exec(bContext *C, wmOperator *op)
{
	Object *obedit = CTX_data_edit_object(C);
	bArmature *arm = (obedit) ? obedit->data : NULL;
	short type = RNA_enum_get(op->ptr, "type");

	/* sanity checks */
	if (ELEM(NULL, obedit, arm))
		return OPERATOR_CANCELLED;

	/* for now, there's only really one type of merging that's performed... */
	if (type == 1) {
		/* go down chains, merging bones */
		ListBase chains = {NULL, NULL};
		LinkData *chain, *nchain;
		EditBone *ebo;

		armature_tag_select_mirrored(arm);

		/* get chains (ends on chains) */
		chains_find_tips(arm->edbo, &chains);
		if (BLI_listbase_is_empty(&chains)) return OPERATOR_CANCELLED;

		/* each 'chain' is the last bone in the chain (with no children) */
		for (chain = chains.first; chain; chain = nchain) {
			EditBone *bstart = NULL, *bend = NULL;
			EditBone *bchild = NULL, *child = NULL;

			/* temporarily remove chain from list of chains */
			nchain = chain->next;
			BLI_remlink(&chains, chain);

			/* only consider bones that are visible and selected */
			for (ebo = chain->data; ebo; child = ebo, ebo = ebo->parent) {
				/* check if visible + selected */
				if (EBONE_VISIBLE(arm, ebo) &&
				    ((ebo->flag & BONE_CONNECTED) || (ebo->parent == NULL)) &&
				    (ebo->flag & BONE_SELECTED) )
				{
					/* set either end or start (end gets priority, unless it is already set) */
					if (bend == NULL) {
						bend = ebo;
						bchild = child;
					}
					else
						bstart = ebo;
				}
				else {
					/* chain is broken... merge any continuous segments then clear */
					if (bstart && bend)
						bones_merge(obedit, bstart, bend, bchild, &chains);

					bstart = NULL;
					bend = NULL;
					bchild = NULL;
				}
			}

			/* merge from bstart to bend if something not merged */
			if (bstart && bend)
				bones_merge(obedit, bstart, bend, bchild, &chains);

			/* put back link */
			BLI_insertlinkbefore(&chains, nchain, chain);
		}

		armature_tag_unselect(arm);

		BLI_freelistN(&chains);
	}

	/* updates */
	ED_armature_edit_sync_selection(arm->edbo);
	WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);

	return OPERATOR_FINISHED;
}
コード例 #12
0
ファイル: armature_edit.c プロジェクト: Ichthyostega/blender
static int armature_calc_roll_exec(bContext *C, wmOperator *op)
{
	Object *ob = CTX_data_edit_object(C);
	eCalcRollTypes type = RNA_enum_get(op->ptr, "type");
	const bool axis_only = RNA_boolean_get(op->ptr, "axis_only");
	/* axis_flip when matching the active bone never makes sense */
	bool axis_flip = ((type >= CALC_ROLL_ACTIVE) ? RNA_boolean_get(op->ptr, "axis_flip") :
	                  (type >= CALC_ROLL_TAN_NEG_X) ? true : false);

	float imat[3][3];

	bArmature *arm = ob->data;
	EditBone *ebone;

	if ((type >= CALC_ROLL_NEG_X) && (type <= CALC_ROLL_TAN_NEG_Z)) {
		type -= (CALC_ROLL_ACTIVE - CALC_ROLL_NEG_X);
		axis_flip = true;
	}

	copy_m3_m4(imat, ob->obmat);
	invert_m3(imat);

	if (type == CALC_ROLL_CURSOR) { /* Cursor */
		Scene *scene = CTX_data_scene(C);
		View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
		float cursor_local[3];
		const float   *cursor = ED_view3d_cursor3d_get(scene, v3d);

		invert_m4_m4(ob->imat, ob->obmat);
		copy_v3_v3(cursor_local, cursor);
		mul_m4_v3(ob->imat, cursor_local);


		/* cursor */
		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
				float cursor_rel[3];
				sub_v3_v3v3(cursor_rel, cursor_local, ebone->head);
				if (axis_flip) negate_v3(cursor_rel);
				if (normalize_v3(cursor_rel) != 0.0f) {
					ebone->roll = ED_armature_ebone_roll_to_vector(ebone, cursor_rel, axis_only);
				}
			}
		}
	}
	else if (ELEM(type, CALC_ROLL_TAN_POS_X, CALC_ROLL_TAN_POS_Z)) {
		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if (ebone->parent) {
				bool is_edit        = (EBONE_VISIBLE(arm, ebone)         && EBONE_EDITABLE(ebone));
				bool is_edit_parent = (EBONE_VISIBLE(arm, ebone->parent) && EBONE_EDITABLE(ebone->parent));

				if (is_edit || is_edit_parent) {
					EditBone *ebone_other = ebone->parent;
					float dir_a[3];
					float dir_b[3];
					float vec[3];
					bool is_vec_zero;

					sub_v3_v3v3(dir_a, ebone->tail, ebone->head);
					normalize_v3(dir_a);

					/* find the first bone in the chane with a different direction */
					do {
						sub_v3_v3v3(dir_b, ebone_other->head, ebone_other->tail);
						normalize_v3(dir_b);

						if (type == CALC_ROLL_TAN_POS_Z) {
							cross_v3_v3v3(vec, dir_a, dir_b);
						}
						else {
							add_v3_v3v3(vec, dir_a, dir_b);
						}
					} while ((is_vec_zero = (normalize_v3(vec) < 0.00001f)) &&
					         (ebone_other = ebone_other->parent));

					if (!is_vec_zero) {
						if (axis_flip) negate_v3(vec);

						if (is_edit) {
							ebone->roll = ED_armature_ebone_roll_to_vector(ebone, vec, axis_only);
						}

						/* parentless bones use cross product with child */
						if (is_edit_parent) {
							if (ebone->parent->parent == NULL) {
								ebone->parent->roll = ED_armature_ebone_roll_to_vector(ebone->parent, vec, axis_only);
							}
						}
					}
				}
			}
		}
	}
	else {
		float vec[3] = {0.0f, 0.0f, 0.0f};
		if (type == CALC_ROLL_VIEW) { /* View */
			RegionView3D *rv3d = CTX_wm_region_view3d(C);
			if (rv3d == NULL) {
				BKE_report(op->reports, RPT_ERROR, "No region view3d available");
				return OPERATOR_CANCELLED;
			}

			copy_v3_v3(vec, rv3d->viewinv[2]);
			mul_m3_v3(imat, vec);
		}
		else if (type == CALC_ROLL_ACTIVE) {
			float mat[3][3];
			ebone = (EditBone *)arm->act_edbone;
			if (ebone == NULL) {
				BKE_report(op->reports, RPT_ERROR, "No active bone set");
				return OPERATOR_CANCELLED;
			}

			ED_armature_ebone_to_mat3(ebone, mat);
			copy_v3_v3(vec, mat[2]);
		}
		else { /* Axis */
			assert(type <= 5);
			if (type < 3) vec[type] = 1.0f;
			else vec[type - 2] = -1.0f;
			mul_m3_v3(imat, vec);
			normalize_v3(vec);
		}

		if (axis_flip) negate_v3(vec);

		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
				/* roll func is a callback which assumes that all is well */
				ebone->roll = ED_armature_ebone_roll_to_vector(ebone, vec, axis_only);
			}
		}
	}

	if (arm->flag & ARM_MIRROR_EDIT) {
		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if ((EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) == 0) {
				EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
				if (ebone_mirr && (EBONE_VISIBLE(arm, ebone_mirr) && EBONE_EDITABLE(ebone_mirr))) {
					ebone->roll = -ebone_mirr->roll;
				}
			}
		}
	}

	/* note, notifier might evolve */
	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);

	return OPERATOR_FINISHED;
}
コード例 #13
0
ファイル: armature_edit.c プロジェクト: Ichthyostega/blender
static int armature_align_bones_exec(bContext *C, wmOperator *op)
{
	Object *ob = CTX_data_edit_object(C);
	bArmature *arm = (bArmature *)ob->data;
	EditBone *actbone = CTX_data_active_bone(C);
	EditBone *actmirb = NULL;
	int num_selected_bones;

	/* there must be an active bone */
	if (actbone == NULL) {
		BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
		return OPERATOR_CANCELLED;
	}
	else if (arm->flag & ARM_MIRROR_EDIT) {
		/* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
		 * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone
		 *   (i.e.  selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
		 *   This is useful for arm-chains, for example parenting lower arm to upper arm
		 * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
		 *   then just use actbone. Useful when doing upper arm to spine.
		 */
		actmirb = ED_armature_ebone_get_mirrored(arm->edbo, actbone);
		if (actmirb == NULL)
			actmirb = actbone;
	}

	/* if there is only 1 selected bone, we assume that that is the active bone,
	 * since a user will need to have clicked on a bone (thus selecting it) to make it active
	 */
	num_selected_bones = CTX_DATA_COUNT(C, selected_editable_bones);
	if (num_selected_bones <= 1) {
		/* When only the active bone is selected, and it has a parent,
		 * align it to the parent, as that is the only possible outcome.
		 */
		if (actbone->parent) {
			bone_align_to_bone(arm->edbo, actbone, actbone->parent);

			if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
				bone_align_to_bone(arm->edbo, actmirb, actmirb->parent);

			BKE_reportf(op->reports, RPT_INFO, "Aligned bone '%s' to parent", actbone->name);
		}
	}
	else {
		/* Align 'selected' bones to the active one
		 * - the context iterator contains both selected bones and their mirrored copies,
		 *   so we assume that unselected bones are mirrored copies of some selected bone
		 * - since the active one (and/or its mirror) will also be selected, we also need
		 *   to check that we are not trying to operate on them, since such an operation
		 *   would cause errors
		 */

		/* align selected bones to the active one */
		CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
		{
			if (ELEM(ebone, actbone, actmirb) == 0) {
				if (ebone->flag & BONE_SELECTED)
					bone_align_to_bone(arm->edbo, ebone, actbone);
				else
					bone_align_to_bone(arm->edbo, ebone, actmirb);
			}
		}
		CTX_DATA_END;

		BKE_reportf(op->reports, RPT_INFO, "%d bones aligned to bone '%s'", num_selected_bones, actbone->name);
	}

	/* note, notifier might evolve */
	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);

	return OPERATOR_FINISHED;
}
コード例 #14
0
ファイル: bwlabel.cpp プロジェクト: LinaW/sentence-training
int bwlabel(IplImage* img, int n, int* labels)
{
	if(n != 4 && n != 8)
		n = 4;
	int nr = img->height;
	int nc = img->width;
	int total = nr * nc;
	// results
	memset(labels, 0, total * sizeof(int));
	int nobj = 0;                               // number of objects found in image
	// other variables                             
	int* lset = new int[total];   // label table
	memset(lset, 0, total * sizeof(int));
	int ntable = 0;
	for( int r = 0; r < nr; r++ ) 
	{
		for( int c = 0; c < nc; c++ ) 
		{            
			if ( ELEM(img, r, c) )   // if A is an object
			{               
				// get the neighboring pixels B, C, D, and E
				int B, C, D, E;
				if ( c == 0 ) 
					B = 0; 
				else 
					B = find( lset, ONETWO(labels, r, c - 1, nc) );
				if ( r == 0 ) 
					C = 0; 
				else 
					C = find( lset, ONETWO(labels, r - 1, c, nc) );
				if ( r == 0 || c == 0 ) 
					D = 0; 
				else 
					D = find( lset, ONETWO(labels, r - 1, c - 1, nc) );
				if ( r == 0 || c == nc - 1 ) 
					E = 0;
				else 
					E = find( lset, ONETWO(labels, r - 1, c + 1, nc) );
				if ( n == 4 ) 
				{
					// apply 4 connectedness
					if ( B && C ) 
					{        // B and C are labeled
						if ( B == C )
							ONETWO(labels, r, c, nc) = B;
						else {
							lset[C] = B;
							ONETWO(labels, r, c, nc) = B;
						}
					} 
					else if ( B )             // B is object but C is not
						ONETWO(labels, r, c, nc) = B;
					else if ( C )               // C is object but B is not
						ONETWO(labels, r, c, nc) = C;
					else 
					{                      // B, C, D not object - new object
						//   label and put into table
						ntable++;
						ONETWO(labels, r, c, nc) = lset[ ntable ] = ntable;
					}
				} 
				else if ( n == 6 ) 
				{
					// apply 6 connected ness
					if ( D )                    // D object, copy label and move on
						ONETWO(labels, r, c, nc) = D;
					else if ( B && C ) 
					{        // B and C are labeled
						if ( B == C )
							ONETWO(labels, r, c, nc) = B;
						else 
						{
							int tlabel = MIN(B,C);
							lset[B] = tlabel;
							lset[C] = tlabel;
							ONETWO(labels, r, c, nc) = tlabel;
						}
					} 
					else if ( B )             // B is object but C is not
						ONETWO(labels, r, c, nc) = B;
					else if ( C )               // C is object but B is not
						ONETWO(labels, r, c, nc) = C;
					else 
					{                      // B, C, D not object - new object
						//   label and put into table
						ntable++;
						ONETWO(labels, r, c, nc) = lset[ ntable ] = ntable;
					}
				}
				else if ( n == 8 ) 
				{
					// apply 8 connectedness
					if ( B || C || D || E ) 
					{
						int tlabel = B;
						if ( B ) 
							tlabel = B;
						else if ( C ) 
							tlabel = C;
						else if ( D ) 
							tlabel = D;
						else if ( E ) 
							tlabel = E;
						ONETWO(labels, r, c, nc) = tlabel;
						if ( B && B != tlabel ) 
							lset[B] = tlabel;
						if ( C && C != tlabel ) 
							lset[C] = tlabel;
						if ( D && D != tlabel ) 
							lset[D] = tlabel;
						if ( E && E != tlabel ) 
							lset[E] = tlabel;
					} 
					else 
					{
						//   label and put into table
						ntable++;
						ONETWO(labels, r, c, nc) = lset[ ntable ] = ntable;
					}
				}
			} 
			else 
			{
				ONETWO(labels, r, c, nc) = NO_OBJECT;      // A is not an object so leave it
			}
		}
	}
	// consolidate component table
	for( int i = 0; i <= ntable; i++ )
		lset[i] = find( lset, i );                                                                                                 
	// run image through the look-up table
	for( int r = 0; r < nr; r++ )
		for( int c = 0; c < nc; c++ )
			ONETWO(labels, r, c, nc) = lset[ ONETWO(labels, r, c, nc) ];
	// count up the objects in the image
	for( int i = 0; i <= ntable; i++ )
		lset[i] = 0;
	for( int r = 0; r < nr; r++ )
		for( int c = 0; c < nc; c++ )
			lset[ ONETWO(labels, r, c, nc) ]++;
	// number the objects from 1 through n objects
	nobj = 0;
	lset[0] = 0;
	for( int i = 1; i <= ntable; i++ )
		if ( lset[i] > 0 )
			lset[i] = ++nobj;
	// run through the look-up table again
	for( int r = 0; r < nr; r++ )
		for( int c = 0; c < nc; c++ )
			ONETWO(labels, r, c, nc) = lset[ ONETWO(labels, r, c, nc) ];
	//
	delete[] lset;
	return nobj;
}
コード例 #15
0
ファイル: interface_utils.c プロジェクト: UPBGE/blender
uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, const char *name, int icon, int x1, int y1, int x2, int y2)
{
	uiBut *but = NULL;

	switch (RNA_property_type(prop)) {
		case PROP_BOOLEAN:
		{
			int arraylen = RNA_property_array_length(ptr, prop);

			if (arraylen && index == -1)
				return NULL;
			
			if (icon && name && name[0] == '\0')
				but = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
			else if (icon)
				but = uiDefIconTextButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
			else
				but = uiDefButR_prop(block, UI_BTYPE_CHECKBOX, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
			break;
		}
		case PROP_INT:
		case PROP_FLOAT:
		{
			int arraylen = RNA_property_array_length(ptr, prop);

			if (arraylen && index == -1) {
				if (ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA)) {
					but = uiDefButR_prop(block, UI_BTYPE_COLOR, 0, name, x1, y1, x2, y2, ptr, prop, -1, 0, 0, -1, -1, NULL);
				}
				else {
					return NULL;
				}
			}
			else if (RNA_property_subtype(prop) == PROP_PERCENTAGE || RNA_property_subtype(prop) == PROP_FACTOR)
				but = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
			else
				but = uiDefButR_prop(block, UI_BTYPE_NUM, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);

			if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
				UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE);
			}
			break;
		}
		case PROP_ENUM:
			if (icon && name && name[0] == '\0')
				but = uiDefIconButR_prop(block, UI_BTYPE_MENU, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
			else if (icon)
				but = uiDefIconTextButR_prop(block, UI_BTYPE_MENU, 0, icon, NULL, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
			else
				but = uiDefButR_prop(block, UI_BTYPE_MENU, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
			break;
		case PROP_STRING:
			if (icon && name && name[0] == '\0')
				but = uiDefIconButR_prop(block, UI_BTYPE_TEXT, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
			else if (icon)
				but = uiDefIconTextButR_prop(block, UI_BTYPE_TEXT, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
			else
				but = uiDefButR_prop(block, UI_BTYPE_TEXT, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);

			PropertySubType subtype = RNA_property_subtype(prop);
			if (!(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME) || (block->flag & UI_BLOCK_LIST_ITEM))) {
				UI_but_flag_enable(but, UI_BUT_VALUE_CLEAR);
			}
			if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
				UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE);
			}
			break;
		case PROP_POINTER:
		{
			PointerRNA pptr;

			pptr = RNA_property_pointer_get(ptr, prop);
			if (!pptr.type)
				pptr.type = RNA_property_pointer_type(ptr, prop);
			icon = RNA_struct_ui_icon(pptr.type);
			if (icon == ICON_DOT)
				icon = 0;

			but = uiDefIconTextButR_prop(block, UI_BTYPE_SEARCH_MENU, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
			break;
		}
		case PROP_COLLECTION:
		{
			char text[256];
			BLI_snprintf(text, sizeof(text), IFACE_("%d items"), RNA_property_collection_length(ptr, prop));
			but = uiDefBut(block, UI_BTYPE_LABEL, 0, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, NULL);
			UI_but_flag_enable(but, UI_BUT_DISABLED);
			break;
		}
		default:
			but = NULL;
			break;
	}

	return but;
}
コード例 #16
0
ファイル: parser.c プロジェクト: Adamantinus/Eternal-Lands
bp_Table * bp_parseTable(bp_Context * context, xmlNodePtr node) {
	bp_Table * result = malloc(sizeof(bp_Table));
	bp_Node * const parent = &result->node;
	xmlAttrPtr attr;
	xmlNodePtr child, grand;

	bp_pushBlockBorder(context);
	bp_pushBlockInside(context);
	bp_pushInline(context);

	bp_initNode(&result->node, BPE_TABLE);
	result->_float = bp_defaultFloatAttributes;
	result->blockOutside = *(context->blockOutside);
	result->caption = NULL;
	result->nCols = 0;
	result->nRows = 0;
	
	for (attr = node->properties; attr; attr = attr->next) {
		bp_parseFloatAttribute(context, &result->_float, attr);
		bp_parseBlockOutsideAttribute(context, &result->blockOutside, attr);
		bp_parseBlockBorderAttribute(context, context->blockBorder, attr);
		bp_parseBlockInsideAttribute(context, context->blockInside, attr);
		bp_parseInlineAttribute(context, context->inlineAttr, attr);
	}

	result->blockBorder = *(context->blockBorder); // shared with children

	for (child = node->children; child; child = child->next) {
		switch(ELEM(child)) {
			case BPE_TR: result->nRows++; break;
			case BPE_TC: result->nCols++; break;
			case BPE_CAPTION:
				result->caption = bp_parseCaption(context, child);
			default: DISCARD(child);
		}
	}

	if (result->nRows) {
		int * colHeights = NULL; 
		int col, row = 0;
		result->nCols = 0;

		for (child = node->children; child; child = child->next) {
			if(ELEM(child) == BPE_TR) {
				bp_pushBlockBorder(context);
				bp_pushBlockInside(context);
				bp_pushInline(context);

				for (attr = child->properties; attr; attr = attr->next) {
					bp_parseBlockBorderAttribute(context, context->blockBorder, attr);
					bp_parseBlockInsideAttribute(context, context->blockInside, attr);
					bp_parseInlineAttribute(context, context->inlineAttr, attr);
				}
				
				col = 0;
				for (grand = child->children; grand; grand = grand->next) {
					while ((col < result->nCols) && (colHeights[col] >= row)) col++;
							
					if(ELEM(grand) == BPE_TD) {
						bp_Cell * cell = bp_parseCell(context, grand, row, col);

						ADD(cell);
						
						if (cell->endCol >= result->nCols) {
							result->nCols = cell->endCol + 1;
							colHeights = realloc(colHeights, result->nCols * sizeof(int));
						}
						
						for (col=cell->startCol; col <= cell->endCol; col++) {
							colHeights[col] = cell->endRow;
						}
					} else {
						DISCARD(grand);
					}
				}

				bp_popBlockBorder(context);
				bp_popBlockInside(context);
				bp_popInline(context);
				row++;
			}
		}

		if(colHeights) free(colHeights);
	} else if (result->nCols) {
		int * rowWidths = NULL; 
		int col = 0, row;
		result->nRows = 0;

		for (child = node->children; child; child = child->next) {
			if(ELEM(child) == BPE_TC) {
				bp_pushBlockBorder(context);
				bp_pushBlockInside(context);
				bp_pushInline(context);

				for (attr = child->properties; attr; attr = attr->next) {
					bp_parseBlockBorderAttribute(context, context->blockBorder, attr);
					bp_parseBlockInsideAttribute(context, context->blockInside, attr);
					bp_parseInlineAttribute(context, context->inlineAttr, attr);
				}
				
				row = 0;
				for (grand = child->children; grand; grand = grand->next) {
					while ((row < result->nRows) && (rowWidths[row] >= col)) row++;
							
					if(ELEM(grand) == BPE_TD) {
						bp_Cell * cell = bp_parseCell(context, grand, row, col);

						ADD(cell);
						
						if (cell->endRow >= result->nRows) {
							result->nRows = cell->endRow + 1;
							rowWidths = realloc(rowWidths, result->nRows * sizeof(int));
						}
						
						for (row=cell->startRow; row <= cell->endRow; row++) {
							rowWidths[row] = cell->endCol;
						}
					} else {
						DISCARD(grand);
					}
				}

				bp_popBlockBorder(context);
				bp_popBlockInside(context);
				bp_popInline(context);
				col++;
			}
		}

		if(rowWidths) free(rowWidths);
	}

	bp_popBlockBorder(context);
	bp_popBlockInside(context);
	bp_popInline(context);

	return result;
}
コード例 #17
0
static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level, int animated)
{
	GroupObject *go;
	Object *ob=NULL, **oblist=NULL, obcopy, *obcopylist=NULL;
	DupliObject *dob;
	ParticleDupliWeight *dw;
	ParticleSettings *part;
	ParticleData *pa;
	ChildParticle *cpa=NULL;
	ParticleKey state;
	ParticleCacheKey *cache;
	float ctime, pa_time, scale = 1.0f;
	float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size=0.0;
	float (*obmat)[4], (*oldobmat)[4];
	int a, b, counter, hair = 0;
	int totpart, totchild, totgroup=0 /*, pa_num */;

	int no_draw_flag = PARS_UNEXIST;

	if (psys==NULL) return;
	
	/* simple preventing of too deep nested groups */
	if (level>MAX_DUPLI_RECUR) return;
	
	part=psys->part;

	if (part==NULL)
		return;

	if (!psys_check_enabled(par, psys))
		return;

	if (G.rendering == 0)
		no_draw_flag |= PARS_NO_DISP;
	
	ctime = BKE_curframe(scene); /* NOTE: in old animsys, used parent object's timeoffset... */

	totpart = psys->totpart;
	totchild = psys->totchild;

	BLI_srandom(31415926 + psys->seed);

	if ((psys->renderdata || part->draw_as==PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
		ParticleSimulationData sim= {NULL};
		sim.scene= scene;
		sim.ob= par;
		sim.psys= psys;
		sim.psmd= psys_get_modifier(par, psys);
		/* make sure emitter imat is in global coordinates instead of render view coordinates */
		invert_m4_m4(par->imat, par->obmat);

		/* first check for loops (particle system object used as dupli object) */
		if (part->ren_as == PART_DRAW_OB) {
			if (ELEM(part->dup_ob, NULL, par))
				return;
		}
		else { /*PART_DRAW_GR */
			if (part->dup_group == NULL || part->dup_group->gobject.first == NULL)
				return;

			for (go=part->dup_group->gobject.first; go; go=go->next)
				if (go->ob == par)
					return;
		}

		/* if we have a hair particle system, use the path cache */
		if (part->type == PART_HAIR) {
			if (psys->flag & PSYS_HAIR_DONE)
				hair= (totchild == 0 || psys->childcache) && psys->pathcache;
			if (!hair)
				return;
			
			/* we use cache, update totchild according to cached data */
			totchild = psys->totchildcache;
			totpart = psys->totcached;
		}

		psys_check_group_weights(part);

		psys->lattice = psys_get_lattice(&sim);

		/* gather list of objects or single object */
		if (part->ren_as==PART_DRAW_GR) {
			group_handle_recalc_and_update(scene, par, part->dup_group);

			if (part->draw & PART_DRAW_COUNT_GR) {
				for (dw=part->dupliweights.first; dw; dw=dw->next)
					totgroup += dw->count;
			}
			else {
				for (go=part->dup_group->gobject.first; go; go=go->next)
					totgroup++;
			}

			/* we also copy the actual objects to restore afterwards, since
			 * where_is_object_time will change the object which breaks transform */
			oblist = MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list");
			obcopylist = MEM_callocN(totgroup*sizeof(Object), "dupgroup copy list");

			
			if (part->draw & PART_DRAW_COUNT_GR && totgroup) {
				dw = part->dupliweights.first;

				for (a=0; a<totgroup; dw=dw->next) {
					for (b=0; b<dw->count; b++, a++) {
						oblist[a] = dw->ob;
						obcopylist[a] = *dw->ob;
					}
				}
			}
			else {
				go = part->dup_group->gobject.first;
				for (a=0; a<totgroup; a++, go=go->next) {
					oblist[a] = go->ob;
					obcopylist[a] = *go->ob;
				}
			}
		}
		else {
			ob = part->dup_ob;
			obcopy = *ob;
		}

		if (totchild==0 || part->draw & PART_DRAW_PARENT)
			a = 0;
		else
			a = totpart;

		for (pa=psys->particles,counter=0; a<totpart+totchild; a++,pa++,counter++) {
			if (a<totpart) {
				/* handle parent particle */
				if (pa->flag & no_draw_flag)
					continue;

				/* pa_num = pa->num; */ /* UNUSED */
				pa_time = pa->time;
				size = pa->size;
			}
			else {
				/* handle child particle */
				cpa = &psys->child[a - totpart];

				/* pa_num = a; */ /* UNUSED */
				pa_time = psys->particles[cpa->parent].time;
				size = psys_get_child_size(psys, cpa, ctime, NULL);
			}

			/* some hair paths might be non-existent so they can't be used for duplication */
			if (hair &&
				((a < totpart && psys->pathcache[a]->steps < 0) ||
				(a >= totpart && psys->childcache[a-totpart]->steps < 0)))
				continue;

			if (part->ren_as==PART_DRAW_GR) {
				/* prevent divide by zero below [#28336] */
				if (totgroup == 0)
					continue;

				/* for groups, pick the object based on settings */
				if (part->draw&PART_DRAW_RAND_GR)
					b= BLI_rand() % totgroup;
				else
					b= a % totgroup;

				ob = oblist[b];
				obmat = oblist[b]->obmat;
				oldobmat = obcopylist[b].obmat;
			}
			else {
				obmat= ob->obmat;
				oldobmat= obcopy.obmat;
			}

			if (hair) {
				/* hair we handle separate and compute transform based on hair keys */
				if (a < totpart) {
					cache = psys->pathcache[a];
					psys_get_dupli_path_transform(&sim, pa, NULL, cache, pamat, &scale);
				}
				else {
					cache = psys->childcache[a-totpart];
					psys_get_dupli_path_transform(&sim, NULL, cpa, cache, pamat, &scale);
				}

				copy_v3_v3(pamat[3], cache->co);
				pamat[3][3]= 1.0f;
				
			}
			else {
				/* first key */
				state.time = ctime;
				if (psys_get_particle_state(&sim, a, &state, 0) == 0) {
					continue;
				}
				else {
					float tquat[4];
					normalize_qt_qt(tquat, state.rot);
					quat_to_mat4(pamat, tquat);
					copy_v3_v3(pamat[3], state.co);
					pamat[3][3]= 1.0f;
				}
			}

			if (part->ren_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
				for (go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) {

					copy_m4_m4(tmat, oblist[b]->obmat);
					/* apply particle scale */
					mul_mat3_m4_fl(tmat, size*scale);
					mul_v3_fl(tmat[3], size*scale);
					/* group dupli offset, should apply after everything else */
					if (!is_zero_v3(part->dup_group->dupli_ofs))
						sub_v3_v3v3(tmat[3], tmat[3], part->dup_group->dupli_ofs);
					/* individual particle transform */
					mult_m4_m4m4(tmat, pamat, tmat);

					if (par_space_mat)
						mult_m4_m4m4(mat, par_space_mat, tmat);
					else
						copy_m4_m4(mat, tmat);

					dob= new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS, animated);
					copy_m4_m4(dob->omat, obcopylist[b].obmat);
					if (G.rendering)
						psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
				}
			}
			else {
				/* to give ipos in object correct offset */
				where_is_object_time(scene, ob, ctime-pa_time);

				copy_v3_v3(vec, obmat[3]);
				obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f;

				/* particle rotation uses x-axis as the aligned axis, so pre-rotate the object accordingly */
				if ((part->draw & PART_DRAW_ROTATE_OB) == 0) {
					float xvec[3], q[4];
					xvec[0] = -1.f;
					xvec[1] = xvec[2] = 0;
					vec_to_quat(q, xvec, ob->trackflag, ob->upflag);
					quat_to_mat4(obmat, q);
					obmat[3][3]= 1.0f;
				}
				
				/* Normal particles and cached hair live in global space so we need to
				 * remove the real emitter's transformation before 2nd order duplication.
				 */
				if (par_space_mat && GS(id->name) != ID_GR)
					mult_m4_m4m4(mat, psys->imat, pamat);
				else
					copy_m4_m4(mat, pamat);

				mult_m4_m4m4(tmat, mat, obmat);
				mul_mat3_m4_fl(tmat, size*scale);

				if (par_space_mat)
					mult_m4_m4m4(mat, par_space_mat, tmat);
				else
					copy_m4_m4(mat, tmat);

				if (part->draw & PART_DRAW_GLOBAL_OB)
					add_v3_v3v3(mat[3], mat[3], vec);

				dob= new_dupli_object(lb, ob, mat, ob->lay, counter, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated);
				copy_m4_m4(dob->omat, oldobmat);
				if (G.rendering)
					psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
			}
		}

		/* restore objects since they were changed in where_is_object_time */
		if (part->ren_as==PART_DRAW_GR) {
			for (a=0; a<totgroup; a++)
				*(oblist[a])= obcopylist[a];
		}
		else
			*ob= obcopy;
	}

	/* clean up */
	if (oblist)
		MEM_freeN(oblist);
	if (obcopylist)
		MEM_freeN(obcopylist);

	if (psys->lattice) {
		end_latt_deform(psys->lattice);
		psys->lattice = NULL;
	}
}
コード例 #18
0
ファイル: lattice.c プロジェクト: shyamalschandra/blender
void curve_deform_verts(
        Scene *scene, Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3],
        int numVerts, const char *vgroup, short defaxis)
{
	Curve *cu;
	int a;
	CurveDeform cd;
	MDeformVert *dvert = NULL;
	int defgrp_index = -1;
	const bool is_neg_axis = (defaxis > 2);

	if (cuOb->type != OB_CURVE)
		return;

	cu = cuOb->data;

	init_curve_deform(cuOb, target, &cd);

	/* dummy bounds, keep if CU_DEFORM_BOUNDS_OFF is set */
	if (is_neg_axis == false) {
		cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = 0.0f;
		cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 1.0f;
	}
	else {
		/* negative, these bounds give a good rest position */
		cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = -1.0f;
		cd.dmax[0] = cd.dmax[1] = cd.dmax[2] =  0.0f;
	}
	
	/* Check whether to use vertex groups (only possible if target is a Mesh or Lattice).
	 * We want either a Mesh/Lattice with no derived data, or derived data with deformverts.
	 */
	if (vgroup && vgroup[0] && ELEM(target->type, OB_MESH, OB_LATTICE)) {
		defgrp_index = defgroup_name_index(target, vgroup);

		if (defgrp_index != -1) {
			/* if there's derived data without deformverts, don't use vgroups */
			if (dm) {
				dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
			}
			else if (target->type == OB_LATTICE) {
				dvert = ((Lattice *)target->data)->dvert;
			}
			else {
				dvert = ((Mesh *)target->data)->dvert;
			}
		}
	}

	if (dvert) {
		MDeformVert *dvert_iter;
		float vec[3];

		if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
			for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
				const float weight = defvert_find_weight(dvert_iter, defgrp_index);

				if (weight > 0.0f) {
					mul_m4_v3(cd.curvespace, vertexCos[a]);
					copy_v3_v3(vec, vertexCos[a]);
					calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
					interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
					mul_m4_v3(cd.objectspace, vertexCos[a]);
				}
			}
		}
		else {
			/* set mesh min/max bounds */
			INIT_MINMAX(cd.dmin, cd.dmax);

			for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
				if (defvert_find_weight(dvert_iter, defgrp_index) > 0.0f) {
					mul_m4_v3(cd.curvespace, vertexCos[a]);
					minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]);
				}
			}

			for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
				const float weight = defvert_find_weight(dvert_iter, defgrp_index);

				if (weight > 0.0f) {
					/* already in 'cd.curvespace', prev for loop */
					copy_v3_v3(vec, vertexCos[a]);
					calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
					interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
					mul_m4_v3(cd.objectspace, vertexCos[a]);
				}
			}
		}
	}
	else {
		if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
			for (a = 0; a < numVerts; a++) {
				mul_m4_v3(cd.curvespace, vertexCos[a]);
				calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL);
				mul_m4_v3(cd.objectspace, vertexCos[a]);
			}
		}
		else {
			/* set mesh min max bounds */
			INIT_MINMAX(cd.dmin, cd.dmax);
				
			for (a = 0; a < numVerts; a++) {
				mul_m4_v3(cd.curvespace, vertexCos[a]);
				minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]);
			}
	
			for (a = 0; a < numVerts; a++) {
				/* already in 'cd.curvespace', prev for loop */
				calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL);
				mul_m4_v3(cd.objectspace, vertexCos[a]);
			}
		}
	}
}
コード例 #19
0
static char *rna_ColorRamp_path(PointerRNA *ptr)
{
	char *path = NULL;
	
	/* handle the cases where a single data-block may have 2 ramp types */
	if (ptr->id.data) {
		ID *id = ptr->id.data;
		
		switch (GS(id->name)) {
			case ID_MA: /* material has 2 cases - diffuse and specular */
			{
				Material *ma = (Material *)id;
				
				if (ptr->data == ma->ramp_col)
					path = BLI_strdup("diffuse_ramp");
				else if (ptr->data == ma->ramp_spec)
					path = BLI_strdup("specular_ramp");
				break;
			}
			
			case ID_NT:
			{
				bNodeTree *ntree = (bNodeTree *)id;
				bNode *node;
				PointerRNA node_ptr;
				char *node_path;
				
				for (node = ntree->nodes.first; node; node = node->next) {
					if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
						if (node->storage == ptr->data) {
							/* all node color ramp properties called 'color_ramp'
							 * prepend path from ID to the node
							 */
							RNA_pointer_create(id, &RNA_Node, node, &node_ptr);
							node_path = RNA_path_from_ID_to_struct(&node_ptr);
							path = BLI_sprintfN("%s.color_ramp", node_path);
							MEM_freeN(node_path);
						}
					}
				}
				break;
			}
			
			case ID_LS:
			{
				char *path = BKE_linestyle_path_to_color_ramp((FreestyleLineStyle *)id, (ColorBand *)ptr->data);
				if (path)
					return path;
				break;
			}
			
			default:
				/* everything else just uses 'color_ramp' */
				path = BLI_strdup("color_ramp");
				break;
		}
	}
	else {
		/* everything else just uses 'color_ramp' */
		path = BLI_strdup("color_ramp");
	}
	
	return path;
}
コード例 #20
0
ファイル: volumetric.c プロジェクト: OldBrunet/BGERTPS
static void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float *lacol)
{
	float visifac, lv[3], lampdist;
	float tr[3]={1.0,1.0,1.0};
	float hitco[3], *atten_co;
	float p, ref_col[3];
	
	if (lar->mode & LA_LAYER) if((lar->lay & shi->obi->lay)==0) return;
	if ((lar->lay & shi->lay)==0) return;
	if (lar->energy == 0.0f) return;
	
	if ((visifac= lamp_get_visibility(lar, co, lv, &lampdist)) == 0.f) return;
	
	copy_v3_v3(lacol, &lar->r);
	
	if(lar->mode & LA_TEXTURE) {
		shi->osatex= 0;
		do_lamp_tex(lar, lv, shi, lacol, LA_TEXTURE);
	}

	mul_v3_fl(lacol, visifac);

	if (ELEM(lar->type, LA_SUN, LA_HEMI))
		VECCOPY(lv, lar->vec);
	negate_v3(lv);
	
	if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADOWED) {
		mul_v3_fl(lacol, vol_get_shadow(shi, lar, co));
	}
	else if (ELEM3(shi->mat->vol.shade_type, MA_VOL_SHADE_SHADED, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE))
	{
		Isect is;
		
		if (shi->mat->vol.shadeflag & MA_VOL_RECV_EXT_SHADOW) {
			mul_v3_fl(lacol, vol_get_shadow(shi, lar, co));
			if (luminance(lacol) < 0.001f) return;
		}
		
		/* find minimum of volume bounds, or lamp coord */
		if (vol_get_bounds(shi, co, lv, hitco, &is, VOL_BOUNDS_SS)) {
			float dist = len_v3v3(co, hitco);
			VlakRen *vlr = (VlakRen *)is.hit.face;
			
			/* simple internal shadowing */
			if (vlr->mat->material_type == MA_TYPE_SURFACE) {
				lacol[0] = lacol[1] = lacol[2] = 0.0f;
				return;
			}

			if (ELEM(lar->type, LA_SUN, LA_HEMI))
				/* infinite lights, can never be inside volume */
				atten_co = hitco;
			else if ( lampdist < dist ) {
				atten_co = lar->co;
			} else
				atten_co = hitco;
			
			vol_get_transmittance(shi, tr, co, atten_co);
			
			mul_v3_v3v3(lacol, lacol, tr);
		}
		else {
			/* Point is on the outside edge of the volume,
			 * therefore no attenuation, full transmission.
			 * Radiance from lamp remains unchanged */
		}
	}
	
	if (luminance(lacol) < 0.001f) return;
	
	normalize_v3(lv);
	p = vol_get_phasefunc(shi, shi->mat->vol.asymmetry, shi->view, lv);
	
	/* physically based scattering with non-physically based RGB gain */
	vol_get_reflection_color(shi, ref_col, co);
	
	lacol[0] *= p * ref_col[0];
	lacol[1] *= p * ref_col[1];
	lacol[2] *= p * ref_col[2];
}
コード例 #21
0
static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
{
	ParticleData *pa=NULL;
	float min[3], max[3], delta[3], d;
	MVert *mv, *mvert = dm->getVertDataArray(dm,0);
	int totvert=dm->getNumVerts(dm), from=psys->part->from;
	int i, j, k, p, res=psys->part->grid_res, size[3], axis;

	/* find bounding box of dm */
	if (totvert > 0) {
		mv=mvert;
		copy_v3_v3(min, mv->co);
		copy_v3_v3(max, mv->co);
		mv++;
		for (i = 1; i < totvert; i++, mv++) {
			minmax_v3v3_v3(min, max, mv->co);
		}
	}
	else {
		zero_v3(min);
		zero_v3(max);
	}

	sub_v3_v3v3(delta, max, min);

	/* determine major axis */
	axis = axis_dominant_v3_single(delta);
	 
	d = delta[axis]/(float)res;

	size[axis] = res;
	size[(axis+1)%3] = (int)ceil(delta[(axis+1)%3]/d);
	size[(axis+2)%3] = (int)ceil(delta[(axis+2)%3]/d);

	/* float errors grrr.. */
	size[(axis+1)%3] = MIN2(size[(axis+1)%3],res);
	size[(axis+2)%3] = MIN2(size[(axis+2)%3],res);

	size[0] = MAX2(size[0], 1);
	size[1] = MAX2(size[1], 1);
	size[2] = MAX2(size[2], 1);

	/* no full offset for flat/thin objects */
	min[0]+= d < delta[0] ? d/2.f : delta[0]/2.f;
	min[1]+= d < delta[1] ? d/2.f : delta[1]/2.f;
	min[2]+= d < delta[2] ? d/2.f : delta[2]/2.f;

	for (i=0,p=0,pa=psys->particles; i<res; i++) {
		for (j=0; j<res; j++) {
			for (k=0; k<res; k++,p++,pa++) {
				pa->fuv[0] = min[0] + (float)i*d;
				pa->fuv[1] = min[1] + (float)j*d;
				pa->fuv[2] = min[2] + (float)k*d;
				pa->flag |= PARS_UNEXIST;
				pa->hair_index = 0; /* abused in volume calculation */
			}
		}
	}

	/* enable particles near verts/edges/faces/inside surface */
	if (from==PART_FROM_VERT) {
		float vec[3];

		pa=psys->particles;

		min[0] -= d/2.0f;
		min[1] -= d/2.0f;
		min[2] -= d/2.0f;

		for (i=0,mv=mvert; i<totvert; i++,mv++) {
			sub_v3_v3v3(vec,mv->co,min);
			vec[0]/=delta[0];
			vec[1]/=delta[1];
			vec[2]/=delta[2];
			pa[((int)(vec[0] * (size[0] - 1))  * res +
			    (int)(vec[1] * (size[1] - 1))) * res +
			    (int)(vec[2] * (size[2] - 1))].flag &= ~PARS_UNEXIST;
		}
	}
	else if (ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
		float co1[3], co2[3];

		MFace *mface= NULL, *mface_array;
		float v1[3], v2[3], v3[3], v4[4], lambda;
		int a, a1, a2, a0mul, a1mul, a2mul, totface;
		int amax= from==PART_FROM_FACE ? 3 : 1;

		totface=dm->getNumTessFaces(dm);
		mface=mface_array=dm->getTessFaceDataArray(dm,CD_MFACE);
		
		for (a=0; a<amax; a++) {
			if (a==0) { a0mul=res*res; a1mul=res; a2mul=1; }
			else if (a==1) { a0mul=res; a1mul=1; a2mul=res*res; }
			else { a0mul=1; a1mul=res*res; a2mul=res; }

			for (a1=0; a1<size[(a+1)%3]; a1++) {
				for (a2=0; a2<size[(a+2)%3]; a2++) {
					mface= mface_array;

					pa = psys->particles + a1*a1mul + a2*a2mul;
					copy_v3_v3(co1, pa->fuv);
					co1[a] -= d < delta[a] ? d/2.f : delta[a]/2.f;
					copy_v3_v3(co2, co1);
					co2[a] += delta[a] + 0.001f*d;
					co1[a] -= 0.001f*d;
					
					/* lets intersect the faces */
					for (i=0; i<totface; i++,mface++) {
						copy_v3_v3(v1, mvert[mface->v1].co);
						copy_v3_v3(v2, mvert[mface->v2].co);
						copy_v3_v3(v3, mvert[mface->v3].co);

						bool intersects_tri = isect_axial_line_segment_tri_v3(a, co1, co2, v2, v3, v1, &lambda);
						if (intersects_tri) {
							if (from==PART_FROM_FACE)
								(pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
							else /* store number of intersections */
								(pa+(int)(lambda*size[a])*a0mul)->hair_index++;
						}

						if (mface->v4 && (!intersects_tri || from==PART_FROM_VOLUME)) {
							copy_v3_v3(v4, mvert[mface->v4].co);

							if (isect_axial_line_segment_tri_v3(a, co1, co2, v4, v1, v3, &lambda)) {
								if (from==PART_FROM_FACE)
									(pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
								else
									(pa+(int)(lambda*size[a])*a0mul)->hair_index++;
							}
						}
					}

					if (from==PART_FROM_VOLUME) {
						int in=pa->hair_index%2;
						if (in) pa->hair_index++;
						for (i=0; i<size[0]; i++) {
							if (in || (pa+i*a0mul)->hair_index%2)
								(pa+i*a0mul)->flag &= ~PARS_UNEXIST;
							/* odd intersections == in->out / out->in */
							/* even intersections -> in stays same */
							in=(in + (pa+i*a0mul)->hair_index) % 2;
						}
					}
				}
			}
		}
	}

	if (psys->part->flag & PART_GRID_HEXAGONAL) {
		for (i=0,p=0,pa=psys->particles; i<res; i++) {
			for (j=0; j<res; j++) {
				for (k=0; k<res; k++,p++,pa++) {
					if (j%2)
						pa->fuv[0] += d/2.f;

					if (k%2) {
						pa->fuv[0] += d/2.f;
						pa->fuv[1] += d/2.f;
					}
				}
			}
		}
	}

	if (psys->part->flag & PART_GRID_INVERT) {
		for (i=0; i<size[0]; i++) {
			for (j=0; j<size[1]; j++) {
				pa=psys->particles + res*(i*res + j);
				for (k=0; k<size[2]; k++, pa++) {
					pa->flag ^= PARS_UNEXIST;
				}
			}
		}
	}

	if (psys->part->grid_rand > 0.f) {
		float rfac = d * psys->part->grid_rand;
		for (p=0,pa=psys->particles; p<psys->totpart; p++,pa++) {
			if (pa->flag & PARS_UNEXIST)
				continue;

			pa->fuv[0] += rfac * (psys_frand(psys, p + 31) - 0.5f);
			pa->fuv[1] += rfac * (psys_frand(psys, p + 32) - 0.5f);
			pa->fuv[2] += rfac * (psys_frand(psys, p + 33) - 0.5f);
		}
	}
}
コード例 #22
0
ファイル: fmodifier.c プロジェクト: wangyxuan/blender
static float fcm_cycles_time(
    FCurve *fcu, FModifier *fcm, float UNUSED(cvalue), float evaltime, void *storage_)
{
  FMod_Cycles *data = (FMod_Cycles *)fcm->data;
  tFCMED_Cycles *storage = storage_;
  float prevkey[2], lastkey[2], cycyofs = 0.0f;
  short side = 0, mode = 0;
  int cycles = 0;
  float ofs = 0;

  /* Initialize storage. */
  storage->cycyofs = 0;

  /* check if modifier is first in stack, otherwise disable ourself... */
  /* FIXME... */
  if (fcm->prev) {
    fcm->flag |= FMODIFIER_FLAG_DISABLED;
    return evaltime;
  }

  /* calculate new evaltime due to cyclic interpolation */
  if (fcu && fcu->bezt) {
    BezTriple *prevbezt = fcu->bezt;
    BezTriple *lastbezt = prevbezt + fcu->totvert - 1;

    prevkey[0] = prevbezt->vec[1][0];
    prevkey[1] = prevbezt->vec[1][1];

    lastkey[0] = lastbezt->vec[1][0];
    lastkey[1] = lastbezt->vec[1][1];
  }
  else if (fcu && fcu->fpt) {
    FPoint *prevfpt = fcu->fpt;
    FPoint *lastfpt = prevfpt + fcu->totvert - 1;

    prevkey[0] = prevfpt->vec[0];
    prevkey[1] = prevfpt->vec[1];

    lastkey[0] = lastfpt->vec[0];
    lastkey[1] = lastfpt->vec[1];
  }
  else {
    return evaltime;
  }

  /* check if modifier will do anything
   * 1) if in data range, definitely don't do anything
   * 2) if before first frame or after last frame, make sure some cycling is in use
   */
  if (evaltime < prevkey[0]) {
    if (data->before_mode) {
      side = -1;
      mode = data->before_mode;
      cycles = data->before_cycles;
      ofs = prevkey[0];
    }
  }
  else if (evaltime > lastkey[0]) {
    if (data->after_mode) {
      side = 1;
      mode = data->after_mode;
      cycles = data->after_cycles;
      ofs = lastkey[0];
    }
  }
  if ((ELEM(0, side, mode))) {
    return evaltime;
  }

  /* find relative place within a cycle */
  {
    float cycdx = 0, cycdy = 0;
    float cycle = 0, cyct = 0;

    /* calculate period and amplitude (total height) of a cycle */
    cycdx = lastkey[0] - prevkey[0];
    cycdy = lastkey[1] - prevkey[1];

    /* check if cycle is infinitely small, to be point of being impossible to use */
    if (cycdx == 0) {
      return evaltime;
    }

    /* calculate the 'number' of the cycle */
    cycle = ((float)side * (evaltime - ofs) / cycdx);

    /* calculate the time inside the cycle */
    cyct = fmod(evaltime - ofs, cycdx);

    /* check that cyclic is still enabled for the specified time */
    if (cycles == 0) {
      /* catch this case so that we don't exit when we have (cycles = 0)
       * as this indicates infinite cycles...
       */
    }
    else if (cycle > cycles) {
      /* we are too far away from range to evaluate
       * TODO: but we should still hold last value...
       */
      return evaltime;
    }

    /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */
    if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
      if (side < 0) {
        cycyofs = (float)floor((evaltime - ofs) / cycdx);
      }
      else {
        cycyofs = (float)ceil((evaltime - ofs) / cycdx);
      }
      cycyofs *= cycdy;
    }

    /* special case for cycle start/end */
    if (cyct == 0.0f) {
      evaltime = (side == 1 ? lastkey[0] : prevkey[0]);

      if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)cycle % 2)) {
        evaltime = (side == 1 ? prevkey[0] : lastkey[0]);
      }
    }
    /* calculate where in the cycle we are (overwrite evaltime to reflect this) */
    else if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle + 1) % 2)) {
      /* When 'mirror' option is used and cycle number is odd, this cycle is played in reverse
       * - for 'before' extrapolation, we need to flip in a different way, otherwise values past
       *   then end of the curve get referenced
       *   (result of fmod will be negative, and with different phase).
       */
      if (side < 0) {
        evaltime = prevkey[0] - cyct;
      }
      else {
        evaltime = lastkey[0] - cyct;
      }
    }
    else {
      /* the cycle is played normally... */
      evaltime = prevkey[0] + cyct;
    }
    if (evaltime < prevkey[0]) {
      evaltime += cycdx;
    }
  }

  /* store temp data if needed */
  if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
    storage->cycyofs = cycyofs;
  }

  /* return the new frame to evaluate */
  return evaltime;
}
コード例 #23
0
ファイル: keyframes_general.c プロジェクト: Moguri/blender
/* This function adds data to the keyframes copy/paste buffer, freeing existing data first */
short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
{	
	bAnimListElem *ale;
	Scene *scene = ac->scene;
	
	/* clear buffer first */
	free_anim_copybuf();
	
	/* assume that each of these is an F-Curve */
	for (ale = anim_data->first; ale; ale = ale->next) {
		FCurve *fcu = (FCurve *)ale->key_data;
		tAnimCopybufItem *aci;
		BezTriple *bezt, *nbezt, *newbuf;
		int i;
		
		/* firstly, check if F-Curve has any selected keyframes
		 *	- skip if no selected keyframes found (so no need to create unnecessary copy-buffer data)
		 *	- this check should also eliminate any problems associated with using sample-data
		 */
		if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ANIM_editkeyframes_ok(BEZT_OK_SELECTED), NULL) == 0)
			continue;
		
		/* init copybuf item info */
		aci = MEM_callocN(sizeof(tAnimCopybufItem), "AnimCopybufItem");
		aci->id = ale->id;
		aci->id_type = GS(ale->id->name);
		aci->grp = fcu->grp;
		aci->rna_path = MEM_dupallocN(fcu->rna_path);
		aci->array_index = fcu->array_index;
		
		/* detect if this is a bone. We do that here rather than during pasting because ID pointers will get invalidated if we undo.
		 * storing the relevant information here helps avoiding crashes if we undo-repaste */
		if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) {
			Object *ob = (Object *)aci->id;
			bPoseChannel *pchan;
			char *bone_name;

			bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones[");
			pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
			if (pchan) {
				aci->is_bone = true;
			}
			if (bone_name) MEM_freeN(bone_name);
		}
		
		BLI_addtail(&animcopybuf, aci);
		
		/* add selected keyframes to buffer */
		/* TODO: currently, we resize array every time we add a new vert -
		 * this works ok as long as it is assumed only a few keys are copied */
		for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
			if (BEZT_ISSEL_ANY(bezt)) {
				/* add to buffer */
				newbuf = MEM_callocN(sizeof(BezTriple) * (aci->totvert + 1), "copybuf beztriple");
				
				/* assume that since we are just re-sizing the array, just copy all existing data across */
				if (aci->bezt)
					memcpy(newbuf, aci->bezt, sizeof(BezTriple) * (aci->totvert));
				
				/* copy current beztriple across too */
				nbezt = &newbuf[aci->totvert];
				*nbezt = *bezt;
				
				/* ensure copy buffer is selected so pasted keys are selected */
				BEZT_SEL_ALL(nbezt);
				
				/* free old array and set the new */
				if (aci->bezt) MEM_freeN(aci->bezt);
				aci->bezt = newbuf;
				aci->totvert++;
				
				/* check if this is the earliest frame encountered so far */
				if (bezt->vec[1][0] < animcopy_firstframe)
					animcopy_firstframe = bezt->vec[1][0];
				if (bezt->vec[1][0] > animcopy_lastframe)
					animcopy_lastframe = bezt->vec[1][0];
			}
		}
		
	}
	
	/* check if anything ended up in the buffer */
	if (ELEM(NULL, animcopybuf.first, animcopybuf.last))
		return -1;

	/* in case 'relative' paste method is used */
	animcopy_cfra = CFRA;

	/* everything went fine */
	return 0;
}
コード例 #24
0
ファイル: paint_image_2d.c プロジェクト: mcgrathd/blender
static void brush_painter_2d_refresh_cache(ImagePaintState *s, BrushPainter *painter, const float pos[2], const float mouse[2], float pressure, float distance, float size)
{
	const Scene *scene = painter->scene;
	UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
	Brush *brush = painter->brush;
	BrushPainterCache *cache = &painter->cache;
	const int diameter = 2 * size;

	bool do_random = false;
	bool do_partial_update = false;
	bool update_color = (brush->flag & BRUSH_USE_GRADIENT) &&
	                    ((ELEM(brush->gradient_stroke_mode,
	                           BRUSH_GRADIENT_SPACING_REPEAT,
	                           BRUSH_GRADIENT_SPACING_CLAMP)) ||
	                     (cache->last_pressure != pressure));
	float tex_rotation = -brush->mtex.rot;
	float mask_rotation = -brush->mask_mtex.rot;

	painter->pool = BKE_image_pool_new();

	/* determine how can update based on textures used */
	if (painter->cache.is_texbrush) {
		if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
			tex_rotation += ups->brush_rotation;
		}
		else if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
			do_random = true;
		else if (!((brush->flag & BRUSH_ANCHORED) || update_color))
			do_partial_update = true;

		brush_painter_2d_tex_mapping(s, diameter, painter->startpaintpos, pos, mouse,
		                             brush->mtex.brush_map_mode, &painter->tex_mapping);
	}

	if (painter->cache.is_maskbrush) {
		bool renew_maxmask = false;
		bool do_partial_update_mask = false;
		/* invalidate case for all mapping modes */
		if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
			mask_rotation += ups->brush_rotation_sec;
		}
		else if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) {
			renew_maxmask = true;
		}
		else if (!(brush->flag & BRUSH_ANCHORED)) {
			do_partial_update_mask = true;
			renew_maxmask = true;
		}
		/* explicilty disable partial update even if it has been enabled above */
		if (brush->mask_pressure) {
			do_partial_update_mask = false;
			renew_maxmask = true;
		}

		if ((diameter != cache->lastdiameter) ||
		    (mask_rotation != cache->last_mask_rotation) ||
		    renew_maxmask)
		{
			if (cache->tex_mask) {
				MEM_freeN(cache->tex_mask);
				cache->tex_mask = NULL;
			}

			brush_painter_2d_tex_mapping(s, diameter, painter->startpaintpos, pos, mouse,
			                             brush->mask_mtex.brush_map_mode, &painter->mask_mapping);

			if (do_partial_update_mask)
				brush_painter_mask_imbuf_partial_update(painter, pos, diameter);
			else
				cache->tex_mask = brush_painter_mask_ibuf_new(painter, diameter);
			cache->last_mask_rotation = mask_rotation;
		}
	}

	/* curve mask can only change if the size changes */
	if (diameter != cache->lastdiameter) {
		if (cache->curve_mask) {
			MEM_freeN(cache->curve_mask);
			cache->curve_mask = NULL;
		}

		cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size);
	}

	/* detect if we need to recreate image brush buffer */
	if ((diameter != cache->lastdiameter) ||
	    (tex_rotation != cache->last_tex_rotation) ||
	    do_random ||
	    update_color)
	{
		if (cache->ibuf) {
			IMB_freeImBuf(cache->ibuf);
			cache->ibuf = NULL;
		}

		if (do_partial_update) {
			/* do partial update of texture */
			brush_painter_imbuf_partial_update(painter, pos, diameter);
		}
		else {
			/* create brush from scratch */
			cache->ibuf = brush_painter_imbuf_new(painter, diameter, pressure, distance);
		}

		cache->lastdiameter = diameter;
		cache->last_tex_rotation = tex_rotation;
		cache->last_pressure = pressure;
	}
	else if (do_partial_update) {
		/* do only partial update of texture */
		int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
		int dy = (int)painter->lastpaintpos[1] - (int)pos[1];

		if ((dx != 0) || (dy != 0)) {
			brush_painter_imbuf_partial_update(painter, pos, diameter);
		}
	}

	BKE_image_pool_free(painter->pool);
	painter->pool = NULL;
}
コード例 #25
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 targeting) */

	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);
	}
}
コード例 #26
0
ファイル: ls_route.c プロジェクト: lally/ioquake
void qhsort(void* start, int n, int sz,
            int (*compar)(void* a, void* b, void* handle),
            void* handle) {
    byte *vec = (byte*) start;
    int left=1, right=n-1;
    const int pivot = 0;
    assert(sort_depth < 16);
    if (n <= 1)
        return;

    sort_depth++;
    while (left < right) {
        while (left < n && compar(ELEM(left), ELEM(pivot), handle) < 0) {
            left++;
        }

        while (right >= 0 && compar(ELEM(right), ELEM(pivot), handle) > 0) {
            right--;
        }

        if (left < right) {
            swapb(ELEM(left), ELEM(right), sz);
        }
    }      

    if (compar(ELEM(right), ELEM(pivot), handle) < 0) {
        swapb(ELEM(right), ELEM(pivot), sz);
    }

    qhsort(start, right, sz, compar, handle);
    qhsort(ELEM(right+1), n-right-1, sz, compar, handle);
    sort_depth--;
}
コード例 #27
0
/* Selects all visible keyframes in the same frames as the specified elements */
static void columnselect_action_keys(bAnimContext *ac, short mode)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;

	Scene *scene = ac->scene;
	CfraElem *ce;
	KeyframeEditFunc select_cb, ok_cb;
	KeyframeEditData ked = {{NULL}};

	/* build list of columns */
	switch (mode) {
		case ACTKEYS_COLUMNSEL_KEYS: /* list of selected keys */
			if (ac->datatype == ANIMCONT_GPENCIL) {
				filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
				ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);

				for (ale = anim_data.first; ale; ale = ale->next)
					ED_gplayer_make_cfra_list(ale->data, &ked.list, 1);
			}
			else {
				filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
				ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);

				for (ale = anim_data.first; ale; ale = ale->next)
					ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL);
			}
			ANIM_animdata_freelist(&anim_data);
			break;

		case ACTKEYS_COLUMNSEL_CFRA: /* current frame */
			/* make a single CfraElem for storing this */
			ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
			BLI_addtail(&ked.list, ce);

			ce->cfra = (float)CFRA;
			break;

		case ACTKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
			ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT);
			break;

		default: /* invalid option */
			return;
	}

	/* set up BezTriple edit callbacks */
	select_cb = ANIM_editkeyframes_select(SELECT_ADD);
	ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);

	/* loop through all of the keys and select additional keyframes
	 * based on the keys found to be selected above
	 */
	if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
	else
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);

	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);

		/* loop over cfraelems (stored in the KeyframeEditData->list)
		 * - we need to do this here, as we can apply fewer NLA-mapping conversions
		 */
		for (ce = ked.list.first; ce; ce = ce->next) {
			/* set frame for validation callback to refer to */
			if (adt)
				ked.f1 = BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
			else
				ked.f1 = ce->cfra;

			/* select elements with frame number matching cfraelem */
			if (ale->type == ANIMTYPE_GPLAYER)
				ED_gpencil_select_frame(ale->data, ce->cfra, SELECT_ADD);
			else if (ale->type == ANIMTYPE_MASKLAYER)
				ED_mask_select_frame(ale->data, ce->cfra, SELECT_ADD);
			else
				ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
		}
	}

	/* free elements */
	BLI_freelistN(&ked.list);
	ANIM_animdata_freelist(&anim_data);
}
コード例 #28
0
/**
 * Calculate smooth groups from sharp edges.
 *
 * \param r_totgroup The total number of groups, 1 or more.
 * \return Polygon aligned array of group index values (bitflags if use_bitflags is true), starting at 1.
 */
int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
                                const MPoly *mpoly, const int totpoly,
                                const MLoop *mloop, const int totloop,
                                int *r_totgroup, const bool use_bitflags)
{
	int *poly_groups;
	int *poly_stack;

	int poly_prev = 0;
	const int temp_poly_group_id = 3;  /* Placeholder value. */
	const int poly_group_id_overflowed = 5;  /* Group we could not find any available bit, will be reset to 0 at end */
	int tot_group = 0;
	bool group_id_overflow = false;

	/* map vars */
	MeshElemMap *edge_poly_map;
	int *edge_poly_mem;

	if (totpoly == 0) {
		*r_totgroup = 0;
		return NULL;
	}

	BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem,
	                              medge, totedge,
	                              mpoly, totpoly,
	                              mloop, totloop);

	poly_groups = MEM_callocN(sizeof(int) * (size_t)totpoly, __func__);
	poly_stack  = MEM_mallocN(sizeof(int) * (size_t)totpoly, __func__);

	while (true) {
		int poly;
		int bit_poly_group_mask = 0;
		int poly_group_id;
		int ps_curr_idx = 0, ps_end_idx = 0;  /* stack indices */

		for (poly = poly_prev; poly < totpoly; poly++) {
			if (poly_groups[poly] == 0) {
				break;
			}
		}

		if (poly == totpoly) {
			/* all done */
			break;
		}

		poly_group_id = use_bitflags ? temp_poly_group_id : ++tot_group;

		/* start searching from here next time */
		poly_prev = poly + 1;

		poly_groups[poly] = poly_group_id;
		poly_stack[ps_end_idx++] = poly;

		while (ps_curr_idx != ps_end_idx) {
			const MPoly *mp;
			const MLoop *ml;
			bool sharp_poly;
			int j;

			poly = poly_stack[ps_curr_idx++];
			BLI_assert(poly_groups[poly] == poly_group_id);

			mp = &mpoly[poly];
			sharp_poly = !(mp->flag & ME_SMOOTH);
			for (ml = &mloop[mp->loopstart], j = mp->totloop; j--; ml++) {
				/* loop over poly users */
				const MeshElemMap *map_ele = &edge_poly_map[ml->e];
				const int *p = map_ele->indices;
				int i = map_ele->count;
				/* Edge is smooth only if its poly is not sharp, edge is not sharp,
				 * and edge is used by exactly two polygons. */
				if (!sharp_poly && !(medge[ml->e].flag & ME_SHARP) && i == 2) {
					for (; i--; p++) {
						/* if we meet other non initialized its a bug */
						BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id));

						if (poly_groups[*p] == 0) {
							poly_groups[*p] = poly_group_id;
							poly_stack[ps_end_idx++] = *p;
						}
					}
				}
				else if (use_bitflags) {
					/* Find contiguous smooth groups already assigned, these are the values we can't reuse! */
					for (; i--; p++) {
						int bit = poly_groups[*p];
						if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) &&
						    !(bit_poly_group_mask & bit))
						{
							bit_poly_group_mask |= bit;
						}
					}
				}
			}
		}
		/* And now, we have all our poly from current group in poly_stack (from 0 to (ps_end_idx - 1)), as well as
		 * all smoothgroups bits we can't use in bit_poly_group_mask.
		 */
		if (use_bitflags) {
			int i, *p, gid_bit = 0;
			poly_group_id = 1;

			/* Find first bit available! */
			for (; (poly_group_id & bit_poly_group_mask) && (gid_bit < 32); gid_bit++) {
				poly_group_id <<= 1;  /* will 'overflow' on last possible iteration. */
			}
			if (UNLIKELY(gid_bit > 31)) {
				/* All bits used in contiguous smooth groups, we can't do much!
				 * Note: this is *very* unlikely - theoretically, four groups are enough, I don't think we can reach
				 *       this goal with such a simple algo, but I don't think either we'll never need all 32 groups!
				 */
				printf("Warning, could not find an available id for current smooth group, faces will me marked "
				       "as out of any smooth group...\n");
				poly_group_id = poly_group_id_overflowed; /* Can't use 0, will have to set them to this value later. */
				group_id_overflow = true;
			}
			if (gid_bit > tot_group) {
				tot_group = gid_bit;
			}
			/* And assign the final smooth group id to that poly group! */
			for (i = ps_end_idx, p = poly_stack; i--; p++) {
				poly_groups[*p] = poly_group_id;
			}
		}
	}

	if (use_bitflags) {
		/* used bits are zero-based. */
		tot_group++;
	}

	if (UNLIKELY(group_id_overflow)) {
		int i = totpoly, *gid = poly_groups;
		for (; i--; gid++) {
			if (*gid == poly_group_id_overflowed) {
				*gid = 0;
			}
		}
		/* Using 0 as group id adds one more group! */
		tot_group++;
	}

	MEM_freeN(edge_poly_map);
	MEM_freeN(edge_poly_mem);
	MEM_freeN(poly_stack);

	*r_totgroup = tot_group;

	return poly_groups;
}
コード例 #29
0
static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang)
{
	BakeShade *bs = handle;
	ShadeSample *ssamp = &bs->ssamp;
	ShadeResult shr;
	VlakRen *vlr = shi->vlr;

	shade_input_init_material(shi);

	if (bs->type == RE_BAKE_AO) {
		ambient_occlusion(shi);

		if (R.r.bake_flag & R_BAKE_NORMALIZE) {
			copy_v3_v3(shr.combined, shi->ao);
		}
		else {
			zero_v3(shr.combined);
			environment_lighting_apply(shi, &shr);
		}
	}
	else {
		if (bs->type == RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */
			shi->r = shi->g = shi->b = 1.0f;

		shade_input_set_shade_texco(shi);
		
		/* only do AO for a full bake (and obviously AO bakes)
		 * AO for light bakes is a leftover and might not be needed */
		if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT))
			shade_samples_do_AO(ssamp);
		
		if (shi->mat->nodetree && shi->mat->use_nodes) {
			ntreeShaderExecTree(shi->mat->nodetree, shi, &shr);
			shi->mat = vlr->mat;  /* shi->mat is being set in nodetree */
		}
		else
			shade_material_loop(shi, &shr);

		if (bs->type == RE_BAKE_NORMALS) {
			float nor[3];

			copy_v3_v3(nor, shi->vn);

			if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA) {
				/* pass */
			}
			else if (R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) {
				float mat[3][3], imat[3][3];

				/* bitangent */
				if (tvn && ttang) {
					copy_v3_v3(mat[0], ttang);
					cross_v3_v3v3(mat[1], tvn, ttang);
					mul_v3_fl(mat[1], ttang[3]);
					copy_v3_v3(mat[2], tvn);
				}
				else {
					copy_v3_v3(mat[0], shi->nmaptang);
					cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang);
					mul_v3_fl(mat[1], shi->nmaptang[3]);
					copy_v3_v3(mat[2], shi->nmapnorm);
				}

				invert_m3_m3(imat, mat);
				mul_m3_v3(imat, nor);
			}
			else if (R.r.bake_normal_space == R_BAKE_SPACE_OBJECT)
				mul_mat3_m4_v3(ob->imat_ren, nor);  /* ob->imat_ren includes viewinv! */
			else if (R.r.bake_normal_space == R_BAKE_SPACE_WORLD)
				mul_mat3_m4_v3(R.viewinv, nor);

			normalize_v3(nor); /* in case object has scaling */

			/* The invert of the red channel is to make
			 * the normal map compliant with the outside world.
			 * It needs to be done because in Blender
			 * the normal used in the renderer points inward. It is generated
			 * this way in calc_vertexnormals(). Should this ever change
			 * this negate must be removed. */
			shr.combined[0] = (-nor[0]) / 2.0f + 0.5f;
			shr.combined[1] = nor[1]    / 2.0f + 0.5f;
			shr.combined[2] = nor[2]    / 2.0f + 0.5f;
		}
		else if (bs->type == RE_BAKE_TEXTURE) {
			copy_v3_v3(shr.combined, &shi->r);
			shr.alpha = shi->alpha;
		}
		else if (bs->type == RE_BAKE_SHADOW) {
			copy_v3_v3(shr.combined, shr.shad);
			shr.alpha = shi->alpha;
		}
		else if (bs->type == RE_BAKE_SPEC_COLOR) {
			copy_v3_v3(shr.combined, &shi->specr);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_SPEC_INTENSITY) {
			copy_v3_fl(shr.combined, shi->spec);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_MIRROR_COLOR) {
			copy_v3_v3(shr.combined, &shi->mirr);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_MIRROR_INTENSITY) {
			copy_v3_fl(shr.combined, shi->ray_mirror);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_ALPHA) {
			copy_v3_fl(shr.combined, shi->alpha);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_EMIT) {
			copy_v3_fl(shr.combined, shi->emit);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_VERTEX_COLORS) {
			copy_v3_v3(shr.combined, shi->vcol);
			shr.alpha = shi->vcol[3];
		}
	}
	
	if (bs->rect_float && !bs->vcol) {
		float *col = bs->rect_float + 4 * (bs->rectx * y + x);
		copy_v3_v3(col, shr.combined);
		if (bs->type == RE_BAKE_ALL || bs->type == RE_BAKE_TEXTURE || bs->type == RE_BAKE_VERTEX_COLORS) {
			col[3] = shr.alpha;
		}
		else {
			col[3] = 1.0;
		}
	}
	else {
		/* Target is char (LDR). */
		unsigned char col[4];

		if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
			float rgb[3];

			copy_v3_v3(rgb, shr.combined);
			if (R.scene_color_manage) {
				/* Vertex colors have no way to specify color space, so they
				 * default to sRGB. */
				if (!bs->vcol)
					IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace);
				else
					linearrgb_to_srgb_v3_v3(rgb, rgb);
			}
			rgb_float_to_uchar(col, rgb);
		}
		else {
			rgb_float_to_uchar(col, shr.combined);
		}
		
		if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE, RE_BAKE_VERTEX_COLORS)) {
			col[3] = FTOCHAR(shr.alpha);
		}
		else {
			col[3] = 255;
		}

		if (bs->vcol) {
			/* Vertex color baking. Vcol has no useful alpha channel (it exists
			 * but is used only for vertex painting). */
			bs->vcol->r = col[0];
			bs->vcol->g = col[1];
			bs->vcol->b = col[2];
		}
		else {
			unsigned char *imcol = (unsigned char *)(bs->rect + bs->rectx * y + x);
			copy_v4_v4_char((char *)imcol, (char *)col);
		}

	}
	
	if (bs->rect_mask) {
		bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED;
	}

	if (bs->do_update) {
		*bs->do_update = true;
	}
}
コード例 #30
0
  PRUint32 mGroup;
  PRUint32 mCanContainGroups;
  PRPackedBool mIsContainer;
  PRPackedBool mCanContainSelf;
};

#ifdef DEBUG
#define ELEM(_tag, _isContainer, _canContainSelf, _group, _canContainGroups) \
  { eHTMLTag_##_tag, _group, _canContainGroups, _isContainer, _canContainSelf }
#else
#define ELEM(_tag, _isContainer, _canContainSelf, _group, _canContainGroups) \
  { _group, _canContainGroups, _isContainer, _canContainSelf }
#endif

static const nsElementInfo kElements[eHTMLTag_userdefined] = {
  ELEM(a, PR_TRUE, PR_FALSE, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
  ELEM(abbr, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
  ELEM(acronym, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
  ELEM(address, PR_TRUE, PR_TRUE, GROUP_BLOCK,
       GROUP_INLINE_ELEMENT | GROUP_P),
  ELEM(applet, PR_TRUE, PR_TRUE, GROUP_SPECIAL | GROUP_BLOCK,
       GROUP_FLOW_ELEMENT | GROUP_OBJECT_CONTENT),
  ELEM(area, PR_FALSE, PR_FALSE, GROUP_MAP_CONTENT, GROUP_NONE),
  ELEM(b, PR_TRUE, PR_TRUE, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
  ELEM(base, PR_FALSE, PR_FALSE, GROUP_HEAD_CONTENT, GROUP_NONE),
  ELEM(basefont, PR_FALSE, PR_FALSE, GROUP_SPECIAL, GROUP_NONE),
  ELEM(bdo, PR_TRUE, PR_TRUE, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
  ELEM(bgsound, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE),
  ELEM(big, PR_TRUE, PR_TRUE, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
  ELEM(blink, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE),
  ELEM(blockquote, PR_TRUE, PR_TRUE, GROUP_BLOCK, GROUP_FLOW_ELEMENT),