Exemple #1
0
static void addedgeface_mesh(EditMesh *em, wmOperator *op)
{
	EditVert *eve, *neweve[4];
	EditEdge *eed;
	EditFace *efa;
	short amount=0;

	/* how many selected ? */
	if(em->selectmode & SCE_SELECT_EDGE) {
		/* in edge mode finding selected vertices means flushing down edge codes... */
		/* can't make face with only edge selection info... */
		EM_selectmode_set(em);
	}
	
	for(eve= em->verts.first; eve; eve= eve->next) {
		if(eve->f & SELECT) {
			amount++;
			if(amount>4) break;			
			neweve[amount-1]= eve;
		}
	}

	if(amount==2) {
		eed= addedgelist(em, neweve[0], neweve[1], NULL);
		EM_select_edge(eed, 1);

		// XXX		DAG_id_tag_update(obedit->data, 0);
		return;
	}
	else if(amount > 4) {
		addfaces_from_edgenet(em);
		return;
	}
	else if(amount<2) {
		BKE_report(op->reports, RPT_WARNING, "More vertices are needed to make an edge/face");
		return;
	}

	efa= NULL; // check later

	if(amount==3) {
		
		if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2], NULL)==0) {
			efa= addfacelist(em, neweve[0], neweve[1], neweve[2], 0, NULL, NULL);
			EM_select_face(efa, 1);
		}
		else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face");
	}
	else if(amount==4) {
		/* this test survives when theres 2 triangles */
		if(exist_face(em, neweve[0], neweve[1], neweve[2], neweve[3])==0) {
			int tria= 0;
			
			/* remove trias if they exist, 4 cases.... */
			if(exist_face(em, neweve[0], neweve[1], neweve[2], NULL)) tria++;
			if(exist_face(em, neweve[0], neweve[1], neweve[3], NULL)) tria++;
			if(exist_face(em, neweve[0], neweve[2], neweve[3], NULL)) tria++;
			if(exist_face(em, neweve[1], neweve[2], neweve[3], NULL)) tria++;
		
			if(tria==2) join_triangles(em);
			else if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2], neweve[3])==0) {
				 /* If there are 4 Verts, But more selected edges, we need to call addfaces_from_edgenet */
					EditEdge *eedcheck;
					int count;
					count = 0;
					for(eedcheck= em->edges.first; eedcheck; eedcheck= eedcheck->next) {
						if(eedcheck->f & SELECT) {
							count++;
						}
					}	
				
				if(count++ > 4){
					addfaces_from_edgenet(em);
					return;
				} else {
				/* if 4 edges exist, we just create the face, convex or not */
					efa= addface_from_edges(em);
					if(efa==NULL) {
						
						/* the order of vertices can be anything, 6 cases to check */
						if( convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co) ) {
							efa= addfacelist(em, neweve[0], neweve[1], neweve[2], neweve[3], NULL, NULL);
						}
						else if( convex(neweve[0]->co, neweve[2]->co, neweve[3]->co, neweve[1]->co) ) {
							efa= addfacelist(em, neweve[0], neweve[2], neweve[3], neweve[1], NULL, NULL);
						}
						else if( convex(neweve[0]->co, neweve[2]->co, neweve[1]->co, neweve[3]->co) ) {
							efa= addfacelist(em, neweve[0], neweve[2], neweve[1], neweve[3], NULL, NULL);
						}
						else if( convex(neweve[0]->co, neweve[1]->co, neweve[3]->co, neweve[2]->co) ) {
							efa= addfacelist(em, neweve[0], neweve[1], neweve[3], neweve[2], NULL, NULL);
						}
						else if( convex(neweve[0]->co, neweve[3]->co, neweve[2]->co, neweve[1]->co) ) {
							efa= addfacelist(em, neweve[0], neweve[3], neweve[2], neweve[1], NULL, NULL);
						}
						else if( convex(neweve[0]->co, neweve[3]->co, neweve[1]->co, neweve[2]->co) ) {
							efa= addfacelist(em, neweve[0], neweve[3], neweve[1], neweve[2], NULL, NULL);
						}
						else BKE_report(op->reports, RPT_WARNING, "cannot find nice quad from concave set of vertices");

					}
				}
			}
			else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face");
		}
		else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face");
	}
	
	if(efa) {
		EM_select_face(efa, 1);

		fix_new_face(em, efa);
		
		recalc_editnormals(em);
	}
	}
