Example #1
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.
			 *
			 * there is also a small 1e-5f bias for precision issues. otherwise
			 * we randomly get 127 or 128 for neutral colors. we choose 128
			 * because it is the convention flat color. * */
			shr.combined[0] = (-nor[0]) / 2.0f + 0.5f + 1e-5f;
			shr.combined[1] = nor[1]    / 2.0f + 0.5f + 1e-5f;
			shr.combined[2] = nor[2]    / 2.0f + 0.5f + 1e-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;
	}
}
Example #2
0
/* draw keyframes in each channel */
void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	View2D *v2d= &ar->v2d;
	bDopeSheet *ads= &saction->ads;
	AnimData *adt= NULL;
	
	float act_start, act_end, y;
	int height, items;
	
	unsigned char col1[3], col2[3];
	unsigned char col1a[3], col2a[3];
	unsigned char col1b[3], col2b[3];
	
	
	/* get theme colors */
	UI_GetThemeColor3ubv(TH_BACK, col2);
	UI_GetThemeColor3ubv(TH_HILITE, col1);
	
	UI_GetThemeColor3ubv(TH_GROUP, col2a);
	UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
	
	UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b);
	UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
	
	/* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */

	/* if in NLA there's a strip active, map the view */
	if (ac->datatype == ANIMCONT_ACTION) {
		adt= ANIM_nla_mapping_get(ac, NULL);
		
		/* start and end of action itself */
		calc_action_range(ac->data, &act_start, &act_end, 0);
	}
	
	/* build list of channels to draw */
	filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
	items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* Update max-extent of channels here (taking into account scrollers):
	 * 	- this is done to allow the channel list to be scrollable, but must be done here
	 * 	  to avoid regenerating the list again and/or also because channels list is drawn first
	 *	- offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
	 *	  start of list offset, and the second is as a correction for the scrollers.
	 */
	height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
	/* don't use totrect set, as the width stays the same 
	 * (NOTE: this is ok here, the configuration is pretty straightforward) 
	 */
	v2d->tot.ymin= (float)(-height);
	
	/* first backdrop strips */
	y= (float)(-ACHANNEL_HEIGHT);
	glEnable(GL_BLEND);
	
	for (ale= anim_data.first; ale; ale= ale->next) {
		const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
		const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
		
		/* check if visible */
		if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
			 IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
		{
			bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
			int sel=0;
			
			/* determine if any need to draw channel */
			if (ale->datatype != ALE_NONE) {
				/* determine if channel is selected */
				if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
					sel= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
				
				if (ELEM3(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
					switch (ale->type) {
						case ANIMTYPE_SUMMARY:
						{
							// FIXME: hardcoded colors - reddish color from NLA
							glColor4f(0.8f, 0.2f, 0.0f, 0.4f);
						}
							break;
						
						case ANIMTYPE_SCENE:
						case ANIMTYPE_OBJECT:
						{
							if (sel) glColor4ub(col1b[0], col1b[1], col1b[2], 0x45); 
							else glColor4ub(col1b[0], col1b[1], col1b[2], 0x22); 
						}
							break;
						
						case ANIMTYPE_FILLACTD:
						case ANIMTYPE_FILLMATD:
						case ANIMTYPE_FILLPARTD:
						case ANIMTYPE_DSSKEY:
						case ANIMTYPE_DSWOR:
						{
							if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45); 
							else glColor4ub(col2b[0], col2b[1], col2b[2], 0x22); 
						}
							break;
						
						case ANIMTYPE_GROUP:
						{
							if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
							else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
						}
							break;
						
						default:
						{
							if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
							else glColor4ub(col2[0], col2[1], col2[2], 0x22);
						}
							break;
					}
					
					/* draw region twice: firstly backdrop, then the current range */
					glRectf(v2d->cur.xmin,  (float)y-ACHANNEL_HEIGHT_HALF,  v2d->cur.xmax+EXTRA_SCROLL_PAD,  (float)y+ACHANNEL_HEIGHT_HALF);
					
					if (ac->datatype == ANIMCONT_ACTION)
						glRectf(act_start,  (float)y-ACHANNEL_HEIGHT_HALF,  act_end,  (float)y+ACHANNEL_HEIGHT_HALF);
				}
				else if (ac->datatype == ANIMCONT_GPENCIL) {
					/* frames less than one get less saturated background */
					if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
					else glColor4ub(col2[0], col2[1], col2[2], 0x22);
					glRectf(0.0f, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmin, (float)y+ACHANNEL_HEIGHT_HALF);
					
					/* frames one and higher get a saturated background */
					if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
					else glColor4ub(col2[0], col2[1], col2[2], 0x44);
					glRectf(v2d->cur.xmin, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmax+EXTRA_SCROLL_PAD,  (float)y+ACHANNEL_HEIGHT_HALF);
				}
			}
		}
		
		/*	Increment the step */
		y -= ACHANNEL_STEP;
	}		
	glDisable(GL_BLEND);
	
	/* Draw keyframes 
	 *	1) Only channels that are visible in the Action Editor get drawn/evaluated.
	 *	   This is to try to optimise this for heavier data sets
	 *	2) Keyframes which are out of view horizontally are disregarded 
	 */
	y= (float)(-ACHANNEL_HEIGHT);
	
	for (ale= anim_data.first; ale; ale= ale->next) {
		const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
		const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
		
		/* check if visible */
		if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
			 IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
		{
			/* check if anything to show for this channel */
			if (ale->datatype != ALE_NONE) {
				adt= ANIM_nla_mapping_get(ac, ale);
				
				/* draw 'keyframes' for each specific datatype */
				switch (ale->datatype) {
					case ALE_ALL:
						draw_summary_channel(v2d, ale->data, y);
						break;
					case ALE_SCE:
						draw_scene_channel(v2d, ads, ale->key_data, y);
						break;
					case ALE_OB:
						draw_object_channel(v2d, ads, ale->key_data, y);
						break;
					case ALE_ACT:
						draw_action_channel(v2d, adt, ale->key_data, y);
						break;
					case ALE_GROUP:
						draw_agroup_channel(v2d, adt, ale->data, y);
						break;
					case ALE_FCURVE:
						draw_fcurve_channel(v2d, adt, ale->key_data, y);
						break;
					case ALE_GPFRAME:
						draw_gpl_channel(v2d, ads, ale->data, y);
						break;
				}
			}
		}
		
		y-= ACHANNEL_STEP;
	}
	
	/* free tempolary channels used for drawing */
	BLI_freelistN(&anim_data);

	/* black line marking 'current frame' for Time-Slide transform mode */
	if (saction->flag & SACTION_MOVING) {
		glColor3f(0.0f, 0.0f, 0.0f);
		
		glBegin(GL_LINES);
			glVertex2f(saction->timeslide, v2d->cur.ymin-EXTRA_SCROLL_PAD);
			glVertex2f(saction->timeslide, v2d->cur.ymax);
		glEnd();
	}
}
Example #3
0
static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, wmEvent *event, const float mval[2])
{
	ReportList *reports = CTX_wm_reports(C); // XXX...
	
	if (mval[1]>te->ys && mval[1]<te->ys+UI_UNIT_Y) {
		int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0;
		TreeStoreElem *tselem= TREESTORE(te);
		
		/* select object that's clicked on and popup context menu */
		if (!(tselem->flag & TSE_SELECTED)) {
			
			if ( outliner_has_one_flag(soops, &soops->tree, TSE_SELECTED, 1) )
				outliner_set_flag(soops, &soops->tree, TSE_SELECTED, 0);
			
			tselem->flag |= TSE_SELECTED;
			/* redraw, same as outliner_select function */
			soops->storeflag |= SO_TREESTORE_REDRAW;
			ED_region_tag_redraw(ar);
		}
		
		set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
		
		if (scenelevel) {
			//if (objectlevel || datalevel || idlevel) error("Mixed selection");
			//else pupmenu("Scene Operations%t|Delete");
		}
		else if (objectlevel) {
			WM_operator_name_call(C, "OUTLINER_OT_object_operation", WM_OP_INVOKE_REGION_WIN, NULL);
		}
		else if (idlevel) {
			if (idlevel==-1 || datalevel) BKE_report(reports, RPT_WARNING, "Mixed selection");
			else {
				if (idlevel==ID_GR)
					WM_operator_name_call(C, "OUTLINER_OT_group_operation", WM_OP_INVOKE_REGION_WIN, NULL);
				else
					WM_operator_name_call(C, "OUTLINER_OT_id_operation", WM_OP_INVOKE_REGION_WIN, NULL);
			}
		}
		else if (datalevel) {
			if (datalevel==-1) BKE_report(reports, RPT_WARNING, "Mixed selection");
			else {
				if (datalevel == TSE_ANIM_DATA)
					WM_operator_name_call(C, "OUTLINER_OT_animdata_operation", WM_OP_INVOKE_REGION_WIN, NULL);
				else if (datalevel == TSE_DRIVER_BASE)
					/* do nothing... no special ops needed yet */;
				else if (ELEM3(datalevel, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS))
					/*WM_operator_name_call(C, "OUTLINER_OT_renderdata_operation", WM_OP_INVOKE_REGION_WIN, NULL)*/;
				else
					WM_operator_name_call(C, "OUTLINER_OT_data_operation", WM_OP_INVOKE_REGION_WIN, NULL);
			}
		}
		
		return 1;
	}
	
	for (te= te->subtree.first; te; te= te->next) {
		if (do_outliner_operation_event(C, scene, ar, soops, te, event, mval))
			return 1;
	}
	return 0;
}
static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObject *args)
{
	VectorObject *line_a, *line_b, *sphere_co;
	float sphere_radius;
	int clip = TRUE;

	float isect_a[3];
	float isect_b[3];

	if (!PyArg_ParseTuple(args, "O!O!O!f|i:intersect_line_sphere",
	                      &vector_Type, &line_a,
	                      &vector_Type, &line_b,
	                      &vector_Type, &sphere_co,
	                      &sphere_radius, &clip))
	{
		return NULL;
	}

	if (BaseMath_ReadCallback(line_a) == -1 ||
	    BaseMath_ReadCallback(line_b) == -1 ||
	    BaseMath_ReadCallback(sphere_co) == -1)
	{
		return NULL;
	}

	if (ELEM3(2, line_a->size, line_b->size, sphere_co->size)) {
		PyErr_SetString(PyExc_ValueError,
		                "geometry.intersect_line_sphere(...): "
		                " can't use 2D Vectors");
		return NULL;
	}
	else {
		short use_a = TRUE;
		short use_b = TRUE;
		float lambda;

		PyObject *ret = PyTuple_New(2);

		switch (isect_line_sphere_v3(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) {
			case 1:
				if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = FALSE;
				use_b = FALSE;
				break;
			case 2:
				if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = FALSE;
				if (!(!clip || (((lambda = line_point_factor_v3(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b = FALSE;
				break;
			default:
				use_a = FALSE;
				use_b = FALSE;
		}

		if (use_a) { PyTuple_SET_ITEM(ret, 0,  Vector_CreatePyObject(isect_a, 3, Py_NEW, NULL)); }
		else       { PyTuple_SET_ITEM(ret, 0,  Py_None); Py_INCREF(Py_None); }

		if (use_b) { PyTuple_SET_ITEM(ret, 1,  Vector_CreatePyObject(isect_b, 3, Py_NEW, NULL)); }
		else       { PyTuple_SET_ITEM(ret, 1,  Py_None); Py_INCREF(Py_None); }

		return ret;
	}
}
Example #5
0
/* Init PoseLib Previewing data */
static void poselib_preview_init_data(bContext *C, wmOperator *op)
{
	tPoseLib_PreviewData *pld;
	Object *ob = get_poselib_object(C);
	int pose_index = RNA_int_get(op->ptr, "pose_index");
	
	/* set up preview state info */
	op->customdata = pld = MEM_callocN(sizeof(tPoseLib_PreviewData), "PoseLib Preview Data");
	
	/* get basic data */
	pld->ob = ob;
	pld->arm = (ob) ? (ob->data) : NULL;
	pld->pose = (ob) ? (ob->pose) : NULL;
	pld->act = (ob) ? (ob->poselib) : NULL;
	
	pld->scene = CTX_data_scene(C);
	pld->sa = CTX_wm_area(C);
	
	/* get starting pose based on RNA-props for this operator */
	if (pose_index == -1)
		pld->marker = poselib_get_active_pose(pld->act);
	else if (pose_index == -2)
		pld->flag |= PL_PREVIEW_SHOWORIGINAL;
	else
		pld->marker = (pld->act) ? BLI_findlink(&pld->act->markers, pose_index) : NULL;
	
	/* check if valid poselib */
	if (ELEM3(NULL, pld->ob, pld->pose, pld->arm)) {
		BKE_report(op->reports, RPT_ERROR, "Pose lib is only for armatures in pose mode");
		pld->state = PL_PREVIEW_ERROR;
		return;
	}
	if (pld->act == NULL) {
		BKE_report(op->reports, RPT_ERROR, "Object does not have a valid pose lib");
		pld->state = PL_PREVIEW_ERROR;
		return;
	}
	if (pld->marker == NULL) {
		if (pld->act->markers.first) {
			/* just use first one then... */
			pld->marker = pld->act->markers.first;
			if (pose_index > -2) 
				BKE_report(op->reports, RPT_WARNING, "Pose lib had no active pose");
		}
		else {
			BKE_report(op->reports, RPT_ERROR, "Pose lib has no poses to preview/apply");
			pld->state = PL_PREVIEW_ERROR;
			return;
		}
	}
	
	/* get ID pointer for applying poses */
	RNA_id_pointer_create(&ob->id, &pld->rna_ptr);
	
	/* make backups for restoring pose */
	poselib_backup_posecopy(pld);
	
	/* set flags for running */
	pld->state = PL_PREVIEW_RUNNING;
	pld->redraw = PL_PREVIEW_REDRAWALL;
	pld->flag |= PL_PREVIEW_FIRSTTIME;
	
	/* set depsgraph flags */
	/* make sure the lock is set OK, unlock can be accidentally saved? */
	pld->pose->flag |= POSE_LOCKED;
	pld->pose->flag &= ~POSE_DO_UNLOCK;
	
	/* clear strings + search */
	pld->headerstr[0] = pld->searchstr[0] = pld->searchold[0] = '\0';
	pld->search_cursor = 0;
}
Example #6
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                  DerivedMesh *derivedData,
                                  ModifierApplyFlag UNUSED(flag))
{
	MaskModifierData *mmd = (MaskModifierData *)md;
	DerivedMesh *dm = derivedData, *result = NULL;
	GHash *vertHash = NULL, *edgeHash, *polyHash;
	GHashIterator *hashIter;
	MDeformVert *dvert = NULL, *dv;
	int numPolys = 0, numLoops = 0, numEdges = 0, numVerts = 0;
	int maxVerts, maxEdges, maxPolys;
	int i;

	MPoly *mpoly;
	MLoop *mloop;

	MPoly *mpoly_new;
	MLoop *mloop_new;
	MEdge *medge_new;
	MVert *mvert_new;


	int *loop_mapping;

	/* Overview of Method:
	 *	1. Get the vertices that are in the vertexgroup of interest 
	 *	2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices
	 *	3. Make a new mesh containing only the mapping data
	 */
	
	/* get original number of verts, edges, and faces */
	maxVerts = dm->getNumVerts(dm);
	maxEdges = dm->getNumEdges(dm);
	maxPolys = dm->getNumPolys(dm);
	
	/* check if we can just return the original mesh 
	 *	- must have verts and therefore verts assigned to vgroups to do anything useful
	 */
	if (!(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) ||
	    (maxVerts == 0) || (ob->defbase.first == NULL) )
	{
		return derivedData;
	}
	
	/* if mode is to use selected armature bones, aggregate the bone groups */
	if (mmd->mode == MOD_MASK_MODE_ARM) { /* --- using selected bones --- */
		GHash *vgroupHash;
		Object *oba = mmd->ob_arm;
		bPoseChannel *pchan;
		bDeformGroup *def;
		char *bone_select_array;
		int bone_select_tot = 0;
		const int defbase_tot = BLI_countlist(&ob->defbase);
		
		/* check that there is armature object with bones to use, otherwise return original mesh */
		if (ELEM3(NULL, mmd->ob_arm, mmd->ob_arm->pose, ob->defbase.first))
			return derivedData;
		
		bone_select_array = MEM_mallocN(defbase_tot * sizeof(char), "mask array");
		
		for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
			pchan = BKE_pose_channel_find_name(oba->pose, def->name);
			if (pchan && pchan->bone && (pchan->bone->flag & BONE_SELECTED)) {
				bone_select_array[i] = TRUE;
				bone_select_tot++;
			}
			else {
				bone_select_array[i] = FALSE;
			}
		}

		/* hashes for finding mapping of:
		 * - vgroups to indices -> vgroupHash  (string, int)
		 * - bones to vgroup indices -> boneHash (index of vgroup, dummy)
		 */
		vgroupHash = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "mask vgroup gh");
		
		/* build mapping of names of vertex groups to indices */
		for (i = 0, def = ob->defbase.first; def; def = def->next, i++) 
			BLI_ghash_insert(vgroupHash, def->name, SET_INT_IN_POINTER(i));
		
		/* if no bones selected, free hashes and return original mesh */
		if (bone_select_tot == 0) {
			BLI_ghash_free(vgroupHash, NULL, NULL);
			MEM_freeN(bone_select_array);
			
			return derivedData;
		}
		
		/* repeat the previous check, but for dverts */
		dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
		if (dvert == NULL) {
			BLI_ghash_free(vgroupHash, NULL, NULL);
			MEM_freeN(bone_select_array);
			
			return derivedData;
		}
		
		/* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
		vertHash = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask vert gh");
		
		/* add vertices which exist in vertexgroups into vertHash for filtering */
		for (i = 0, dv = dvert; i < maxVerts; i++, dv++) {
			MDeformWeight *dw = dv->dw;
			int j;
			
			for (j = dv->totweight; j > 0; j--, dw++) {
				if (dw->def_nr < defbase_tot) {
					if (bone_select_array[dw->def_nr]) {
						if (dw->weight != 0.0f) {
							break;
						}
					}
				}
			}
			
			/* check if include vert in vertHash */
			if (mmd->flag & MOD_MASK_INV) {
				/* if this vert is in the vgroup, don't include it in vertHash */
				if (dw) continue;
			}
			else {
				/* if this vert isn't in the vgroup, don't include it in vertHash */
				if (!dw) continue;
			}
			
			/* add to ghash for verts (numVerts acts as counter for mapping) */
			BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
			numVerts++;
		}
		
		/* free temp hashes */
		BLI_ghash_free(vgroupHash, NULL, NULL);
		MEM_freeN(bone_select_array);
	}
	else {  /* --- Using Nominated VertexGroup only --- */
		int defgrp_index = defgroup_name_index(ob, mmd->vgroup);
		
		/* get dverts */
		if (defgrp_index >= 0)
			dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
			
		/* if no vgroup (i.e. dverts) found, return the initial mesh */
		if ((defgrp_index < 0) || (dvert == NULL))
			return dm;
			
		/* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
		vertHash = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask vert2 bh");
		
		/* add vertices which exist in vertexgroup into ghash for filtering */
		for (i = 0, dv = dvert; i < maxVerts; i++, dv++) {
			const int weight_set = defvert_find_weight(dv, defgrp_index) != 0.0f;
			
			/* check if include vert in vertHash */
			if (mmd->flag & MOD_MASK_INV) {
				/* if this vert is in the vgroup, don't include it in vertHash */
				if (weight_set) continue;
			}
			else {
				/* if this vert isn't in the vgroup, don't include it in vertHash */
				if (!weight_set) continue;
			}
			
			/* add to ghash for verts (numVerts acts as counter for mapping) */
			BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
			numVerts++;
		}
	}

	/* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
	edgeHash = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask ed2 gh");
	polyHash = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask fa2 gh");
	
	mpoly = dm->getPolyArray(dm);
	mloop = dm->getLoopArray(dm);

	loop_mapping = MEM_callocN(sizeof(int) * maxPolys, "mask loopmap"); /* overalloc, assume all polys are seen */

	/* loop over edges and faces, and do the same thing to 
	 * ensure that they only reference existing verts 
	 */
	for (i = 0; i < maxEdges; i++)  {
		MEdge me;
		dm->getEdge(dm, i, &me);
		
		/* only add if both verts will be in new mesh */
		if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) &&
		    BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
		{
			BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges));
			numEdges++;
		}
	}
	for (i = 0; i < maxPolys; i++) {
		MPoly *mp = &mpoly[i];
		MLoop *ml = mloop + mp->loopstart;
		int ok = TRUE;
		int j;
		
		for (j = 0; j < mp->totloop; j++, ml++) {
			if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml->v))) {
				ok = FALSE;
				break;
			}
		}
		
		/* all verts must be available */
		if (ok) {
			BLI_ghash_insert(polyHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numPolys));
			loop_mapping[numPolys] = numLoops;
			numPolys++;
			numLoops += mp->totloop;
		}
	}
	
	
	/* now we know the number of verts, edges and faces, 
	 * we can create the new (reduced) mesh
	 */
	result = CDDM_from_template(dm, numVerts, numEdges, 0, numLoops, numPolys);
	
	mpoly_new = CDDM_get_polys(result);
	mloop_new = CDDM_get_loops(result);
	medge_new = CDDM_get_edges(result);
	mvert_new = CDDM_get_verts(result);
	
	/* using ghash-iterators, map data into new mesh */
	/* vertices */
	for (hashIter = BLI_ghashIterator_new(vertHash);
	     !BLI_ghashIterator_isDone(hashIter);
	     BLI_ghashIterator_step(hashIter) )
	{
		MVert source;
		MVert *dest;
		int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
		int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
		
		dm->getVert(dm, oldIndex, &source);
		dest = &mvert_new[newIndex];
		
		DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
		*dest = source;
	}
	BLI_ghashIterator_free(hashIter);
		
	/* edges */
	for (hashIter = BLI_ghashIterator_new(edgeHash);
	     !BLI_ghashIterator_isDone(hashIter);
	     BLI_ghashIterator_step(hashIter))
	{
		MEdge source;
		MEdge *dest;
		int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
		int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
		
		dm->getEdge(dm, oldIndex, &source);
		dest = &medge_new[newIndex];
		
		source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
		source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
		
		DM_copy_edge_data(dm, result, oldIndex, newIndex, 1);
		*dest = source;
	}
	BLI_ghashIterator_free(hashIter);
	
	/* faces */
	for (hashIter = BLI_ghashIterator_new(polyHash);
	     !BLI_ghashIterator_isDone(hashIter);
	     BLI_ghashIterator_step(hashIter) )
	{
		int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
		int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
		MPoly *source = &mpoly[oldIndex];
		MPoly *dest = &mpoly_new[newIndex];
		int oldLoopIndex = source->loopstart;
		int newLoopIndex = loop_mapping[newIndex];
		MLoop *source_loop = &mloop[oldLoopIndex];
		MLoop *dest_loop = &mloop_new[newLoopIndex];
		
		DM_copy_poly_data(dm, result, oldIndex, newIndex, 1);
		DM_copy_loop_data(dm, result, oldLoopIndex, newLoopIndex, source->totloop);

		*dest = *source;
		dest->loopstart = newLoopIndex;
		for (i = 0; i < source->totloop; i++) {
			dest_loop[i].v = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source_loop[i].v)));
			dest_loop[i].e = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(source_loop[i].e)));
		}
	}

	BLI_ghashIterator_free(hashIter);

	MEM_freeN(loop_mapping);

	/* why is this needed? - campbell */
	/* recalculate normals */
	CDDM_calc_normals(result);
	
	/* free hashes */
	BLI_ghash_free(vertHash, NULL, NULL);
	BLI_ghash_free(edgeHash, NULL, NULL);
	BLI_ghash_free(polyHash, NULL, NULL);

	/* return the new mesh */
	return result;
}
Example #7
0
/* Write into "name" buffer, the name of the property (retrieved using RNA from the curve's settings),
 * and return the icon used for the struct that this property refers to 
 * WARNING: name buffer we're writing to cannot exceed 256 chars (check anim_channels_defines.c for details)
 */
