*/}}
Browse Source

Always origin and select linked

YimingWu 7 months ago
parent
commit
e143158434
6 changed files with 70 additions and 15 deletions
  1. 5 0
      la_tns.h
  2. 12 3
      la_tns_kernel.c
  3. 18 3
      la_tns_mesh.c
  4. 7 0
      la_tns_shape.c
  5. 27 9
      resources/la_modelling.c
  6. 1 0
      resources/la_widgets_viewers.c

+ 5 - 0
la_tns.h

@@ -1131,6 +1131,7 @@ tnsShapeObject* tnsDuplicateShappeObject(tnsShapeObject* from);
 
 void tnsInitMeshPlane(tnsMeshObject* mo, real size);
 void tnsAddMMeshPlane(tnsMeshObject* mo, real size);
+void tnsInitShapeSquare(tnsShapeObject* so, real size);
 
 int tnsAnyObjectsSelected(tnsObject* parent);
 void tnsDeselectAllObjects(tnsObject* parent);
@@ -1182,6 +1183,7 @@ void tnsMMeshEnsureSelectionFromEdges(tnsMeshObject* mo);
 void tnsMMeshEnsureSelection(tnsMeshObject* mo, int SelectMode);
 void tnsMMeshExpandBandList(tnsMeshObject* mo, tnsMEdge* me, laListHandle* lst);
 int tnsMMeshSelectRingBandFrom(tnsMeshObject* mo, tnsMEdge* me, int ring_band, int select, int toggle);
+void tnsMMeshSelectLinked(tnsMeshObject* mo);
 
 int tnsMMeshVertsCanMerge(tnsMeshObject* mo, tnsMVert* into, tnsMVert* mv);
 int tnsMMeshMergeVerts(tnsMeshObject* mo, tnsMVert* into, tnsMVert* mv);
@@ -1200,6 +1202,8 @@ void tnsShapeDeselectAll(tnsShapeObject* so);
 void tnsShapeSelectAll(tnsShapeObject* so);
 void tnsShapeSelectPoint(tnsShapeObject* so, tnsSPoint* sp, int select, int toggle, int lr);
 void tnsShapeSelectRingFrom(tnsShapeObject* so, tnsSPoint* sp, int select, int toggle);
+void tnsShapeSelectLinked(tnsShapeObject* so);
+
 void tnsShapeSetEndPoint(tnsShape* s, tnsSPoint* p);
 void tnsShapeRefreshIndex(tnsShapeObject* so);
 tnsShape* tnsShapeRemovePoint(tnsShapeObject* so, tnsShape* s, tnsSPoint* sp, int SplitShape);
@@ -1248,6 +1252,7 @@ void tnsEnsureEvaluatedScene(tnsEvaluateData* ed, tnsObject* root);
 void tnsPrintEvaluatedNode(tnsEvaluatedNode* en,int level);
 
 void tnsDrawObjectTree(tnsObject* from, int Layers,void* CustomData, int DrawRuntime);
+void tnsDrawSingleObjectOrigin(tnsObject* o);
 void tnsDrawObjectOrigins(tnsObject *from, tnsObject *active, int AllOrigins);
 void tnsDrawCursor(tnsObject* root);
 void tnsDrawScene(int W, int H, tnsObject *root);

+ 12 - 3
la_tns_kernel.c

