|
@@ -212,11 +212,11 @@ int OPINV_Select(laOperator *a, laEvent *e){
|
|
|
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);
|
|
|
- tnsInvaliateMeshBatch(mo);
|
|
|
+ tnsInvalidateMeshBatch(mo);
|
|
|
}else{
|
|
|
if(tnsAnyObjectsSelected(root)) tnsDeselectAllObjects(root); else tnsSelectAllObjects(root);
|
|
|
}
|
|
|
- laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world");
|
|
|
+ laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world", "Toggle selection",mo->Mode==TNS_MESH_EDIT_MODE?TNS_HINT_GEOMETRY:TNS_HINT_TRANSFORM);
|
|
|
return LA_FINISHED;
|
|
|
}
|
|
|
|
|
@@ -235,8 +235,8 @@ int OPINV_Select(laOperator *a, laEvent *e){
|
|
|
int id=la_SelectGetClosest(sd, e->x-ui->L, e->y-ui->U, LA_RH)-1;
|
|
|
void* p; if(id>=0 && id<sd->next){ p=sd->Refs[id]; }
|
|
|
la_DoMeshSelect(mo, p, ex->SelectMode, DeselectAll, 1, 1); tnsMMeshEnsureSelection(mo,ex->SelectMode);
|
|
|
- tnsInvaliateMeshBatch(mo);
|
|
|
- laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world");
|
|
|
+ tnsInvalidateMeshBatch(mo);
|
|
|
+ laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Mesh selection",TNS_HINT_GEOMETRY);
|
|
|
}else{
|
|
|
la_PopulateSelectDataObjects(sd,root,ex->ViewingCamera);
|
|
|
if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "box")){
|
|
@@ -247,7 +247,7 @@ int OPINV_Select(laOperator *a, laEvent *e){
|
|
|
int id=la_SelectGetClosest(sd, e->x-ui->L, e->y-ui->U, LA_RH*2);
|
|
|
if(id && id<sd->next){ la_DoObjectSelect(root, sd->Refs[id], ex, DeselectAll, 1, 1); }
|
|
|
else{ la_DoObjectSelect(root, 0, ex, DeselectAll, 1, 1); }
|
|
|
- laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world");
|
|
|
+ laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Object selection",TNS_HINT_TRANSFORM);
|
|
|
}
|
|
|
|
|
|
la_FreeSelectData(sd);
|
|
@@ -280,7 +280,7 @@ int OPMOD_Select(laOperator *a, laEvent *e){
|
|
|
la_DoMeshSelect(mo, p, ex->SelectMode, 0, !Remove, 0);
|
|
|
}
|
|
|
tnsMMeshEnsureSelection(mo,ex->SelectMode);
|
|
|
- tnsInvaliateMeshBatch(mo);
|
|
|
+ tnsInvalidateMeshBatch(mo);
|
|
|
}else{
|
|
|
la_DoObjectSelect(se->root, 0, ex, DeselectAll, 0, 0);
|
|
|
int len; int* ids=la_SelectGetBox(se->sd, ex->ClickedX, ex->ClickedY, e->x-ui->L, e->y-ui->U, &len);
|
|
@@ -288,7 +288,7 @@ int OPMOD_Select(laOperator *a, laEvent *e){
|
|
|
int id=ids[i]; if(id && id<se->sd->next){ la_DoObjectSelect(se->root, se->sd->Refs[id], ex, 0, !Remove, 0); }
|
|
|
}
|
|
|
}
|
|
|
- laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world");
|
|
|
+ laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Box selection",mo->Mode==TNS_MESH_EDIT_MODE?TNS_HINT_GEOMETRY:TNS_HINT_TRANSFORM);
|
|
|
ex->DrawCursor=0;
|
|
|
la_FreeSelectData(se->sd);
|
|
|
laRedrawCurrentPanel();
|
|
@@ -326,7 +326,7 @@ STRUCTURE(MTransformData){
|
|
|
void* Originals; int next,max;
|
|
|
int mode;
|
|
|
int LockAxis[3];
|
|
|
- int Local;
|
|
|
+ int UseLocal;
|
|
|
real DeltaVal, UserDeltaVal;
|
|
|
laStringEdit* Entry; int UseUserDelta;
|
|
|
};
|
|
@@ -400,9 +400,9 @@ void la_ApplyTranslation(MTransformData* td, int x, int y){
|
|
|
if(td->LockAxis[0]>0){ use_delta[1]=use_delta[2]=0; real l=fabs(use_delta[0]); use_delta[0]=l?use_delta[0]*len/l:1e-7; }
|
|
|
if(td->LockAxis[1]>0){ use_delta[0]=use_delta[2]=0; real l=fabs(use_delta[1]); use_delta[1]=l?use_delta[1]*len/l:1e-7; }
|
|
|
if(td->LockAxis[2]>0){ use_delta[0]=use_delta[1]=0; real l=fabs(use_delta[2]); use_delta[2]=l?use_delta[2]*len/l:1e-7; }
|
|
|
- if(td->LockAxis[0]<0){ use_delta[0]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l:0); }
|
|
|
- if(td->LockAxis[1]<0){ use_delta[1]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l:0); }
|
|
|
- if(td->LockAxis[2]<0){ use_delta[2]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l:0); }
|
|
|
+ if(td->LockAxis[0]<0){ use_delta[0]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l*len/l:0); }
|
|
|
+ if(td->LockAxis[1]<0){ use_delta[1]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l*len/l:0); }
|
|
|
+ if(td->LockAxis[2]<0){ use_delta[2]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l*len/l:0); }
|
|
|
td->DeltaVal=tnsLength3d(use_delta);
|
|
|
if(td->UseUserDelta){
|
|
|
tnsVectorMultiSelf3d(use_delta,1/tnsLength3d(use_delta)*td->UserDeltaVal);
|
|
@@ -414,14 +414,15 @@ void la_ApplyTranslation(MTransformData* td, int x, int y){
|
|
|
for(int i=0;i<td->next;i++){
|
|
|
MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject)); memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
|
|
|
if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
|
|
|
- tnsGlobalMatrixChanged(to->o, 0); tnsMoveObjectGlobal(to->o, LA_COLOR3(use_delta));
|
|
|
+ tnsGlobalMatrixChanged(to->o, 0);
|
|
|
+ if(td->UseLocal) tnsMoveObjectLocal(to->o, LA_COLOR3(use_delta)); else tnsMoveObjectGlobal(to->o, LA_COLOR3(use_delta));
|
|
|
}
|
|
|
}else{
|
|
|
tnsMakeTranslationMatrix44d(trans, LA_COLOR3(use_delta));
|
|
|
for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
|
|
|
- tnsApplyTransform43d(gp, trans, to->p); tnsApplyTransform43d(to->mv->p, td->obmatinv, gp);
|
|
|
+ tnsApplyTransform43d(gp, trans, to->p); if(!td->UseLocal) tnsApplyTransform43d(to->mv->p, td->obmatinv, gp); else tnsVectorCopy3d(gp, to->mv->p);
|
|
|
}
|
|
|
- tnsInvaliateMeshBatch(td->mo);
|
|
|
+ tnsInvalidateMeshBatch(td->mo);
|
|
|
}
|
|
|
}
|
|
|
void la_ApplyScale(MTransformData* td, int uix, int uiy){
|
|
@@ -441,7 +442,7 @@ void la_ApplyScale(MTransformData* td, int uix, int uiy){
|
|
|
for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
|
|
|
tnsApplyTransform43d(gp, final, to->p); tnsApplyTransform43d(to->mv->p, td->obmatinv, gp);
|
|
|
}
|
|
|
- tnsInvaliateMeshBatch(td->mo);
|
|
|
+ tnsInvalidateMeshBatch(td->mo);
|
|
|
}
|
|
|
}
|
|
|
void la_ApplyRotation(MTransformData* td, int uix, int uiy){
|
|
@@ -465,7 +466,7 @@ void la_ApplyRotation(MTransformData* td, int uix, int uiy){
|
|
|
for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
|
|
|
tnsApplyTransform43d(gp, final, to->p); tnsApplyTransform43d(to->mv->p, td->obmatinv, gp);
|
|
|
}
|
|
|
- tnsInvaliateMeshBatch(td->mo);
|
|
|
+ tnsInvalidateMeshBatch(td->mo);
|
|
|
}
|
|
|
}
|
|
|
void la_CancelTransformObjects(MTransformData* td){
|
|
@@ -477,17 +478,18 @@ void la_CancelTransformObjects(MTransformData* td){
|
|
|
}
|
|
|
}else{
|
|
|
for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert)); tnsVectorCopy3d(to->origp,to->mv->p); }
|
|
|
- tnsInvaliateMeshBatch(td->mo);
|
|
|
+ tnsInvalidateMeshBatch(td->mo);
|
|
|
}
|
|
|
}
|
|
|
void la_RecordTransformDifferences(MTransformData* td){
|
|
|
if(!td->mo){
|
|
|
for(int i=0;i<td->next;i++){ MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject));
|
|
|
laRecordInstanceDifferences(to->o, "tns_object");
|
|
|
- } laPushDifferences("Object Transformation", TNS_HINT_TRANSFORM);
|
|
|
+ } laPushDifferences(td->mode==LA_TRANSFORM_MODE_GRAB?"Moved objects":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotated objects":"Scaled objects", TNS_HINT_TRANSFORM);
|
|
|
}else{
|
|
|
- laRecordInstanceDifferences(td->mo, "tns_mesh_object"); laPushDifferences("Mesh transformation", TNS_HINT_GEOMETRY);
|
|
|
- tnsInvaliateMeshBatch(td->mo);
|
|
|
+ laRecordInstanceDifferences(td->mo, "tns_mesh_object");
|
|
|
+ laPushDifferences(td->mode==LA_TRANSFORM_MODE_GRAB?"Moved primitives":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotated primitives":"Scaled primitives", TNS_HINT_GEOMETRY);
|
|
|
+ tnsInvalidateMeshBatch(td->mo);
|
|
|
}
|
|
|
}
|
|
|
void la_FreeTransformData(MTransformData* td){
|
|
@@ -500,8 +502,9 @@ void la_MakeTransformOperatorHint(laOperator* a, MTransformData* td){
|
|
|
strSafePrint(&a->RuntimeHint, "%s ",
|
|
|
td->mode==LA_TRANSFORM_MODE_GRAB?"Grab":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotate":td->mode==LA_TRANSFORM_MODE_SCALE?"Scale":"");
|
|
|
char* entry=strGetEditString(td->Entry,0);
|
|
|
- strSafePrint(&a->RuntimeHint, "Delta: %.3lf [🔢 %s] 🆇🆈🆉 Lock axis: %s ", td->DeltaVal, (entry&&entry[0])?entry:"Type...",
|
|
|
- td->LockAxis[0]?"X":td->LockAxis[1]?"Y":td->LockAxis[2]?"Z":"None");
|
|
|
+ strSafePrint(&a->RuntimeHint, "Delta: %.3lf [🔢 %s] 🆇🆈🆉 Lock axis: %s 🈳 %s ", td->DeltaVal, (entry&&entry[0])?entry:"Type...",
|
|
|
+ td->LockAxis[0]?"X":td->LockAxis[1]?"Y":td->LockAxis[2]?"Z":"None",
|
|
|
+ td->UseLocal?"Global/[Local]":"[Global]/Local");
|
|
|
free(entry);
|
|
|
if(td->mode==LA_TRANSFORM_MODE_GRAB){ strSafePrint(&a->RuntimeHint, "🡅🆇🆈🆉 Reverse: %s ",
|
|
|
(td->LockAxis[0]<0||td->LockAxis[1]<0||td->LockAxis[2]<0)?"Yes":"No"); }
|
|
@@ -554,7 +557,7 @@ int OPMOD_Transformation(laOperator *a, laEvent *e){
|
|
|
MTransformData* td=a->CustomData;
|
|
|
|
|
|
if (e->Input=='x'||e->Input=='y'||e->Input=='z'||e->Input=='g'||e->Input=='s'||e->Input=='r'||
|
|
|
- e->Input=='X'||e->Input=='Y'||e->Input=='Z'){ /*pass*/ }
|
|
|
+ e->Input=='X'||e->Input=='Y'||e->Input=='Z'||e->Input==' '){ /*pass*/ }
|
|
|
else{ la_ProcessTextEdit(e, td->Entry, 0); }
|
|
|
|
|
|
char* entered;
|
|
@@ -571,6 +574,7 @@ int OPMOD_Transformation(laOperator *a, laEvent *e){
|
|
|
if(e->key=='g' && td->mode!=LA_TRANSFORM_MODE_GRAB){ td->mode=LA_TRANSFORM_MODE_GRAB; ex->DrawCursor=0; }
|
|
|
if(e->key=='s' && td->mode!=LA_TRANSFORM_MODE_SCALE){ td->mode=LA_TRANSFORM_MODE_SCALE; la_GetTransformInitialScale(td,ui,e->x,e->y);ex->DrawCursor=LA_CANVAS_CURSOR_ARROW; }
|
|
|
if(e->key=='r' && td->mode!=LA_TRANSFORM_MODE_ROTATE){ td->mode=LA_TRANSFORM_MODE_ROTATE; la_GetTransformInitialRotation(td,ui,e->x,e->y);ex->DrawCursor=LA_CANVAS_CURSOR_ARROW; }
|
|
|
+ if(e->key==' '){ td->UseLocal=!td->UseLocal; }
|
|
|
}
|
|
|
|
|
|
if(e->Type==LA_MOUSEMOVE || e->Type==LA_KEY_DOWN){
|
|
@@ -765,22 +769,27 @@ void la_ExtrudeMakeDuplication(MExtrudeExtra* ee){
|
|
|
ee->df[i].omf->flags&=(~TNS_MESH_FLAG_SELECTED);
|
|
|
ee->df[i].nmf->flags|=TNS_MESH_FLAG_SELECTED; }
|
|
|
}
|
|
|
-void la_ReconnectFaces(MExtrudeExtra* ee){
|
|
|
+void la_RemoveOriginalFaces(MExtrudeExtra* ee){
|
|
|
tnsMeshObject* mo=ee->mo;
|
|
|
if(ee->RemoveOriginalFaces){
|
|
|
for(int i=0;i<ee->nextf;i++){ tnsMMeshRemoveFaceOnly(mo, ee->df[i].omf); }
|
|
|
for(int i=0;i<ee->nexte;i++){ if(ee->de[i].IsBorder) continue; tnsMMeshRemoveEdgeFace(mo, ee->de[i].ome); }
|
|
|
for(int i=0;i<ee->nextv;i++){ if(ee->dv[i].IsBorder) continue; tnsMMeshRemoveVertEdgeFace(mo, ee->dv[i].omv); }
|
|
|
}
|
|
|
+}
|
|
|
+void la_ReconnectFaces(MExtrudeExtra* ee){
|
|
|
+ tnsMeshObject* mo=ee->mo;
|
|
|
for(int i=0;i<ee->nexte;i++){
|
|
|
if(!ee->de[i].IsBorder) continue; MEDupEdge*de=&ee->de[i];
|
|
|
tnsMMeshMakeFace4v(mo, de->ome->vl, de->ome->vr, de->nme->vr, de->nme->vl);
|
|
|
}
|
|
|
}
|
|
|
-void la_FinishExtrude(MExtrudeExtra* ee){
|
|
|
+void la_FinishExtrude(MExtrudeExtra* ee, int PushDifferences){
|
|
|
tnsMMeshRefreshIndex(ee->mo);
|
|
|
- tnsInvaliateMeshBatch(ee->mo);
|
|
|
- laRecordInstanceDifferences(ee->mo, "tns_mesh_object"); laPushDifferences("Extruded", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
|
|
|
+ tnsInvalidateMeshBatch(ee->mo);
|
|
|
+ if(PushDifferences){
|
|
|
+ laRecordInstanceDifferences(ee->mo, "tns_mesh_object"); laPushDifferences("Extruded", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
|
|
|
+ }
|
|
|
free(ee->dv); free(ee->de); free(ee->df); memFree(ee);
|
|
|
}
|
|
|
int OPINV_Extrude(laOperator *a, laEvent *e){
|
|
@@ -796,13 +805,14 @@ int OPINV_Extrude(laOperator *a, laEvent *e){
|
|
|
la_ExtrudeMakeDuplication(ee);
|
|
|
|
|
|
if(strSame(strGetArgumentString(a->ExtraInstructionsP,"duplicate_only"), "true")){
|
|
|
- la_FinishExtrude(ee);
|
|
|
+ la_FinishExtrude(ee, 1);
|
|
|
if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB)) return LA_RUNNING; return LA_FINISHED;
|
|
|
}
|
|
|
|
|
|
+ la_RemoveOriginalFaces(ee);
|
|
|
la_ReconnectFaces(ee);
|
|
|
|
|
|
- la_FinishExtrude(ee);
|
|
|
+ la_FinishExtrude(ee, 1);
|
|
|
if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB)) return LA_RUNNING; return LA_FINISHED;
|
|
|
|
|
|
return LA_FINISHED;
|
|
@@ -910,7 +920,7 @@ int OPINV_Delete(laOperator *a, laEvent *e){
|
|
|
}
|
|
|
tnsMMeshDeselectAll(mo);
|
|
|
tnsMMeshRefreshIndex(mo);
|
|
|
- tnsInvaliateMeshBatch(mo);
|
|
|
+ tnsInvalidateMeshBatch(mo);
|
|
|
laRecordInstanceDifferences(mo, "tns_mesh_object"); laPushDifferences("Deleted primitives", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
|
|
|
}
|
|
|
|
|
@@ -1044,13 +1054,146 @@ int OPINV_Make(laOperator *a, laEvent *e){
|
|
|
|
|
|
tnsMMeshRefreshIndex(mo);
|
|
|
tnsMMeshEnsureSelection(mo,ex->SelectMode);
|
|
|
- tnsInvaliateMeshBatch(mo);
|
|
|
+ tnsInvalidateMeshBatch(mo);
|
|
|
if(laRecordInstanceDifferences(mo, "tns_mesh_object")) laPushDifferences("Make primitives", TNS_HINT_GEOMETRY);
|
|
|
laNotifyUsers("tns.world");
|
|
|
|
|
|
return LA_FINISHED;
|
|
|
}
|
|
|
|
|
|
+int OPINV_Subdiv(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 LA_CANCELED; }
|
|
|
+
|
|
|
+ laListHandle pending={0}; for(tnsMEdge* me=mo->me.pFirst;me;me=me->Item.pNext){ if(me->flags&TNS_MESH_FLAG_SELECTED) lstAppendPointer(&pending, me); }
|
|
|
+ if(!pending.pFirst) return LA_FINISHED;
|
|
|
+ tnsMEdge* me; while(me=lstPopPointer(&pending)){ tnsMVert* mv=tnsMMeshEdgeInsertVertAt(mo,me,0.5,0,0,0); mv->flags|=TNS_MESH_FLAG_SELECTED; }
|
|
|
+
|
|
|
+ tnsMMeshRefreshIndex(mo);
|
|
|
+ tnsMMeshEnsureSelection(mo,ex->SelectMode);
|
|
|
+ tnsInvalidateMeshBatch(mo);
|
|
|
+ if(laRecordInstanceDifferences(mo, "tns_mesh_object")) laPushDifferences("Subdivide edges", TNS_HINT_GEOMETRY);
|
|
|
+ laNotifyUsers("tns.world");
|
|
|
+
|
|
|
+ return LA_FINISHED;
|
|
|
+}
|
|
|
+
|
|
|
+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;
|
|
|
+
|
|
|
+ if(mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){
|
|
|
+ if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"PLANE")){ tnsDeselectAllObjects(root);
|
|
|
+ no=tnsCreateMeshPlane(root, "Plane",0,0,0,10); 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"); }
|
|
|
+ }else{
|
|
|
+ if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"PLANE")){
|
|
|
+ tnsMMeshDeselectAll(mo); tnsAddMMeshPlane(mo, 10); 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; }
|
|
|
+ if(ran){
|
|
|
+ tnsMMeshRefreshIndex(mo); tnsInvalidateMeshBatch(mo);
|
|
|
+ laRecordInstanceDifferences(mo, "tns_mesh_object"); laPushDifferences("Add primitives", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return LA_FINISHED;
|
|
|
+}
|
|
|
+void laui_Add(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
|
|
|
+ laColumn* c=laFirstColumn(uil);
|
|
|
+ laShowItemFull(uil,c,pp,"_this_M_add",0,"mode=PLANE;text=Plane",0,0);
|
|
|
+}
|
|
|
+
|
|
|
+int OPINV_Separate(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;
|
|
|
+
|
|
|
+ if(mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){
|
|
|
+ return LA_CANCELED;
|
|
|
+ }
|
|
|
+ if(!tnsMMeshAnySelected(mo)) return LA_CANCELED;
|
|
|
+
|
|
|
+ MExtrudeExtra* ee=la_InitExtrude(mo);
|
|
|
+ la_ExtrudeMakeDuplication(ee);
|
|
|
+ ee->RemoveOriginalFaces=1;la_RemoveOriginalFaces(ee);
|
|
|
+
|
|
|
+ tnsMeshObject* no=tnsCreateMeshEmpty(mo->Base.ParentObject?mo->Base.ParentObject:mo->Base.InRoot, mo->Base.Name->Ptr, 0,0,0);
|
|
|
+ tnsCopyObjectTransformationsLocal(no,mo);
|
|
|
+ no->Mode=TNS_MESH_EDIT_MODE;
|
|
|
+ tnsMVert* nmv; for(tnsMVert* mv=mo->mv.pFirst;mv;mv=nmv){ nmv=mv->Item.pNext; if(!(mv->flags&TNS_MESH_FLAG_SELECTED))continue;
|
|
|
+ lstRemoveItem(&mo->mv, mv); lstAppendItem(&no->mv, mv); no->totmv++; mo->totmv--; }
|
|
|
+ tnsMEdge* nme; for(tnsMEdge* me=mo->me.pFirst;me;me=nme){ nme=me->Item.pNext; if(!(me->flags&TNS_MESH_FLAG_SELECTED))continue;
|
|
|
+ lstRemoveItem(&mo->me, me); lstAppendItem(&no->me, me); no->totme++; mo->totme--; }
|
|
|
+ tnsMFace* nmf; for(tnsMFace* mf=mo->mf.pFirst;mf;mf=nmf){ nmf=mf->Item.pNext; if(!(mf->flags&TNS_MESH_FLAG_SELECTED))continue;
|
|
|
+ lstRemoveItem(&mo->mf, mf); lstAppendItem(&no->mf, mf); no->totmf++; mo->totmf--; }
|
|
|
+ tnsMMeshRefreshIndex(no); tnsMeshLeaveEditMode(no);
|
|
|
+
|
|
|
+ la_FinishExtrude(ee, 0);
|
|
|
+
|
|
|
+ tnsMMeshRefreshIndex(mo); tnsInvalidateMeshBatch(mo);
|
|
|
+ laRecordAndPush(0,"tns.world","Separate mesh parts",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
|
|
|
+
|
|
|
+ return LA_FINISHED;
|
|
|
+}
|
|
|
+
|
|
|
+void la_PopulateSelectedMeshObjects(tnsObject* root, laListHandle* l){
|
|
|
+ if(root->Type==TNS_OBJECT_MESH && root->Flags&TNS_OBJECT_FLAGS_SELECTED){ lstAppendPointer(l,root); }
|
|
|
+ for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
|
|
|
+ la_PopulateSelectedMeshObjects(lip->p, l);
|
|
|
+ }
|
|
|
+}
|
|
|
+int OPINV_Combine(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;
|
|
|
+
|
|
|
+ if(!mo || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode==TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
|
|
|
+
|
|
|
+ laListHandle pending={0}; la_PopulateSelectedMeshObjects(root,&pending);
|
|
|
+ tnsMeshObject* o; while(o=lstPopPointer(&pending)){ if(o==mo || o->Mode==TNS_MESH_EDIT_MODE) continue;
|
|
|
+ if(tnsMergeMeshObjects(mo, o)) ran++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(ran){
|
|
|
+ tnsMMeshRefreshIndex(mo); tnsInvalidateMeshBatch(mo);
|
|
|
+ laRecordAndPush(0,"tns.world","Merge mesh objects",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
|
|
|
+ }
|
|
|
+
|
|
|
+ return LA_FINISHED;
|
|
|
+}
|
|
|
+
|
|
|
+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;
|
|
|
+
|
|
|
+ if(!mo || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode==TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
|
|
|
+
|
|
|
+ laListHandle pending={0}; la_PopulateSelectedMeshObjects(root,&pending);
|
|
|
+ tnsMeshObject* o; tnsMeshObject* no;while(o=lstPopPointer(&pending)){ if(o->Mode==TNS_MESH_EDIT_MODE) continue;
|
|
|
+ if(no=tnsDuplicateMeshObjects(o)){ no->Base.Flags|=TNS_OBJECT_FLAGS_SELECTED; o->Base.Flags&=(~TNS_OBJECT_FLAGS_SELECTED);
|
|
|
+ if(mo==o){ memAssignRef(root,&root->Active,no); } ran++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(ran){
|
|
|
+ laRecordAndPush(0,"tns.world","Merge mesh objects",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
|
|
|
+ if(la_InitTransform(a,e,LA_TRANSFORM_MODE_GRAB)) return LA_RUNNING; return LA_FINISHED;
|
|
|
+ }
|
|
|
+
|
|
|
+ return LA_FINISHED;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
void la_RegisterModellingOperators(){
|
|
|
laPropContainer *pc; laProp *p;
|
|
|
laOperatorType *at;
|
|
@@ -1070,5 +1213,10 @@ void la_RegisterModellingOperators(){
|
|
|
at=laCreateOperatorType("M_delete", "Delete", "Delete parts of the mesh", 0, 0, 0, OPINV_Delete, OPMOD_FinishOnData, 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;
|
|
|
+ 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);
|
|
|
+ laCreateOperatorType("M_duplicate", "Duplicate", "Duplicate objects", 0, 0, 0, OPINV_Duplicate, OPMOD_Transformation, 0, 0);
|
|
|
}
|