|
@@ -76,10 +76,16 @@ int OPINV_ToggleEdit(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) return 0;
|
|
|
- if(mo->Base.Type!=TNS_OBJECT_MESH) return LA_CANCELED;
|
|
|
- if(mo->Mode==TNS_MESH_EDIT_MODE) tnsMeshLeaveEditMode(mo); else tnsMeshEnterEditMode(mo);
|
|
|
- laRecordInstanceDifferences(mo, "tns_mesh_object"); laPushDifferences("Toggle edit mode", TNS_HINT_GEOMETRY);
|
|
|
+ tnsObject* o=root->Active; if(!o) return 0;
|
|
|
+ char* ObType=0;
|
|
|
+ if(o->Type==TNS_OBJECT_MESH){ tnsMeshObject* mo=o; ObType="tns_mesh_object";
|
|
|
+ if(mo->Mode==TNS_MESH_EDIT_MODE) tnsMeshLeaveEditMode(mo); else tnsMeshEnterEditMode(mo);
|
|
|
+ }elif(o->Type==TNS_OBJECT_SHAPE){ tnsShapeObject* so=o; ObType="tns_shape_object";
|
|
|
+ if(so->Mode==TNS_MESH_EDIT_MODE) tnsShapeLeaveEditMode(so); else tnsShapeEnterEditMode(so);
|
|
|
+ }else{
|
|
|
+ return LA_CANCELED;
|
|
|
+ }
|
|
|
+ laRecordInstanceDifferences(o, ObType); laPushDifferences("Toggle edit mode", TNS_HINT_GEOMETRY);
|
|
|
laNotifyUsers("tns.world");
|
|
|
return LA_FINISHED_PASS;
|
|
|
}
|
|
@@ -119,9 +125,9 @@ void la_PopulateSelectDataObjects(MSelectData* sd, tnsObject* root, laCanvasExtr
|
|
|
tnsViewportWithScissor(0,0,w,h);tnsResetViewMatrix();tnsResetModelMatrix();tnsResetProjectionMatrix();
|
|
|
|
|
|
NVGcontext* vg=MAIN.CurrentWindow->nvg;
|
|
|
- la3DObjectDrawExtra de={0}; de.W=w; de.H=h;
|
|
|
+ la3DObjectDrawExtra de={0}; de.W=w; de.H=h; de.PointScale=1.0f/LA_RH;
|
|
|
tnsMatrix44d mview,mproj; tnsRootObject* ro=root;
|
|
|
- if(ro && ro->Is2D){ la_SetCanvasOrtho(e,w,h); }
|
|
|
+ if(ro && ro->Is2D){ la_SetCanvasOrtho(e,w,h); de.PointScale=e->ZoomX; }
|
|
|
else{ tnsApplyCameraView(w, h, camera, mview,mproj); tnsMultiply44d(de.mViewProj,mproj,mview); de.Is3D=1; }
|
|
|
la_BeginNVG(vg,e,w,h,ro->Is2D);
|
|
|
|
|
@@ -136,7 +142,7 @@ void la_PopulateSelectVerts(MSelectData* sd, tnsMeshObject* mo){
|
|
|
arrEnsureLength(&sd->RefsV,0,&sd->maxV,sizeof(tnsMVert*));
|
|
|
if(mo->Base.Type!=TNS_OBJECT_MESH||!mo->mv.pFirst){ return; }
|
|
|
for(tnsMVert* v=mo->mv.pFirst;v;v=v->Item.pNext){
|
|
|
- arrEnsureLength(&sd->RefsV, v->i, &sd->maxV, sizeof(tnsObject*));
|
|
|
+ arrEnsureLength(&sd->RefsV, v->i, &sd->maxV, sizeof(tnsMVert*));
|
|
|
sd->RefsV[v->i]=v; sd->nextV=TNS_MAX2(v->i, sd->nextV);
|
|
|
}
|
|
|
sd->nextV++;
|
|
@@ -150,32 +156,63 @@ void la_PopulateSelectEdges(MSelectData* sd, tnsMeshObject* mo){
|
|
|
}
|
|
|
sd->nextE++;
|
|
|
}
|
|
|
-void la_PopulateSelectDataPrimitives(MSelectData* sd, tnsMeshObject* mo, tnsCamera* camera, int WhatPrim, int SelectThrough){
|
|
|
+void la_PopulateSelectPoints(MSelectData* sd, tnsShapeObject* so){
|
|
|
+ sd->nextV=0;
|
|
|
+ arrEnsureLength(&sd->RefsV,sd->nextV,&sd->maxV,sizeof(tnsSPoint*));
|
|
|
+ if(so->Base.Type!=TNS_OBJECT_SHAPE||!so->Shapes.pFirst){ return; }
|
|
|
+ for(tnsShape*s=so->Shapes.pFirst;s;s=s->Item.pNext){
|
|
|
+ for(tnsSPoint*sp=s->Points.pFirst;sp;sp=sp->Item.pNext){
|
|
|
+ arrEnsureLength(&sd->RefsV, sd->nextV, &sd->maxV, sizeof(tnsSPoint*));
|
|
|
+ sd->RefsV[sd->nextV]=sp; sd->nextV++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sd->nextV++;
|
|
|
+}
|
|
|
+void la_PopulateSelectDataPrimitives(MSelectData* sd, tnsObject* o, tnsCamera* camera, int WhatPrim, tnsObject* root, laCanvasExtra* e){
|
|
|
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); }
|
|
|
- if(DoEdges || Knife){ la_PopulateSelectEdges(sd,mo); }
|
|
|
+ tnsMeshObject* mo=o; tnsShapeObject* so=o;
|
|
|
+ if(o->Type==TNS_OBJECT_MESH){
|
|
|
+ if(DoVerts || Knife){ la_PopulateSelectVerts(sd,mo); }
|
|
|
+ if(DoEdges || Knife){ la_PopulateSelectEdges(sd,mo); }
|
|
|
+ }elif(o->Type==TNS_OBJECT_SHAPE){
|
|
|
+ la_PopulateSelectPoints(sd,so);
|
|
|
+ }
|
|
|
int w=sd->Color->Width, h=sd->Color->Height;
|
|
|
tnsUnbindTexture(); tnsUniformUseTexture(T->immShader,0,0); tnsUseMultiplyColor(0);
|
|
|
tnsEnableShaderv(T->SelectionShader);
|
|
|
tnsViewportWithScissor(0,0,w,h);tnsResetViewMatrix();tnsResetModelMatrix();tnsResetProjectionMatrix();
|
|
|
- tnsApplyCameraView(w,h,camera,0,0);
|
|
|
+
|
|
|
+ NVGcontext* vg=MAIN.CurrentWindow->nvg;
|
|
|
+ la3DObjectDrawExtra de={0}; de.W=w; de.H=h; de.PointScale=1.0f/LA_RH;
|
|
|
+ tnsMatrix44d mview,mproj; tnsRootObject* ro=root;
|
|
|
+ if(ro && ro->Is2D){ la_SetCanvasOrtho(e,w,h); de.PointScale=e->ZoomX; }
|
|
|
+ else{ tnsApplyCameraView(w, h, camera, mview,mproj); tnsMultiply44d(de.mViewProj,mproj,mview); de.Is3D=1; }
|
|
|
+ la_BeginNVG(vg,e,w,h,ro->Is2D);
|
|
|
+
|
|
|
glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
|
|
|
- tnsPushMatrix(); tnsApplyModelMatrix(mo->Base.GlobalTransform);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);
|
|
|
+ tnsPushMatrix(); tnsApplyModelMatrix(o->GlobalTransform);glEnable(GL_DEPTH_TEST);
|
|
|
+ if(o->Type==TNS_OBJECT_MESH){
|
|
|
+ if(!e->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(o->Type==TNS_OBJECT_MESH){
|
|
|
+ if(DoEdges || Knife){ tnsDrawBatch(mo->Batch, "edges_select",0,0); }
|
|
|
+ if(DoVerts || Knife){ tnsDrawBatch(mo->Batch, "verts_select",0,0); }
|
|
|
+ }elif(o->Type==TNS_OBJECT_SHAPE){
|
|
|
+ tnsEvaluatedInstance ei; memcpy(&ei.Mat,o->GlobalTransform,sizeof(tnsMatrix44d)); ei.Object=o;
|
|
|
+ tnsDrawShapePointsSelectionID(&ei,&de);
|
|
|
+ }
|
|
|
tnsUniformUseOffset(T->SelectionShader,0);
|
|
|
tnsPopMatrix();
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
- tnsEnableShaderv(T->immShader);
|
|
|
+ nvgEndFrame(vg); tnsRestoreFromNanoVG(); tnsEnableShaderv(T->immShader);
|
|
|
}
|
|
|
void la_PadSelectionBuffer(uint8_t* buf, int w, int h, int sx, int sy, int ex, int ey, int real_endx){
|
|
|
if(!sx&&!sy&&!ex&&!ey) return;
|
|
@@ -289,6 +326,9 @@ void la_DoMeshSelect(tnsMeshObject* mo, void* p, int WhatPrim, int DeselectAll,
|
|
|
if(p){ if(WhatPrim==LA_CANVAS_SELECT_MODE_VERTS) tnsMMeshSelectVert(mo,p,Select,Toggle);
|
|
|
elif(WhatPrim==LA_CANVAS_SELECT_MODE_EDGES) tnsMMeshSelectEdge(mo,p,Select,Toggle); }
|
|
|
}
|
|
|
+void la_DoShapeSelect(tnsShapeObject* so, void* p, int DeselectAll, int Select, int Toggle){
|
|
|
+ if(DeselectAll){ tnsShapeDeselectAll(so); } if(p) tnsShapeSelectPoint(so,p,Select,Toggle);
|
|
|
+}
|
|
|
|
|
|
#define LA_SELECT_MODE_BOX 1
|
|
|
STRUCTURE(MSelectExtra){
|
|
@@ -308,13 +348,16 @@ int OPINV_Select(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;
|
|
|
+ tnsObject* o=root->Active; tnsMeshObject* mo=o; tnsShapeObject* so=o;
|
|
|
|
|
|
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(o && o->Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
|
|
|
if(tnsMMeshAnySelected(mo)) tnsMMeshDeselectAll(mo); else tnsMMeshSelectAll(mo);
|
|
|
tnsInvalidateMeshBatch(mo); is_geo=1;
|
|
|
+ }elif(o && o->Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){ is_geo=1;
|
|
|
+ if(tnsShapeAnySelected(so)) tnsShapeDeselectAll(so); else tnsShapeSelectAll(so);
|
|
|
+ //tnsInvalidateMeshBatch(mo);
|
|
|
}else{
|
|
|
if(tnsAnyObjectsSelected(root)) tnsDeselectAllObjects(root); else tnsSelectAllObjects(root);
|
|
|
}
|
|
@@ -330,8 +373,8 @@ int OPINV_Select(laOperator *a, laEvent *e){
|
|
|
int DeselectAll=1;
|
|
|
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, ex->SelectThrough);
|
|
|
+ if(o&&o->Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
|
|
|
+ la_PopulateSelectDataPrimitives(sd, mo, ex->ViewingCamera, SelectMode, root, ex);
|
|
|
if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "box")){
|
|
|
MSelectExtra* se=memAcquire(sizeof(MSelectExtra));
|
|
|
ex->OnX=e->x; ex->OnX=e->y;
|
|
@@ -345,6 +388,18 @@ int OPINV_Select(laOperator *a, laEvent *e){
|
|
|
}
|
|
|
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){
|
|
|
+ la_PopulateSelectDataPrimitives(sd, mo, ex->ViewingCamera, SelectMode, root, ex);
|
|
|
+ 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);
|
|
|
+ la_DoShapeSelect(mo, p, DeselectAll, 1, 1);
|
|
|
+ if(ring_band && p){ tnsShapeSelectRingFrom(mo,p,1,Append); }
|
|
|
+ laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Shape selection",TNS_HINT_GEOMETRY);
|
|
|
}else{
|
|
|
la_PopulateSelectDataObjects(sd,root,ex);
|
|
|
if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "box")){
|
|
@@ -366,7 +421,7 @@ int OPMOD_Select(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;
|
|
|
+ tnsObject* o=root->Active; tnsMeshObject* mo=o; tnsShapeObject* so=o;
|
|
|
MSelectExtra* se=a->CustomData;
|
|
|
|
|
|
if(e->Type==LA_L_MOUSE_DOWN){ se->InSelect=1; ex->DrawCursor=2; ex->ClickedX=e->x; ex->ClickedY=e->y; laRedrawCurrentPanel(); }
|
|
@@ -381,7 +436,7 @@ int OPMOD_Select(laOperator *a, laEvent *e){
|
|
|
|
|
|
int is_geo=0;
|
|
|
if(se->InSelect && e->Type==LA_L_MOUSE_UP){
|
|
|
- if(mo && mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
|
|
|
+ if(o && o->Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){ is_geo=1;
|
|
|
la_DoMeshSelect(mo, 0, ex->SelectMode, DeselectAll, 0, 0);
|
|
|
int len; int* ids=la_SelectGetBox(se->sd, ex->ClickedX-ui->L, ex->ClickedY-ui->U, e->x-ui->L, e->y-ui->U, &len);
|
|
|
for(int i=0;i<len;i++){
|
|
@@ -389,7 +444,14 @@ int OPMOD_Select(laOperator *a, laEvent *e){
|
|
|
la_DoMeshSelect(mo, p, ex->SelectMode, 0, !Remove, 0);
|
|
|
}
|
|
|
tnsMMeshEnsureSelection(mo,ex->SelectMode);
|
|
|
- tnsInvalidateMeshBatch(mo); is_geo=1;
|
|
|
+ tnsInvalidateMeshBatch(mo);
|
|
|
+ }elif(o && o->Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){ is_geo=1;
|
|
|
+ la_DoShapeSelect(so, 0, DeselectAll, 0, 0);
|
|
|
+ int len; int* ids=la_SelectGetBox(se->sd, ex->ClickedX-ui->L, ex->ClickedY-ui->U, e->x-ui->L, e->y-ui->U, &len);
|
|
|
+ for(int i=0;i<len;i++){
|
|
|
+ int id=ids[i]-1; void* p=la_SelectGetRef(se->sd,id,ex->SelectMode==LA_CANVAS_SELECT_MODE_EDGES?TNS_MMESH_EDGE_BIT:0);
|
|
|
+ la_DoShapeSelect(so, p, 0, !Remove, 0);
|
|
|
+ }
|
|
|
}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);
|
|
@@ -428,13 +490,19 @@ STRUCTURE(MTOrigMVert){
|
|
|
tnsVector3d origp;
|
|
|
tnsMVert* mv;
|
|
|
};
|
|
|
+STRUCTURE(MTOrigSPoint){
|
|
|
+ tnsVector2d p;
|
|
|
+ tnsVector2d origp;
|
|
|
+ tnsSPoint* sp;
|
|
|
+};
|
|
|
STRUCTURE(MTransformData){
|
|
|
tnsMatrix44d Delta;
|
|
|
tnsMatrix44d ViewProjection;
|
|
|
tnsVector4d Up,Right,Foward;
|
|
|
tnsVector4d TCenter,TLCenter;
|
|
|
int CenterX,CenterY; real Initial;
|
|
|
- tnsObject* mo; tnsMatrix44d obmatinv,deltainv;
|
|
|
+ tnsObject* mo; tnsShapeObject* so;
|
|
|
+ tnsMatrix44d obmatinv,deltainv;
|
|
|
tnsCamera* c; tnsObject* root;
|
|
|
int w,h;
|
|
|
void* Originals; int next,max;
|
|
@@ -511,10 +579,32 @@ int la_PopulateTransformVerticies(MTransformData* td, tnsMeshObject* mo){
|
|
|
la_GetTransformCenter2D(td);
|
|
|
return any;
|
|
|
}
|
|
|
+int la_PopulateTransformPoints(MTransformData* td, tnsShapeObject* so){
|
|
|
+ int any=0; td->so=so; td->next=0;
|
|
|
+ arrEnsureLength(&td->Originals, 0, &td->max, sizeof(MTOrigSPoint));
|
|
|
+ tnsInverse44d(td->obmatinv, so->Base.GlobalTransform);
|
|
|
+ tnsInverse44d(td->deltainv, so->Base.DeltaTransform);
|
|
|
+ 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_MESH_FLAG_SELECTED)) continue;
|
|
|
+ arrEnsureLength(&td->Originals, td->next, &td->max, sizeof(MTOrigSPoint));
|
|
|
+ MTOrigSPoint* to=arrElement(td->Originals, td->next, sizeof(MTOrigSPoint)); td->next++; to->sp=sp;
|
|
|
+ tnsVector3d tp; tnsVector3d fp={sp->p[0],sp->p[1],0};
|
|
|
+ tnsApplyTransform43d(tp, so->Base.GlobalTransform, fp);
|
|
|
+ tnsVectorSet2v(to->p,tp); tnsVectorSet2v(to->origp,sp->p); any++;
|
|
|
+ tnsVectorAccum2d(td->TCenter,to->p);
|
|
|
+ tnsVectorAccum2d(td->TLCenter,sp->p);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ tnsVectorMultiSelf2d(td->TCenter, 1.0f/any);
|
|
|
+ tnsVectorMultiSelf2d(td->TLCenter, 1.0f/any);
|
|
|
+ la_GetTransformCenter2D(td);
|
|
|
+ return any;
|
|
|
+}
|
|
|
void la_ApplyTranslation(MTransformData* td, int x, int y){
|
|
|
tnsMatrix44d trans; tnsVector3d deltay,delta; tnsVector3d gp; tnsVector3d use_delta;
|
|
|
- if(td->Is2D){
|
|
|
- use_delta[0]=x*td->zoomx; use_delta[1]=-y*td->zoomy; use_delta[2]=0;
|
|
|
+ if(td->Is2D || td->so){
|
|
|
+ use_delta[0]=x*(td->so?(1.0f/LA_RH):td->zoomx); use_delta[1]=-y*(td->so?(1.0f/LA_RH):td->zoomy); use_delta[2]=0;
|
|
|
if(td->LockAxis[0]){ use_delta[1]=0; } if(td->LockAxis[1]){ use_delta[0]=0; }
|
|
|
}else{
|
|
|
tnsVectorMulti3d(delta, td->Right, x); tnsVectorMulti3d(deltay, td->Up, y); tnsVectorAccum3d(delta, deltay);
|
|
@@ -534,7 +624,23 @@ void la_ApplyTranslation(MTransformData* td, int x, int y){
|
|
|
real dir=tnsDot3d(use_delta, lock, 0); tnsVectorMultiSelf3d(use_delta,(td->UserDeltaVal*dir<=0)?-1:1);
|
|
|
td->DeltaVal=td->UserDeltaVal;
|
|
|
}
|
|
|
- if(!td->mo){
|
|
|
+ if(td->mo){
|
|
|
+ tnsMakeTranslationMatrix44d(trans, LA_COLOR3(use_delta)); tnsMatrix44d final;
|
|
|
+ if(!td->UseLocal) tnsMultiply44d(final,td->obmatinv,trans);
|
|
|
+ else tnsMultiply44d(final,trans,td->obmatinv);
|
|
|
+ for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
|
|
|
+ tnsApplyTransform43d(to->mv->p, final, to->p);
|
|
|
+ }
|
|
|
+ tnsInvalidateMeshBatch(td->mo); tnsMMeshCalculateNormal(td->mo);
|
|
|
+ }elif(td->so){
|
|
|
+ tnsMakeTranslationMatrix44d(trans, LA_COLOR3(use_delta)); tnsMatrix44d final;
|
|
|
+ if(!td->UseLocal) tnsMultiply44d(final,td->obmatinv,trans);
|
|
|
+ else tnsMultiply44d(final,trans,td->obmatinv);
|
|
|
+ for(int i=0;i<td->next;i++){ MTOrigSPoint* to=arrElement(td->Originals, i, sizeof(MTOrigSPoint));
|
|
|
+ tnsVector3d fp={to->p[0],to->p[1],0}, tp;
|
|
|
+ tnsApplyTransform43d(tp, final, fp); tnsVectorSet3v(to->sp->p,tp);
|
|
|
+ }
|
|
|
+ }else{
|
|
|
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; }
|
|
@@ -547,30 +653,15 @@ void la_ApplyTranslation(MTransformData* td, int x, int y){
|
|
|
else tnsMoveObjectGlobal(to->o, LA_COLOR3(use_delta));
|
|
|
}
|
|
|
}
|
|
|
- }else{
|
|
|
- tnsMakeTranslationMatrix44d(trans, LA_COLOR3(use_delta)); tnsMatrix44d final;
|
|
|
- if(!td->UseLocal) tnsMultiply44d(final,td->obmatinv,trans);
|
|
|
- else tnsMultiply44d(final,trans,td->obmatinv);
|
|
|
- for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
|
|
|
- tnsApplyTransform43d(to->mv->p, final, to->p);
|
|
|
- }
|
|
|
- tnsInvalidateMeshBatch(td->mo); tnsMMeshCalculateNormal(td->mo);
|
|
|
}
|
|
|
}
|
|
|
void la_ApplyScale(MTransformData* td, int uix, int uiy){
|
|
|
tnsMatrix44d trans; real d=tnsDistIdv2(uix,uiy,td->CenterX,td->CenterY); if(!td->Initial){ td->Initial=100; }
|
|
|
real s=d/td->Initial; tnsVector3d gp;
|
|
|
td->DeltaVal=s; if(td->UseUserDelta) td->DeltaVal=s=td->UserDeltaVal;
|
|
|
- if(!td->mo){
|
|
|
- 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; }
|
|
|
- if(td->CanvasDeltaMode) tnsGlobalMatrixChangedForDelta(to->o, 0); else tnsGlobalMatrixChanged(to->o, 0);
|
|
|
- if(td->CanvasDeltaMode) tnsScaleObjectDelta(to->o,s,s,s,LA_COLOR3(td->TCenter));
|
|
|
- else tnsScaleObject(to->o, s,s,s, LA_COLOR3(td->TCenter));
|
|
|
- }
|
|
|
- }else{
|
|
|
- tnsVector3d use_delta={s,s,s};
|
|
|
+ tnsMatrix44d t1,t2,t3,final;
|
|
|
+ if(td->mo || td->so){
|
|
|
+ tnsVector3d use_delta={s,s,s};\
|
|
|
if(td->LockAxis[0]>0){ use_delta[1]=use_delta[2]=1;}
|
|
|
if(td->LockAxis[1]>0){ use_delta[0]=use_delta[2]=1;}
|
|
|
if(td->LockAxis[2]>0){ use_delta[0]=use_delta[1]=1;}
|
|
@@ -578,26 +669,59 @@ void la_ApplyScale(MTransformData* td, int uix, int uiy){
|
|
|
if(td->LockAxis[1]<0){ use_delta[1]=1; }
|
|
|
if(td->LockAxis[2]<0){ use_delta[2]=1; }
|
|
|
tnsMakeScaleMatrix44d(trans,LA_COLOR3(use_delta));
|
|
|
- tnsMatrix44d t1,t2,t3; tnsMakeTranslationMatrix44d(t1,LA_COLOR3(td->TCenter)); tnsInverse44d(t2,t1);
|
|
|
- tnsMatrix44d final; tnsMultiply44d(t3,t1,trans); tnsMultiply44d(t1,t3,t2);
|
|
|
+ tnsMakeTranslationMatrix44d(t1,LA_COLOR3(td->TCenter)); tnsInverse44d(t2,t1);
|
|
|
+ tnsMultiply44d(t3,t1,trans); tnsMultiply44d(t1,t3,t2);
|
|
|
if(!td->UseLocal) tnsMultiply44d(final,td->obmatinv,t1);
|
|
|
else tnsMultiply44d(final,t1,td->obmatinv);
|
|
|
+ }
|
|
|
+ if(td->mo){
|
|
|
for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
|
|
|
tnsApplyTransform43d(to->mv->p, final, to->p);
|
|
|
}
|
|
|
tnsInvalidateMeshBatch(td->mo); tnsMMeshCalculateNormal(td->mo);
|
|
|
+ }elif(td->so){
|
|
|
+ for(int i=0;i<td->next;i++){ MTOrigSPoint* to=arrElement(td->Originals, i, sizeof(MTOrigSPoint));
|
|
|
+ tnsVector3d fp={to->p[0],to->p[1],0}, tp;
|
|
|
+ tnsApplyTransform43d(tp, final, fp); tnsVectorSet3v(to->sp->p,tp);
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ 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; }
|
|
|
+ if(td->CanvasDeltaMode) tnsGlobalMatrixChangedForDelta(to->o, 0); else tnsGlobalMatrixChanged(to->o, 0);
|
|
|
+ if(td->CanvasDeltaMode) tnsScaleObjectDelta(to->o,s,s,s,LA_COLOR3(td->TCenter));
|
|
|
+ else tnsScaleObject(to->o, s,s,s, LA_COLOR3(td->TCenter));
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
void la_ApplyRotation(MTransformData* td, int uix, int uiy){
|
|
|
tnsMatrix44d trans; real a=atan2(uiy-td->CenterY,uix-td->CenterX);
|
|
|
real angle=a-td->Initial; tnsVector3d gp; tnsVector3d LimFoward={0}; real* use_forward=td->Foward;
|
|
|
- if(td->Is2D){ use_forward=LimFoward; LimFoward[2]=1; }
|
|
|
+ tnsMatrix44d t1,t2,t3,final;
|
|
|
+ if(td->Is2D || td->so){ use_forward=LimFoward; LimFoward[2]=1; }
|
|
|
if(td->LockAxis[0]||td->LockAxis[1]||td->LockAxis[2]){ use_forward=LimFoward; }
|
|
|
if(td->LockAxis[0]){ LimFoward[0]=1; LimFoward[2]=0; }
|
|
|
if(td->LockAxis[1]){ LimFoward[1]=1; LimFoward[2]=0; }
|
|
|
if(td->LockAxis[2]){ LimFoward[2]=1; }
|
|
|
if(td->UseUserDelta) angle=rad(td->UserDeltaVal); td->DeltaVal=deg(angle);
|
|
|
- if(!td->mo){
|
|
|
+ if(td->mo||td->so){
|
|
|
+ tnsMakeRotationMatrix44d(trans, angle, LA_COLOR3(use_forward));
|
|
|
+ tnsMakeTranslationMatrix44d(t1,LA_COLOR3(td->UseLocal?td->TLCenter:td->TCenter)); tnsInverse44d(t2,t1);
|
|
|
+ tnsMultiply44d(t3,t1,trans); tnsMultiply44d(t1,t3,t2);
|
|
|
+ if(!td->UseLocal) tnsMultiply44d(final,td->obmatinv,t1);
|
|
|
+ else tnsMultiply44d(final,t1,td->obmatinv);
|
|
|
+ }
|
|
|
+ if(td->mo){
|
|
|
+ for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
|
|
|
+ tnsApplyTransform43d(to->mv->p, final, to->p);
|
|
|
+ }
|
|
|
+ tnsInvalidateMeshBatch(td->mo); tnsMMeshCalculateNormal(td->mo);
|
|
|
+ }elif(td->so){
|
|
|
+ for(int i=0;i<td->next;i++){ MTOrigSPoint* to=arrElement(td->Originals, i, sizeof(MTOrigSPoint));
|
|
|
+ tnsVector3d fp={to->p[0],to->p[1],0}, tp;
|
|
|
+ tnsApplyTransform43d(tp, final, fp); tnsVectorSet3v(to->sp->p,tp);
|
|
|
+ }
|
|
|
+ }else{
|
|
|
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; }
|
|
@@ -610,40 +734,36 @@ void la_ApplyRotation(MTransformData* td, int uix, int uiy){
|
|
|
else tnsRotateObjectGlobal(to->o,LA_COLOR3(use_forward),angle,LA_COLOR3(td->TCenter));
|
|
|
}
|
|
|
}
|
|
|
- }else{
|
|
|
- tnsMakeRotationMatrix44d(trans, angle, LA_COLOR3(use_forward));
|
|
|
- tnsMatrix44d t1,t2,t3; tnsMakeTranslationMatrix44d(t1,LA_COLOR3(td->UseLocal?td->TLCenter:td->TCenter)); tnsInverse44d(t2,t1);
|
|
|
- tnsMatrix44d final; tnsMultiply44d(t3,t1,trans); tnsMultiply44d(t1,t3,t2);
|
|
|
- if(!td->UseLocal) tnsMultiply44d(final,td->obmatinv,t1);
|
|
|
- else tnsMultiply44d(final,t1,td->obmatinv);
|
|
|
- for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
|
|
|
- tnsApplyTransform43d(to->mv->p, final, to->p);
|
|
|
- }
|
|
|
- tnsInvalidateMeshBatch(td->mo); tnsMMeshCalculateNormal(td->mo);
|
|
|
}
|
|
|
}
|
|
|
void la_CancelTransformObjects(MTransformData* td){
|
|
|
- if(!td->mo){
|
|
|
+ if(td->mo){
|
|
|
+ for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert)); tnsVectorCopy3d(to->origp,to->mv->p); }
|
|
|
+ tnsInvalidateMeshBatch(td->mo);
|
|
|
+ }elif(td->so){
|
|
|
+ for(int i=0;i<td->next;i++){ MTOrigSPoint* to=arrElement(td->Originals, i, sizeof(MTOrigSPoint)); tnsVectorCopy2d(to->origp,to->sp->p); }
|
|
|
+ }else{
|
|
|
for(int i=0;i<td->next;i++){ MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject));
|
|
|
if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
|
|
|
memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
|
|
|
if(td->CanvasDeltaMode) tnsGlobalMatrixChangedForDelta(to->o, 1);
|
|
|
else tnsGlobalMatrixChanged(to->o, 1);
|
|
|
}
|
|
|
- }else{
|
|
|
- for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert)); tnsVectorCopy3d(to->origp,to->mv->p); }
|
|
|
- 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(td->mode==LA_TRANSFORM_MODE_GRAB?"Moved objects":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotated objects":"Scaled objects", TNS_HINT_TRANSFORM);
|
|
|
- }else{
|
|
|
+ if(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);
|
|
|
+ }elif(td->so){
|
|
|
+ laRecordInstanceDifferences(td->so, "tns_shape_object");
|
|
|
+ laPushDifferences(td->mode==LA_TRANSFORM_MODE_GRAB?"Moved points":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotated points":"Scaled points", TNS_HINT_GEOMETRY);
|
|
|
+ }else{
|
|
|
+ for(int i=0;i<td->next;i++){ MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject));
|
|
|
+ laRecordInstanceDifferences(to->o, "tns_object");
|
|
|
+ } laPushDifferences(td->mode==LA_TRANSFORM_MODE_GRAB?"Moved objects":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotated objects":"Scaled objects", TNS_HINT_TRANSFORM);
|
|
|
}
|
|
|
}
|
|
|
void la_FreeTransformData(MTransformData* td){
|
|
@@ -683,7 +803,8 @@ int la_InitTransform(laOperator* a, laEvent* e, int mode, int restore_type, int
|
|
|
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; tnsRootObject*ro=root;
|
|
|
+ tnsObject* o=root->Active; tnsRootObject*ro=root;
|
|
|
+ tnsMeshObject* mo=o; tnsShapeObject* so=o;
|
|
|
|
|
|
MTransformData* td=la_InitTransformData(
|
|
|
ex->OffScr->pColor[0]->Width, ex->OffScr->pColor[0]->Height, c, ex->DeltaMode,
|
|
@@ -693,8 +814,10 @@ int la_InitTransform(laOperator* a, laEvent* e, int mode, int restore_type, int
|
|
|
td->root=root;
|
|
|
|
|
|
int ret=0;
|
|
|
- if(mo && mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
|
|
|
+ if(o && o->Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
|
|
|
if(la_PopulateTransformVerticies(td, mo)){ ex->ClickedX=e->x; ex->ClickedY=e->y; ret=1; }
|
|
|
+ }if(o && o->Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){
|
|
|
+ if(la_PopulateTransformPoints(td, so)){ ex->ClickedX=e->x; ex->ClickedY=e->y; ret=1; }
|
|
|
}else{
|
|
|
if(la_PopulateTransformObjects(td,root)){ ex->ClickedX=e->x; ex->ClickedY=e->y; ret=1; }
|
|
|
if(ret && restore_type){
|
|
@@ -1353,10 +1476,10 @@ int OPINV_Separate(laOperator *a, laEvent *e){
|
|
|
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); }
|
|
|
+void la_PopulateSelectedObjects(tnsObject* root, laListHandle* l, int FilterType){
|
|
|
+ if(root->Flags&TNS_OBJECT_FLAGS_SELECTED){ if(root->Type && ((!FilterType) || root->Type==FilterType)) lstAppendPointer(l,root); }
|
|
|
for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
|
|
|
- la_PopulateSelectedMeshObjects(lip->p, l);
|
|
|
+ la_PopulateSelectedObjects(lip->p, l, FilterType);
|
|
|
}
|
|
|
}
|
|
|
int OPINV_Combine(laOperator *a, laEvent *e){
|
|
@@ -1367,7 +1490,7 @@ int OPINV_Combine(laOperator *a, laEvent *e){
|
|
|
|
|
|
if(!mo || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode==TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
|
|
|
|
|
|
- laListHandle pending={0}; la_PopulateSelectedMeshObjects(root,&pending);
|
|
|
+ laListHandle pending={0}; la_PopulateSelectedObjects(root,&pending,TNS_OBJECT_MESH);
|
|
|
tnsMeshObject* o; while(o=lstPopPointer(&pending)){ if(o==mo || o->Mode==TNS_MESH_EDIT_MODE) continue;
|
|
|
if(tnsMergeMeshObjects(mo, o)) ran++;
|
|
|
}
|
|
@@ -1386,12 +1509,16 @@ int OPINV_Duplicate(laOperator *a, laEvent *e){
|
|
|
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; }
|
|
|
+ if(!mo || mo->Mode==TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
|
|
|
|
|
|
- laListHandle pending={0}; la_PopulateSelectedMeshObjects(root,&pending);
|
|
|
+ laListHandle pending={0}; la_PopulateSelectedObjects(root,&pending,0);
|
|
|
tnsMeshObject* o; tnsMeshObject* no; laListItemPointer* lip;
|
|
|
for(lip=pending.pFirst;lip;lip=lip->pNext){ o=lip->p; o->Base.EditDuplicateTemp=0; if (o->Mode == TNS_MESH_EDIT_MODE) continue;
|
|
|
- if (no = tnsDuplicateMeshObject(o)){ o->Base.EditDuplicateTemp=no;
|
|
|
+ if(o->Base.Type==TNS_OBJECT_MESH) no = tnsDuplicateMeshObject(o);
|
|
|
+ elif(o->Base.Type==TNS_OBJECT_SHAPE) no = tnsDuplicateShapeObject(o);
|
|
|
+ elif(o->Base.Type==TNS_OBJECT_INSTANCER) no = tnsDuplicateShapeObject(o);
|
|
|
+
|
|
|
+ if(no){ o->Base.EditDuplicateTemp=no;
|
|
|
no->Base.Flags |= TNS_OBJECT_FLAGS_SELECTED; o->Base.Flags &= (~TNS_OBJECT_FLAGS_SELECTED);
|
|
|
if (mo == o) { memAssignRef(root, &root->Active, no); } ran++;
|
|
|
}
|
|
@@ -1403,7 +1530,7 @@ int OPINV_Duplicate(laOperator *a, laEvent *e){
|
|
|
while(o=lstPopPointer(&pending)){ o->Base.EditDuplicateTemp=0; }
|
|
|
|
|
|
if(ran){
|
|
|
- laRecordAndPush(0,"tns.world","Merge mesh objects",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
|
|
|
+ laRecordAndPush(0,"tns.world","Duplicated objects",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
|
|
|
if(la_InitTransform(a,e,LA_TRANSFORM_MODE_GRAB,0,0)) return LA_RUNNING; return LA_FINISHED;
|
|
|
}
|
|
|
|
|
@@ -1536,7 +1663,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,ex->SelectThrough);
|
|
|
+ la_PopulateSelectDataPrimitives(sd,mo,c,SelectMode,root,ex);
|
|
|
|
|
|
if(se->IsLoop){ strSafePrint(&a->RuntimeHint,"◧ Cut ◨ Cancel"); }
|
|
|
else{ strSafePrint(&a->RuntimeHint,"◧ Place Cut ◨ Cancel ⮨ Confirm"); }
|