*/}}
ソースを参照

Basic hole display

YimingWu 1 年間 前
コミット
ed383dbe2f
3 ファイル変更46 行追加6 行削除
  1. 3 1
      la_tns.h
  2. 42 5
      la_tns_shape.c
  3. 1 0
      resources/la_widgets_viewers.c

+ 3 - 1
la_tns.h

@@ -733,9 +733,10 @@ STRUCTURE(tnsMaterialSlot){
 #define TNS_SPOINT_FREE    (1<<4)
 #define TNS_SPOINT_SELECTED_L (1<<5)
 #define TNS_SPOINT_SELECTED_R (1<<6)
-#define TNS_SPOINT_BEZIER (TNS_SPOINT_ALIGNED|TNS_SPOINT_FREE)
+#define TNS_SPOINT_BEZIER  (TNS_SPOINT_ALIGNED|TNS_SPOINT_FREE)
 #define TNS_SPOINT_SELECTED (TNS_MESH_FLAG_SELECTED|TNS_SPOINT_SELECTED_R|TNS_SPOINT_SELECTED_L)
 #define TNS_SHAPE_CLOSED   (1<<7)
+#define TNS_SHAPE_HOLE     (1<<8)
 
 STRUCTURE(tnsSPoint){
     laListItem Item;
@@ -1191,6 +1192,7 @@ void tnsEnsureMeshBatch(tnsMeshObject* mo);
 void tnsEvaluateMeshObject(tnsMeshObject* mo, tnsEvaluateData* ed);
 void tnsEvaluateShapeObject(tnsShapeObject* so, tnsEvaluateData* ed);
 
+void tnsShapeSetHole(tnsShape* s, int closed, int toggle);
 void tnsShapeSetClosed(tnsShape* s, int closed, int toggle);
 int tnsShapePointAnySelected(tnsShape* s);
 int tnsShapeAnySelected(tnsShapeObject* so);

+ 42 - 5
la_tns_shape.c

@@ -37,6 +37,10 @@ tnsSPoint* tnsShapeInsertSPointAt(tnsShape* s, tnsSPoint* pivot, int before){
     if(before){ lstInsertItemBefore(&s->Points,sp,pivot); }
     else{ lstInsertItemAfter(&s->Points,sp,pivot); }
 }
+void tnsShapeSetHole(tnsShape* s, int closed, int toggle){
+    if(toggle) tnsShapeSetHole(s,!(s->flags&TNS_SHAPE_HOLE),0);
+    else{ if(closed) s->flags|=TNS_SHAPE_HOLE; else s->flags&=(~TNS_SHAPE_HOLE); }
+}
 void tnsShapeSetClosed(tnsShape* s, int closed, int toggle){
     if(toggle) tnsShapeSetClosed(s,!(s->flags&TNS_SHAPE_CLOSED),0);
     else{ if(closed) s->flags|=TNS_SHAPE_CLOSED; else s->flags&=(~TNS_SHAPE_CLOSED); }
@@ -245,7 +249,7 @@ void tns_DrawShape(tnsShape* s, real* override_color, int DrawEdit, real PointSc
         nvgShapeAntiAlias(vg,1);
         return;
     }
-    nvgBeginPath(vg);
+    if(DrawEdit){ nvgBeginPath(vg); }
     tnsSPoint* sp1=s->Points.pFirst; nvgMoveTo(vg,sp1->p[0],sp1->p[1]); if(sp1->flags&TNS_SPOINT_SELECTED){HasSelection=1;}
     for(tnsSPoint* sp=sp1->Item.pNext;sp;sp=sp->Item.pNext){
         if(sp->flags&TNS_SPOINT_SELECTED){HasSelection=1;}
@@ -265,8 +269,10 @@ void tns_DrawShape(tnsShape* s, real* override_color, int DrawEdit, real PointSc
         if(sp->flags&TNS_SPOINT_BEZIER){ tnsVectorAccum2d(c2,sp->dl); }
         nvgBezierTo(vg,c1[0],c1[1],c2[0],c2[1],sp->p[0],sp->p[1]);
         nvgClosePath(vg);
-        nvgFillColor(vg, override_color?nvgRGBAf(LA_COLOR4(override_color)):nvgRGBAf(0.8,0.8,0.8,1));
-        nvgFill(vg);
+        nvgPathWinding(vg,(s->flags&TNS_SHAPE_HOLE)?NVG_HOLE:NVG_SOLID);
+        if(!(s->flags&TNS_SHAPE_HOLE)){
+            nvgFillColor(vg, override_color?nvgRGBAf(LA_COLOR4(override_color)):nvgRGBAf(0.8,0.8,0.8,1));
+        }
     }
     if(DrawEdit || (!closed)){
         tnsVector4d color; tnsVectorCopy4d(laAccentColor(LA_BT_VERTEX),color);
@@ -310,8 +316,18 @@ void tnsDrawShapeObjectShapes(tnsEvaluatedInstance* ei, la3DObjectDrawExtra* de,
         nvgTranslate(vg,ei->Mat[12],-ei->Mat[13]);
         nvgScale(vg,sca[0],-sca[1]); nvgRotate(vg,rot[2]);
     }
-    for(tnsShape*s=so->Shapes.pFirst;s;s=s->Item.pNext){
-        tns_DrawShape(s,override_color,DrawEdit?DrawEdit:(so->Mode==TNS_MESH_EDIT_MODE),de->PointScale/sca[0]);
+    if(DrawEdit!=2){ int begun=0; int ishole=0,nexthole=0;
+        for(tnsShape*s=so->Shapes.pFirst;s;s=s->Item.pNext){
+            if(!begun){ begun=1; nvgBeginPath(vg); }
+            ishole=s->flags&TNS_SHAPE_HOLE; tnsShape* ns=s->Item.pNext; nexthole=ns?(ns->flags&TNS_SHAPE_HOLE):0;
+            tns_DrawShape(s,override_color,0,de->PointScale/sca[0]);
+            if((!ns) || (ishole&&(!nexthole))){ nvgFill(vg); begun=0; }
+        }
+    }
+    if(DrawEdit||so->Mode==TNS_MESH_EDIT_MODE){
+        for(tnsShape*s=so->Shapes.pFirst;s;s=s->Item.pNext){
+            tns_DrawShape(s,override_color,DrawEdit?DrawEdit:so->Mode==TNS_MESH_EDIT_MODE,de->PointScale/sca[0]);
+        }
     }
     nvgRestore(vg);
 }
@@ -435,6 +451,26 @@ int OPINV_SetShapeClosed(laOperator *a, laEvent *e){
     }
     return LA_FINISHED;
 }
+int OPINV_SetShapeHole(laOperator *a, laEvent *e){
+    laCanvasExtra* ex=a->This->EndInstance; laUiItem* ui=ex->ParentUi;
+    tnsObject*root=ui?ui->PP.EndInstance:0;
+    if(!root || !root->Active || root->Active->Type!=TNS_OBJECT_SHAPE) return LA_FINISHED;
+    tnsShapeObject* so=root->Active; int ran=0;
+
+    char* mode=strGetArgumentString(a->ExtraInstructionsP,"mode");
+    int set=2; if(strSame(mode,"HOLE")){ set=1; }elif(strSame(mode,"FILL")){ set=0; }
+
+    for(tnsShape*s=so->Shapes.pFirst;s;s=s->Item.pNext){
+        for(tnsSPoint*sp=s->Points.pFirst;sp;sp=sp->Item.pNext){ if(!(sp->flags&TNS_SPOINT_SELECTED)) continue;
+            tnsShapeSetHole(s,set,set==2); ran=1; break;
+        }
+    }
+    if(ran){
+        laRecordInstanceDifferences(so,"tns_shape_object"); laPushDifferences("Open/Close shape",TNS_HINT_GEOMETRY);
+        laNotifyUsers("tns.world");
+    }
+    return LA_FINISHED;
+}
 void la_RegisterShapeOperators(){
     laPropContainer *pc; laProp *p;
     laOperatorType *at; laEnumProp *ep;
@@ -442,4 +478,5 @@ void la_RegisterShapeOperators(){
     at=laCreateOperatorType("M_set_point_handle", "Set Point Handle", "Set handle type of selected points",OPCHK_IsAnyPointSelected,0,0,OPINV_SetPointHandle,OPMOD_FinishOnData,0,0);
     at->UiDefine=laui_SetPointHandle;
     at=laCreateOperatorType("M_set_shape_closed", "Set Shape Closed", "Set shape closed or open",OPCHK_IsAnyPointSelected,0,0,OPINV_SetShapeClosed,0,0,0);
+    at=laCreateOperatorType("M_set_shape_hole", "Set Shape Hole", "Set shape as hole or fill",OPCHK_IsAnyPointSelected,0,0,OPINV_SetShapeHole,0,0,0);
 }

+ 1 - 0
resources/la_widgets_viewers.c

@@ -1201,4 +1201,5 @@ void la_RegisterUiTypesViewerWidgets(){
     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);
     laAssignNewKey(km, 0, "M_set_shape_closed", LA_KM_SEL_UI_EXTRA, LA_KEY_SHIFT, LA_KEY_DOWN, 'q', "reset=TRUE");
+    laAssignNewKey(km, 0, "M_set_shape_hole", LA_KM_SEL_UI_EXTRA, 0, LA_KEY_DOWN, 'n', 0);
 }