@@ -2289,7 +2289,9 @@ void tnsFlush(){
 
     for (int i=0;i<T->NextCommand;i++){ c=&T->DrawingCommand[i];
         if (c->LineWidth!=T->SetLineWidth){ glLineWidth(c->LineWidth); T->SetLineWidth=c->LineWidth; }
-        if (c->PointSize!=T->SetPointSize){ glLineWidth(c->PointSize); T->SetPointSize=c->PointSize; }
+        if (c->PointSize!=T->SetPointSize){
+            glPointSize(c->PointSize); T->SetPointSize=c->PointSize;
+            }
         if (c->ReplaceShader && c->ReplaceShader != T->CurrentShader){
             tnsEnableShaderv(c->ReplaceShader); cs = c->ReplaceShader;
             if (!cs) continue;
@@ -4117,12 +4119,19 @@ void tnsDrawObjectTree(tnsObject* from, int Layers,void* CustomData, int DrawRun
     if(Layers&TNS_EVAL_LAYER_SELECTION){ tnsDrawLayer(ed,TNS_EVAL_LAYER_SELECTION,CustomData); }
 }
 
+void tnsDrawSingleObjectOrigin(tnsObject* o){
+    real* c=laThemeColor(_LA_THEME_3D_VIEW,LA_BT_BORDER); tnsColor4d(LA_COLOR3(c),0.5);
+    tnsPointSize(8); tnsVertex3d(0,0,0); tnsPackAs(GL_POINTS); 
+    tnsFlush(); tnsPointSize(1);
+}
 void tnsDrawObjectOrigins(tnsObject *from, tnsObject *active, int AllOrigins){
     tnsObject *o; if(!from) return;
     tnsVector4d pos;
     for (laListItemPointer* lip=from->ChildObjects.pFirst;lip;lip=lip->pNext){
-        o=lip->p; if((!AllOrigins) && (o!=active) && (!(o->Flags&TNS_OBJECT_FLAGS_SELECTED))) continue;
-        if(o->Type==TNS_OBJECT_MESH && ((tnsMeshObject*)o)->Mode==TNS_MESH_EDIT_MODE){ continue; }
+        o=lip->p; if((!AllOrigins)){
+            if((o!=active) && (!(o->Flags&TNS_OBJECT_FLAGS_SELECTED))) continue;
+            if(o->Type==TNS_OBJECT_MESH && ((tnsMeshObject*)o)->Mode==TNS_MESH_EDIT_MODE){ continue; }
+        }
         if(T->BindedShader==T->SelectionShader){  int i=o->SelectID; real color[4]={0,0,0,1}; TNS_ID_TO_COLOR(color,i); tnsColor4dv(color); }
         else{
             if(o==active){ tnsColor4dv(laAccentColor(LA_BT_TEXT_ACTIVE)); }

+ 18 - 3
la_tns_mesh.c

@@ -339,13 +339,15 @@ void tnsDrawMeshObjectOutline(tnsEvaluatedInstance* ei, void* unused){
     tnsDrawBatch(((tnsMeshObject*)ei->Object)->Batch, "body", color, 0);
 }
 void tnsDrawMeshObject(tnsEvaluatedInstance* ei, la3DObjectDrawExtra* de){
+    tnsMeshObject* mo=ei->Object;
+    if((!mo->totv) && (!mo->totmv)){ tnsDrawSingleObjectOrigin(mo); return; }
     tnsEnsureMeshBatch(ei->Object); tnsUseNormal(1);
     if(de->DisplayMode==LA_CANVAS_DISPLAY_MATERIAL){
-        if(!tnsDrawBatch(((tnsMeshObject*)ei->Object)->Batch,"mat",0,0)){
-            tnsDrawBatch(((tnsMeshObject*)ei->Object)->Batch,"body",0,0);
+        if(!tnsDrawBatch(mo->Batch,"mat",0,0)){
+            tnsDrawBatch(mo->Batch,"body",0,0);
         }
     }else{
-        tnsDrawBatch(((tnsMeshObject*)ei->Object)->Batch,"body",0,0);
+        tnsDrawBatch(mo->Batch,"body",0,0);
     }
     tnsUseNormal(0);
 }
@@ -794,6 +796,19 @@ int tnsMMeshSelectRingBandFrom(tnsMeshObject* mo, tnsMEdge* me, int ring_band, i
     }
     while(lstPopPointer(&lst)); return 1;
 }
+void tnsMMeshSelectLinkedRecursive(tnsMeshObject* mo, tnsMVert* mv){
+    for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){ tnsMEdge* me=lip->p;
+        if(!(me->vl->flags&TNS_MESH_FLAG_SELECTED)){ me->vl->flags|=TNS_MESH_FLAG_SELECTED;tnsMMeshSelectLinkedRecursive(mo,me->vl); }
+        if(!(me->vr->flags&TNS_MESH_FLAG_SELECTED)){ me->vr->flags|=TNS_MESH_FLAG_SELECTED;tnsMMeshSelectLinkedRecursive(mo,me->vr); }
+    }
+}
+void tnsMMeshSelectLinked(tnsMeshObject* mo){
+    if((!mo) || (mo->Mode!=TNS_MESH_EDIT_MODE)){ return; }
+    for(tnsMVert* mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){
+        if(mv->flags&TNS_MESH_FLAG_SELECTED){ tnsMMeshSelectLinkedRecursive(mo,mv); }
+    }
+    tnsMMeshEnsureSelectionFromVerts(mo);
+}
 
 void tnsMMeshReduceFaceEdge(tnsMeshObject* mo, tnsMFace* mf, tnsMEdge* me){
     lstRemovePointerLeave(&mf->l,me); mf->looplen--;

+ 7 - 0
la_tns_shape.c

@@ -100,6 +100,12 @@ void tnsShapeSelectRingFrom(tnsShapeObject* so, tnsSPoint* sp, int select, int t
         if(select){ isp->flags|=TNS_SPOINT_SELECTED; }else{ isp->flags&=(~TNS_SPOINT_SELECTED); }
     }
 }
+void tnsShapeSelectLinked(tnsShapeObject* so){
+    for(tnsShape* s=so->Shapes.pFirst;s;s=s->Item.pNext){
+        if(!tnsShapePointAnySelected(s)){ continue; }
+        for(tnsSPoint* sp=s->Points.pFirst;sp;sp=sp->Item.pNext){ sp->flags|=TNS_SPOINT_SELECTED; }
+    }
+}
 
 tnsShape* tnsShapeRemovePoint(tnsShapeObject* so, tnsShape* s, tnsSPoint* sp, int SplitShape){
     if(SplitShape && sp->Item.pNext && sp->Item.pPrev){
@@ -332,6 +338,7 @@ void tnsDrawShapeObjectShapes(tnsEvaluatedInstance* ei, la3DObjectDrawExtra* de,
     nvgRestore(vg);
 }
 void tnsDrawShapeObject(tnsEvaluatedInstance* ei, la3DObjectDrawExtra* de){
+    tnsShapeObject* so=ei->Object; if(!so->Shapes.pFirst){ tnsDrawSingleObjectOrigin(so); }
     tnsDrawShapeObjectShapes(ei,de,0,0);
 }
 void tnsDrawShapeObjectSelectionID(tnsEvaluatedInstance* ei, la3DObjectDrawExtra* de){

+ 27 - 9
resources/la_modelling.c

@@ -135,6 +135,7 @@ void la_PopulateSelectDataObjects(MSelectData* sd, tnsObject* root, laCanvasExtr
     glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST);
     tnsInvalidateEvaluation(root); tnsSetObjectTreeEvaluationArgs(root,root->Active,1,1); tnsEvaluateObjectTree(root,0,0);
     tnsDrawObjectTree(root,TNS_EVAL_LAYER_SELECTION,&de,0);
+    tnsDrawObjectOrigins(root,root->Active,1); tnsFlush();
     glDisable(GL_DEPTH_TEST); 
 
     nvgEndFrame(vg); tnsRestoreFromNanoVG(); tnsEnableShaderv(T->immShader);
@@ -472,6 +473,23 @@ int OPMOD_Select(laOperator *a, laEvent *e){
     return LA_RUNNING;
 }
 
+int OPINV_SelectLinked(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;
+    tnsObject* o=root->Active; tnsMeshObject* mo=o; tnsShapeObject* so=o;
+    
+    if(o&&o->Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
+        tnsMMeshSelectLinked(mo); tnsInvalidateMeshBatch(mo);
+        laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Mesh selection",TNS_HINT_GEOMETRY);
+    }elif(o&&o->Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){
+        tnsShapeSelectLinked(so);
+        laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Shape selection",TNS_HINT_GEOMETRY);
+    }
+    
+    return LA_FINISHED_PASS;
+}
+
 
 #define LA_TRANSFORM_MODE_GRAB   1
 #define LA_TRANSFORM_MODE_ROTATE 2
@@ -1281,7 +1299,7 @@ int OPINV_Delete(laOperator *a, laEvent *e){
         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){
+    }elif(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){
@@ -1483,11 +1501,12 @@ int OPINV_Add(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; int ran=0; tnsObject* no=0;
+    tnsMeshObject* mo=root->Active; tnsShapeObject* so=mo;int ran=0; tnsObject* no=0;
     laObjectAddData *ad=memAcquire(sizeof(laObjectAddData));a->CustomData=ad;
     char* str=strGetArgumentString(a->ExtraInstructionsP, "mode");
 
-    if((!mo) || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){ ad->Context=LA_ADD_CTX_OBJECT;
+    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)){ ad->Context=LA_ADD_CTX_OBJECT;
         if(strSame(str,"PLANE")){ tnsDeselectAllObjects(root); 
             no=tnsCreateMeshPlane(root, "Plane",0,0,0,1); no->Flags|=TNS_OBJECT_FLAGS_SELECTED; memAssignRef(root,&root->Active,no); ran=1; }
         elif(strSame(str,"INSTANCER")){ tnsDeselectAllObjects(root);
@@ -1496,7 +1515,7 @@ int OPINV_Add(laOperator *a, laEvent *e){
             no=tnsCreateShapeSquare(root, "Square",0,0,0,1); no->Flags|=TNS_OBJECT_FLAGS_SELECTED; memAssignRef(root,&root->Active,no); ran=1; }
         else{ laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING; }
         if(ran){ laRecordAndPush(0,"tns.world","Add object",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world"); }
-    }elif(mo->Base.Type==TNS_OBJECT_MESH && mo->Mode!=TNS_MESH_EDIT_MODE){ ad->Context=LA_ADD_CTX_MESH;
+    }elif(mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){ ad->Context=LA_ADD_CTX_MESH;
         if(strSame(str,"PLANE")){
             tnsMMeshDeselectAll(mo); tnsAddMMeshPlane(mo, 1); tnsMMeshEnsureSelection(mo,ex->SelectMode); ran=1;
         }else{ laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING; }
@@ -1504,14 +1523,12 @@ int OPINV_Add(laOperator *a, laEvent *e){
             tnsMMeshRefreshIndex(mo); tnsInvalidateMeshBatch(mo); 
             laRecordInstanceDifferences(mo, "tns_mesh_object"); laPushDifferences("Add primitives", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
         }
-    }elif(mo->Base.Type==TNS_OBJECT_SHAPE && mo->Mode!=TNS_MESH_EDIT_MODE){ ad->Context=LA_ADD_CTX_SHAPE;
+    }elif(so->Base.Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){ ad->Context=LA_ADD_CTX_SHAPE;
         if(strSame(str,"SQUARE")){
-            //stuff
-            ran=1;
+            tnsShapeDeselectAll(so); tnsInitShapeSquare(so,1); ran=1;
         }else{ laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING; }
         if(ran){
-            //stuff
-            laRecordInstanceDifferences(mo, "tns_shape_object"); laPushDifferences("Add primitives", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
+            laRecordInstanceDifferences(so, "tns_shape_object"); laPushDifferences("Add shape", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
         }
     }
     return LA_FINISHED;
@@ -2022,6 +2039,7 @@ void la_RegisterModellingOperators(){
     laAddEnumItemAs(p,"OBJECT","Object","Object context",LA_ADD_CTX_OBJECT,0);
     laAddEnumItemAs(p,"MESH","Mesh","Mesh context",LA_ADD_CTX_MESH,0);
     laAddEnumItemAs(p,"SHAPE","Shape","Shape context",LA_ADD_CTX_SHAPE,0);
+    laCreateOperatorType("M_select_linked", "Select Linked", "Select linked geometry or shapes", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_SelectLinked, 0, 0, LA_EXTRA_TO_PANEL);
 
     laCreateOperatorType("M_separate", "Separate", "Separate mesh parts", 0, 0, 0, OPINV_Separate, 0, 0, 0);
     laCreateOperatorType("M_combine", "Combine", "Combine mesh objects", 0, 0, 0, OPINV_Combine, 0, 0, 0);

+ 1 - 0
resources/la_widgets_viewers.c

@@ -1197,6 +1197,7 @@ void la_RegisterUiTypesViewerWidgets(){
     laAssignNewKey(km, 0, "M_knife", LA_KM_SEL_UI_EXTRA, 0, LA_KEY_DOWN, 'k', 0);
     laAssignNewKey(km, 0, "M_knife", LA_KM_SEL_UI_EXTRA, LA_KEY_CTRL, LA_KEY_DOWN, 'r', "mode=loop_cut");
     laAssignNewKey(km, 0, "M_merge", LA_KM_SEL_UI_EXTRA, LA_KEY_ALT, LA_KEY_DOWN, 'm', 0);
+    laAssignNewKey(km, 0, "M_select_linked", LA_KM_SEL_UI_EXTRA, LA_KEY_CTRL, LA_KEY_DOWN, 'l', 0);
 
     laAssignNewKey(km, 0, "M_set_point_handle", LA_KM_SEL_UI_EXTRA, 0, LA_KEY_DOWN, 'v', 0);
     laAssignNewKey(km, 0, "M_set_shape_closed", LA_KM_SEL_UI_EXTRA, 0, LA_KEY_DOWN, 'q', 0);