|  | @@ -142,9 +142,9 @@ int la_SelectGetClosest(MSelectData* sd, int uix, int uiy, int radius){
 | 
	
		
			
				|  |  |          for(int j=0;j<w;j++){
 | 
	
		
			
				|  |  |              uint8_t* p=&buf[(i*w+j)*4]; int id=(p[0])|(p[1]<<8)|(p[2]<<16);
 | 
	
		
			
				|  |  |              if(id && (d=tnsDistIdv2(i,j, radius, radius))<MinD ){ MinD=d; MinID=id; }
 | 
	
		
			
				|  |  | -            printf("%d ",buf[(i*w+j)*4]);
 | 
	
		
			
				|  |  | +            //printf("%d ",buf[(i*w+j)*4]);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        printf("\n");
 | 
	
		
			
				|  |  | +        //printf("\n");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      free(buf);
 | 
	
		
			
				|  |  |      return MinID;
 | 
	
	
		
			
				|  | @@ -357,7 +357,7 @@ void la_GetTransformCenter2D(MTransformData* td){
 | 
	
		
			
				|  |  |  int la_AddTransformObjectsRecursive(MTransformData* td, tnsObject*root){
 | 
	
		
			
				|  |  |      int any=0; for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
 | 
	
		
			
				|  |  |          tnsObject* o=lip->p; if(o->ChildObjects.pFirst) any+=la_AddTransformObjectsRecursive(td,o);
 | 
	
		
			
				|  |  | -        if(!o->Flags&TNS_OBJECT_FLAGS_SELECTED) continue;
 | 
	
		
			
				|  |  | +        if(!(o->Flags&TNS_OBJECT_FLAGS_SELECTED)) continue;
 | 
	
		
			
				|  |  |          arrEnsureLength(&td->Originals, td->next, &td->max, sizeof(MTOrigObject));
 | 
	
		
			
				|  |  |          MTOrigObject* to=arrElement(td->Originals, td->next, sizeof(MTOrigObject)); td->next++; to->o=o;
 | 
	
		
			
				|  |  |          memcpy(to->Global, o->GlobalTransform, sizeof(tnsMatrix44d));
 | 
	
	
		
			
				|  | @@ -379,13 +379,15 @@ int la_PopulateTransformVerticies(MTransformData* td, tnsMeshObject* mo){
 | 
	
		
			
				|  |  |      arrEnsureLength(&td->Originals, 0, &td->max, sizeof(MTOrigMVert));
 | 
	
		
			
				|  |  |      tnsInverse44d(td->obmatinv, mo->Base.GlobalTransform);
 | 
	
		
			
				|  |  |      for(tnsMVert* mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){
 | 
	
		
			
				|  |  | -        if(!mv->flags&TNS_MESH_FLAG_SELECTED) continue;
 | 
	
		
			
				|  |  | +        if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
 | 
	
		
			
				|  |  | +        printf("v %d ",mv->i);
 | 
	
		
			
				|  |  |          arrEnsureLength(&td->Originals, td->next, &td->max, sizeof(MTOrigMVert));
 | 
	
		
			
				|  |  |          MTOrigMVert* to=arrElement(td->Originals, td->next, sizeof(MTOrigMVert)); td->next++; to->mv=mv;
 | 
	
		
			
				|  |  |          tnsApplyTransform43d(to->p, mo->Base.GlobalTransform, mv->p);
 | 
	
		
			
				|  |  |          memcpy(to->origp, mv->p, sizeof(tnsVector3d)); any++;
 | 
	
		
			
				|  |  |          tnsVectorAccum3d(td->TCenter,to->p);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    printf(" [totmv %d]\n",mo->totmv);
 | 
	
		
			
				|  |  |      tnsVectorMultiSelf3d(td->TCenter, 1.0f/any);
 | 
	
		
			
				|  |  |      la_GetTransformCenter2D(td);
 | 
	
		
			
				|  |  |      return any;
 | 
	
	
		
			
				|  | @@ -597,14 +599,14 @@ int OPMOD_Transformation(laOperator *a, laEvent *e){
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  int la_ParentableRecursive(tnsObject* root, tnsObject* parent){
 | 
	
		
			
				|  |  |      for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
 | 
	
		
			
				|  |  | -        tnsObject* o=lip->p; if(!o || !o->Flags&TNS_OBJECT_FLAGS_SELECTED || o==parent) continue;
 | 
	
		
			
				|  |  | +        tnsObject* o=lip->p; if((!o) || (!(o->Flags&TNS_OBJECT_FLAGS_SELECTED)) || (o==parent)) continue;
 | 
	
		
			
				|  |  |          if(!tnsCheckParentable(o,parent)) return 0;
 | 
	
		
			
				|  |  |          if(!la_ParentableRecursive(o,parent)) return 0;
 | 
	
		
			
				|  |  |      }return 1;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  void la_MakeParentExecuteRecursive(tnsObject* root, tnsObject* parent, int Unparent, int KeepTransform){
 | 
	
		
			
				|  |  |      for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
 | 
	
		
			
				|  |  | -        tnsObject* o=lip->p; if(!o || !o->Flags&TNS_OBJECT_FLAGS_SELECTED) continue;
 | 
	
		
			
				|  |  | +        tnsObject* o=lip->p; if((!o) || (!(o->Flags&TNS_OBJECT_FLAGS_SELECTED))) continue;
 | 
	
		
			
				|  |  |          if(Unparent) tnsUnparentObject(o, KeepTransform);
 | 
	
		
			
				|  |  |          else tnsParentObject(o, parent, KeepTransform);
 | 
	
		
			
				|  |  |          la_MakeParentExecuteRecursive(o,parent,Unparent,KeepTransform);
 | 
	
	
		
			
				|  | @@ -623,7 +625,7 @@ int OPINV_MakeParent(laOperator *a, laEvent *e){
 | 
	
		
			
				|  |  |      if(strSame(action,"unparent")){  Unparent=1; }
 | 
	
		
			
				|  |  |      if(strSame(keep,"false")){ KeepTransform=0; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if(!Unparent){ if(!mo || !mo->Flags&TNS_OBJECT_FLAGS_SELECTED) return LA_FINISHED; 
 | 
	
		
			
				|  |  | +    if(!Unparent){ if((!mo) || (!(mo->Flags&TNS_OBJECT_FLAGS_SELECTED))) return LA_FINISHED; 
 | 
	
		
			
				|  |  |          if(!la_ParentableRecursive(root,mo)) laEnableMessagePanel(0,0,"It didn't work","There are loops in parenting",e->x,e->y,0,e); return LA_FINISHED;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -648,7 +650,7 @@ void laui_Unparent(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  int la_ClearTransformationRecursive(tnsObject* root, int global,int location,int rotation,int scale){
 | 
	
		
			
				|  |  |      int any=0; for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
 | 
	
		
			
				|  |  | -        tnsObject* o=lip->p; if(!o->Flags&TNS_OBJECT_FLAGS_SELECTED) continue;
 | 
	
		
			
				|  |  | +        tnsObject* o=lip->p; if(!(o->Flags&TNS_OBJECT_FLAGS_SELECTED)) continue;
 | 
	
		
			
				|  |  |          if(location){
 | 
	
		
			
				|  |  |              if(global){ o->GLocation[0]=o->GLocation[1]=o->GLocation[2]=0;}
 | 
	
		
			
				|  |  |              else{ o->Location[0]=o->Location[1]=o->Location[2]=0; }
 | 
	
	
		
			
				|  | @@ -922,6 +924,133 @@ void laui_Delete(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *e
 | 
	
		
			
				|  |  |      laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=only_faces;text=Only Faces",0,0);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +STRUCTURE(MIslandInfo){
 | 
	
		
			
				|  |  | +    laListItem Item;
 | 
	
		
			
				|  |  | +    laListHandle v,e,f;int numv,nume,numf;
 | 
	
		
			
				|  |  | +    int Paired,HasBranches;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +STRUCTURE(MMakeData){
 | 
	
		
			
				|  |  | +    laListHandle Islands; int NumIslands;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define M_SHOULD_INCL_PRIM(m)\
 | 
	
		
			
				|  |  | +    ((!(m->flags&TNS_MESH_FLAG_PICKED)) && (m->flags&TNS_MESH_FLAG_SELECTED))
 | 
	
		
			
				|  |  | +#define M_SHOULD_USE_OE(oe,sf)\
 | 
	
		
			
				|  |  | +    (((!oe->fl)&&(oe->fr!=sf))||((!oe->fr)&&(oe->fl!=sf)))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +MIslandInfo* la_NewMIsland(MMakeData* md){ MIslandInfo* ii=memAcquireSimple(sizeof(MIslandInfo)); lstAppendItem(&md->Islands, ii); md->NumIslands++; return ii; }
 | 
	
		
			
				|  |  | +void la_FillIslandFromVert(MIslandInfo* ii, tnsMVert* mv, int SelectMode){
 | 
	
		
			
				|  |  | +    mv->flags|=TNS_MESH_FLAG_PICKED; lstAppendPointer(&ii->v,mv); ii->numv++; int connections=0;
 | 
	
		
			
				|  |  | +    for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){ tnsMEdge* oe=lip->p; tnsMVert* ov=tnsMMeshEdgeAnotherVert(oe,mv);
 | 
	
		
			
				|  |  | +        if(ov->flags&TNS_MESH_FLAG_SELECTED) connections++; else continue;
 | 
	
		
			
				|  |  | +        if(SelectMode==LA_CANVAS_SELECT_MODE_EDGES){ if(!(oe->flags&TNS_MESH_FLAG_SELECTED)) continue; }
 | 
	
		
			
				|  |  | +        if(M_SHOULD_INCL_PRIM(ov)){ la_FillIslandFromVert(ii,ov,SelectMode); } else { continue; }
 | 
	
		
			
				|  |  | +        if(M_SHOULD_INCL_PRIM(oe)){ lstAppendPointer(&ii->e,oe); ii->nume++; oe->flags|=TNS_MESH_FLAG_PICKED; }
 | 
	
		
			
				|  |  | +        if(oe->fl&&M_SHOULD_INCL_PRIM(oe->fl)){ lstAppendPointer(&ii->f,oe->fl); ii->numf++; oe->fl->flags|=TNS_MESH_FLAG_PICKED; }
 | 
	
		
			
				|  |  | +        if(oe->fr&&M_SHOULD_INCL_PRIM(oe->fr)){ lstAppendPointer(&ii->f,oe->fr); ii->numf++; oe->fr->flags|=TNS_MESH_FLAG_PICKED; }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if(connections>2) ii->HasBranches=1;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void la_GetSelectionIslands(tnsMeshObject* mo, MMakeData* md, int SelectMode){
 | 
	
		
			
				|  |  | +    tnsMMeshClearPickedFlags(mo);
 | 
	
		
			
				|  |  | +    for(tnsMVert* mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){
 | 
	
		
			
				|  |  | +        if(M_SHOULD_INCL_PRIM(mv)){ MIslandInfo* ii=la_NewMIsland(md); la_FillIslandFromVert(ii,mv,SelectMode); }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void la_ClearIslands(MMakeData* md){ MIslandInfo* ii; while(ii=lstPopItem(&md->Islands)){ while(lstPopPointer(&ii->v)); memFree(ii); } }
 | 
	
		
			
				|  |  | +tnsMFace* la_MakeFacesFrom1Vert(tnsMeshObject* mo, tnsMVert* mv){
 | 
	
		
			
				|  |  | +    tnsMEdge* oe1=0,*oe2=0; tnsMVert* ov1,*ov2;
 | 
	
		
			
				|  |  | +    for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){
 | 
	
		
			
				|  |  | +        tnsMEdge* oe=lip->p; if(oe->flags&TNS_MESH_FLAG_SELECTED) continue; if((!oe->fl)||(!oe->fr)){ if(!oe1)oe1=oe;elif(!oe2)oe2=oe;else return 0; /* more than 2 empty edges connected */ }
 | 
	
		
			
				|  |  | +    } if(!oe1||!oe2) return 0;
 | 
	
		
			
				|  |  | +    ov1=tnsMMeshEdgeAnotherVert(oe1,mv); ov2=tnsMMeshEdgeAnotherVert(oe2,mv);
 | 
	
		
			
				|  |  | +    laListHandle vl={0}; lstAppendPointer(&vl,ov1); lstAppendPointer(&vl,mv); lstAppendPointer(&vl,ov2);
 | 
	
		
			
				|  |  | +    tnsMFace* f=tnsMMeshMakeFaceN(mo, 3, &vl); while(lstPopPointer(&vl)); return f;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +tnsMFace* la_MakeFacesFrom2Verts(tnsMeshObject* mo, tnsMVert* mv1, tnsMVert* mv2){
 | 
	
		
			
				|  |  | +    tnsMEdge* oe1=0,*oe2=0; tnsMVert* ov1,*ov2; tnsMFace* sf=0;
 | 
	
		
			
				|  |  | +    tnsMEdge* se=tnsMMeshVertShareEdge(mv1,mv2);  if(se->fl && se->fr) return 0; sf=se->fl?se->fl:se->fr;
 | 
	
		
			
				|  |  | +    for(laListItemPointer* lip=mv1->elink.pFirst;lip;lip=lip->pNext){
 | 
	
		
			
				|  |  | +        tnsMEdge* oe=lip->p; if(oe->flags&TNS_MESH_FLAG_SELECTED) continue; if(M_SHOULD_USE_OE(oe,sf)){ if(!oe1)oe1=oe;else return 0; /* more than 1 empty edge connected */ }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    for(laListItemPointer* lip=mv2->elink.pFirst;lip;lip=lip->pNext){
 | 
	
		
			
				|  |  | +        tnsMEdge* oe=lip->p; if(oe->flags&TNS_MESH_FLAG_SELECTED) continue; if(M_SHOULD_USE_OE(oe,sf)){ if(!oe2)oe2=oe;else return 0; /* more than 1 empty edge connected */ }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if(!oe1||!oe2) return 0;
 | 
	
		
			
				|  |  | +    ov1=tnsMMeshEdgeAnotherVert(oe1,mv1); ov2=tnsMMeshEdgeAnotherVert(oe2,mv2);
 | 
	
		
			
				|  |  | +    ov1->flags|=TNS_MESH_FLAG_SELECTED;ov2->flags|=TNS_MESH_FLAG_SELECTED; mv1->flags&=(~TNS_MESH_FLAG_SELECTED);mv2->flags&=(~TNS_MESH_FLAG_SELECTED);
 | 
	
		
			
				|  |  | +    laListHandle vl={0}; lstAppendPointer(&vl,ov1); lstAppendPointer(&vl,mv1); lstAppendPointer(&vl,mv2); lstAppendPointer(&vl,ov2);
 | 
	
		
			
				|  |  | +    tnsMFace* f=tnsMMeshMakeFaceN(mo, 4, &vl); while(lstPopPointer(&vl)); return f;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int la_IsEndingVert(tnsMVert* mv){
 | 
	
		
			
				|  |  | +    int sel=0; for(laListItemPointer*lip=mv->elink.pFirst;lip;lip=lip->pNext){ tnsMEdge* me=lip->p;
 | 
	
		
			
				|  |  | +        if(tnsMMeshEdgeAnotherVert(me,mv)->flags&TNS_MESH_FLAG_SELECTED){ sel++; if(sel>1) return 0; }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if(sel==1) return 1; return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void la_EnsureIslandVertsSequence(MIslandInfo* ii){
 | 
	
		
			
				|  |  | +    laListHandle l={0}; tnsMVert* startv=((laListItemPointer*)ii->v.pFirst)->p; laListItemPointer* nextlip;
 | 
	
		
			
				|  |  | +    for(laListItemPointer*lip=ii->v.pFirst;lip;lip=lip->pNext){ if(la_IsEndingVert(lip->p)){ startv=lip->p; break; } } // otherwise a loop, doesn't matter.
 | 
	
		
			
				|  |  | +    lstRemovePointer(&ii->v, startv); lstAppendPointer(&l, startv);
 | 
	
		
			
				|  |  | +    while(ii->v.pFirst){
 | 
	
		
			
				|  |  | +        for(laListItemPointer*lip=ii->v.pFirst;lip;lip=lip->pNext){ nextlip=lip->pNext;
 | 
	
		
			
				|  |  | +            if(tnsMMeshVertShareEdge(startv, lip->p)){ startv=lip->p; lstRemoveItem(&ii->v,lip); lstAppendItem(&l, lip); break; }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    memcpy(&ii->v, &l, sizeof(laListHandle));
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +MIslandInfo* la_GetNeighborIsland(tnsMVert* from, MMakeData* md){
 | 
	
		
			
				|  |  | +    int found=0; real dist=1e10; MIslandInfo* rii=0; for(MIslandInfo* ii=md->Islands.pFirst;ii;ii=ii->Item.pNext){ if(ii->Paired) continue;
 | 
	
		
			
				|  |  | +        found=1; tnsMVert* mv1=((laListItemPointer*)ii->v.pFirst)->p,*mv2=((laListItemPointer*)ii->v.pLast)->p;
 | 
	
		
			
				|  |  | +        real d1=tnsDist3dv(mv1->p, from->p),d2=tnsDist3dv(mv2->p, from->p);
 | 
	
		
			
				|  |  | +        if(d2<d1 && d2<dist){ lstReverse(&ii->v); } if(d1<dist || d2<dist){ rii=ii; }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if(rii) rii->Paired=1;
 | 
	
		
			
				|  |  | +    return rii;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int la_MakeFacesFromIslands(tnsMeshObject* mo, MMakeData* md){
 | 
	
		
			
				|  |  | +    int success=0;
 | 
	
		
			
				|  |  | +    if(!md->Islands.pFirst) return 0;
 | 
	
		
			
				|  |  | +    if(md->Islands.pFirst==md->Islands.pLast){
 | 
	
		
			
				|  |  | +        MIslandInfo* ii=md->Islands.pFirst; if(ii->HasBranches) return 0;
 | 
	
		
			
				|  |  | +        if(ii->numv==1){ laListItemPointer*lip=ii->v.pFirst; if(la_MakeFacesFrom1Vert(mo,lip->p)) success++; }
 | 
	
		
			
				|  |  | +        elif(ii->numv==2){ laListItemPointer*lip=ii->v.pFirst,*lip2=ii->v.pLast; if(la_MakeFacesFrom2Verts(mo,lip->p, lip2->p)) success++; }
 | 
	
		
			
				|  |  | +        else{ la_EnsureIslandVertsSequence(ii); if(tnsMMeshMakeFaceN(mo, ii->numv, &ii->v)) success++; }
 | 
	
		
			
				|  |  | +    }else{
 | 
	
		
			
				|  |  | +        for(MIslandInfo* ii=md->Islands.pFirst;ii;ii=ii->Item.pNext){ if(ii->HasBranches) return 0; la_EnsureIslandVertsSequence(ii); }
 | 
	
		
			
				|  |  | +        laListHandle final={0}; int vcount=0;
 | 
	
		
			
				|  |  | +        MIslandInfo* ii=md->Islands.pFirst; ii->Paired=1; for(laListItemPointer* lip=ii->v.pFirst;lip;lip=lip->pNext){ lstAppendPointer(&final, lip->p); vcount++; }
 | 
	
		
			
				|  |  | +        while((ii=la_GetNeighborIsland(((laListItemPointer*)ii->v.pLast)->p, md))){
 | 
	
		
			
				|  |  | +            for(laListItemPointer* lip=ii->v.pFirst;lip;lip=lip->pNext){ lstAppendPointer(&final, lip->p); vcount++; }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if(tnsMMeshMakeFaceN(mo,vcount,&final)) success++;
 | 
	
		
			
				|  |  | +        while(lstPopPointer(&final));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return success;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int OPINV_Make(laOperator *a, laEvent *e){
 | 
	
		
			
				|  |  | +    if(!a->This || !a->This->EndInstance){ return 0; }
 | 
	
		
			
				|  |  | +    laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
 | 
	
		
			
				|  |  | +    tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
 | 
	
		
			
				|  |  | +    tnsMeshObject* mo=root->Active;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    if(mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    MMakeData md={0};
 | 
	
		
			
				|  |  | +    la_GetSelectionIslands(mo,&md,ex->SelectMode);
 | 
	
		
			
				|  |  | +    int success=la_MakeFacesFromIslands(mo,&md);
 | 
	
		
			
				|  |  | +    la_ClearIslands(&md);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //tnsMMeshDeselectAll(mo);
 | 
	
		
			
				|  |  | +    tnsMMeshRefreshIndex(mo);
 | 
	
		
			
				|  |  | +    tnsMMeshEnsureSelection(mo,ex->SelectMode);
 | 
	
		
			
				|  |  | +    tnsInvaliateMeshBatch(mo);
 | 
	
		
			
				|  |  | +    if(laRecordInstanceDifferences(mo, "tns_mesh_object")) laPushDifferences("Make primitives", TNS_HINT_GEOMETRY);
 | 
	
		
			
				|  |  | +    laNotifyUsers("tns.world");
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    return LA_FINISHED;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void la_RegisterModellingOperators(){
 | 
	
		
			
				|  |  |      laPropContainer *pc; laProp *p;
 | 
	
		
			
				|  |  |      laOperatorType *at;
 | 
	
	
		
			
				|  | @@ -940,5 +1069,6 @@ void la_RegisterModellingOperators(){
 | 
	
		
			
				|  |  |      laCreateOperatorType("M_extrude", "Extrude", "Extrude parts of the mesh", 0, 0, 0, OPINV_Extrude, OPMOD_Transformation, 0, 0);
 | 
	
		
			
				|  |  |      at=laCreateOperatorType("M_delete", "Delete", "Delete parts of the mesh", 0, 0, 0, OPINV_Delete, OPMOD_FinishOnData, 0, 0);
 | 
	
		
			
				|  |  |      at->UiDefine=laui_Delete;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +    laCreateOperatorType("M_make", "Make", "Make mesh primitive from selected ones", 0, 0, 0, OPINV_Make, 0, 0, 0);
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  |  }
 |