int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
{
	int icon = 0;
	
	/* sanity checks */
	if (name == NULL)
		return icon;
	else if (ELEM3(NULL, id, fcu, fcu->rna_path)) {
		if (fcu == NULL)
			strcpy(name, IFACE_("<invalid>"));
		else if (fcu->rna_path == NULL)
			strcpy(name, IFACE_("<no path>"));
		else /* id == NULL */
			BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index);
	}
	else {
		PointerRNA id_ptr, ptr;
		PropertyRNA *prop;
		
		/* get RNA pointer, and resolve the path */
		RNA_id_pointer_create(id, &id_ptr);
		
		/* try to resolve the path */
		if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
			const char *structname = NULL, *propname = NULL;
			char arrayindbuf[16];
			const char *arrayname = NULL;
			short free_structname = 0;
			
			/* For now, name will consist of 3 parts: struct-name, property name, array index
			 * There are several options possible:
			 *	1) <struct-name>.<property-name>.<array-index>
			 *		i.e. Bone1.Location.X, or Object.Location.X
			 *	2) <array-index> <property-name> (<struct name>)
			 *		i.e. X Location (Bone1), or X Location (Object)
			 *
			 * Currently, option 2 is in use, to try and make it easier to quickly identify F-Curves (it does have
			 * problems with looking rather odd though). Option 1 is better in terms of revealing a consistent sense of 
			 * hierarchy though, which isn't so clear with option 2.
			 */
			
			/* for structname
			 *	- as base, we use a custom name from the structs if one is available 
			 *	- however, if we're showing subdata of bones (probably there will be other exceptions later)
			 *	  need to include that info too since it gets confusing otherwise
			 *	- if a pointer just refers to the ID-block, then don't repeat this info
			 *	  since this just introduces clutter
			 */
			if (strstr(fcu->rna_path, "bones") && strstr(fcu->rna_path, "constraints")) {
				/* perform string 'chopping' to get "Bone Name : Constraint Name" */
				char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones[");
				char *constName = BLI_str_quoted_substrN(fcu->rna_path, "constraints[");
				
				/* assemble the string to display in the UI... */
				structname = BLI_sprintfN("%s : %s", pchanName, constName);
				free_structname = 1;
				
				/* free the temp names */
				if (pchanName) MEM_freeN(pchanName);
				if (constName) MEM_freeN(constName);
			}
			else if (ptr.data != ptr.id.data) {
				PropertyRNA *nameprop = RNA_struct_name_property(ptr.type);
				if (nameprop) {
					/* this gets a string which will need to be freed */
					structname = RNA_property_string_get_alloc(&ptr, nameprop, NULL, 0, NULL);
					free_structname = 1;
				}
				else
					structname = RNA_struct_ui_name(ptr.type);
			}
			
			/* Property Name is straightforward */
			propname = RNA_property_ui_name(prop);
			
			/* Array Index - only if applicable */
			if (RNA_property_array_check(prop)) {
				char c = RNA_property_array_item_char(prop, fcu->array_index);
				
				/* we need to write the index to a temp buffer (in py syntax) */
				if (c) BLI_snprintf(arrayindbuf, sizeof(arrayindbuf), "%c ", c);
				else BLI_snprintf(arrayindbuf, sizeof(arrayindbuf), "[%d]", fcu->array_index);
				
				arrayname = &arrayindbuf[0];
			}
			else {
				/* no array index */
				arrayname = "";
			}
			
			/* putting this all together into the buffer */
			/* XXX we need to check for invalid names...
			 * XXX the name length limit needs to be passed in or as some define */
			if (structname)
				BLI_snprintf(name, 256, "%s%s (%s)", arrayname, propname, structname);
			else
				BLI_snprintf(name, 256, "%s%s", arrayname, propname);
			
			/* free temp name if nameprop is set */
			if (free_structname)
				MEM_freeN((void *)structname);
			
			
			/* Icon for this property's owner:
			 *	use the struct's icon if it is set
			 */
			icon = RNA_struct_ui_icon(ptr.type);
			
			/* valid path - remove the invalid tag since we now know how to use it saving
			 * users manual effort to reenable using "Revive Disabled FCurves" [#29629]
			 */
			fcu->flag &= ~FCURVE_DISABLED;
		}
		else {
			/* invalid path */
			BLI_snprintf(name, 256, "\"%s[%d]\"", fcu->rna_path, fcu->array_index);
			
			/* icon for this should be the icon for the base ID */
			/* TODO: or should we just use the error icon? */
			icon = RNA_struct_ui_icon(id_ptr.type);
			
			/* tag F-Curve as disabled - as not usable path */
			fcu->flag |= FCURVE_DISABLED;
		}
	}
	
	/* return the icon that the active data had */
	return icon;
}
Example #8
0
// TODO: this function needs to be split up! It's getting a bit too large...
static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *idv, 
                                         TreeElement *parent, short type, short index)
{
	TreeElement *te;
	TreeStoreElem *tselem;
	ID *id = idv;
	int a = 0;
	
	if (ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
		id = ((PointerRNA *)idv)->id.data;
		if (!id) id = ((PointerRNA *)idv)->data;
	}

	if (id == NULL) return NULL;

	te = MEM_callocN(sizeof(TreeElement), "tree elem");
	/* add to the visual tree */
	BLI_addtail(lb, te);
	/* add to the storage */
	check_persistent(soops, te, id, type, index);
	tselem = TREESTORE(te);
	
	/* if we are searching for something expand to see child elements */
	if (SEARCHING_OUTLINER(soops))
		tselem->flag |= TSE_CHILDSEARCH;
	
	te->parent = parent;
	te->index = index;   // for data arays
	if (ELEM3(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) ;
	else if (ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) ;
	else if (type == TSE_ANIM_DATA) ;
	else {
		te->name = id->name + 2; // default, can be overridden by Library or non-ID data
		te->idcode = GS(id->name);
	}
	
	if (type == 0) {
		/* ID datablock */
		outliner_add_id_contents(soops, te, tselem, id);
	}
	else if (type == TSE_ANIM_DATA) {
		IdAdtTemplate *iat = (IdAdtTemplate *)idv;
		AnimData *adt = (AnimData *)iat->adt;
		
		/* this element's info */
		te->name = "Animation";
		te->directdata = adt;
		
		/* Action */
		outliner_add_element(soops, &te->subtree, adt->action, te, 0, 0);
		
		/* Drivers */
		if (adt->drivers.first) {
			TreeElement *ted = outliner_add_element(soops, &te->subtree, adt, te, TSE_DRIVER_BASE, 0);
			ID *lastadded = NULL;
			FCurve *fcu;
			
			ted->name = "Drivers";
		
			for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
				if (fcu->driver && fcu->driver->variables.first) {
					ChannelDriver *driver = fcu->driver;
					DriverVar *dvar;
					
					for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
						/* loop over all targets used here */
						DRIVER_TARGETS_USED_LOOPER(dvar) 
						{
							if (lastadded != dtar->id) {
								// XXX this lastadded check is rather lame, and also fails quite badly...
								outliner_add_element(soops, &ted->subtree, dtar->id, ted, TSE_LINKED_OB, 0);
								lastadded = dtar->id;
							}
						}
						DRIVER_TARGETS_LOOPER_END
					}
				}
			}
Example #9
0
struct CharTrans *BKE_vfont_to_curve(Main *bmain, Scene *scene, Object *ob, int mode)
{
	VFont *vfont, *oldvfont;
	VFontData *vfd = NULL;
	Curve *cu;
	CharInfo *info = NULL, *custrinfo;
	TextBox *tb;
	VChar *che;
	struct CharTrans *chartransdata = NULL, *ct;
	float *f, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4;
	float twidth, maxlen = 0;
	int i, slen, j;
	int curbox;
	int selstart, selend;
	int utf8len;
	short cnr = 0, lnr = 0, wsnr = 0;
	wchar_t *mem, *tmp, ascii;

	/* remark: do calculations including the trailing '\0' of a string
	 * because the cursor can be at that location */

	if (ob->type != OB_FONT) return NULL;

	/* Set font data */
	cu = (Curve *) ob->data;
	vfont = cu->vfont;

	if (cu->str == NULL) return NULL;
	if (vfont == NULL) return NULL;

	/* Create unicode string */
	utf8len = BLI_strlen_utf8(cu->str);
	mem = MEM_mallocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem");

	BLI_strncpy_wchar_from_utf8(mem, cu->str, utf8len + 1);

	/* Count the wchar_t string length */
	slen = wcslen(mem);

	if (cu->ulheight == 0.0f)
		cu->ulheight = 0.05f;
	
	if (cu->strinfo == NULL) /* old file */
		cu->strinfo = MEM_callocN((slen + 4) * sizeof(CharInfo), "strinfo compat");
	
	custrinfo = cu->strinfo;
	if (cu->editfont)
		custrinfo = cu->editfont->textbufinfo;
	
	if (cu->tb == NULL)
		cu->tb = MEM_callocN(MAXTEXTBOX * sizeof(TextBox), "TextBox compat");

	vfd = vfont_get_data(bmain, vfont);

	/* The VFont Data can not be found */
	if (!vfd) {
		if (mem)
			MEM_freeN(mem);
		return NULL;
	}

	/* calc offset and rotation of each char */
	ct = chartransdata =
	         (struct CharTrans *)MEM_callocN((slen + 1) * sizeof(struct CharTrans), "buildtext");

	/* We assume the worst case: 1 character per line (is freed at end anyway) */

	linedata  = MEM_mallocN(sizeof(float) * (slen * 2 + 1), "buildtext2");
	linedata2 = MEM_mallocN(sizeof(float) * (slen * 2 + 1), "buildtext3");
	linedata3 = MEM_callocN(sizeof(float) * (slen * 2 + 1), "buildtext4");
	linedata4 = MEM_callocN(sizeof(float) * (slen * 2 + 1), "buildtext5");
	
	linedist = cu->linedist;
	
	xof = cu->xof + (cu->tb[0].x / cu->fsize);
	yof = cu->yof + (cu->tb[0].y / cu->fsize);

	xtrax = 0.5f * cu->spacing - 0.5f;

	oldvfont = NULL;

	for (i = 0; i < slen; i++) custrinfo[i].flag &= ~(CU_CHINFO_WRAP | CU_CHINFO_SMALLCAPS_CHECK);

	if (cu->selboxes) MEM_freeN(cu->selboxes);
	cu->selboxes = NULL;
	if (BKE_vfont_select_get(ob, &selstart, &selend))
		cu->selboxes = MEM_callocN((selend - selstart + 1) * sizeof(SelBox), "font selboxes");

	tb = &(cu->tb[0]);
	curbox = 0;
	for (i = 0; i <= slen; i++) {
makebreak:
		/* Characters in the list */
		info = &(custrinfo[i]);
		ascii = mem[i];
		if (info->flag & CU_CHINFO_SMALLCAPS) {
			ascii = towupper(ascii);
			if (mem[i] != ascii) {
				mem[i] = ascii;
				info->flag |= CU_CHINFO_SMALLCAPS_CHECK;
			}
		}

		vfont = which_vfont(cu, info);
		
		if (vfont == NULL) break;

		che = find_vfont_char(vfd, ascii);

		/*
		 * The character wasn't in the current curve base so load it
		 * But if the font is built-in then do not try loading since
		 * whole font is in the memory already
		 */
		if (che == NULL && BKE_vfont_is_builtin(vfont) == FALSE) {
			BLI_vfontchar_from_freetypefont(vfont, ascii);
		}

		/* Try getting the character again from the list */
		che = find_vfont_char(vfd, ascii);

		/* No VFont found */
		if (vfont == NULL) {
			if (mem)
				MEM_freeN(mem);
			MEM_freeN(chartransdata);
			return NULL;
		}

		if (vfont != oldvfont) {
			vfd = vfont_get_data(bmain, vfont);
			oldvfont = vfont;
		}

		/* VFont Data for VFont couldn't be found */
		if (!vfd) {
			if (mem)
				MEM_freeN(mem);
			MEM_freeN(chartransdata);
			return NULL;
		}

		twidth = char_width(cu, che, info);

		/* Calculate positions */
		if ((tb->w != 0.0f) &&
		    (ct->dobreak == 0) &&
		    (((xof - (tb->x / cu->fsize) + twidth) * cu->fsize) > tb->w + cu->xof * cu->fsize))
		{
			//		fprintf(stderr, "linewidth exceeded: %c%c%c...\n", mem[i], mem[i+1], mem[i+2]);
			for (j = i; j && (mem[j] != '\n') && (mem[j] != '\r') && (chartransdata[j].dobreak == 0); j--) {
				if (mem[j] == ' ' || mem[j] == '-') {
					ct -= (i - (j - 1));
					cnr -= (i - (j - 1));
					if (mem[j] == ' ') wsnr--;
					if (mem[j] == '-') wsnr++;
					i = j - 1;
					xof = ct->xof;
					ct[1].dobreak = 1;
					custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
					goto makebreak;
				}
				if (chartransdata[j].dobreak) {
					//				fprintf(stderr, "word too long: %c%c%c...\n", mem[j], mem[j+1], mem[j+2]);
					ct->dobreak = 1;
					custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
					ct -= 1;
					cnr -= 1;
					i--;
					xof = ct->xof;
					goto makebreak;
				}
			}
		}

		if (ascii == '\n' || ascii == '\r' || ascii == 0 || ct->dobreak) {
			ct->xof = xof;
			ct->yof = yof;
			ct->linenr = lnr;
			ct->charnr = cnr;

			yof -= linedist;

			maxlen = max_ff(maxlen, (xof - tb->x / cu->fsize));
			linedata[lnr] = xof - tb->x / cu->fsize;
			linedata2[lnr] = cnr;
			linedata3[lnr] = tb->w / cu->fsize;
			linedata4[lnr] = wsnr;
			
			if ((tb->h != 0.0f) &&
			    ((-(yof - (tb->y / cu->fsize))) > ((tb->h / cu->fsize) - (linedist * cu->fsize)) - cu->yof) &&
			    (cu->totbox > (curbox + 1)) )
			{
				maxlen = 0;
				tb++;
				curbox++;
				yof = cu->yof + tb->y / cu->fsize;
			}

			/* XXX, has been unused for years, need to check if this is useful, r4613 r5282 - campbell */
#if 0
			if (ascii == '\n' || ascii == '\r')
				xof = cu->xof;
			else
				xof = cu->xof + (tb->x / cu->fsize);
#else
			xof = cu->xof + (tb->x / cu->fsize);
#endif
			lnr++;
			cnr = 0;
			wsnr = 0;
		}
		else if (ascii == 9) {    /* TAB */
			float tabfac;
			
			ct->xof = xof;
			ct->yof = yof;
			ct->linenr = lnr;
			ct->charnr = cnr++;

			tabfac = (xof - cu->xof + 0.01f);
			tabfac = 2.0f * ceilf(tabfac / 2.0f);
			xof = cu->xof + tabfac;
		}
		else {
			SelBox *sb = NULL;
			float wsfac;

			ct->xof = xof;
			ct->yof = yof;
			ct->linenr = lnr;
			ct->charnr = cnr++;

			if (cu->selboxes && (i >= selstart) && (i <= selend)) {
				sb = &(cu->selboxes[i - selstart]);
				sb->y = yof * cu->fsize - linedist * cu->fsize * 0.1f;
				sb->h = linedist * cu->fsize;
				sb->w = xof * cu->fsize;
			}
	
			if (ascii == 32) {
				wsfac = cu->wordspace; 
				wsnr++;
			}
			else {
				wsfac = 1.0f;
			}
			
			/* Set the width of the character */
			twidth = char_width(cu, che, info);

			xof += (twidth * wsfac * (1.0f + (info->kern / 40.0f)) ) + xtrax;
			
			if (sb) {
				sb->w = (xof * cu->fsize) - sb->w;
			}
		}
		ct++;
	}
	
	cu->lines = 1;
	ct = chartransdata;
	tmp = mem;
	for (i = 0; i <= slen; i++, tmp++, ct++) {
		ascii = *tmp;
		if (ascii == '\n' || ascii == '\r' || ct->dobreak) cu->lines++;
	}

	/* linedata is now: width of line
	 * linedata2 is now: number of characters
	 * linedata3 is now: maxlen of that line
	 * linedata4 is now: number of whitespaces of line */

	if (cu->spacemode != CU_LEFT) {
		ct = chartransdata;

		if (cu->spacemode == CU_RIGHT) {
			for (i = 0; i < lnr; i++) linedata[i] = linedata3[i] - linedata[i];
			for (i = 0; i <= slen; i++) {
				ct->xof += linedata[ct->linenr];
				ct++;
			}
		}
		else if (cu->spacemode == CU_MIDDLE) {
			for (i = 0; i < lnr; i++) linedata[i] = (linedata3[i] - linedata[i]) / 2;
			for (i = 0; i <= slen; i++) {
				ct->xof += linedata[ct->linenr];
				ct++;
			}
		}
		else if ((cu->spacemode == CU_FLUSH) && (cu->tb[0].w != 0.0f)) {
			for (i = 0; i < lnr; i++)
				if (linedata2[i] > 1)
					linedata[i] = (linedata3[i] - linedata[i]) / (linedata2[i] - 1);
			for (i = 0; i <= slen; i++) {
				for (j = i; (!ELEM3(mem[j], '\0', '\n', '\r')) && (chartransdata[j].dobreak == 0) && (j < slen); j++) {
					/* do nothing */
				}

//				if ((mem[j] != '\r') && (mem[j] != '\n') && (mem[j])) {
				ct->xof += ct->charnr * linedata[ct->linenr];
//				}
				ct++;
			}
		}
		else if ((cu->spacemode == CU_JUSTIFY) && (cu->tb[0].w != 0.0f)) {
			float curofs = 0.0f;
			for (i = 0; i <= slen; i++) {
				for (j = i; (mem[j]) && (mem[j] != '\n') &&
				     (mem[j] != '\r') && (chartransdata[j].dobreak == 0) && (j < slen);
				     j++)
				{
					/* pass */
				}

				if ((mem[j] != '\r') && (mem[j] != '\n') &&
				    ((chartransdata[j].dobreak != 0)))
				{
					if (mem[i] == ' ') curofs += (linedata3[ct->linenr] - linedata[ct->linenr]) / linedata4[ct->linenr];
					ct->xof += curofs;
				}
				if (mem[i] == '\n' || mem[i] == '\r' || chartransdata[i].dobreak) curofs = 0;
				ct++;
			}
		}
	}
	
	/* TEXT ON CURVE */
	/* Note: Only OB_CURVE objects could have a path  */
	if (cu->textoncurve && cu->textoncurve->type == OB_CURVE) {
		Curve *cucu = cu->textoncurve->data;
		int oldflag = cucu->flag;
		
		cucu->flag |= (CU_PATH + CU_FOLLOW);
		
		if (cu->textoncurve->curve_cache == NULL || cu->textoncurve->curve_cache->path == NULL) {
			BKE_displist_make_curveTypes(scene, cu->textoncurve, 0);
		}
		if (cu->textoncurve->curve_cache->path) {
			float distfac, imat[4][4], imat3[3][3], cmat[3][3];
			float minx, maxx, miny, maxy;
			float timeofs, sizefac;
			
			invert_m4_m4(imat, ob->obmat);
			copy_m3_m4(imat3, imat);

			copy_m3_m4(cmat, cu->textoncurve->obmat);
			mul_m3_m3m3(cmat, cmat, imat3);
			sizefac = normalize_v3(cmat[0]) / cu->fsize;
			
			minx = miny = 1.0e20f;
			maxx = maxy = -1.0e20f;
			ct = chartransdata;
			for (i = 0; i <= slen; i++, ct++) {
				if (minx > ct->xof) minx = ct->xof;
				if (maxx < ct->xof) maxx = ct->xof;
				if (miny > ct->yof) miny = ct->yof;
				if (maxy < ct->yof) maxy = ct->yof;
			}
			
			/* we put the x-coordinaat exact at the curve, the y is rotated */
			
			/* length correction */
			distfac = sizefac * cu->textoncurve->curve_cache->path->totdist / (maxx - minx);
			timeofs = 0.0f;
			
			if (distfac > 1.0f) {
				/* path longer than text: spacemode involves */
				distfac = 1.0f / distfac;
				
				if (cu->spacemode == CU_RIGHT) {
					timeofs = 1.0f - distfac;
				}
				else if (cu->spacemode == CU_MIDDLE) {
					timeofs = (1.0f - distfac) / 2.0f;
				}
				else if (cu->spacemode == CU_FLUSH) {
					distfac = 1.0f;
				}
			}
			else {
				distfac = 1.0;
			}

			distfac /= (maxx - minx);
			
			timeofs += distfac * cu->xof;  /* not cyclic */
			
			ct = chartransdata;
			for (i = 0; i <= slen; i++, ct++) {
				float ctime, dtime, vec[4], tvec[4], rotvec[3];
				float si, co;
				
				/* rotate around center character */
				ascii = mem[i];

				che = find_vfont_char(vfd, ascii);
	
				twidth = char_width(cu, che, info);

				dtime = distfac * 0.5f * twidth;

				ctime = timeofs + distfac * (ct->xof - minx);
				CLAMP(ctime, 0.0f, 1.0f);

				/* calc the right loc AND the right rot separately */
				/* vec, tvec need 4 items */
				where_on_path(cu->textoncurve, ctime, vec, tvec, NULL, NULL, NULL);
				where_on_path(cu->textoncurve, ctime + dtime, tvec, rotvec, NULL, NULL, NULL);
				
				mul_v3_fl(vec, sizefac);
				
				ct->rot = (float)M_PI - atan2f(rotvec[1], rotvec[0]);

				si = sinf(ct->rot);
				co = cosf(ct->rot);

				yof = ct->yof;
				
				ct->xof = vec[0] + si * yof;
				ct->yof = vec[1] + co * yof;
				
			}
			cucu->flag = oldflag;
		}
	}

	if (cu->selboxes) {
		ct = chartransdata;
		for (i = 0; i <= selend; i++, ct++) {
			if (i >= selstart) {
				cu->selboxes[i - selstart].x = ct->xof * cu->fsize;
				cu->selboxes[i - selstart].y = ct->yof * cu->fsize;
			}
		}
	}

	if (mode == FO_CURSUP || mode == FO_CURSDOWN || mode == FO_PAGEUP || mode == FO_PAGEDOWN) {
		/* 2: curs up
		 * 3: curs down */
		ct = chartransdata + cu->pos;
		
		if ((mode == FO_CURSUP || mode == FO_PAGEUP) && ct->linenr == 0) {
			/* pass */
		}
		else if ((mode == FO_CURSDOWN || mode == FO_PAGEDOWN) && ct->linenr == lnr) {
			/* pass */
		}
		else {
			switch (mode) {
				case FO_CURSUP:     lnr = ct->linenr - 1; break;
				case FO_CURSDOWN:   lnr = ct->linenr + 1; break;
				case FO_PAGEUP:     lnr = ct->linenr - 10; break;
				case FO_PAGEDOWN:   lnr = ct->linenr + 10; break;
			}
			cnr = ct->charnr;
			/* seek for char with lnr en cnr */
			cu->pos = 0;
			ct = chartransdata;
			for (i = 0; i < slen; i++) {
				if (ct->linenr == lnr) {
					if ((ct->charnr == cnr) || ((ct + 1)->charnr == 0)) {
						break;
					}
				}
				else if (ct->linenr > lnr) {
					break;
				}
				cu->pos++;
				ct++;
			}
		}
	}
	
	/* cursor first */
	if (cu->editfont) {
		float si, co;
		
		ct = chartransdata + cu->pos;
		si = sinf(ct->rot);
		co = cosf(ct->rot);

		f = cu->editfont->textcurs[0];
		
		f[0] = cu->fsize * (-0.1f * co + ct->xof);
		f[1] = cu->fsize * ( 0.1f * si + ct->yof);
		
		f[2] = cu->fsize * ( 0.1f * co + ct->xof);
		f[3] = cu->fsize * (-0.1f * si + ct->yof);
		
		f[4] = cu->fsize * ( 0.1f * co + 0.8f * si + ct->xof);
		f[5] = cu->fsize * (-0.1f * si + 0.8f * co + ct->yof);
		
		f[6] = cu->fsize * (-0.1f * co + 0.8f * si + ct->xof);
		f[7] = cu->fsize * ( 0.1f * si + 0.8f * co + ct->yof);
		
	}

	MEM_freeN(linedata);
	MEM_freeN(linedata2);
	MEM_freeN(linedata3);
	MEM_freeN(linedata4);

	if (mode == FO_SELCHANGE) {
		MEM_freeN(chartransdata);
		MEM_freeN(mem);
		return NULL;
	}

	if (mode == FO_EDIT) {
		/* make nurbdata */
		BKE_nurbList_free(&cu->nurb);
		
		ct = chartransdata;
		if (cu->sepchar == 0) {
			for (i = 0; i < slen; i++) {
				unsigned long cha = (uintptr_t) mem[i];
				info = &(custrinfo[i]);
				if (info->mat_nr > (ob->totcol)) {
					/* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */
					info->mat_nr = 0;
				}
				/* We do not want to see any character for \n or \r */
				if (cha != '\n' && cha != '\r')
					buildchar(bmain, cu, cha, info, ct->xof, ct->yof, ct->rot, i);
				
				if ((info->flag & CU_CHINFO_UNDERLINE) && (cu->textoncurve == NULL) && (cha != '\n') && (cha != '\r')) {
					float ulwidth, uloverlap = 0.0f;
					
					if ((i < (slen - 1)) && (mem[i + 1] != '\n') && (mem[i + 1] != '\r') &&
					    ((mem[i + 1] != ' ') || (custrinfo[i + 1].flag & CU_CHINFO_UNDERLINE)) &&
					    ((custrinfo[i + 1].flag & CU_CHINFO_WRAP) == 0))
					{
						uloverlap = xtrax + 0.1f;
					}
					/* Find the character, the characters has to be in the memory already
					 * since character checking has been done earlier already. */
					che = find_vfont_char(vfd, cha);

					twidth = char_width(cu, che, info);
					ulwidth = cu->fsize * ((twidth * (1.0f + (info->kern / 40.0f))) + uloverlap);
					build_underline(cu, ct->xof * cu->fsize, ct->yof * cu->fsize + (cu->ulpos - 0.05f) * cu->fsize,
					                ct->xof * cu->fsize + ulwidth,
					                ct->yof * cu->fsize + (cu->ulpos - 0.05f) * cu->fsize - cu->ulheight * cu->fsize,
					                i, info->mat_nr);
				}
				ct++;
			}
		}
		else {
			int outta = 0;
			for (i = 0; (i < slen) && (outta == 0); i++) {
				ascii = mem[i];
				info = &(custrinfo[i]);
				if (cu->sepchar == (i + 1)) {
					float vecyo[3];

					vecyo[0] = ct->xof;
					vecyo[1] = ct->yof;
					vecyo[2] = 0.0f;

					mem[0] = ascii;
					mem[1] = 0;
					custrinfo[0] = *info;
					cu->pos = 1;
					cu->len = 1;
					mul_v3_m4v3(ob->loc, ob->obmat, vecyo);
					outta = 1;
					cu->sepchar = 0;
				}
				ct++;
			}
		}
	}

	if (mode == FO_DUPLI) {
		MEM_freeN(mem);
		return chartransdata;
	}

	if (mem)
		MEM_freeN(mem);

	MEM_freeN(chartransdata);
	return NULL;
}
Example #10
0
/* Create new physics sim collision shape for object and store it,
 * or remove the existing one first and replace...
 */
static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
{
	RigidBodyOb *rbo = ob->rigidbody_object;
	rbCollisionShape *new_shape = NULL;
	BoundBox *bb = NULL;
	float size[3] = {1.0f, 1.0f, 1.0f};
	float radius = 1.0f;
	float height = 1.0f;
	float capsule_height;
	float hull_margin = 0.0f;
	bool can_embed = true;
	bool has_volume;

	/* sanity check */
	if (rbo == NULL)
		return;

	/* don't create a new shape if we already have one and don't want to rebuild it */
	if (rbo->physics_shape && !rebuild)
		return;

	/* if automatically determining dimensions, use the Object's boundbox
	 *	- assume that all quadrics are standing upright on local z-axis
	 *	- assume even distribution of mass around the Object's pivot
	 *	  (i.e. Object pivot is centralized in boundbox)
	 */
	// XXX: all dimensions are auto-determined now... later can add stored settings for this
	/* get object dimensions without scaling */
	bb = BKE_object_boundbox_get(ob);
	if (bb) {
		size[0] = (bb->vec[4][0] - bb->vec[0][0]);
		size[1] = (bb->vec[2][1] - bb->vec[0][1]);
		size[2] = (bb->vec[1][2] - bb->vec[0][2]);
	}
	mul_v3_fl(size, 0.5f);

	if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
		/* take radius as largest x/y dimension, and height as z-dimension */
		radius = MAX2(size[0], size[1]);
		height = size[2];
	}
	else if (rbo->shape == RB_SHAPE_SPHERE) {
		/* take radius to the the largest dimension to try and encompass everything */
		radius = MAX3(size[0], size[1], size[2]);
	}

	/* create new shape */
	switch (rbo->shape) {
		case RB_SHAPE_BOX:
			new_shape = RB_shape_new_box(size[0], size[1], size[2]);
			break;

		case RB_SHAPE_SPHERE:
			new_shape = RB_shape_new_sphere(radius);
			break;

		case RB_SHAPE_CAPSULE:
			capsule_height = (height - radius) * 2.0f;
			new_shape = RB_shape_new_capsule(radius, (capsule_height > 0.0f) ? capsule_height : 0.0f);
			break;
		case RB_SHAPE_CYLINDER:
			new_shape = RB_shape_new_cylinder(radius, height);
			break;
		case RB_SHAPE_CONE:
			new_shape = RB_shape_new_cone(radius, height * 2.0f);
			break;

		case RB_SHAPE_CONVEXH:
			/* try to emged collision margin */
			has_volume = (MIN3(size[0], size[1], size[2]) > 0.0f);

			if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && has_volume)
				hull_margin = 0.04f;
			new_shape = rigidbody_get_shape_convexhull_from_mesh(ob, hull_margin, &can_embed);
			if (!(rbo->flag & RBO_FLAG_USE_MARGIN))
				rbo->margin = (can_embed && has_volume) ? 0.04f : 0.0f;  /* RB_TODO ideally we shouldn't directly change the margin here */
			break;
		case RB_SHAPE_TRIMESH:
			new_shape = rigidbody_get_shape_trimesh_from_mesh(ob);
			break;
	}
	/* assign new collision shape if creation was successful */
	if (new_shape) {
		if (rbo->physics_shape)
			RB_shape_delete(rbo->physics_shape);
		rbo->physics_shape = new_shape;
		RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo));
	}
	/* use box shape if we can't fall back to old shape */
	else if (rbo->physics_shape == NULL) {
		rbo->shape = RB_SHAPE_BOX;
		rigidbody_validate_sim_shape(ob, true);
	}
}
Example #11
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;
			int j;

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

			mp = &mpoly[poly];
			for (ml = &mloop[mp->loopstart], j = mp->totloop; j--; ml++) {
				/* loop over poly users */
				const MeshElemMap *map_ele = &edge_poly_map[ml->e];
				int *p = map_ele->indices;
				int i = map_ele->count;
				if (!(medge[ml->e].flag & ME_SHARP)) {
					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 (!ELEM3(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 (UNLIKELY(group_id_overflow)) {
		int i = totpoly, *gid = poly_groups;
		for (; i--; gid++) {
			if (*gid == poly_group_id_overflowed) {
				*gid = 0;
			}
		}
	}

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

	*r_totgroup = tot_group + 1;

	return poly_groups;
}
Example #12
0
void drawConstraint(TransInfo *t)
{
	TransCon *tc = &(t->con);

	if (!ELEM3(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE))
		return;
	if (!(tc->mode & CON_APPLY))
		return;
	if (t->flag & T_USES_MANIPULATOR)
		return;
	if (t->flag & T_NO_CONSTRAINT)
		return;

	/* nasty exception for Z constraint in camera view */
	// TRANSFORM_FIX_ME
//	if ((t->flag & T_OBJECT) && G.vd->camera==OBACT && G.vd->persp==V3D_CAMOB)
//		return;

	if (tc->drawExtra) {
		tc->drawExtra(t);
	}
	else {
		if (tc->mode & CON_SELECT) {
			float vec[3];
			char col2[3] = {255, 255, 255};
			int depth_test_enabled;

			convertViewVec(t, vec, (t->mval[0] - t->con.imval[0]), (t->mval[1] - t->con.imval[1]));
			add_v3_v3(vec, tc->center);

			drawLine(t, tc->center, tc->mtx[0], 'X', 0);
			drawLine(t, tc->center, tc->mtx[1], 'Y', 0);
			drawLine(t, tc->center, tc->mtx[2], 'Z', 0);

			glColor3ubv((GLubyte *)col2);

			depth_test_enabled = glIsEnabled(GL_DEPTH_TEST);
			if (depth_test_enabled)
				glDisable(GL_DEPTH_TEST);

			setlinestyle(1);
			glBegin(GL_LINE_STRIP);
			glVertex3fv(tc->center);
			glVertex3fv(vec);
			glEnd();
			setlinestyle(0);

			if (depth_test_enabled)
				glEnable(GL_DEPTH_TEST);
		}

		if (tc->mode & CON_AXIS0) {
			drawLine(t, tc->center, tc->mtx[0], 'X', DRAWLIGHT);
		}
		if (tc->mode & CON_AXIS1) {
			drawLine(t, tc->center, tc->mtx[1], 'Y', DRAWLIGHT);
		}
		if (tc->mode & CON_AXIS2) {
			drawLine(t, tc->center, tc->mtx[2], 'Z', DRAWLIGHT);
		}
	}
}
Example #13
0
static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase,
	DerivedMesh **derivedFinal, int forRender, int forOrco)
{
	Curve *cu = ob->data;

	/* we do allow duplis... this is only displist on curve level */
	if(!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;

	if(ob->type==OB_SURF) {
		makeDispListSurf(scene, ob, dispbase, derivedFinal, forRender, forOrco);
	}
	else if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
		ListBase dlbev;
		ListBase *nubase;
		float (*originalVerts)[3];
		float (*deformedVerts)[3];
		int numVerts;

		nubase= BKE_curve_nurbs(cu);

		BLI_freelistN(&(cu->bev));

		if(cu->path) free_path(cu->path);
		cu->path= NULL;

		if(ob->type==OB_FONT) BKE_text_to_curve(G.main, scene, ob, 0);

		if(!forOrco) curve_calc_modifiers_pre(scene, ob, forRender, &originalVerts, &deformedVerts, &numVerts);

		makeBevelList(ob);

		/* If curve has no bevel will return nothing */
		makebevelcurve(scene, ob, &dlbev, forRender);

		/* no bevel or extrude, and no width correction? */
		if (!dlbev.first && cu->width==1.0f) {
			curve_to_displist(cu, nubase, dispbase, forRender);
		} else {
			float widfac= cu->width - 1.0f;
			BevList *bl= cu->bev.first;
			Nurb *nu= nubase->first;

			for (; bl && nu; bl=bl->next,nu=nu->next) {
				DispList *dl;
				float *fp1, *data;
				BevPoint *bevp;
				int a,b;

				if (bl->nr) { /* blank bevel lists can happen */

					/* exception handling; curve without bevel or extrude, with width correction */
					if(dlbev.first==NULL) {
						dl= MEM_callocN(sizeof(DispList), "makeDispListbev");
						dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts");
						BLI_addtail(dispbase, dl);

						if(bl->poly!= -1) dl->type= DL_POLY;
						else dl->type= DL_SEGM;

						if(dl->type==DL_SEGM) dl->flag = (DL_FRONT_CURVE|DL_BACK_CURVE);

						dl->parts= 1;
						dl->nr= bl->nr;
						dl->col= nu->mat_nr;
						dl->charidx= nu->charidx;

						/* dl->rt will be used as flag for render face and */
						/* CU_2D conflicts with R_NOPUNOFLIP */
						dl->rt= nu->flag & ~CU_2D;

						a= dl->nr;
						bevp= (BevPoint *)(bl+1);
						data= dl->verts;
						while(a--) {
							data[0]= bevp->vec[0]+widfac*bevp->sina;
							data[1]= bevp->vec[1]+widfac*bevp->cosa;
							data[2]= bevp->vec[2];
							bevp++;
							data+=3;
						}
					}
					else {
						DispList *dlb;

						for (dlb=dlbev.first; dlb; dlb=dlb->next) {
	
							/* for each part of the bevel use a separate displblock */
							dl= MEM_callocN(sizeof(DispList), "makeDispListbev1");
							dl->verts= data= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts");
							BLI_addtail(dispbase, dl);
	
							dl->type= DL_SURF;
							
							dl->flag= dlb->flag & (DL_FRONT_CURVE|DL_BACK_CURVE);
							if(dlb->type==DL_POLY) dl->flag |= DL_CYCL_U;
							if(bl->poly>=0) dl->flag |= DL_CYCL_V;
							
							dl->parts= bl->nr;
							dl->nr= dlb->nr;
							dl->col= nu->mat_nr;
							dl->charidx= nu->charidx;

							/* dl->rt will be used as flag for render face and */
							/* CU_2D conflicts with R_NOPUNOFLIP */
							dl->rt= nu->flag & ~CU_2D;

							dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "bevelSplitFlag");
	
							/* for each point of poly make a bevel piece */
							bevp= (BevPoint *)(bl+1);
							for(a=0; a<bl->nr; a++,bevp++) {
								float fac=1.0;
								if (cu->taperobj==NULL) {
									if ( (cu->bevobj!=NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) )
										fac = bevp->radius;
								} else {
									fac = calc_taper(scene, cu->taperobj, a, bl->nr);
								}

								if (bevp->split_tag) {
									dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F);
								}
	
									/* rotate bevel piece and write in data */
								fp1= dlb->verts;
								for (b=0; b<dlb->nr; b++,fp1+=3,data+=3) {
									if(cu->flag & CU_3D) {
										float vec[3];
	
										vec[0]= fp1[1]+widfac;
										vec[1]= fp1[2];
										vec[2]= 0.0;

										mul_qt_v3(bevp->quat, vec);

										data[0]= bevp->vec[0] + fac*vec[0];
										data[1]= bevp->vec[1] + fac*vec[1];
										data[2]= bevp->vec[2] + fac*vec[2];
									}
									else {
										data[0]= bevp->vec[0] + fac*(widfac+fp1[1])*bevp->sina;
										data[1]= bevp->vec[1] + fac*(widfac+fp1[1])*bevp->cosa;
										data[2]= bevp->vec[2] + fac*fp1[2];
									}
								}
							}
							
							/* gl array drawing: using indices */
							displist_surf_indices(dl);
						}
					}
				}

			}
			freedisplist(&dlbev);
		}
Example #14
0
/* Add given channel into (active) group 
 *	- assumes that channel is not linked to anything anymore
 *	- always adds at the end of the group 
 */
void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve)
{	
	/* sanity checks */
	if (ELEM3(NULL, act, agrp, fcurve))
		return;
	
	/* if no channels anywhere, just add to two lists at the same time */
	if (act->curves.first == NULL) {
		fcurve->next = fcurve->prev = NULL;
		
		agrp->channels.first = agrp->channels.last = fcurve;
		act->curves.first = act->curves.last = fcurve;
	}
	
	/* if the group already has channels, the F-Curve can simply be added to the list 
	 * (i.e. as the last channel in the group)
	 */
	else if (agrp->channels.first) {
		/* if the group's last F-Curve is the action's last F-Curve too, 
		 * then set the F-Curve as the last for the action first so that
		 * the lists will be in sync after linking
		 */
		if (agrp->channels.last == act->curves.last)
			act->curves.last = fcurve;
			
		/* link in the given F-Curve after the last F-Curve in the group,
		 * which means that it should be able to fit in with the rest of the
		 * list seamlessly
		 */
		BLI_insertlinkafter(&agrp->channels, agrp->channels.last, fcurve);
	}
	
	/* otherwise, need to find the nearest F-Curve in group before/after current to link with */
	else {
		bActionGroup *grp;
		
		/* firstly, link this F-Curve to the group */
		agrp->channels.first = agrp->channels.last = fcurve;
		
		/* step through the groups preceding this one, finding the F-Curve there to attach this one after */
		for (grp = agrp->prev; grp; grp = grp->prev) {
			/* if this group has F-Curves, we want weave the given one in right after the last channel there,
			 * but via the Action's list not this group's list
			 *	- this is so that the F-Curve is in the right place in the Action,
			 *	  but won't be included in the previous group
			 */
			if (grp->channels.last) {
				/* once we've added, break here since we don't need to search any further... */
				BLI_insertlinkafter(&act->curves, grp->channels.last, fcurve);
				break;
			}
		}
		
		/* if grp is NULL, that means we fell through, and this F-Curve should be added as the new first
		 * since group is (effectively) the first group. Thus, the existing first F-Curve becomes the 
		 * second in the chain, etc. etc.
		 */
		if (grp == NULL)
			BLI_insertlinkbefore(&act->curves, act->curves.first, fcurve);
	}
	
	/* set the F-Curve's new group */
	fcurve->grp = agrp;
}	
Example #15
0
/* perform syncing updates for F-Curves */
static void animchan_sync_fcurve (bAnimContext *UNUSED(ac), bAnimListElem *ale)
{
	FCurve *fcu= (FCurve *)ale->data;
	ID *owner_id= ale->id;
	
	/* major priority is selection status, so refer to the checks done in anim_filter.c 
	 * skip_fcurve_selected_data() for reference about what's going on here...
	 */
	if (ELEM3(NULL, fcu, fcu->rna_path, owner_id))
		return;
		
	if (GS(owner_id->name) == ID_OB) {
		Object *ob= (Object *)owner_id;
		
		/* only affect if F-Curve involves pose.bones */
		if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) {
			bPoseChannel *pchan;
			char *bone_name;
			
			/* get bone-name, and check if this bone is selected */
			bone_name= BLI_getQuotedStr(fcu->rna_path, "pose.bones[");
			pchan= get_pose_channel(ob->pose, bone_name);
			if (bone_name) MEM_freeN(bone_name);
			
			/* F-Curve selection depends on whether the bone is selected */
			if ((pchan) && (pchan->bone)) {
				if (pchan->bone->flag & BONE_SELECTED)
					fcu->flag |= FCURVE_SELECTED;
				else
					fcu->flag &= ~FCURVE_SELECTED;
			}
		}
	}
	else if (GS(owner_id->name) == ID_SCE) {
		Scene *scene = (Scene *)owner_id;
		
		/* only affect if F-Curve involves sequence_editor.sequences */
		if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
			Editing *ed= seq_give_editing(scene, FALSE);
			Sequence *seq;
			char *seq_name;
			
			/* get strip name, and check if this strip is selected */
			seq_name= BLI_getQuotedStr(fcu->rna_path, "sequences_all[");
			seq = get_seq_by_name(ed->seqbasep, seq_name, FALSE);
			if (seq_name) MEM_freeN(seq_name);
			
			/* can only add this F-Curve if it is selected */
			if (seq) {
				if (seq->flag & SELECT)
					fcu->flag |= FCURVE_SELECTED;
				else
					fcu->flag &= ~FCURVE_SELECTED;
			}
		}
	}
	else if (GS(owner_id->name) == ID_NT) {
		bNodeTree *ntree = (bNodeTree *)owner_id;
		
		/* check for selected nodes */
		if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) {
			bNode *node;
			char *node_name;
			
			/* get strip name, and check if this strip is selected */
			node_name= BLI_getQuotedStr(fcu->rna_path, "nodes[");
			node = nodeFindNodebyName(ntree, node_name);
			if (node_name) MEM_freeN(node_name);
			
			/* can only add this F-Curve if it is selected */
			if (node) {
				if (node->flag & NODE_SELECT)
					fcu->flag |= FCURVE_SELECTED;
				else
					fcu->flag &= ~FCURVE_SELECTED;
			}
		}
	}
}
Example #16
0
	/* axis is using another define!!! */