Exemple #2
0
static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
{
	ViewContext vc;
	EditVert *eve;
	float min[3], max[3];
	int done= 0;
	short use_proj;

	em_setup_viewcontext(C, &vc);

	use_proj= (vc.scene->toolsettings->snap_flag & SCE_SNAP) &&	(vc.scene->toolsettings->snap_mode==SCE_SNAP_MODE_FACE);
	
	invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); 
	
	INIT_MINMAX(min, max);
	
	for(eve= vc.em->verts.first; eve; eve= eve->next) {
		if(eve->f & SELECT) {
			DO_MINMAX(eve->co, min, max);
			done= 1;
		}
	}

	/* call extrude? */
	if(done) {
		const short rot_src= RNA_boolean_get(op->ptr, "rotate_source");
		EditEdge *eed;
		float vec[3], cent[3], mat[3][3];
		float nor[3]= {0.0, 0.0, 0.0};
		
		/* 2D normal calc */
		float mval_f[2];

		mval_f[0]= (float)event->mval[0];
		mval_f[1]= (float)event->mval[1];

		done= 0;

		/* calculate the normal for selected edges */
		for(eed= vc.em->edges.first; eed; eed= eed->next) {
			if(eed->f & SELECT) {
				float co1[3], co2[3];
				mul_v3_m4v3(co1, vc.obedit->obmat, eed->v1->co);
				mul_v3_m4v3(co2, vc.obedit->obmat, eed->v2->co);
				project_float_noclip(vc.ar, co1, co1);
				project_float_noclip(vc.ar, co2, co2);
				
				/* 2D rotate by 90d while adding.
				 *  (x, y) = (y, -x)
				 *
				 * accumulate the screenspace normal in 2D,
				 * with screenspace edge length weighting the result. */
				if(line_point_side_v2(co1, co2, mval_f) >= 0.0f) {
					nor[0] +=  (co1[1] - co2[1]);
					nor[1] += -(co1[0] - co2[0]);
				}
				else {
					nor[0] +=  (co2[1] - co1[1]);
					nor[1] += -(co2[0] - co1[0]);
				}
				done= 1;
			}
		}

		if(done) {
			float view_vec[3], cross[3];

			/* convert the 2D nomal into 3D */
			mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* worldspace */
			mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */
			
			/* correct the normal to be aligned on the view plane */
			copy_v3_v3(view_vec, vc.rv3d->viewinv[2]);
			mul_mat3_m4_v3(vc.obedit->imat, view_vec);
			cross_v3_v3v3(cross, nor, view_vec);
			cross_v3_v3v3(nor, view_vec, cross);
			normalize_v3(nor);
		}
		
		/* center */
		mid_v3_v3v3(cent, min, max);
		copy_v3_v3(min, cent);
		
		mul_m4_v3(vc.obedit->obmat, min);	// view space
		view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE);
		mul_m4_v3(vc.obedit->imat, min); // back in object space
		
		sub_v3_v3(min, cent);
		
		/* calculate rotation */
		unit_m3(mat);
		if(done) {
			float dot;
			
			copy_v3_v3(vec, min);
			normalize_v3(vec);
			dot= dot_v3v3(vec, nor);

			if( fabs(dot)<0.999) {
				float cross[3], si, q1[4];
				
				cross_v3_v3v3(cross, nor, vec);
				normalize_v3(cross);
				dot= 0.5f*saacos(dot);
				
				/* halve the rotation if its applied twice */
				if(rot_src) dot *= 0.5f;
				
				si= (float)sin(dot);
				q1[0]= (float)cos(dot);
				q1[1]= cross[0]*si;
				q1[2]= cross[1]*si;
				q1[3]= cross[2]*si;				
				quat_to_mat3( mat,q1);
			}
		}
		
		if(rot_src) {
			rotateflag(vc.em, SELECT, cent, mat);
			/* also project the source, for retopo workflow */
			if(use_proj)
				EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);
		}
		
		extrudeflag(vc.obedit, vc.em, SELECT, nor, 0);
		rotateflag(vc.em, SELECT, cent, mat);
		translateflag(vc.em, SELECT, min);
		
		recalc_editnormals(vc.em);
	}
	else if(vc.em->selectmode & SCE_SELECT_VERTEX) {

		float imat[4][4];
		const float *curs= give_cursor(vc.scene, vc.v3d);
		
		copy_v3_v3(min, curs);
		view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE);

		eve= addvertlist(vc.em, 0, NULL);

		invert_m4_m4(imat, vc.obedit->obmat);
		mul_v3_m4v3(eve->co, imat, min);
		
		eve->f= SELECT;
	}

	if(use_proj)
		EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);

	WM_event_add_notifier(C, NC_GEOM|ND_DATA, vc.obedit->data); 
	DAG_id_tag_update(vc.obedit->data, 0);
	
	return OPERATOR_FINISHED;
}
Exemple #3
0
static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int seg,
		int subdiv, float dia, float depth, int ext, int fill)
{
	/*
	 * type - for the type of shape
	 * dia - the radius for cone,sphere cylinder etc.
	 * depth - 
	 * ext - extrude
	 * fill - end capping, and option to fill in circle
	 * cent[3] - center of the data. 
	 * */
	EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
	EditVert *eve, *v1=NULL, *v2, *v3, *v4=NULL, *vtop, *vdown;
	float phi, phid, vec[3];
	float q[4], cmat[3][3], nor[3]= {0.0, 0.0, 0.0};
	short a, b;
	
	EM_clear_flag_all(em, SELECT);

	phid= 2.0f*(float)M_PI/tot;
	phi= .25f*(float)M_PI;

	switch(type) {
	case PRIM_GRID: /*  grid */
		/* clear flags */
		eve= em->verts.first;
		while(eve) {
			eve->f= 0;
			eve= eve->next;
		}
		
		/* one segment first: the X axis */		
		phi = (2*dia)/(float)(tot-1);
		phid = (2*dia)/(float)(seg-1);
		for(a=tot-1;a>=0;a--) {
			vec[0] = (phi*a) - dia;
			vec[1]= - dia;
			vec[2]= 0.0f;
			eve= addvertlist(em, vec, NULL);
			eve->f= 1+2+4;
			if(a < tot -1) addedgelist(em, eve->prev, eve, NULL);
		}
		/* extrude and translate */
		vec[0]= vec[2]= 0.0;
		vec[1]= phid;
		
		for(a=0;a<seg-1;a++) {
			extrudeflag_vert(obedit, em, 2, nor, 0);	// nor unused
			translateflag(em, 2, vec);
		}
			
		/* and now do imat */
		eve= em->verts.first;
		while(eve) {
			if(eve->f & SELECT) {
				mul_m4_v3(mat,eve->co);
			}
			eve= eve->next;
		}
		recalc_editnormals(em);
		break;
			
	case PRIM_UVSPHERE: /*  UVsphere */
		
		/* clear all flags */
		eve= em->verts.first;
		while(eve) {
			eve->f= 0;
			eve= eve->next;
		}
		
		/* one segment first */
		phi= 0; 
		phid/=2;
		for(a=0; a<=tot; a++) {
			vec[0]= dia*sinf(phi);
			vec[1]= 0.0;
			vec[2]= dia*cosf(phi);
			eve= addvertlist(em, vec, NULL);
			eve->f= 1+2+4;
			if(a==0) v1= eve;
			else addedgelist(em, eve, eve->prev, NULL);
			phi+= phid;
		}
		
		/* extrude and rotate */
		phi= M_PI/seg;
		q[0]= cos(phi);
		q[3]= sin(phi);
		q[1]=q[2]= 0;
		quat_to_mat3( cmat,q);
		
		for(a=0; a<seg; a++) {
			extrudeflag_vert(obedit, em, 2, nor, 0); // nor unused
			rotateflag(em, 2, v1->co, cmat);
		}

		removedoublesflag(em, 4, 0, 0.0001);

		/* and now do imat */
		eve= em->verts.first;
		while(eve) {
			if(eve->f & SELECT) {
				mul_m4_v3(mat,eve->co);
			}
			eve= eve->next;
		}
		recalc_editnormals(em);
		break;
	case PRIM_ICOSPHERE: /* Icosphere */
		{
			EditVert *eva[12];
			EditEdge *eed;
			
			/* clear all flags */
			eve= em->verts.first;
			while(eve) {
				eve->f= 0;
				eve= eve->next;
			}
			dia/=200;
			for(a=0;a<12;a++) {
				vec[0]= dia*icovert[a][0];
				vec[1]= dia*icovert[a][1];
				vec[2]= dia*icovert[a][2];
				eva[a]= addvertlist(em, vec, NULL);
				eva[a]->f= 1+2;
			}
			for(a=0;a<20;a++) {
				EditFace *evtemp;
				v1= eva[ icoface[a][0] ];
				v2= eva[ icoface[a][1] ];
				v3= eva[ icoface[a][2] ];
				evtemp = addfacelist(em, v1, v2, v3, 0, NULL, NULL);
				evtemp->e1->f = 1+2;
				evtemp->e2->f = 1+2;
				evtemp->e3->f = 1+2;
			}

			dia*=200;
			for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0, B_SPHERE,1, SUBDIV_CORNER_PATH, 0);
			/* and now do imat */
			eve= em->verts.first;
			while(eve) {
				if(eve->f & 2) {
					mul_m4_v3(mat,eve->co);
				}
				eve= eve->next;
			}
			
			// Clear the flag 2 from the edges
			for(eed=em->edges.first;eed;eed=eed->next){
				if(eed->f & 2){
					   eed->f &= !2;
				}   
			}
		}
		break;
	case PRIM_MONKEY: /* Monkey */
		{
			//extern int monkeyo, monkeynv, monkeynf;
			//extern signed char monkeyf[][4];
			//extern signed char monkeyv[][3];
			EditVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv");
			int i;

			for (i=0; i<monkeynv; i++) {
				float v[3];
				v[0]= (monkeyv[i][0]+127)/128.0, v[1]= monkeyv[i][1]/128.0, v[2]= monkeyv[i][2]/128.0;
				tv[i]= addvertlist(em, v, NULL);
				tv[i]->f |= SELECT;
				tv[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]:addvertlist(em, v, NULL);
				tv[monkeynv+i]->f |= SELECT;
			}
			for (i=0; i<monkeynf; i++) {
				addfacelist(em, tv[monkeyf[i][0]+i-monkeyo], tv[monkeyf[i][1]+i-monkeyo], tv[monkeyf[i][2]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL);
				addfacelist(em, tv[monkeynv+monkeyf[i][2]+i-monkeyo], tv[monkeynv+monkeyf[i][1]+i-monkeyo], tv[monkeynv+monkeyf[i][0]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeynv+monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL);
			}

			MEM_freeN(tv);

			/* and now do imat */
			for(eve= em->verts.first; eve; eve= eve->next) {
				if(eve->f & SELECT) {
					mul_m4_v3(mat,eve->co);
				}
			}
			recalc_editnormals(em);
		}
		break;
	default: /* all types except grid, sphere... */
		if(type==PRIM_CONE);
		else if(ext==0) 
			depth= 0.0f;
	
		/* first vertex at 0° for circular objects */
		if( ELEM3(type, PRIM_CIRCLE,PRIM_CYLINDER,PRIM_CONE) )
			phi = 0.0f;
			
		vtop= vdown= v1= v2= 0;
		for(b=0; b<=ext; b++) {
			for(a=0; a<tot; a++) {
				
				vec[0]= dia*sinf(phi);
				vec[1]= dia*cosf(phi);
				vec[2]= b?depth:-depth;
				
				mul_m4_v3(mat, vec);
				eve= addvertlist(em, vec, NULL);
				eve->f= SELECT;
				if(a==0) {
					if(b==0) v1= eve;
					else v2= eve;
				}
				phi+=phid;
			}
		}
			
		/* center vertices */
		/* type PRIM_CONE can only have 1 one side filled
		 * if the cone has no capping, dont add vtop */
		if(type == PRIM_CONE || (fill && !ELEM(type, PRIM_PLANE, PRIM_CUBE))) {
			vec[0]= vec[1]= 0.0f;
			vec[2]= type==PRIM_CONE ? depth : -depth;
			mul_m4_v3(mat, vec);
			vdown= addvertlist(em, vec, NULL);
			if((ext || type==PRIM_CONE) && fill) {
				vec[0]= vec[1]= 0.0f;
				vec[2]= type==PRIM_CONE ? -depth : depth;
				mul_m4_v3(mat,vec);
				vtop= addvertlist(em, vec, NULL);
			}
		} else {
			vdown= v1;
			vtop= v2;
		}
		if(vtop) vtop->f= SELECT;
		if(vdown) vdown->f= SELECT;
	
		/* top and bottom face */
		if(fill || type==PRIM_CONE) {
			if(tot==4 && ELEM(type, PRIM_PLANE, PRIM_CUBE)) {
				v3= v1->next->next;
				if(ext) v4= v2->next->next;
				
				addfacelist(em, v3, v1->next, v1, v3->next, NULL, NULL);
				if(ext) addfacelist(em, v2, v2->next, v4, v4->next, NULL, NULL);
				
			}
			else {
				v3= v1;
				v4= v2;
				for(a=1; a<tot; a++) {
					addfacelist(em, vdown, v3, v3->next, 0, NULL, NULL);
					v3= v3->next;
					if(ext && fill) {
						addfacelist(em, vtop, v4, v4->next, 0, NULL, NULL);
						v4= v4->next;
					}
				}
				if(!ELEM(type, PRIM_PLANE, PRIM_CUBE)) {
					addfacelist(em, vdown, v3, v1, 0, NULL, NULL);
					if(ext) addfacelist(em, vtop, v4, v2, 0, NULL, NULL);
				}
			}
		}
		else if(type==PRIM_CIRCLE) {  /* we need edges for a circle */
			v3= v1;
			for(a=1;a<tot;a++) {
				addedgelist(em, v3, v3->next, NULL);
				v3= v3->next;
			}
			addedgelist(em, v3, v1, NULL);
		}
		/* side faces */
		if(ext) {
			v3= v1;
			v4= v2;
			for(a=1; a<tot; a++) {
				addfacelist(em, v3, v3->next, v4->next, v4, NULL, NULL);
				v3= v3->next;
				v4= v4->next;
			}
			addfacelist(em, v3, v1, v2, v4, NULL, NULL);
		}
		else if(fill && type==PRIM_CONE) {
			/* add the bottom flat area of the cone
			 * if capping is disabled dont bother */
			v3= v1;
			for(a=1; a<tot; a++) {
				addfacelist(em, vtop, v3->next, v3, 0, NULL, NULL);
				v3= v3->next;
			}
			addfacelist(em, vtop, v1, v3, 0, NULL, NULL);
		}
	}
	
	EM_stats_update(em);
	/* simple selection flush OK, based on fact it's a single model */
	EM_select_flush(em); /* flushes vertex -> edge -> face selection */

	if(!ELEM5(type, PRIM_GRID, PRIM_PLANE, PRIM_ICOSPHERE, PRIM_UVSPHERE, PRIM_MONKEY))
		EM_recalc_normal_direction(em, FALSE, TRUE);	/* otherwise monkey has eyes in wrong direction */

	BKE_mesh_end_editmesh(obedit->data, em);
}
Exemple #4
0
static void edge_drawflags(Mesh *me, EditMesh *em)
{
	EditVert *eve;
	EditEdge *eed, *e1, *e2, *e3, *e4;
	EditFace *efa;
	
	/* - count number of times edges are used in faces: 0 en 1 time means draw edge
	 * - edges more than 1 time used: in *tmp.f is pointer to first face
	 * - check all faces, when normal differs to much: draw (flag becomes 1)
	 */

	/* later on: added flags for 'cylinder' and 'sphere' intersection tests in old
	   game engine (2.04)
	 */
	
	recalc_editnormals(em);
	
	/* init */
	eve= em->verts.first;
	while(eve) {
		eve->f1= 1;		/* during test it's set at zero */
		eve= eve->next;
	}
	eed= em->edges.first;
	while(eed) {
		eed->f2= eed->f1= 0;
		eed->tmp.f = 0;
		eed= eed->next;
	}

	efa= em->faces.first;
	while(efa) {
		e1= efa->e1;
		e2= efa->e2;
		e3= efa->e3;
		e4= efa->e4;
		if(e1->f2<4) e1->f2+= 1;
		if(e2->f2<4) e2->f2+= 1;
		if(e3->f2<4) e3->f2+= 1;
		if(e4 && e4->f2<4) e4->f2+= 1;
		
		if(e1->tmp.f == 0) e1->tmp.f = (void *) efa;
		if(e2->tmp.f == 0) e2->tmp.f = (void *) efa;
		if(e3->tmp.f ==0) e3->tmp.f = (void *) efa;
		if(e4 && (e4->tmp.f == 0)) e4->tmp.f = (void *) efa;
		
		efa= efa->next;
	}

	if(me->drawflag & ME_ALLEDGES) {
		efa= em->faces.first;
		while(efa) {
			if(efa->e1->f2>=2) efa->e1->f2= 1;
			if(efa->e2->f2>=2) efa->e2->f2= 1;
			if(efa->e3->f2>=2) efa->e3->f2= 1;
			if(efa->e4 && efa->e4->f2>=2) efa->e4->f2= 1;
			
			efa= efa->next;
		}		
	}	
	else {
		
		/* handle single-edges for 'test cylinder flag' (old engine) */
		
		eed= em->edges.first;
		while(eed) {
			if(eed->f2==1) eed->f1= 1;
			eed= eed->next;
		}

		/* all faces, all edges with flag==2: compare normal */
		efa= em->faces.first;
		while(efa) {
			if(efa->e1->f2==2) edge_normal_compare(efa->e1, efa);
			else efa->e1->f2= 1;
			if(efa->e2->f2==2) edge_normal_compare(efa->e2, efa);
			else efa->e2->f2= 1;
			if(efa->e3->f2==2) edge_normal_compare(efa->e3, efa);
			else efa->e3->f2= 1;
			if(efa->e4) {
				if(efa->e4->f2==2) edge_normal_compare(efa->e4, efa);
				else efa->e4->f2= 1;
			}
			efa= efa->next;
		}
		
		/* sphere collision flag */
		
		eed= em->edges.first;
		while(eed) {
			if(eed->f1!=1) {
				eed->v1->f1= eed->v2->f1= 0;
			}
			eed= eed->next;
		}
		
	}
}
Exemple #5
0
/* is used for both read and write... */
static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float lim)
{
	uiBlock *block= (layout)? uiLayoutAbsoluteBlock(layout): NULL;
	MDeformVert *dvert=NULL;
	TransformProperties *tfp;
	float median[6], ve_median[6];
	int tot, totw, totweight, totedge, totradius;
	char defstr[320];
	
	median[0]= median[1]= median[2]= median[3]= median[4]= median[5]= 0.0;
	tot= totw= totweight= totedge= totradius= 0;
	defstr[0]= 0;

	/* make sure we got storage */
	if(v3d->properties_storage==NULL)
		v3d->properties_storage= MEM_callocN(sizeof(TransformProperties), "TransformProperties");
	tfp= v3d->properties_storage;
	
	if(ob->type==OB_MESH) {
		Mesh *me= ob->data;
		EditMesh *em = BKE_mesh_get_editmesh(me);
		EditVert *eve, *evedef=NULL;
		EditEdge *eed;
		
		eve= em->verts.first;
		while(eve) {
			if(eve->f & SELECT) {
				evedef= eve;
				tot++;
				add_v3_v3(median, eve->co);
			}
			eve= eve->next;
		}
		eed= em->edges.first;
		while(eed) {
			if((eed->f & SELECT)) {
				totedge++;
				median[3]+= eed->crease;
			}
			eed= eed->next;
		}

		/* check for defgroups */
		if(evedef)
			dvert= CustomData_em_get(&em->vdata, evedef->data, CD_MDEFORMVERT);
		if(tot==1 && dvert && dvert->totweight) {
			bDeformGroup *dg;
			int i, max=1, init=1;
			char str[320];
			
			for (i=0; i<dvert->totweight; i++){
				dg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
				if(dg) {
					max+= BLI_snprintf(str, sizeof(str), "%s %%x%d|", dg->name, dvert->dw[i].def_nr); 
					if(max<320) strcat(defstr, str);
				}

				if(tfp->curdef==dvert->dw[i].def_nr) {
					init= 0;
					tfp->defweightp= &dvert->dw[i].weight;
				}
			}
			
			if(init) {	// needs new initialized 
				tfp->curdef= dvert->dw[0].def_nr;
				tfp->defweightp= &dvert->dw[0].weight;
			}
		}

		BKE_mesh_end_editmesh(me, em);
	}
	else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
		Curve *cu= ob->data;
		Nurb *nu;
		BPoint *bp;
		BezTriple *bezt;
		int a;
		ListBase *nurbs= ED_curve_editnurbs(cu);

		nu= nurbs->first;
		while(nu) {
			if(nu->type == CU_BEZIER) {
				bezt= nu->bezt;
				a= nu->pntsu;
				while(a--) {
					if(bezt->f2 & SELECT) {
						add_v3_v3(median, bezt->vec[1]);
						tot++;
						median[4]+= bezt->weight;
						totweight++;
						median[5]+= bezt->radius;
						totradius++;
					}
					else {
						if(bezt->f1 & SELECT) {
							add_v3_v3(median, bezt->vec[0]);
							tot++;
						}
						if(bezt->f3 & SELECT) {
							add_v3_v3(median, bezt->vec[2]);
							tot++;
						}
					}
					bezt++;
				}
			}
			else {
				bp= nu->bp;
				a= nu->pntsu*nu->pntsv;
				while(a--) {
					if(bp->f1 & SELECT) {
						add_v3_v3(median, bp->vec);
						median[3]+= bp->vec[3];
						totw++;
						tot++;
						median[4]+= bp->weight;
						totweight++;
						median[5]+= bp->radius;
						totradius++;
					}
					bp++;
				}
			}
			nu= nu->next;
		}
	}
	else if(ob->type==OB_LATTICE) {
		Lattice *lt= ob->data;
		BPoint *bp;
		int a;
		
		a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
		bp= lt->editlatt->latt->def;
		while(a--) {
			if(bp->f1 & SELECT) {
				add_v3_v3(median, bp->vec);
				tot++;
				median[4]+= bp->weight;
				totweight++;
			}
			bp++;
		}
	}
	
	if(tot==0) {
		uiDefBut(block, LABEL, 0, "Nothing selected",0, 130, 200, 20, NULL, 0, 0, 0, 0, "");
		return;
	}
	median[0] /= (float)tot;
	median[1] /= (float)tot;
	median[2] /= (float)tot;
	if(totedge) median[3] /= (float)totedge;
	else if(totw) median[3] /= (float)totw;
	if(totweight) median[4] /= (float)totweight;
	if(totradius) median[5] /= (float)totradius;
	
	if(v3d->flag & V3D_GLOBAL_STATS)
		mul_m4_v3(ob->obmat, median);
	
	if(block) {	// buttons
		uiBut *but;

		memcpy(tfp->ve_median, median, sizeof(tfp->ve_median));
		
		uiBlockBeginAlign(block);
		if(tot==1) {
			uiDefBut(block, LABEL, 0, "Vertex:",					0, 130, 200, 20, NULL, 0, 0, 0, 0, "");
			uiBlockBeginAlign(block);

			but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:",		0, 110, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
			uiButSetUnitType(but, PROP_UNIT_LENGTH);
			but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:",		0, 90, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
			uiButSetUnitType(but, PROP_UNIT_LENGTH);
			but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:",		0, 70, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
			uiButSetUnitType(but, PROP_UNIT_LENGTH);

			if(totw==1) {
				uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:",	0, 50, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 1, 3, "");
				uiBlockBeginAlign(block);
				uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global",		0, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
				uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local",		100, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
				uiBlockEndAlign(block);
				if(totweight)
					uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:",	0, 0, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 1, 3, "");
				if(totradius)
					uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:",	0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 1, 3, "Radius of curve CPs");
				}
			else {
				uiBlockBeginAlign(block);
				uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global",		0, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
				uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local",		100, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
				uiBlockEndAlign(block);
				if(totweight)
					uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:",	0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "");
				if(totradius)
					uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:",	0, 20, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 10, 3, "Radius of curve CPs");
			}
		}
		else {
			uiDefBut(block, LABEL, 0, "Median:",					0, 130, 200, 20, NULL, 0, 0, 0, 0, "");
			uiBlockBeginAlign(block);
			but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:",		0, 110, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
			uiButSetUnitType(but, PROP_UNIT_LENGTH);
			but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:",		0, 90, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
			uiButSetUnitType(but, PROP_UNIT_LENGTH);
			but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:",		0, 70, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
			uiButSetUnitType(but, PROP_UNIT_LENGTH);
			if(totw==tot) {
				uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:",	0, 50, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 1, 3, "");
				uiBlockEndAlign(block);
				uiBlockBeginAlign(block);
				uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global",		0, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
				uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local",		100, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
				uiBlockEndAlign(block);
				if(totweight)
					uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:",	0, 0, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "Weight is used for SoftBody Goal");
				if(totradius)
					uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:",	0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 10, 3, "Radius of curve CPs");
				uiBlockEndAlign(block);
			}
			else {
				uiBlockBeginAlign(block);
				uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global",		0, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
				uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local",		100, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
				uiBlockEndAlign(block);
				if(totweight)
					uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:",	0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 1, 3, "Weight is used for SoftBody Goal");
				if(totradius)
					uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:",	0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 1, 3, "Radius of curve CPs");
				uiBlockEndAlign(block);
			}
		}
				
		if(totedge==1)
			uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Crease:",	0, 20, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 1, 3, "");
		else if(totedge>1)
			uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Mean Crease:",	0, 20, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 1, 3, "");
		
	}
	else {	// apply
		memcpy(ve_median, tfp->ve_median, sizeof(tfp->ve_median));
		
		if(v3d->flag & V3D_GLOBAL_STATS) {
			invert_m4_m4(ob->imat, ob->obmat);
			mul_m4_v3(ob->imat, median);
			mul_m4_v3(ob->imat, ve_median);
		}
		sub_v3_v3v3(median, ve_median, median);
		median[3]= ve_median[3]-median[3];
		median[4]= ve_median[4]-median[4];
		median[5]= ve_median[5]-median[5];
		
		if(ob->type==OB_MESH) {
			Mesh *me= ob->data;
			EditMesh *em = BKE_mesh_get_editmesh(me);

			/* allow for some rounding error becasue of matrix transform */
			if(len_v3(median) > 0.000001f) {
				EditVert *eve;

				for(eve= em->verts.first; eve; eve= eve->next) {
					if(eve->f & SELECT) {
						add_v3_v3(eve->co, median);
					}
				}

				recalc_editnormals(em);
			}

			if(median[3] != 0.0f) {
				EditEdge *eed;
				const float fixed_crease= (ve_median[3] <= 0.0f ? 0.0f : (ve_median[3] >= 1.0f ? 1.0f : FLT_MAX));
				
				if(fixed_crease != FLT_MAX) {
					/* simple case */

					for(eed= em->edges.first; eed; eed= eed->next) {
						if(eed->f & SELECT) {
							eed->crease= fixed_crease;
						}
					}
				}
				else {
					/* scale crease to target median */
					float median_new= ve_median[3];
					float median_orig= ve_median[3] - median[3]; /* previous median value */

					/* incase of floating point error */
					CLAMP(median_orig, 0.0f, 1.0f);
					CLAMP(median_new, 0.0f, 1.0f);

					if(median_new < median_orig) {
						/* scale down */
						const float sca= median_new / median_orig;
						
						for(eed= em->edges.first; eed; eed= eed->next) {
							if(eed->f & SELECT) {
								eed->crease *= sca;
								CLAMP(eed->crease, 0.0f, 1.0f);
							}
						}
					}
					else {
						/* scale up */
						const float sca= (1.0f - median_new) / (1.0f - median_orig);

						for(eed= em->edges.first; eed; eed= eed->next) {
							if(eed->f & SELECT) {
								eed->crease = 1.0f - ((1.0f - eed->crease) * sca);
								CLAMP(eed->crease, 0.0f, 1.0f);
							}
						}
					}
				}
			}

			BKE_mesh_end_editmesh(me, em);
		}
		else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
			Curve *cu= ob->data;
			Nurb *nu;
			BPoint *bp;
			BezTriple *bezt;
			int a;
			ListBase *nurbs= ED_curve_editnurbs(cu);

			nu= nurbs->first;
			while(nu) {
				if(nu->type == CU_BEZIER) {
					bezt= nu->bezt;
					a= nu->pntsu;
					while(a--) {
						if(bezt->f2 & SELECT) {
							add_v3_v3(bezt->vec[0], median);
							add_v3_v3(bezt->vec[1], median);
							add_v3_v3(bezt->vec[2], median);
							bezt->weight+= median[4];
							bezt->radius+= median[5];
						}
						else {
							if(bezt->f1 & SELECT) {
								add_v3_v3(bezt->vec[0], median);
							}
							if(bezt->f3 & SELECT) {
								add_v3_v3(bezt->vec[2], median);
							}
						}
						bezt++;
					}
				}
				else {
					bp= nu->bp;
					a= nu->pntsu*nu->pntsv;
					while(a--) {
						if(bp->f1 & SELECT) {
							add_v3_v3(bp->vec, median);
							bp->vec[3]+= median[3];
							bp->weight+= median[4];
							bp->radius+= median[5];
						}
						bp++;
					}
				}
				test2DNurb(nu);
				testhandlesNurb(nu); /* test for bezier too */

				nu= nu->next;
			}
		}
		else if(ob->type==OB_LATTICE) {
			Lattice *lt= ob->data;
			BPoint *bp;
			int a;
			
			a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
			bp= lt->editlatt->latt->def;
			while(a--) {
				if(bp->f1 & SELECT) {
					add_v3_v3(bp->vec, median);
					bp->weight+= median[4];
				}
				bp++;
			}
		}
		
