*/}}
Browse Source

Ring & band selection.

YimingWu 1 year ago
parent
commit
d0cac9d85e
4 changed files with 82 additions and 9 deletions
  1. 1 0
      la_tns.h
  2. 63 0
      la_tns_mesh.c
  3. 13 7
      resources/la_modelling.c
  4. 5 2
      resources/la_widgets_viewers.c

+ 1 - 0
la_tns.h

@@ -1215,6 +1215,7 @@ void tnsMMeshSelectEdge(tnsMeshObject* mo, tnsMEdge* me, int select, int toggle)
 void tnsMMeshEnsureSelectionFromVerts(tnsMeshObject* mo);
 void tnsMMeshEnsureSelectionFromEdges(tnsMeshObject* mo);
 void tnsMMeshEnsureSelection(tnsMeshObject* mo, int SelectMode);
+int tnsMMeshSelectRingBandFrom(tnsMeshObject* mo, tnsMEdge* me, int ring_band, int select, int toggle);
 
 void tnsInvalidateMeshBatch(tnsMeshObject* mo);
 void tnsRegenerateMeshBatch(tnsMeshObject* mo);

+ 63 - 0
la_tns_mesh.c

@@ -651,6 +651,69 @@ void tnsMMeshEnsureSelection(tnsMeshObject* mo, int SelectMode){
     if(SelectMode==LA_CANVAS_SELECT_MODE_VERTS){ tnsMMeshEnsureSelectionFromVerts(mo); }
     elif(SelectMode==LA_CANVAS_SELECT_MODE_EDGES){ tnsMMeshEnsureSelectionFromEdges(mo); }
 }