static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, CurveDeform *cd, float *quatp)
{
	Curve *cu= par->data;
	float fac, loc[4], dir[3], new_quat[4], radius;
	short /*upflag, */ index;

	index= axis-1;
	if(index>2)
		index -= 3; /* negative  */

	/* to be sure, mostly after file load */
	if(cu->path==NULL) {
		makeDispListCurveTypes(scene, par, 0);
		if(cu->path==NULL) return 0;	// happens on append...
	}
	
	/* options */
	if(ELEM3(axis, OB_NEGX+1, OB_NEGY+1, OB_NEGZ+1)) { /* OB_NEG# 0-5, MOD_CURVE_POS# 1-6 */
		if(cu->flag & CU_STRETCH)
			fac= (-co[index]-cd->dmax[index])/(cd->dmax[index] - cd->dmin[index]);
		else
			fac= (cd->dloc[index])/(cu->path->totdist) - (co[index]-cd->dmax[index])/(cu->path->totdist);
	}
	else {
		if(cu->flag & CU_STRETCH)
			fac= (co[index]-cd->dmin[index])/(cd->dmax[index] - cd->dmin[index]);
		else
			fac= (cd->dloc[index])/(cu->path->totdist) + (co[index]-cd->dmin[index])/(cu->path->totdist);
	}
	
#if 0 // XXX old animation system
	/* we want the ipo to work on the default 100 frame range, because there's no  
	   actual time involved in path position */
	// huh? by WHY!!!!???? - Aligorith
	if(cu->ipo) {
		fac*= 100.0f;
		if(calc_ipo_spec(cu->ipo, CU_SPEED, &fac)==0)
			fac/= 100.0;
	}
#endif // XXX old animation system
	
	if( where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) {	/* returns OK */
		float quat[4], cent[3];

#if 0	// XXX - 2.4x Z-Up, Now use bevel tilt.
		if(cd->no_rot_axis)	/* set by caller */
			dir[cd->no_rot_axis-1]= 0.0f;
		
		/* -1 for compatibility with old track defines */
		vec_to_quat( quat,dir, axis-1, upflag);
		
		/* the tilt */
		if(loc[3]!=0.0) {
			normalize_v3(dir);
			q[0]= (float)cos(0.5*loc[3]);
			fac= (float)sin(0.5*loc[3]);
			q[1]= -fac*dir[0];
			q[2]= -fac*dir[1];
			q[3]= -fac*dir[2];
			mul_qt_qtqt(quat, q, quat);
		}
#endif

		if(cd->no_rot_axis) {	/* set by caller */

			/* this is not exactly the same as 2.4x, since the axis is having rotation removed rather than
			 * changing the axis before calculating the tilt but serves much the same purpose */
			float dir_flat[3]={0,0,0}, q[4];
			copy_v3_v3(dir_flat, dir);
			dir_flat[cd->no_rot_axis-1]= 0.0f;

			normalize_v3(dir);
			normalize_v3(dir_flat);

			rotation_between_vecs_to_quat(q, dir, dir_flat); /* Could this be done faster? */

			mul_qt_qtqt(new_quat, q, new_quat);
		}


		/* Logic for 'cent' orientation *
		 *
		 * The way 'co' is copied to 'cent' may seem to have no meaning, but it does.
		 *
		 * Use a curve modifier to stretch a cube out, color each side RGB, positive side light, negative dark.
		 * view with X up (default), from the angle that you can see 3 faces RGB colors (light), anti-clockwise
		 * Notice X,Y,Z Up all have light colors and each ordered CCW.
		 *
		 * Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell
		 *
		 * note: moved functions into quat_apply_track/vec_apply_track
		 * */
		copy_qt_qt(quat, new_quat);
		copy_v3_v3(cent, co);

		/* zero the axis which is not used,
		 * the big block of text above now applies to these 3 lines */
		quat_apply_track(quat, axis-1, (axis==1 || axis==3) ? 1:0); /* up flag is a dummy, set so no rotation is done */
		vec_apply_track(cent, axis-1);
		cent[axis < 4 ? axis-1 : axis-4]= 0.0f;


		/* scale if enabled */
		if(cu->flag & CU_PATH_RADIUS)
			mul_v3_fl(cent, radius);
		
		/* local rotation */
		normalize_qt(quat);
		mul_qt_v3(quat, cent);

		/* translation */
		add_v3_v3v3(co, cent, loc);

		if(quatp)
			copy_qt_qt(quatp, quat);

		return 1;
	}
	return 0;
}