|  | @@ -1144,23 +1144,25 @@ int OPINV_Extrude(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 0;
 | 
	
		
			
				|  |  | +    tnsMeshObject* mo=root->Active; tnsShapeObject* so=mo; if(!mo) return 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if(!tnsMMeshAnySelected(mo)) return LA_FINISHED;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    MExtrudeExtra* ee=la_InitExtrude(mo);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    la_ExtrudeMakeDuplication(ee);
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | -    if(strSame(strGetArgumentString(a->ExtraInstructionsP,"duplicate_only"), "true")){
 | 
	
		
			
				|  |  | +    if(mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
 | 
	
		
			
				|  |  | +        if(!tnsMMeshAnySelected(mo)) return LA_FINISHED;
 | 
	
		
			
				|  |  | +        MExtrudeExtra* ee=la_InitExtrude(mo);
 | 
	
		
			
				|  |  | +        la_ExtrudeMakeDuplication(ee);
 | 
	
		
			
				|  |  | +        if(strSame(strGetArgumentString(a->ExtraInstructionsP,"duplicate_only"), "true")){
 | 
	
		
			
				|  |  | +            la_FinishExtrude(ee, 1);
 | 
	
		
			
				|  |  | +            if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB,0,0)) return LA_RUNNING; return LA_FINISHED;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        la_RemoveOriginalFaces(ee);
 | 
	
		
			
				|  |  | +        la_ReconnectFaces(ee);
 | 
	
		
			
				|  |  |          la_FinishExtrude(ee, 1);
 | 
	
		
			
				|  |  | -        if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB,0,0)) return LA_RUNNING; return LA_FINISHED;
 | 
	
		
			
				|  |  | +    }elif(so->Base.Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){
 | 
	
		
			
				|  |  | +        int duponly=strSame(strGetArgumentString(a->ExtraInstructionsP,"duplicate_only"), "true");
 | 
	
		
			
				|  |  | +        tnsShapeExtrudeSelected(so,duponly);
 | 
	
		
			
				|  |  | +    }else{
 | 
	
		
			
				|  |  | +        return LA_CANCELED;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    la_RemoveOriginalFaces(ee);
 | 
	
		
			
				|  |  | -    la_ReconnectFaces(ee);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    la_FinishExtrude(ee, 1);
 | 
	
		
			
				|  |  |      if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB,0,0)) return LA_RUNNING; return LA_FINISHED;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      return LA_FINISHED;
 | 
	
	
		
			
				|  | @@ -1235,6 +1237,15 @@ void la_DeleteFaces(tnsMeshObject* mo, int OnlyFaces){
 | 
	
		
			
				|  |  |          tnsMVert* mv; while(mv=lstPopPointer(&lv)){ tnsMMeshRemoveVertEdgeFace(mo,mv); }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +void la_DeletePoints(tnsShapeObject* so, int SplitShape){
 | 
	
		
			
				|  |  | +    for(tnsShape* s=so->Shapes.pFirst;s;s=s->Item.pNext){
 | 
	
		
			
				|  |  | +        tnsSPoint* NextSP; for(tnsSPoint* sp=s->Points.pFirst;sp;sp=NextSP){ NextSP=sp->Item.pNext;
 | 
	
		
			
				|  |  | +            if(!(sp->flags&TNS_MESH_FLAG_SELECTED)) continue;      
 | 
	
		
			
				|  |  | +            tnsShapeRemovePoint(so,s,sp,SplitShape);      
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    tnsShapeRefreshIndex(so);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  int la_DeleteSelectedObjectsRecursive(tnsObject* root){
 | 
	
		
			
				|  |  |      int any=0; for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){ if(!lip->p) continue;
 | 
	
		
			
				|  |  |          tnsObject* o=lip->p; la_DeleteSelectedObjectsRecursive(lip->p);
 | 
	
	
		
			
				|  | @@ -1242,17 +1253,17 @@ int la_DeleteSelectedObjectsRecursive(tnsObject* root){
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      return any;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +STRUCTURE(MDeleteData){
 | 
	
		
			
				|  |  | +    int _PAD;
 | 
	
		
			
				|  |  | +    int Context;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  |  int OPINV_Delete(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) return 0;
 | 
	
		
			
				|  |  | +    tnsMeshObject* mo=root->Active; tnsShapeObject* so=mo; if(!mo) return 0;
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    if(mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){
 | 
	
		
			
				|  |  | -        if(la_DeleteSelectedObjectsRecursive(root)){
 | 
	
		
			
				|  |  | -            laRecordInstanceDifferences(T->World, "tns_world"); laPushDifferences("Deleted objects", TNS_HINT_TRANSFORM); laNotifyUsers("tns.world");
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }else{
 | 
	
		
			
				|  |  | +    if(mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
 | 
	
		
			
				|  |  |          if(!tnsMMeshAnySelected(mo)) return LA_FINISHED;
 | 
	
		
			
				|  |  |          if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"vertices")){
 | 
	
		
			
				|  |  |              la_DeleteVertices(mo);
 | 
	
	
		
			
				|  | @@ -1263,23 +1274,43 @@ int OPINV_Delete(laOperator *a, laEvent *e){
 | 
	
		
			
				|  |  |          }elif(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"only_faces")){
 | 
	
		
			
				|  |  |              la_DeleteFaces(mo,1);
 | 
	
		
			
				|  |  |          }else{
 | 
	
		
			
				|  |  | -            laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e);
 | 
	
		
			
				|  |  | -            return LA_RUNNING;
 | 
	
		
			
				|  |  | +            MDeleteData* md=memAcquire(sizeof(MDeleteData)); a->CustomData=md; md->Context=TNS_OBJECT_MESH;
 | 
	
		
			
				|  |  | +            laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          tnsMMeshDeselectAll(mo);
 | 
	
		
			
				|  |  |          tnsMMeshRefreshIndex(mo);
 | 
	
		
			
				|  |  |          tnsInvalidateMeshBatch(mo);
 | 
	
		
			
				|  |  |          laRecordInstanceDifferences(mo, "tns_mesh_object"); laPushDifferences("Deleted primitives", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
 | 
	
		
			
				|  |  | +    }if(so->Base.Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){
 | 
	
		
			
				|  |  | +        if(!tnsShapeAnySelected(so)) return LA_FINISHED;
 | 
	
		
			
				|  |  | +        char* split=strGetArgumentString(a->ExtraInstructionsP, "split");
 | 
	
		
			
				|  |  | +        if(split){
 | 
	
		
			
				|  |  | +            int SplitShapes=strSame(split,"TRUE"); la_DeletePoints(so,SplitShapes);
 | 
	
		
			
				|  |  | +        }else{
 | 
	
		
			
				|  |  | +            MDeleteData* md=memAcquire(sizeof(MDeleteData)); a->CustomData=md; md->Context=TNS_OBJECT_SHAPE;
 | 
	
		
			
				|  |  | +            laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        laRecordInstanceDifferences(so, "tns_shape_object"); laPushDifferences("Deleted points", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
 | 
	
		
			
				|  |  | +    }else{
 | 
	
		
			
				|  |  | +        if(la_DeleteSelectedObjectsRecursive(root)){
 | 
	
		
			
				|  |  | +            laRecordInstanceDifferences(T->World, "tns_world"); laPushDifferences("Deleted objects", TNS_HINT_TRANSFORM); laNotifyUsers("tns.world");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      return LA_FINISHED;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  void laui_Delete(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
 | 
	
		
			
				|  |  | -    laColumn* c=laFirstColumn(uil);
 | 
	
		
			
				|  |  | -    laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=vertices;text=Vertices",0,0);
 | 
	
		
			
				|  |  | -    laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=edges;text=Edges",0,0);
 | 
	
		
			
				|  |  | -    laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=faces;text=Faces",0,0);
 | 
	
		
			
				|  |  | -    laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=only_faces;text=Only Faces",0,0);
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil); laUiItem* b;
 | 
	
		
			
				|  |  | +    b=laOnConditionThat(uil,c,laEqual(laPropExpression(actinst,"context"),laIntExpression(TNS_OBJECT_MESH)));{
 | 
	
		
			
				|  |  | +        laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=vertices;text=Vertices",0,0);
 | 
	
		
			
				|  |  | +        laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=edges;text=Edges",0,0);
 | 
	
		
			
				|  |  | +        laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=faces;text=Faces",0,0);
 | 
	
		
			
				|  |  | +        laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=only_faces;text=Only Faces",0,0);
 | 
	
		
			
				|  |  | +    }laEndCondition(uil,b);
 | 
	
		
			
				|  |  | +    b=laOnConditionThat(uil,c,laEqual(laPropExpression(actinst,"context"),laIntExpression(TNS_OBJECT_SHAPE)));{
 | 
	
		
			
				|  |  | +        laShowItemFull(uil,c,pp,"_this_M_delete",0,"split=FALSE;",0,0);
 | 
	
		
			
				|  |  | +        laShowItemFull(uil,c,pp,"_this_M_delete",0,"split=TRUE;text=Delet and Split",0,0);
 | 
	
		
			
				|  |  | +    }laEndCondition(uil,b);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  STRUCTURE(MIslandInfo){
 | 
	
	
		
			
				|  | @@ -1396,20 +1427,27 @@ 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;
 | 
	
		
			
				|  |  | +    tnsMeshObject* mo=root->Active; tnsShapeObject*so=mo;
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    if(!mo||mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
 | 
	
		
			
				|  |  | +    if(!mo){ return LA_CANCELED; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    MMakeData md={0};
 | 
	
		
			
				|  |  | -    la_GetSelectionIslands(mo,&md,ex->SelectMode);
 | 
	
		
			
				|  |  | -    int success=la_MakeFacesFromIslands(mo,&md); if(success){ tnsMMeshCalculateNormal(mo); }
 | 
	
		
			
				|  |  | -    la_ClearIslands(&md);
 | 
	
		
			
				|  |  | +    if(mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
 | 
	
		
			
				|  |  | +        MMakeData md={0};
 | 
	
		
			
				|  |  | +        la_GetSelectionIslands(mo,&md,ex->SelectMode);
 | 
	
		
			
				|  |  | +        int success=la_MakeFacesFromIslands(mo,&md); if(success){ tnsMMeshCalculateNormal(mo); }
 | 
	
		
			
				|  |  | +        la_ClearIslands(&md);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    tnsMMeshRefreshIndex(mo);
 | 
	
		
			
				|  |  | -    tnsMMeshEnsureSelection(mo,ex->SelectMode);
 | 
	
		
			
				|  |  | -    tnsInvalidateMeshBatch(mo);
 | 
	
		
			
				|  |  | -    if(laRecordInstanceDifferences(mo, "tns_mesh_object")) laPushDifferences("Make primitives", TNS_HINT_GEOMETRY);
 | 
	
		
			
				|  |  | -    laNotifyUsers("tns.world");
 | 
	
		
			
				|  |  | +        tnsMMeshRefreshIndex(mo);
 | 
	
		
			
				|  |  | +        tnsMMeshEnsureSelection(mo,ex->SelectMode);
 | 
	
		
			
				|  |  | +        tnsInvalidateMeshBatch(mo);
 | 
	
		
			
				|  |  | +        if(laRecordInstanceDifferences(mo, "tns_mesh_object")) laPushDifferences("Make primitives", TNS_HINT_GEOMETRY);
 | 
	
		
			
				|  |  | +        laNotifyUsers("tns.world");
 | 
	
		
			
				|  |  | +    }elif(so->Base.Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){
 | 
	
		
			
				|  |  | +        if(tnsShapeConnectSelected(so)){
 | 
	
		
			
				|  |  | +            laRecordInstanceDifferences(so, "tns_shape_object"); laPushDifferences("Connect shapes", TNS_HINT_GEOMETRY);
 | 
	
		
			
				|  |  | +            laNotifyUsers("tns.world");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  |      return LA_FINISHED;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -1566,9 +1604,10 @@ int OPINV_Duplicate(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 LA_CANCELED;
 | 
	
		
			
				|  |  | -    tnsMeshObject* mo=root->Active; int ran=0;
 | 
	
		
			
				|  |  | +    tnsMeshObject* mo=root->Active; tnsShapeObject* so=mo; int ran=0;
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    if(!mo || mo->Mode==TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
 | 
	
		
			
				|  |  | +    if(!mo || (mo->Base.Type==TNS_OBJECT_MESH&&mo->Mode==TNS_MESH_EDIT_MODE)||
 | 
	
		
			
				|  |  | +        (so->Base.Type==TNS_OBJECT_SHAPE&&so->Mode==TNS_MESH_EDIT_MODE)){ return LA_CANCELED; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      laListHandle pending={0}; la_PopulateSelectedObjects(root,&pending,0);
 | 
	
		
			
				|  |  |      tnsMeshObject* o; tnsMeshObject* no; laListItemPointer* lip;
 | 
	
	
		
			
				|  | @@ -1971,12 +2010,14 @@ void la_RegisterModellingOperators(){
 | 
	
		
			
				|  |  |      at=laCreateOperatorType("M_unparent", "Unparent", "Unparent selected objects", 0, 0, 0, OPINV_MakeParent, OPMOD_FinishOnData, 0, 0);
 | 
	
		
			
				|  |  |      at->UiDefine = laui_Unparent;
 | 
	
		
			
				|  |  |      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=laCreateOperatorType("M_delete", "Delete", "Delete parts of the mesh", 0, 0, OPEXT_FreeUserData, OPINV_Delete, OPMOD_FinishOnData, 0, 0);
 | 
	
		
			
				|  |  | +    pc = laDefineOperatorProps(at, 1);
 | 
	
		
			
				|  |  | +    laAddIntProperty(pc,"context","Context","Delete menu context",0,0,0,0,0,0,0,0,offsetof(MDeleteData,Context),0,0,0,0,0,0,0,0,0,0,0);
 | 
	
		
			
				|  |  |      at->UiDefine=laui_Delete;
 | 
	
		
			
				|  |  |      laCreateOperatorType("M_make", "Make", "Make mesh primitive from selected ones", 0, 0, 0, OPINV_Make, 0, 0, 0);
 | 
	
		
			
				|  |  |      laCreateOperatorType("M_subdiv", "Subdiv", "Subdivide edges", 0, 0, 0, OPINV_Subdiv, 0, 0, 0);
 | 
	
		
			
				|  |  | -    at=laCreateOperatorType("M_add", "Add", "Add mesh or primitives", 0, 0, 0, OPINV_Add, OPMOD_FinishOnData, 0, 0);
 | 
	
		
			
				|  |  | -    at->UiDefine=laui_Add; pc = laDefineOperatorProps(at, 2);
 | 
	
		
			
				|  |  | +    at=laCreateOperatorType("M_add", "Add", "Add mesh or primitives", 0, 0, OPEXT_FreeUserData, OPINV_Add, OPMOD_FinishOnData, 0, 0);
 | 
	
		
			
				|  |  | +    at->UiDefine=laui_Add; pc = laDefineOperatorProps(at, 1);
 | 
	
		
			
				|  |  |      p=laAddEnumProperty(pc,"context","Context","Context of adding",0,0,0,0,0,offsetof(laObjectAddData,Context),0,0,0,0,0,0,0,0,0,0);
 | 
	
		
			
				|  |  |      laAddEnumItemAs(p,"OBJECT","Object","Object context",LA_ADD_CTX_OBJECT,0);
 | 
	
		
			
				|  |  |      laAddEnumItemAs(p,"MESH","Mesh","Mesh context",LA_ADD_CTX_MESH,0);
 |