+tnsMEdge* tnsMMeshGetRingEdge(tnsMEdge* me, int from_right){
+    tnsMEdge* candidate=0; tnsMVert* VL=from_right?me->vr:me->vl, *VR=from_right?me->vl:me->vr;
+    for(laListItemPointer* lip=VL->elink.pFirst;lip;lip=lip->pNext){
+        tnsMEdge* te=lip->p; if(te==me || (te->flags&TNS_MESH_FLAG_PICKED)){ continue; }
+        if((!te->fl) || (!te->fr)){ candidate=te; break; }
+    }
+    if(candidate){ candidate->flags|=TNS_MESH_FLAG_PICKED; return candidate; }
+    if(lstCountElements(&VL->elink)!=4) return 0;
+    tnsMFace* f1=0,*f2=0;
+    for(laListItemPointer* lip=VL->elink.pFirst;lip;lip=lip->pNext){
+        tnsMEdge* te=lip->p; if(te==me || (te->flags&TNS_MESH_FLAG_PICKED)){ continue; }
+        if(tnsMMeshFaceHasVert(te->fl,VR) || tnsMMeshFaceHasVert(te->fr,VR)){ continue; }
+        else{ te->flags|=TNS_MESH_FLAG_PICKED; return te; }
+    }
+    return 0;
+}
+void tnsMMeshExpandRingList(tnsMeshObject* mo, tnsMEdge* me, laListHandle* lst){
+    tnsMEdge* el,*er;
+    int flc=0,frc=0; if(me->fl) flc=me->fl->looplen; if(me->fr) frc=me->fr->looplen;
+    if(TNS_MAX2(flc,frc)>4){
+        if(flc>frc){ for(laListItemPointer* lip=me->fl->l.pFirst;lip;lip=lip->pNext){ lstAppendPointer(lst,lip->p); } return; }
+        elif(flc<frc){ for(laListItemPointer* lip=me->fr->l.pFirst;lip;lip=lip->pNext){ lstAppendPointer(lst,lip->p); } return; }
+    }
+    if(el=tnsMMeshGetRingEdge(me,0)){ lstAppendPointer(lst,el); tnsMMeshExpandRingList(mo,el,lst); }
+    if(er=tnsMMeshGetRingEdge(me,1)){ lstAppendPointer(lst,er); tnsMMeshExpandRingList(mo,er,lst); }
+}
+tnsMEdge* tnsMMeshGetBandEdge(tnsMEdge* me, int from_right){
+    tnsMFace* FL=from_right?me->fl:me->fr;
+    if(FL->looplen!=4){ return 0;}
+    for(laListItemPointer* lip=FL->l.pFirst;lip;lip=lip->pNext){
+        tnsMEdge* te=lip->p; if((!(te->flags&TNS_MESH_FLAG_PICKED)) && (!tnsMMeshEdgeShareVert(te,me))){
+            te->flags|=TNS_MESH_FLAG_PICKED; return te;
+        }
+    }
+    return 0;
+}
+void tnsMMeshExpandBandList(tnsMeshObject* mo, tnsMEdge* me, laListHandle* lst){
+    tnsMEdge* el,*er;
+    if(el=tnsMMeshGetBandEdge(me,0)){ lstAppendPointer(lst,el); tnsMMeshExpandBandList(mo,el,lst); }
+    if(er=tnsMMeshGetBandEdge(me,1)){ lstAppendPointer(lst,er); tnsMMeshExpandBandList(mo,er,lst); }
+}
+int tnsMMeshSelectRingBandFrom(tnsMeshObject* mo, tnsMEdge* me, int ring_band, int select, int toggle){
+    if(!ring_band) return 0;
+    tnsMMeshClearExtraFlags(mo);
+    laListHandle lst={0}; lstAppendPointer(&lst,me); me->flags|=TNS_MESH_FLAG_PICKED;
+    if(ring_band==1) tnsMMeshExpandRingList(mo,me,&lst);
+    elif(ring_band==2) tnsMMeshExpandBandList(mo,me,&lst);
+    if(lst.pFirst==lst.pLast){ while(lstPopPointer(&lst)); return 0; }
+    int has_idle=0;
+    if(toggle){
+        for(laListItemPointer* lip=lst.pFirst;lip;lip=lip->pNext){
+            tnsMEdge* te=lip->p; if(te!=me && (!(te->flags&TNS_MESH_FLAG_SELECTED))) has_idle=1;
+            if(has_idle){ break; }
+        }
+        if(has_idle){ select=1; }else{ select=0; }
+    }
+    for(laListItemPointer* lip=lst.pFirst;lip;lip=lip->pNext){
+        tnsMEdge* te=lip->p;
+        if(select){ te->flags|=TNS_MESH_FLAG_SELECTED; te->vl->flags|=TNS_MESH_FLAG_SELECTED; te->vr->flags|=TNS_MESH_FLAG_SELECTED; }
+        else{ te->flags&=(~TNS_MESH_FLAG_SELECTED); te->vl->flags&=(~TNS_MESH_FLAG_SELECTED); te->vr->flags&=(~TNS_MESH_FLAG_SELECTED); }
+    }
+    while(lstPopPointer(&lst)); return 1;
+}
 
 tnsMeshObject *tnsCreateMeshEmpty(tnsObject *under, char *Name, real AtX, real AtY, real AtZ){
     tnsMeshObject *mo = memAcquireHyper(sizeof(tnsMeshObject));

+ 13 - 7
resources/la_modelling.c

@@ -286,7 +286,7 @@ int OPINV_Select(laOperator *a, laEvent *e){
     tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
     tnsMeshObject* mo=root->Active;
 
-    int is_geo=0;
+    int is_geo=0, SelectMode=ex->SelectMode, ring_band=0;
     if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "toggle")){
         if(mo && mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
             if(tnsMMeshAnySelected(mo)) tnsMMeshDeselectAll(mo); else tnsMMeshSelectAll(mo);
@@ -297,6 +297,9 @@ int OPINV_Select(laOperator *a, laEvent *e){
         laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world", "Toggle selection",is_geo?TNS_HINT_GEOMETRY:TNS_HINT_TRANSFORM);
         return LA_FINISHED;
     }
+    int spk=e->SpecialKeyBit & (LA_KEY_CTRL|LA_KEY_ALT);
+    if(spk==LA_KEY_ALT){ ring_band=1; SelectMode=LA_CANVAS_SELECT_MODE_EDGES; }
+    elif(spk==(LA_KEY_CTRL|LA_KEY_ALT)){ ring_band=2; SelectMode=LA_CANVAS_SELECT_MODE_EDGES; }
     
     MSelectData* sd=la_InitSelectData(ex->OffScr->pColor[0]->Width, ex->OffScr->pColor[0]->Height, c);
 
@@ -304,15 +307,18 @@ int OPINV_Select(laOperator *a, laEvent *e){
     int Append=e->SpecialKeyBit&LA_KEY_SHIFT; if(Append) DeselectAll=0;
     
     if(mo && mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
-        la_PopulateSelectDataPrimitives(sd, mo, ex->ViewingCamera, ex->SelectMode);
+        la_PopulateSelectDataPrimitives(sd, mo, ex->ViewingCamera, SelectMode);
         if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "box")){
             MSelectExtra* se=memAcquire(sizeof(MSelectExtra));
             ex->OnX=e->x; ex->OnX=e->y;
             a->CustomData=se; se->sd=sd; se->Mode=LA_SELECT_MODE_BOX; se->mo=mo; se->cam=c; ex->DrawCursor=1; se->root=root; return LA_RUNNING;
         }
         int elemtype,id=la_SelectGetClosest(sd, e->x-ui->L, e->y-ui->U, LA_RH,&elemtype)-1;
-        void* p=la_SelectGetRef(sd,id,elemtype); printf("%d %d\n",id,elemtype);
-        la_DoMeshSelect(mo, p, ex->SelectMode, DeselectAll, 1, 1); tnsMMeshEnsureSelection(mo,ex->SelectMode);
+        void* p=la_SelectGetRef(sd,id,elemtype);
+        la_DoMeshSelect(mo, p, SelectMode, DeselectAll, 1, 1); tnsMMeshEnsureSelection(mo,ex->SelectMode);
+        if(ring_band && p){
+            tnsMMeshSelectRingBandFrom(mo,p,ring_band,1,Append); tnsMMeshEnsureSelection(mo,ex->SelectMode);
+        }
         tnsInvalidateMeshBatch(mo);
         laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Mesh selection",TNS_HINT_GEOMETRY);
     }else{
@@ -322,7 +328,7 @@ int OPINV_Select(laOperator *a, laEvent *e){
             ex->OnX=e->x; ex->OnX=e->y;
             a->CustomData=se; se->sd=sd; se->Mode=LA_SELECT_MODE_BOX; se->cam=c; ex->DrawCursor=1; se->root=root; return LA_RUNNING;
         }
-        int elemtype,id=la_SelectGetClosest(sd, e->x-ui->L, e->y-ui->U, LA_RH*2,&elemtype); printf("%d\n",elemtype);
+        int elemtype,id=la_SelectGetClosest(sd, e->x-ui->L, e->y-ui->U, LA_RH*2,&elemtype);
         void* p=la_SelectGetRef(sd,id,elemtype); if(p){ la_DoObjectSelect(root, p, ex, DeselectAll, 1, 1);  }
         else{ la_DoObjectSelect(root, 0, ex, DeselectAll, 1, 1); }
         laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Object selection",TNS_HINT_TRANSFORM);
@@ -460,14 +466,14 @@ int la_PopulateTransformVerticies(MTransformData* td, tnsMeshObject* mo){
     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;
-        printf("v %d ",mv->i);
+        //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);
+    //printf(" [totmv %d]\n",mo->totmv);
     tnsVectorMultiSelf3d(td->TCenter, 1.0f/any);
     la_GetTransformCenter2D(td);
     return any;

+ 5 - 2
resources/la_widgets_viewers.c

@@ -1074,13 +1074,16 @@ void la_RegisterUiTypesViewerWidgets(){
     laAssignNewKey(km, 0, "LA_3d_view_camera_rotate", LA_KM_SEL_UI_EXTRA, 0, LA_M_MOUSE_DOWN, 0, 0);
     laAssignNewKey(km, 0, "LA_3d_view_camera_move", LA_KM_SEL_UI_EXTRA, LA_KEY_SHIFT, LA_M_MOUSE_DOWN, 0, 0);
     laAssignNewKey(km, 0, "LA_3d_view_camera_move", LA_KM_SEL_UI_EXTRA, LA_KEY_SHIFT | LA_KEY_ALT, LA_L_MOUSE_DOWN, 0, 0);
-    laAssignNewKey(km, 0, "TNS_align_camera_to_view", LA_KM_SEL_UI_EXTRA, LA_KEY_ALT | LA_KEY_SHIFT, LA_R_MOUSE_DOWN, 0, 0);
-    laAssignNewKey(km, 0, "TNS_align_view_to_camera", LA_KM_SEL_UI_EXTRA, 0, LA_KEY_DOWN, '0', 0);
+    //laAssignNewKey(km, 0, "TNS_align_camera_to_view", LA_KM_SEL_UI_EXTRA, LA_KEY_ALT | LA_KEY_SHIFT, LA_R_MOUSE_DOWN, 0, 0);
+    //laAssignNewKey(km, 0, "TNS_align_view_to_camera", LA_KM_SEL_UI_EXTRA, 0, LA_KEY_DOWN, '0', 0);
 
     laAssignNewKey(km, 0, "M_set_cursor", LA_KM_SEL_UI_EXTRA, 0, LA_L_MOUSE_DOWN, 0, 0);
     laAssignNewKey(km, 0, "M_toggle_edit_mode", LA_KM_SEL_UI_EXTRA, 0, LA_KEY_DOWN, LA_KEY_TAB, 0);
     laAssignNewKey(km, 0, "M_select", LA_KM_SEL_UI_EXTRA, LA_KEY_ALT, LA_R_MOUSE_DOWN, 0, 0);
+    laAssignNewKey(km, 0, "M_select", LA_KM_SEL_UI_EXTRA, LA_KEY_ALT|LA_KEY_CTRL, LA_R_MOUSE_DOWN, 0, 0);
     laAssignNewKey(km, 0, "M_select", LA_KM_SEL_UI_EXTRA, LA_KEY_SHIFT, LA_R_MOUSE_DOWN, 0, 0);
+    laAssignNewKey(km, 0, "M_select", LA_KM_SEL_UI_EXTRA, LA_KEY_SHIFT|LA_KEY_ALT, LA_R_MOUSE_DOWN, 0, 0);
+    laAssignNewKey(km, 0, "M_select", LA_KM_SEL_UI_EXTRA, LA_KEY_SHIFT|LA_KEY_ALT|LA_KEY_CTRL, LA_R_MOUSE_DOWN, 0, 0);
     laAssignNewKey(km, 0, "M_select", LA_KM_SEL_UI_EXTRA, 0, LA_R_MOUSE_DOWN, 0, 0);
     laAssignNewKey(km, 0, "M_select", LA_KM_SEL_UI_EXTRA, 0, LA_KEY_DOWN, 'b', "mode=box;");
     laAssignNewKey(km, 0, "M_select", LA_KM_SEL_UI_EXTRA, 0, LA_KEY_DOWN, 'a', "mode=toggle;");