*/}}
Browse Source

Better selection (select through and viewport etc)

YimingWu 1 year ago
parent
commit
7e058e3b64
7 changed files with 117 additions and 61 deletions
  1. 3 1
      la_kernel.c
  2. 9 5
      la_tns.h
  3. 31 7
      la_tns_kernel.c
  4. 25 11
      la_tns_mesh.c
  5. 34 23
      resources/la_modelling.c
  6. 5 2
      resources/la_tns_shaders.cpp
  7. 10 12
      resources/la_widgets_viewers.c

+ 3 - 1
la_kernel.c

@@ -4918,7 +4918,7 @@ int la_UpdateUiListRecursive(laUiList *uil, int U, int L, int R, int B, int Fast
         H = ui->Type->GetHeight ? ui->Type->GetHeight(ui) : 1;
         ui->TU = ui->C->B + (NoGap?_PT:bt->TP);
         if (H < 0){
-            if(B){ H = B + (H+1) * LA_RH - ui->TU+_PB; }
+            if(B){ H = B + (H+1) * LA_RH - ui->TU+_PB+((H<-1)?_PT:0); }
             else{ H=LA_RH; }
         } 
         else H *= LA_RH;
@@ -5320,6 +5320,7 @@ void la_DrawUiListScrollerV(laUiList *uil, int DisplayOffset, int TotalH, int Di
 
     int HU=(U+B)/2+LA_RH2;
     tnsDrawStringAuto("☰",laThemeColor(bt, LA_BT_BORDER),L-100,R+100,HU,LA_TEXT_REVERT_Y|LA_TEXT_ALIGN_CENTER);
+    tnsFlush();
 }
 void la_DrawUiListScrollerH(laUiList *uil, int DisplayOffset, int TotalW, int DisplayW, int UiB){
     if(!uil->ScrollerShownH) return;
@@ -5366,6 +5367,7 @@ void la_DrawUiListScrollerH(laUiList *uil, int DisplayOffset, int TotalW, int Di
 
     int HU=(U+B)/2+LA_RH2;
     tnsDrawStringAuto("↔",laThemeColor(bt, LA_BT_BORDER),L-100,R+100,HU,LA_TEXT_REVERT_Y|LA_TEXT_ALIGN_CENTER);
+    tnsFlush();
 }
 void la_DrawInstanceBkg(laUiList *uil, real* color){
     tnsUseNoTexture();

+ 9 - 5
la_tns.h

@@ -598,8 +598,6 @@ struct _tnsObject
     laListHandle ChildObjects;
 
     laListHandle Drivers; // rack
-
-    tnsBatch *ExtraBatch; // for root.
 };
 
 NEED_STRUCTURE(laNodeInSocket);
@@ -801,6 +799,7 @@ STRUCTURE(tnsMeshObject){
     int TriangulatedEdgeCount;
     
     tnsBatch *Batch;
+    tnsBatch *ExtraBatch;
 
     int Mode;
 };
@@ -1222,7 +1221,9 @@ int tnsMMeshSelectRingBandFrom(tnsMeshObject* mo, tnsMEdge* me, int ring_band, i
 void tnsInvalidateMeshBatch(tnsMeshObject* mo);
 void tnsRegenerateMeshBatch(tnsMeshObject* mo);
 void tnsEnsureMeshBatch(tnsMeshObject* mo);
-void tnsDrawMeshObject(tnsMeshObject* mo, int DrawAsObjectSelection, int MeshSelectionMode, tnsMeshObject* Active);
+void tnsDrawMeshObject(tnsMeshObject* mo, int DrawAsObjectSelection, int MeshSelectionMode, tnsMeshObject* Active,
+    int ViewMode, int SelectThrough, laListHandle* XRayCommands);
+void tnsDrawMeshObjectXRay(tnsMeshObject* mo, int MeshSelectionMode, int ViewMode, int SelectThrough);
 
 void la_RegisterModellingOperators();
 
@@ -1235,8 +1236,11 @@ void tnsApplyObjectMatrix(tnsObject *Object);
 
 void tnsLookAt(tnsObject *o, tnsVector3d Target, tnsVector3d Up);
 
-void tnsDrawThisObject(tnsObject *o, tnsObject *active, int DrawAsObjectSelection, int MeshSelectionMode);
-void tnsDrawObjectTree(tnsObject *from, tnsObject *active, int DrawAsObjectSelection, int MeshSelectionMode);
+void tnsDrawThisObject(tnsObject *o, tnsObject *active, int DrawAsObjectSelection, int MeshSelectionMode,
+    int ViewMode, int SelectThrough, laListHandle* XRayCommands);
+void tnsDrawObjectTree(tnsObject *from, tnsObject *active, int DrawAsObjectSelection, int MeshSelectionMode,
+    int ViewMode, int SelectThrough, laListHandle* XRayCommands);
+void tnsDrawXRay(laListHandle* XRayPasses, int MeshSelectionMode, int ViewMode, int SelectThrough);
 void tnsDrawObjectOrigins(tnsObject *from, tnsObject *active, int AllOrigins);
 void tnsDrawCursor(tnsObject* root);
 void tnsDrawScene(int W, int H, tnsObject *root);

+ 31 - 7
la_tns_kernel.c

@@ -1583,6 +1583,8 @@ void tnsDrawBatch(tnsBatch* batch, const char* OverrideCommand, real* OverrideUn
             glVertexAttribPointer(cs->iColor, batch->ColorDimension, GL_FLOAT, 0, 0, 0);
         }
     }
+    if(cs->iUV>=0){ glDisableVertexAttribArray(cs->iUV); }
+    tnsUniformUseTexture(cs, 0, 0);
 
     int IsOverrideColor=0; int PointSizeChanged=0,LineWidthChanged=0;
 	for (tnsBatchCommand* bc = batch->Branches.pFirst; bc; bc = bc->Item.pNext) {
@@ -3745,11 +3747,12 @@ void tnsDrawPlaceholder(tnsObject* o, tnsObject *active, int DrawAsSelection){
     tnsPackAs(GL_LINES);
     tnsFlush();
 }
-void tnsDrawThisObject(tnsObject *o,tnsObject *active, int DrawAsObjectSelection, int MeshSelectionMode){
+void tnsDrawThisObject(tnsObject *o,tnsObject *active, int DrawAsObjectSelection, int MeshSelectionMode,
+                        int ViewMode, int SelectThrough, laListHandle* XRayCommands){
     if (!o->Show) return;
     switch (o->Type){
     case TNS_OBJECT_MESH:
-        tnsDrawMeshObject(o, DrawAsObjectSelection, MeshSelectionMode, active);
+        tnsDrawMeshObject(o, DrawAsObjectSelection, MeshSelectionMode, active, ViewMode, SelectThrough, XRayCommands);
         break;
     case TNS_OBJECT_CAMERA:
         tnsDrawCamera(o);
@@ -3760,19 +3763,40 @@ void tnsDrawThisObject(tnsObject *o,tnsObject *active, int DrawAsObjectSelection
         break;
     }
 }
+void tnsDrawThisObjectXRay(tnsObject *o, int MeshSelectionMode, int ViewMode, int SelectThrough){
+    if (!o->Show) return;
+    switch (o->Type){
+    case TNS_OBJECT_MESH:
+        tnsDrawMeshObjectXRay(o, MeshSelectionMode, ViewMode, SelectThrough);
+        break;
+    case TNS_OBJECT_CAMERA:
+    case TNS_OBJECT_EMPTY:
+    default:
+        break;
+    }
+}
 
-void tnsDrawObjectTree(tnsObject *from, tnsObject *active, int DrawAsObjectSelection, int MeshSelectionMode){
+void tnsDrawObjectTree(tnsObject *from, tnsObject *active, int DrawAsObjectSelection, int MeshSelectionMode,
+                       int ViewMode, int SelectThrough, laListHandle* XRayCommands){
     tnsObject *o; if(!from) return;
 
     for (laListItemPointer* lip=from->ChildObjects.pFirst;lip;lip=lip->pNext){
         o=lip->p;
         tnsPushMatrix(); tnsApplyObjectMatrix(o);
-        tnsDrawThisObject(o, active, DrawAsObjectSelection, MeshSelectionMode);
-        if (o->ChildObjects.pFirst){ tnsDrawObjectTree(o, active, DrawAsObjectSelection, MeshSelectionMode); }
+        tnsDrawThisObject(o, active, DrawAsObjectSelection, MeshSelectionMode, ViewMode, SelectThrough, XRayCommands);
+        if (o->ChildObjects.pFirst){
+            tnsDrawObjectTree(o, active, DrawAsObjectSelection, MeshSelectionMode, ViewMode, SelectThrough, XRayCommands);
+        }
+        tnsPopMatrix();
+    }
+}
+void tnsDrawXRay(laListHandle* XRayPasses, int MeshSelectionMode, int ViewMode, int SelectThrough){
+    if(!XRayPasses->pFirst){ return; } tnsObject* o;
+    glClear(GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE);
+    while(o=lstPopPointer(XRayPasses)){ tnsPushMatrix(); tnsApplyObjectMatrix(o);
+        tnsDrawThisObjectXRay(o,MeshSelectionMode, ViewMode, SelectThrough);
         tnsPopMatrix();
     }
-    glDisable(GL_DEPTH_TEST);
-    tnsDrawBatch(from->ExtraBatch,0,0,0);
 }
 void tnsDrawObjectOrigins(tnsObject *from, tnsObject *active, int AllOrigins){
     tnsObject *o; if(!from) return;

+ 25 - 11
la_tns_mesh.c

@@ -273,10 +273,21 @@ void tnsEnsureMeshBatch(tnsMeshObject* mo){
     if(mo->Batch) return;
     tnsRegenerateMeshBatch(mo);
 }
-void tnsDrawMeshObject(tnsMeshObject* mo, int DrawAsObjectSelection, int MeshSelectionMode, tnsMeshObject* Active){
+void tnsDrawMeshObjectEdit(tnsMeshObject* mo, int MeshSelectionMode){
+    tnsUniformUseOffset(T->immShader,1);
+    glPointSize(6); glLineWidth(3);
+    if(MeshSelectionMode==LA_CANVAS_SELECT_MODE_VERTS){
+        tnsDrawBatch(mo->Batch,"verts",0,0); tnsDrawBatch(mo->Batch,"lines",0,0);
+    }else{
+        tnsDrawBatch(mo->Batch,"edges",0,0);
+    }
+    glPointSize(1); glLineWidth(1);
+    tnsUniformUseOffset(T->immShader,0);
+}
+void tnsDrawMeshObject(tnsMeshObject* mo, int DrawAsObjectSelection, int MeshSelectionMode, tnsMeshObject* Active, int ViewMode, int SelectThrough, laListHandle* XRayPasses){
     tnsEnsureMeshBatch(mo);
     if(DrawAsObjectSelection){
-        if(mo->Base.Flags&TNS_OBJECT_FLAGS_SELECTED && mo->Mode!=TNS_MESH_EDIT_MODE){
+        if((mo->Base.Flags&TNS_OBJECT_FLAGS_SELECTED) && (mo->Mode!=TNS_MESH_EDIT_MODE)){
             real* color=(Active==mo)?laAccentColor(LA_BT_TEXT):laAccentColor(LA_BT_NORMAL);
             tnsDrawBatch(mo->Batch, "body", color, 0);
         }
@@ -285,21 +296,24 @@ void tnsDrawMeshObject(tnsMeshObject* mo, int DrawAsObjectSelection, int MeshSel
             int i=mo->Base.SelectID; real color[4]={0,0,0,1}; TNS_ID_TO_COLOR(color,i);
             tnsDrawBatch(mo->Batch,"body",color,0);
         }else{
-            tnsUseNormal(1);
-            tnsDrawBatch(mo->Batch,"body",0,0);
-            tnsUseNormal(0);
-            if(mo->Mode==TNS_MESH_EDIT_MODE){
-                tnsUniformUseOffset(T->immShader,1);
-                if(MeshSelectionMode==LA_CANVAS_SELECT_MODE_VERTS){
-                    tnsDrawBatch(mo->Batch,"verts",0,0); tnsDrawBatch(mo->Batch,"lines",0,0);
+            tnsUseNormal(1); tnsDrawBatch(mo->Batch,"body",0,0); tnsUseNormal(0);
+            if(mo->Mode==TNS_MESH_EDIT_MODE){ int xray=0;
+                if(mo->ExtraBatch){xray=1;}
+                if(SelectThrough){
+                    if(XRayPasses){xray=1;}
                 }else{
-                    tnsDrawBatch(mo->Batch,"edges",0,0);
+                    tnsDrawMeshObjectEdit(mo,MeshSelectionMode);
                 }
-                tnsUniformUseOffset(T->immShader,0);
+                if(xray){ lstAppendPointer(XRayPasses,mo); }
             }
         }
     }
 }
+void tnsDrawMeshObjectXRay(tnsMeshObject* mo, int MeshSelectionMode, int ViewMode, int SelectThrough){
+    if(SelectThrough){ tnsDrawMeshObjectEdit(mo, MeshSelectionMode); }
+    if(mo->ExtraBatch){ tnsDrawBatch(mo->ExtraBatch,0,0,0); }
+}
+
 
 tnsMFace* tnsMMeshNewFace(tnsMeshObject* mo){ tnsMFace* mf=memAcquireSimple(sizeof(tnsMFace)); mf->i=mo->totmf; mo->totmf++; lstAppendItem(&mo->mf,mf); return mf; }
 tnsMEdge* tnsMMeshNewEdge(tnsMeshObject* mo){ tnsMEdge* me=memAcquireSimple(sizeof(tnsMEdge)); me->i=mo->totme; mo->totme++; lstAppendItem(&mo->me,me); return me; }

+ 34 - 23
resources/la_modelling.c

@@ -118,7 +118,7 @@ void la_PopulateSelectDataObjects(MSelectData* sd, tnsObject* root, tnsCamera* c
     tnsApplyCameraView(w,h,camera);
     glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
     glEnable(GL_DEPTH_TEST);
-    tnsDrawObjectTree(root,0,0,0);
+    tnsDrawObjectTree(root,0,0,0,0,0,0);
     glDisable(GL_DEPTH_TEST);
 }
 void la_PopulateSelectVerts(MSelectData* sd, tnsMeshObject* mo){
@@ -139,7 +139,7 @@ void la_PopulateSelectEdges(MSelectData* sd, tnsMeshObject* mo){
     }
     sd->nextE++;
 }
-void la_PopulateSelectDataPrimitives(MSelectData* sd, tnsMeshObject* mo, tnsCamera* camera, int WhatPrim){
+void la_PopulateSelectDataPrimitives(MSelectData* sd, tnsMeshObject* mo, tnsCamera* camera, int WhatPrim, int SelectThrough){
     int DoVerts=(WhatPrim==LA_CANVAS_SELECT_MODE_VERTS),DoEdges=(WhatPrim==LA_CANVAS_SELECT_MODE_EDGES);
     int Knife=(WhatPrim==LA_CANVAS_SELECT_MODE_KNIFE);
     if(DoVerts || Knife){ la_PopulateSelectVerts(sd,mo); }
@@ -150,12 +150,17 @@ void la_PopulateSelectDataPrimitives(MSelectData* sd, tnsMeshObject* mo, tnsCame
     tnsViewportWithScissor(0,0,w,h);tnsResetViewMatrix();tnsResetModelMatrix();tnsResetProjectionMatrix();
     tnsApplyCameraView(w,h,camera);
     glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
-    glEnable(GL_DEPTH_TEST);
-    tnsPushMatrix(); tnsApplyObjectMatrix(mo);
-    if(Knife){ glPointSize(5); }
+    tnsPushMatrix(); tnsApplyObjectMatrix(mo);glEnable(GL_DEPTH_TEST);
+    if(!SelectThrough){
+        glDepthMask(GL_TRUE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+        tnsUniformUseOffset(T->SelectionShader,0);
+        tnsDrawBatch(mo->Batch,"body",0,0);
+        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_FALSE);
+    }
+    tnsUniformUseOffset(T->SelectionShader,1);
     if(DoEdges || Knife){ tnsDrawBatch(mo->Batch, "edges_select",0,0); }
     if(DoVerts || Knife){ tnsDrawBatch(mo->Batch, "verts_select",0,0); }
-    if(Knife){ glPointSize(1); }
+    tnsUniformUseOffset(T->SelectionShader,0);
     tnsPopMatrix();
     glDisable(GL_DEPTH_TEST);
 }
@@ -204,18 +209,23 @@ uint8_t* la_ReadSelectionBox(MSelectData* sd, int uix, int uiy, int uix2, int ui
 }
 int la_SelectGetClosest(MSelectData* sd, int uix, int uiy, int radius, int *ElemType){
     *ElemType=0; uint8_t* buf=la_ReadSelectionRadius(sd, uix, uiy, radius); if(!buf) return 0;
-    int w=radius*2; int MinD=INT_MAX; int MinID=0, d, elemtype=0;
+    int w=radius*2; int MinD=INT_MAX,MinDe=INT_MAX; int MinID=0,MinIDe=0, d, elemtype=0;
     for(int i=0;i<w;i++){
         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)&(~TNS_MMESH_TYPE_BIT));
-            if(id && (d=tnsDistIdv2(i,j, radius, radius))<MinD ){ MinD=d; MinID=id; elemtype=((p[2]<<16)&TNS_MMESH_TYPE_BIT); }
+            uint8_t* p=&buf[(i*w+j)*4]; int id=(p[0])|(p[1]<<8)|((p[2]<<16)&(~TNS_MMESH_TYPE_BIT)); if(!id){continue;}
+            d=tnsDistIdv2(i,j, radius, radius); elemtype=((p[2]<<16)&TNS_MMESH_TYPE_BIT);
+            if(elemtype==TNS_MMESH_EDGE_BIT){ if(d<MinDe){ MinDe=d; MinIDe=id; } }
+            elif(d<MinD){ MinD=d; MinID=id; }
             //printf("%d ",buf[(i*w+j)*4]);
         }
         //printf("\n");
     }
+    printf("%d %d\n",MinID, MinIDe);
     free(buf);
-    *ElemType=elemtype;
-    return MinID;
+    if(MinID && MinIDe){ if(MinD<MinDe*5){ *ElemType=0; return MinID; } }
+    if(MinIDe){ *ElemType=TNS_MMESH_EDGE_BIT; return MinIDe; }
+    if(MinID){ *ElemType=0; return MinID; }
+    *ElemType=0; return 0;
 }
 int* la_SelectGetBox(MSelectData* sd, int uix, int uiy, int uix2, int uiy2, int* r_length){
     uint8_t* buf=la_ReadSelectionBox(sd, uix, uiy, uix2, uiy2); if(!buf) return 0;
@@ -308,7 +318,7 @@ 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, SelectMode);
+        la_PopulateSelectDataPrimitives(sd, mo, ex->ViewingCamera, SelectMode, ex->SelectThrough);
         if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "box")){
             MSelectExtra* se=memAcquire(sizeof(MSelectExtra));
             ex->OnX=e->x; ex->OnX=e->y;
@@ -1306,21 +1316,21 @@ STRUCTURE(MKnifeElement){
     void* p;
     int Type;
 };
-void la_KnifeUpdateToolBatch(MSelectExtra* se,tnsObject* o){
-    if(se->root->ExtraBatch) tnsDeleteBatch(se->root->ExtraBatch); se->root->ExtraBatch=0;
+void la_KnifeUpdateToolBatch(MSelectExtra* se,tnsMeshObject* o){
+    if(o->ExtraBatch) tnsDeleteBatch(o->ExtraBatch); o->ExtraBatch=0;
     int count=lstCountElements(&se->KnifeElements); if((!count) && (!se->PendingElem)) return;
     float* points=calloc((count+1)*3,sizeof(real));
     float* p=points; real tmp[3],trans[4];
     for(MKnifeElement* ke=se->KnifeElements.pFirst;ke;ke=ke->Item.pNext){
         if(ke->Type==TNS_MMESH_EDGE_BIT){ tnsMEdge* me=ke->p; tnsVectorSet3v(tmp,me->vl->p); tnsVectorAccum3d(tmp,me->vr->p);
-            tnsVectorMultiSelf3d(tmp,0.5); tnsApplyTransform43d(trans,o->GlobalTransform,tmp); tnsVectorSet3v(p,trans); }
-        else{ tnsMVert* mv=ke->p; tnsApplyTransform43d(trans,o->GlobalTransform,mv->p); tnsVectorSet3v(p,trans); }
+            tnsVectorMultiSelf3d(tmp,0.5); tnsApplyTransform43d(trans,o->Base.GlobalTransform,tmp); tnsVectorSet3v(p,trans); }
+        else{ tnsMVert* mv=ke->p; tnsApplyTransform43d(trans,o->Base.GlobalTransform,mv->p); tnsVectorSet3v(p,trans); }
         p+=3;
     }
     if(se->PendingElem){
         if(se->PendingElemType==TNS_MMESH_EDGE_BIT){ tnsMEdge* me=se->PendingElem; tnsVectorSet3v(tmp,me->vl->p); tnsVectorAccum3d(tmp,me->vr->p);
-        tnsVectorMultiSelf3d(tmp,0.5); tnsApplyTransform43d(trans,o->GlobalTransform,tmp); tnsVectorSet3v(p,trans); }
-        else{ tnsMVert* mv=se->PendingElem; tnsApplyTransform43d(trans,o->GlobalTransform,mv->p); tnsVectorSet3v(p,trans); }
+        tnsVectorMultiSelf3d(tmp,0.5); tnsApplyTransform43d(trans,o->Base.GlobalTransform,tmp); tnsVectorSet3v(p,trans); }
+        else{ tnsMVert* mv=se->PendingElem; tnsApplyTransform43d(trans,o->Base.GlobalTransform,mv->p); tnsVectorSet3v(p,trans); }
     }elif(count){
         tnsVectorSet3v(p,p-3);
     }
@@ -1328,6 +1338,7 @@ void la_KnifeUpdateToolBatch(MSelectExtra* se,tnsObject* o){
     tnsBatch* batch=tnsCreateBatch(count+1,3,points,0,0,0,0); tnsBatchCommand*c;
     c=tnsCreateCommand(batch, "hovering_point", 1, 3, GL_POINTS, &elem, 0);
     tnsCommandUseUniformColor(c,laAccentColor(LA_BT_SVERTEX));
+    tnsCommandUseWidth(c, 8);
     if(count){
         c=tnsCreateCommand(batch, "edges", count+(se->IsLoop?0:1), 3, se->IsLoop?GL_LINE_LOOP:GL_LINE_STRIP, 0, 0);
         tnsCommandUseUniformColor(c,laAccentColor(LA_BT_NORMAL));
@@ -1336,7 +1347,7 @@ void la_KnifeUpdateToolBatch(MSelectExtra* se,tnsObject* o){
         tnsCommandUseUniformColor(c,laAccentColor(LA_BT_NORMAL));
         tnsCommandUseWidth(c, 6);
     }
-    se->root->ExtraBatch=batch;
+    o->ExtraBatch=batch;
     free(points);
 }
 int la_KnifeIsDuplicated(MSelectExtra* se, void* ref){
@@ -1366,7 +1377,7 @@ int la_KnifeRegisterCuts(MSelectExtra* se, tnsMeshObject* mo, int TryClose){
     if(changed){ tnsMMeshRefreshIndex(mo); tnsMMeshCalculateNormal(mo); }
     return changed;
 }
-void la_KnifeFinish(MSelectExtra* se, tnsObject*o){
+void la_KnifeFinish(MSelectExtra* se, tnsMeshObject*o){
     if(o->ExtraBatch) tnsDeleteBatch(o->ExtraBatch); o->ExtraBatch=0;
     while(lstPopPointer(&se->KnifeElements));
     la_FreeSelectData(se->sd); memFree(se);
@@ -1411,7 +1422,7 @@ int OPINV_Knife(laOperator *a, laEvent *e){
     int SelectMode=LA_CANVAS_SELECT_MODE_KNIFE;
     if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "loop_cut")){
         se->IsLoop=1; SelectMode=LA_CANVAS_SELECT_MODE_EDGES; }
-    la_PopulateSelectDataPrimitives(sd,mo,c,SelectMode);
+    la_PopulateSelectDataPrimitives(sd,mo,c,SelectMode,ex->SelectThrough);
 
     if(se->IsLoop){ strSafePrint(&a->RuntimeHint,"◧ Cut  ◨ Cancel"); }
     else{ strSafePrint(&a->RuntimeHint,"◧ Place Cut  ◨ Cancel  ⮨ Confirm"); }
@@ -1427,7 +1438,7 @@ int OPMOD_Knife(laOperator *a, laEvent *e){
     int changed=0;
 
     if(e->Type==LA_R_MOUSE_DOWN || (e->Type == LA_KEY_DOWN && e->key==LA_KEY_ESCAPE)){
-        la_KnifeFinish(se,root); laNotifyUsers("tns.world"); return LA_FINISHED;
+        la_KnifeFinish(se,mo); laNotifyUsers("tns.world"); return LA_FINISHED;
     }
 
     if(e->Type&LA_MOUSE_EVENT){
@@ -1451,7 +1462,7 @@ int OPMOD_Knife(laOperator *a, laEvent *e){
             tnsInvalidateMeshBatch(mo); laNotifyUsers("tns.world");
             laRecordAndPush(0,"tns.world",se->IsLoop?"Loop Cut":"Knife Cut",TNS_HINT_GEOMETRY);
         }
-        la_KnifeFinish(se,root); return LA_FINISHED;
+        la_KnifeFinish(se,mo); return LA_FINISHED;
     }
     
     if(changed){

+ 5 - 2
resources/la_tns_shaders.cpp

@@ -606,7 +606,7 @@ flat out vec3 fNormal;
 out vec3 fGPos;
 void main(){
 	vec4 pos=mProjection * mView * mModel * vVertex;
-	if(DoOffset>0){ pos.xyw*=1.0001; }
+	if(DoOffset>0){ pos.xyw*=1.00005; }
     gl_Position = pos;
     fColor = vColor;
     fUV=vUV;
@@ -856,9 +856,12 @@ in vec3 vColor;
 uniform mat4 mProjection;
 uniform mat4 mModel;
 uniform mat4 mView;
+uniform int DoOffset;
 flat out vec3 fIdColor;
 void main(){
-    gl_Position = mProjection * mView * mModel * vVertex;
+	vec4 pos = mProjection * mView * mModel * vVertex;
+	if(DoOffset>0){ pos.xyw*=1.00005; }
+    gl_Position = pos;
     fIdColor = vColor;
 })";
 

+ 10 - 12
resources/la_widgets_viewers.c

@@ -143,7 +143,7 @@ void la_RootObjectDraw(laBoxedTheme *bt, tnsObject *root, laUiItem* ui){
 
     tnsDrawToOffscreen(e->OffScr,3,TNS_ATTACHMENT_ARRAY_0_1_2);
     //tnsDrawToOffscreen(e->DeferredOffScr,3,TNS_ATTACHMENT_ARRAY_0_1_2);
-    tnsViewportWithScissor(0, 0, W, H);
+    tnsViewportWithScissor(0, 0, W, H); glDepthMask(GL_TRUE);
     tnsClearColorv(laThemeColor(bt,LA_BT_NORMAL)); tnsClearAll(); float gpos_clear[]={-1e20, -1e20, -1e20, 0};
     glClearBufferfv(GL_COLOR, 2, gpos_clear);
 
@@ -151,18 +151,19 @@ void la_RootObjectDraw(laBoxedTheme *bt, tnsObject *root, laUiItem* ui){
     tnsPushMatrix();
     tnsPopMatrix(); //those are necessary when ui is the first in list;
 
+    laListHandle xrays={0};
+
     if(root){
         glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND);
 
-        tnsEnableShaderv(T->immShader);
+        tnsUseShader(T->immShader); tnsEnableShaderv(T->immShader);
         tnsUnbindTexture(); tnsUniformUseTexture(T->immShader,0,0); tnsUseMultiplyColor(0);
-        glPointSize(6); glLineWidth(3); 
-        tnsDrawObjectTree(root, 0, 0, e->SelectMode);
-        glPointSize(1); glLineWidth(3); 
-
+        tnsDrawObjectTree(root, 0, 0, e->SelectMode, 0, e->SelectThrough,&xrays);
+        
+        glLineWidth(3); 
         glEnable(GL_POLYGON_OFFSET_LINE); glPolygonOffset(-1,-1);
         glDepthMask(GL_FALSE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-        tnsDrawObjectTree(root, root->Active, 1, 0);
+        tnsDrawObjectTree(root, root->Active, 1, 0, 0, 0, 0);
         glDepthMask(GL_TRUE); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
         glLineWidth(1);
         glDisable(GL_POLYGON_OFFSET_LINE);
@@ -175,6 +176,8 @@ void la_RootObjectDraw(laBoxedTheme *bt, tnsObject *root, laUiItem* ui){
         tnsFlush();
     }
 
+    tnsDrawXRay(&xrays,e->SelectMode,0,e->SelectThrough);
+
     if(root){
         glDisable(GL_DEPTH_TEST);
         tnsDrawCursor(root);
@@ -478,11 +481,6 @@ void laDefault3DViewOverlay(laUiItem *ui){
 
     laShowColumnAdjuster(uil, c);
 
-    b=laBeginRow(uil,cl,0,0);
-    laShowItem(uil,cl,&ui->ExtraPP,"select_mode")->Flags|=LA_UI_FLAGS_EXPAND;
-    laShowItem(uil,cl,&ui->ExtraPP,"select_through");
-    laEndRow(uil,b);
-
     g = laMakeFoldableGroup(uil, cll, "Tools", 0, 1, 0);{
         gu = g->Page; gc = laFirstColumn(gu);
         laSplitColumn(gu, gc, 0.35); gcl = laLeftColumn(gc, 0); gcr = laRightColumn(gc, 0);