Beispiel #1
1
/* turns Mesh into editmesh */
void make_editMesh(Scene *scene, Object *ob)
{
	Mesh *me= ob->data;
	MFace *mface;
	MVert *mvert;
	MSelect *mselect;
	KeyBlock *actkey;
	EditMesh *em;
	EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4;
	EditFace *efa, *efa_last_sel= NULL;
	EditEdge *eed;
	EditSelection *ese;
	float *co, (*keyco)[3]= NULL;
	int tot, a, eekadoodle= 0;
	const short is_paint_face_sel=                             paint_facesel_test(ob);
	const short is_paint_vert_sel= is_paint_face_sel ? FALSE : paint_vertsel_test(ob);

	if(me->edit_mesh==NULL)
		me->edit_mesh= MEM_callocN(sizeof(EditMesh), "editmesh");
	else 
		/* because of reload */
		free_editMesh(me->edit_mesh);
	
	em= me->edit_mesh;
	
	em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced
	em->act_face = NULL;
	em->totvert= tot= me->totvert;
	em->totedge= me->totedge;
	em->totface= me->totface;
	
	if(tot==0) {
		return;
	}
	
	if(ob->actcol > 0)
		em->mat_nr= ob->actcol-1;

	/* initialize fastmalloc for editmesh */
	init_editmesh_fastmalloc(em, me->totvert, me->totedge, me->totface);

	actkey = ob_get_keyblock(ob);
	if(actkey) {
		/* undo-ing in past for previous editmode sessions gives corrupt 'keyindex' values */
		undo_editmode_clear();
		keyco= actkey->data;
		em->shapenr= ob->shapenr;
	}

	/* make editverts */
	CustomData_copy(&me->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
	mvert= me->mvert;

	evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist");
	for(a=0; a<tot; a++, mvert++) {
		
		co= mvert->co;

		/* edit the shape key coordinate if available */
		if(keyco && a < actkey->totelem)
			co= keyco[a];

		eve= addvertlist(em, co, NULL);
		evlist[a]= eve;
		
		/* face select sets selection in next loop */
		if(!is_paint_face_sel)
			eve->f |= (mvert->flag & SELECT);
		
		if (mvert->flag & ME_HIDE) eve->h= 1;
		normal_short_to_float_v3(eve->no, mvert->no);

		eve->bweight= ((float)mvert->bweight)/255.0f;

		/* lets overwrite the keyindex of the editvert
		 * with the order it used to be in before
		 * editmode
		 */
		eve->keyindex = a;

		CustomData_to_em_block(&me->vdata, &em->vdata, a, &eve->data);
	}

	if(actkey && actkey->totelem!=me->totvert);
	else {
		MEdge *medge= me->medge;
		
		CustomData_copy(&me->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
		/* make edges */
		for(a=0; a<me->totedge; a++, medge++) {
			eed= addedgelist(em, evlist[medge->v1], evlist[medge->v2], NULL);
			/* eed can be zero when v1 and v2 are identical, dxf import does this... */
			if(eed) {
				int is_sel;
				if (is_paint_vert_sel) {
					/* when from vertex select, flush flags to edges,
					 * allow selection, code below handles editmode selection conversion */
					is_sel= (eed->v1->f & SELECT) && (eed->v2->f & SELECT);
				}
				else {
					is_sel= (medge->flag & SELECT);
				}

				eed->crease= ((float)medge->crease)/255.0f;
				eed->bweight= ((float)medge->bweight)/255.0f;
				
				if(medge->flag & ME_SEAM) eed->seam= 1;
				if(medge->flag & ME_SHARP) eed->sharp = 1;
				if(medge->flag & ME_FGON) eed->h= EM_FGON;	// 2 different defines!
				if(medge->flag & ME_HIDE) eed->h |= 1;
				if(is_sel) eed->f |= SELECT;
				if(em->selectmode==SCE_SELECT_EDGE)
					EM_select_edge(eed, eed->f & SELECT);		// force edge selection to vertices, seems to be needed ...
				CustomData_to_em_block(&me->edata,&em->edata, a, &eed->data);
			}
		}
		
		CustomData_copy(&me->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0);

		/* make faces */
		mface= me->mface;

		for(a=0; a<me->totface; a++, mface++) {
			eve1= evlist[mface->v1];
			eve2= evlist[mface->v2];
			if(!mface->v3) eekadoodle= 1;
			eve3= evlist[mface->v3];
			if(mface->v4) eve4= evlist[mface->v4]; else eve4= NULL;
			
			efa= addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL);

			if(efa) {
				CustomData_to_em_block(&me->fdata, &em->fdata, a, &efa->data);

				efa->mat_nr= mface->mat_nr;
				efa->flag= mface->flag & ~ME_HIDE;
				
				/* select and hide face flag */
				if(mface->flag & ME_HIDE) {
					efa->h= 1;
				} else {
					int is_sel;

					if (!is_paint_vert_sel) {
						is_sel= (mface->flag & ME_FACE_SEL);
					}
					else {
						/* when from vertex select, flush flags to edges,
						 * allow selection, code below handles editmode selection conversion */
						is_sel= ( (efa->v1->f & SELECT) &&
						          (efa->v2->f & SELECT) &&
						          (efa->v3->f & SELECT) &&
						          (efa->v4 == NULL || efa->v4->f & SELECT)
						          );
					}

					if (a==me->act_face) {
						EM_set_actFace(em, efa);
					}
					
					/* dont allow hidden and selected */
					if(is_sel) {
						efa->f |= SELECT;
						
						if(is_paint_face_sel) {
							EM_select_face(efa, 1); /* flush down */
						}

						efa_last_sel= efa;
					}
				}
			}
		}
	}
	
	if(EM_get_actFace(em, 0)==NULL && efa_last_sel) {
		EM_set_actFace(em, efa_last_sel);
	}

	if(eekadoodle)
		error("This Mesh has old style edgecodes, please put it in the bugtracker!");
	
	MEM_freeN(evlist);

	end_editmesh_fastmalloc();	// resets global function pointers
	
	if(me->mselect){
		//restore editselections
		EM_init_index_arrays(em, 1,1,1);
		mselect = me->mselect;
		
		for(a=0; a<me->totselect; a++, mselect++){
			/*check if recorded selection is still valid, if so copy into editmesh*/
			if ( (mselect->type == EDITVERT && me->mvert[mselect->index].flag & SELECT) ||
			     (mselect->type == EDITEDGE && me->medge[mselect->index].flag & SELECT) ||
			     (mselect->type == EDITFACE && me->mface[mselect->index].flag & ME_FACE_SEL) )
			{
				ese = MEM_callocN(sizeof(EditSelection), "Edit Selection");
				ese->type = mselect->type;	
				if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(mselect->index); else
				if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(mselect->index); else
				if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(mselect->index);
				BLI_addtail(&(em->selected),ese);
			}
		}
		EM_free_index_arrays();
	}
	/* this creates coherent selections. also needed for older files */
	EM_selectmode_set(em);
	/* paranoia check to enforce hide rules */
	EM_hide_reset(em);
	/* sets helper flags which arent saved */
	EM_fgon_flags(em);
	
	if (EM_get_actFace(em, 0)==NULL) {
		EM_set_actFace(em, em->faces.first ); /* will use the first face, this is so we alwats have an active face */
	}
}
Beispiel #2
0
/* frees all editmode stuff */
void ED_editors_exit(bContext *C)
{
	Main *bmain= CTX_data_main(C);
	Scene *sce;

	if(!bmain)
		return;
	
	/* frees all editmode undos */
	undo_editmode_clear();
	ED_undo_paint_free();
	
	for(sce=bmain->scene.first; sce; sce= sce->id.next) {
		if(sce->obedit) {
			Object *ob= sce->obedit;
		
			/* global in meshtools... */
			mesh_octree_table(NULL, NULL, NULL, 'e');
			mesh_mirrtopo_table(NULL, 'e');
			
			if(ob) {
				if(ob->type==OB_MESH) {
					Mesh *me= ob->data;
					if(me->edit_mesh) {
						free_editMesh(me->edit_mesh);
						MEM_freeN(me->edit_mesh);
						me->edit_mesh= NULL;
					}
				}
				else if(ob->type==OB_ARMATURE) {
					ED_armature_edit_free(ob);
				}
				else if(ob->type==OB_FONT) {
					//			free_editText();
				}
				//		else if(ob->type==OB_MBALL) 
				//			BLI_freelistN(&editelems);
				//	free_editLatt();
				//	free_posebuf();		// XXX this is still a global...
			}
		}
		else if(sce->basact && sce->basact->object) {
			Object *ob= sce->basact->object;
			
			/* if weight-painting is on, free mesh octree data */
			if(ob->mode & OB_MODE_WEIGHT_PAINT) {
				mesh_octree_table(NULL, NULL, NULL, 'e');
				mesh_mirrtopo_table(NULL, 'e');
			}
		}
	}
	
}
Beispiel #3
0
/* frees all editmode stuff */
void ED_editors_exit(bContext *C)
{
	Main *bmain = CTX_data_main(C);
	Scene *sce;

	if (!bmain)
		return;
	
	/* frees all editmode undos */
	undo_editmode_clear();
	ED_undo_paint_free();
	
	for (sce = bmain->scene.first; sce; sce = sce->id.next) {
		if (sce->obedit) {
			Object *ob = sce->obedit;
		
			if (ob) {
				if (ob->type == OB_MESH) {
					Mesh *me = ob->data;
					if (me->edit_btmesh) {
						EDBM_mesh_free(me->edit_btmesh);
						MEM_freeN(me->edit_btmesh);
						me->edit_btmesh = NULL;
					}
				}
				else if (ob->type == OB_ARMATURE) {
					ED_armature_edit_free(ob->data);
				}
			}
		}
	}

	/* global in meshtools... */
	ED_mesh_mirror_spatial_table(NULL, NULL, NULL, 'e');
	ED_mesh_mirror_topo_table(NULL, 'e');
}
Beispiel #4
0
/* note: also check undo_history_exec() in bottom if you change notifiers */
static int ed_undo_step(bContext *C, int step, const char *undoname)
{
	wmWindowManager *wm = CTX_wm_manager(C);
	wmWindow *win = CTX_wm_window(C);
	Scene *scene = CTX_data_scene(C);
	Object *obedit = CTX_data_edit_object(C);
	Object *obact = CTX_data_active_object(C);
	ScrArea *sa = CTX_wm_area(C);

	/* undo during jobs are running can easily lead to freeing data using by jobs,
	 * or they can just lead to freezing job in some other cases */
	if (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY)) {
		return OPERATOR_CANCELLED;
	}

	/* grease pencil can be can be used in plenty of spaces, so check it first */
	if (ED_gpencil_session_active()) {
		return ED_undo_gpencil_step(C, step, undoname);
	}

	if (sa && (sa->spacetype == SPACE_IMAGE)) {
		SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
		
		if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
			if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname) && undoname) {
				if (U.uiflag & USER_GLOBALUNDO) {
					ED_viewport_render_kill_jobs(C, true);
					BKE_undo_name(C, undoname);
				}
			}
			
			WM_event_add_notifier(C, NC_WINDOW, NULL);
			return OPERATOR_FINISHED;
		}
	}

	if (sa && (sa->spacetype == SPACE_TEXT)) {
		ED_text_undo_step(C, step);
	}
	else if (obedit) {
		if (OB_TYPE_SUPPORT_EDITMODE(obedit->type)) {
			if (undoname)
				undo_editmode_name(C, undoname);
			else
				undo_editmode_step(C, step);
			
			WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
		}
	}
	else {
		/* Note: we used to do a fall-through here where if the
		 * mode-specific undo system had no more steps to undo (or
		 * redo), the global undo would run.
		 *
		 * That was inconsistent with editmode, and also makes for
		 * unecessarily tricky interaction with the other undo
		 * systems. */
		if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
			ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname);
		}
		else if (obact && obact->mode & OB_MODE_SCULPT) {
			ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname);
		}
		else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
			if (step == 1)
				PE_undo(scene);
			else
				PE_redo(scene);
		}
		else if (U.uiflag & USER_GLOBALUNDO) {
			// note python defines not valid here anymore.
			//#ifdef WITH_PYTHON
			// XXX		BPY_scripts_clear_pyobjects();
			//#endif
			
			/* for global undo/redo we should just clear the editmode stack */
			/* for example, texface stores image pointers */
			undo_editmode_clear();
			
			ED_viewport_render_kill_jobs(C, true);

			if (undoname)
				BKE_undo_name(C, undoname);
			else
				BKE_undo_step(C, step);

			scene = CTX_data_scene(C);
				
			WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
		}
	}
	
	WM_event_add_notifier(C, NC_WINDOW, NULL);

	if (win) {
		win->addmousemove = true;
	}
	
	return OPERATOR_FINISHED;
}