//		ED_undo_push(C, "Transform properties");
	}
}
Exemple #6
0
/* copied from editobject.c, now uses (almost) proper depgraph */
static void special_transvert_update(Scene *scene, Object *obedit)
{
	
	if(obedit) {
		
		DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
		
		if(obedit->type==OB_MESH) {
			Mesh *me= obedit->data;
			recalc_editnormals(me->edit_mesh);	// does face centers too
		}
		else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
			Curve *cu= obedit->data;
			Nurb *nu= cu->editnurb->first;
			
			while(nu) {
				test2DNurb(nu);
				testhandlesNurb(nu); /* test for bezier too */
				nu= nu->next;
			}
		}
		else if(obedit->type==OB_ARMATURE){
			bArmature *arm= obedit->data;
			EditBone *ebo;
			TransVert *tv= transvmain;
			int a=0;
			
			/* Ensure all bone tails are correctly adjusted */
			for (ebo= arm->edbo->first; ebo; ebo=ebo->next) {
				/* adjust tip if both ends selected */
				if ((ebo->flag & BONE_ROOTSEL) && (ebo->flag & BONE_TIPSEL)) {
					if (tv) {
						float diffvec[3];
						
						VecSubf(diffvec, tv->loc, tv->oldloc);
						VecAddf(ebo->tail, ebo->tail, diffvec);
						
						a++;
						if (a<tottrans) tv++;
					}
				}
			}
			
			/* Ensure all bones are correctly adjusted */
			for (ebo= arm->edbo->first; ebo; ebo=ebo->next) {
				if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
					/* If this bone has a parent tip that has been moved */
					if (ebo->parent->flag & BONE_TIPSEL){
						VECCOPY (ebo->head, ebo->parent->tail);
					}
					/* If this bone has a parent tip that has NOT been moved */
					else{
						VECCOPY (ebo->parent->tail, ebo->head);
					}
				}
			}
			if(arm->flag & ARM_MIRROR_EDIT) 
				transform_armature_mirror_update(obedit);
		}
		else if(obedit->type==OB_LATTICE) {
			Lattice *lt= obedit->data;
			
			if(lt->editlatt->flag & LT_OUTSIDE) 
				outside_lattice(lt->editlatt);
		}
	}
}