*/}}

la_modelling.c 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443
  1. /*
  2. * LaGUI: A graphical application framework.
  3. * Copyright (C) 2022-2023 Wu Yiming
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "../la_5.h"
  19. extern LA MAIN;
  20. extern struct _tnsMain *T;
  21. void la_ReadGLocation(tnsOffscreen* off, int x, int y,float* xyz0){
  22. glBindFramebuffer(GL_READ_FRAMEBUFFER, off->FboHandle);
  23. glReadBuffer(GL_COLOR_ATTACHMENT2); glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  24. glReadPixels(x,y,1,1, GL_RGBA, GL_FLOAT, xyz0);
  25. }
  26. int OPINV_SetCursor(laOperator *a, laEvent *e){
  27. if(!a->This || !a->This->EndInstance){ return 0; }
  28. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  29. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root || root->Type!=TNS_OBJECT_ROOT) return 0;
  30. float pos[4]; la_ReadGLocation(ex->OffScr, e->x-ui->L,ui->B-e->y,pos);
  31. if(pos[0]>-1e20){
  32. tnsVectorSet3v(root->GLocation,pos); laNotifyUsers("tns.world"); return LA_FINISHED_PASS;
  33. }else
  34. {
  35. if(!ex->ViewingCamera){ return LA_FINISHED_PASS; }
  36. real vv[4], gp[4]; tnsMatrix44d proj; tnsMatrix44d inv;
  37. real focus=ex->ViewingCamera->FocusDistance, _near=ex->ViewingCamera->ZMin, _far=ex->ViewingCamera->ZMax;
  38. tnsGetCameraViewProjection(proj,ui->R-ui->L,ui->B-ui->U,ex->ViewingCamera); tnsInverse44d(inv,proj);
  39. vv[0]=(real)(e->x-ui->L)/(real)(ui->R-ui->L)*2-1; vv[0]*=focus;
  40. vv[1]=(real)(ui->B-e->y)/(real)(ui->B-ui->U)*2-1; vv[1]*=focus;
  41. vv[2]=tnsGetRatiod(1/_near,1/_far,1/focus)*focus;
  42. vv[3]=focus;
  43. tnsApplyTransform44dTrue(gp, inv, vv);
  44. tnsVectorMultiSelf3d(gp,1/gp[3]);
  45. real vv0[3]={0,0,-1}, vv1[3], ray[3], p0[3]; real t; tnsMatrix44d inv2;
  46. tnsSelfTransformValueChanged(ex->ViewingCamera);tnsInverse44d(inv2,ex->ViewingCamera->Base.GlobalTransform);
  47. tnsApplyRotation43d(vv1,inv2,vv0);
  48. tnsVectorMulti3d(vv0,vv1,focus);
  49. tnsVectorAccum3d(vv0,ex->ViewingCamera->Base.GLocation);
  50. tnsVectorMinus3d(ray, gp, ex->ViewingCamera->Base.GLocation);
  51. tnsNormalizeSelf3d(ray);
  52. if(tnsIntersectPlaneRay(vv1,vv0,ex->ViewingCamera->Base.GLocation,ray,&t)){
  53. tnsVectorMultiSelf3d(ray,t); tnsVectorPlus3d(gp,ray,ex->ViewingCamera->Base.GLocation);
  54. }
  55. tnsVectorSet3v(root->GLocation,gp); laNotifyUsers("tns.world"); return LA_FINISHED_PASS;
  56. }
  57. return LA_FINISHED_PASS;
  58. }
  59. int OPCHK_ThereIsActiveObject(laPropPack *This, laStringSplitor *ss){
  60. if(!This || !This->EndInstance){ return 0; }
  61. laCanvasExtra* ex=This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  62. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  63. tnsMeshObject* mo=root->Active; if(!mo) return 0; return 1;
  64. }
  65. int OPINV_ToggleEdit(laOperator *a, laEvent *e){
  66. if(!a->This || !a->This->EndInstance){ return 0; }
  67. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  68. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  69. tnsMeshObject* mo=root->Active; if(!mo) return 0;
  70. if(mo->Base.Type!=TNS_OBJECT_MESH) return LA_CANCELED;
  71. if(mo->Mode==TNS_MESH_EDIT_MODE) tnsMeshLeaveEditMode(mo); else tnsMeshEnterEditMode(mo);
  72. laRecordInstanceDifferences(mo, "tns_mesh_object"); laPushDifferences("Toggle edit mode", TNS_HINT_GEOMETRY);
  73. laNotifyUsers("tns.world");
  74. return LA_FINISHED_PASS;
  75. }
  76. STRUCTURE(MSelectData){
  77. tnsOffscreen* FBO;
  78. tnsTexture* Color;
  79. void** RefsV; int nextV,maxV;
  80. void** RefsE; int nextE,maxE;
  81. };
  82. MSelectData* la_InitSelectData(int w, int h, tnsCamera* camera){
  83. MSelectData* sd=memAcquireSimple(sizeof(MSelectData));
  84. if (!sd->FBO || sd->FBO->pColor[0]->Height != h || sd->FBO->pColor[0]->Width != w){
  85. if (sd->FBO) tnsDelete2DOffscreen(sd->FBO);
  86. sd->FBO = tnsCreate2DOffscreen(GL_RGB, w, h, 0, 1, 0); sd->Color=sd->FBO->pColor[0];
  87. }
  88. tnsDrawToOffscreen(sd->FBO, 1, 0);
  89. return sd;
  90. }
  91. void la_AssignObjectSelectIDRecursive(tnsObject* root, MSelectData* sd){
  92. for(laListItemPointer*lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  93. tnsObject* o=lip->p; if(!o) continue;
  94. arrEnsureLength(&sd->RefsV, sd->nextV, &sd->maxV, sizeof(tnsObject*));
  95. sd->RefsV[sd->nextV]=o; o->SelectID=sd->nextV; sd->nextV++;
  96. if(o->ChildObjects.pFirst){ la_AssignObjectSelectIDRecursive(o,sd); }
  97. }
  98. }
  99. void la_PopulateSelectDataObjects(MSelectData* sd, tnsObject* root, tnsCamera* camera){
  100. arrEnsureLength(&sd->RefsV,0,&sd->maxV,sizeof(tnsObject*));
  101. sd->nextV++; // starting from 1;
  102. la_AssignObjectSelectIDRecursive(root, sd);
  103. if(sd->nextV==1) return; int w=sd->Color->Width, h=sd->Color->Height;
  104. tnsUnbindTexture(); tnsUniformUseTexture(T->immShader,0,0); tnsUseMultiplyColor(0);
  105. tnsEnableShaderv(T->SelectionShader);
  106. glDisableVertexAttribArray(T->SelectionShader->iColor); glVertexAttrib4f(T->SelectionShader->iColor,0,0,0,0);
  107. tnsViewportWithScissor(0,0,w,h);tnsResetViewMatrix();tnsResetModelMatrix();tnsResetProjectionMatrix();
  108. tnsApplyCameraView(w,h,camera);
  109. glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  110. glEnable(GL_DEPTH_TEST);
  111. tnsDrawObjectTree(root,0,0,0);
  112. glDisable(GL_DEPTH_TEST);
  113. }
  114. void la_PopulateSelectVerts(MSelectData* sd, tnsMeshObject* mo){
  115. arrEnsureLength(&sd->RefsV,0,&sd->maxV,sizeof(tnsMVert*));
  116. if(mo->Base.Type!=TNS_OBJECT_MESH||!mo->mv.pFirst){ return; }
  117. for(tnsMVert* v=mo->mv.pFirst;v;v=v->Item.pNext){
  118. arrEnsureLength(&sd->RefsV, v->i, &sd->maxV, sizeof(tnsObject*));
  119. sd->RefsV[v->i]=v; sd->nextV=TNS_MAX2(v->i, sd->nextV);
  120. }
  121. sd->nextV++;
  122. }
  123. void la_PopulateSelectEdges(MSelectData* sd, tnsMeshObject* mo){
  124. arrEnsureLength(&sd->RefsE,0,&sd->maxE,sizeof(tnsMEdge*));
  125. if(mo->Base.Type!=TNS_OBJECT_MESH||!mo->mv.pFirst){ return; }
  126. for(tnsMEdge* e=mo->me.pFirst;e;e=e->Item.pNext){
  127. arrEnsureLength(&sd->RefsE, e->i, &sd->maxE, sizeof(tnsObject*));
  128. sd->RefsE[e->i]=e; sd->nextE=TNS_MAX2(e->i, sd->nextE);
  129. }
  130. sd->nextE++;
  131. }
  132. void la_PopulateSelectDataPrimitives(MSelectData* sd, tnsMeshObject* mo, tnsCamera* camera, int WhatPrim){
  133. int DoVerts=(WhatPrim==LA_CANVAS_SELECT_MODE_VERTS),DoEdges=(WhatPrim==LA_CANVAS_SELECT_MODE_EDGES);
  134. int Knife=(WhatPrim==LA_CANVAS_SELECT_MODE_KNIFE);
  135. if(DoVerts || Knife){ la_PopulateSelectVerts(sd,mo); }
  136. if(DoEdges || Knife){ la_PopulateSelectEdges(sd,mo); }
  137. int w=sd->Color->Width, h=sd->Color->Height;
  138. tnsUnbindTexture(); tnsUniformUseTexture(T->immShader,0,0); tnsUseMultiplyColor(0);
  139. tnsEnableShaderv(T->SelectionShader);
  140. tnsViewportWithScissor(0,0,w,h);tnsResetViewMatrix();tnsResetModelMatrix();tnsResetProjectionMatrix();
  141. tnsApplyCameraView(w,h,camera);
  142. glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  143. glEnable(GL_DEPTH_TEST);
  144. tnsPushMatrix(); tnsApplyObjectMatrix(mo);
  145. if(Knife){ glPointSize(10); }
  146. if(DoEdges || Knife){ tnsDrawBatch(mo->Batch, "edges_select",0,0); }
  147. if(DoVerts || Knife){ tnsDrawBatch(mo->Batch, "verts_select",0,0); }
  148. if(Knife){ glPointSize(1); }
  149. tnsPopMatrix();
  150. glDisable(GL_DEPTH_TEST);
  151. }
  152. void la_PadSelectionBuffer(uint8_t* buf, int w, int h, int sx, int sy, int ex, int ey, int real_endx){
  153. if(!sx&&!sy&&!ex&&!ey) return;
  154. uint8_t* pad=calloc(1,sizeof(uint8_t)*4*w*h);
  155. for(int i=0;i<h;i++){
  156. if(i<sy || i>=h-ey){ memset(&pad[i*w*4],0,w*4); continue; }
  157. for(int j=0;j<w;j++){
  158. if(j<sx || j>=w-sx){ memset(&pad[(i*w+j)*4],0,4); continue; }
  159. memcpy(&pad[(i*w+j)*4], &buf[((i-sy)*(real_endx-sx)+j-sx)*4], 4);
  160. }
  161. }
  162. memcpy(buf,pad,sizeof(uint8_t)*4*w*h);
  163. free(pad);
  164. }
  165. uint8_t* la_ReadSelection(MSelectData* sd, u8bit* buf, int x, int y, int w, int h){
  166. glFlush(); glFinish(); glGetError();
  167. glBindFramebuffer(GL_READ_FRAMEBUFFER, sd->FBO->FboHandle);
  168. glReadBuffer(GL_COLOR_ATTACHMENT0);
  169. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  170. glReadPixels(x,y,w,h, GL_RGBA, GL_UNSIGNED_BYTE, buf);
  171. return buf;
  172. }
  173. uint8_t* la_ReadSelectionRadius(MSelectData* sd, int uix, int uiy, int radius){
  174. int w=radius*2; int vh=sd->Color->Height,vw=sd->Color->Width;
  175. uint8_t* buf=calloc(1,sizeof(uint8_t)*4*w*w);
  176. int startx=uix-radius, starty=vh-uiy-radius, endx=uix+radius, endy=vh-uiy+radius;
  177. TNS_CLAMP(startx,0,vw);TNS_CLAMP(endx,0,vw);TNS_CLAMP(starty,0,vh);TNS_CLAMP(endy,0,vh);
  178. int _startx=TNS_MAX2(startx,0), _starty=TNS_MAX2(starty,0), _endx=TNS_MIN2(endx,vw), _endy=TNS_MIN2(endy,vh);
  179. la_ReadSelection(sd, buf, _startx, _starty, _endx-_startx, _endy-_starty);
  180. la_PadSelectionBuffer(buf, w, w, _startx-startx, _starty-starty, endx-_endx, endy-_endy,_endx);
  181. return buf;
  182. }
  183. uint8_t* la_ReadSelectionBox(MSelectData* sd, int uix, int uiy, int uix2, int uiy2){
  184. int vh=sd->Color->Height,vw=sd->Color->Width;
  185. if(uix2<uix) LA_SWAP(int,uix,uix2); if(uiy2<uiy) LA_SWAP(int,uiy,uiy2);
  186. TNS_CLAMP(uix,0,vw);TNS_CLAMP(uix2,0,vw);TNS_CLAMP(uiy,0,vh);TNS_CLAMP(uiy2,0,vh);
  187. int w=uix2-uix, h=uiy2-uiy;
  188. uint8_t* buf=calloc(1,sizeof(uint8_t)*4*w*h);
  189. int startx=uix, starty=vh-uiy2, endx=uix+w, endy=starty+h;
  190. int _startx=TNS_MAX2(startx,0), _starty=TNS_MAX2(starty,0), _endx=TNS_MIN2(endx,vw), _endy=TNS_MIN2(endy,vh);
  191. la_ReadSelection(sd, buf, _startx, _starty, _endx-_startx, _endy-_starty);
  192. la_PadSelectionBuffer(buf, w, h, _startx-startx, _starty-starty, endx-_endx, endy-_endy,_endx);
  193. return buf;
  194. }
  195. int la_SelectGetClosest(MSelectData* sd, int uix, int uiy, int radius, int *ElemType){
  196. *ElemType=0; uint8_t* buf=la_ReadSelectionRadius(sd, uix, uiy, radius); if(!buf) return 0;
  197. int w=radius*2; int MinD=INT_MAX; int MinID=0, d, elemtype=0;
  198. for(int i=0;i<w;i++){
  199. for(int j=0;j<w;j++){
  200. uint8_t* p=&buf[(i*w+j)*4]; int id=(p[0])|(p[1]<<8)|((p[2]<<16)&(~TNS_MMESH_TYPE_BIT));
  201. if(id && (d=tnsDistIdv2(i,j, radius, radius))<MinD ){ MinD=d; MinID=id; elemtype=((p[2]<<16)&TNS_MMESH_TYPE_BIT); }
  202. //printf("%d ",buf[(i*w+j)*4]);
  203. }
  204. //printf("\n");
  205. }
  206. free(buf);
  207. *ElemType=elemtype;
  208. return MinID;
  209. }
  210. int* la_SelectGetBox(MSelectData* sd, int uix, int uiy, int uix2, int uiy2, int* r_length){
  211. uint8_t* buf=la_ReadSelectionBox(sd, uix, uiy, uix2, uiy2); if(!buf) return 0;
  212. int vh=sd->Color->Height,vw=sd->Color->Width;
  213. if(uix2<uix) LA_SWAP(int,uix,uix2); if(uiy2<uiy) LA_SWAP(int,uiy,uiy2);
  214. TNS_CLAMP(uix,0,vw);TNS_CLAMP(uix2,0,vw);TNS_CLAMP(uiy,0,vh);TNS_CLAMP(uiy2,0,vh);
  215. int w=uix2-uix, h=uiy2-uiy;
  216. int* ids=0; int next=0,max=0;
  217. arrEnsureLength(&ids, next, &max, sizeof(int));
  218. for(int i=0;i<h;i++){
  219. for(int j=0;j<w;j++){
  220. uint8_t* p=&buf[(i*w+j)*4]; int id=(p[0])|(p[1]<<8)|((p[2]<<16)&(~TNS_MMESH_TYPE_BIT));
  221. if(id){ int found=0;
  222. for(int a=0;a<next;a++){ if(ids[a]==id){ found=1; break; } }
  223. if(!found){
  224. arrEnsureLength(&ids, next, &max, sizeof(int)); ids[next]=id; next++; }
  225. }
  226. }
  227. }
  228. free(buf);
  229. *r_length=next;
  230. return ids;
  231. }
  232. void la_FreeSelectData(MSelectData* sd){
  233. tnsDelete2DOffscreen(sd->FBO);
  234. free(sd->RefsV);
  235. free(sd->RefsE);
  236. memFree(sd);
  237. }
  238. void* la_SelectGetRef(MSelectData* sd, int id, int elemtype){
  239. if(!elemtype){ if(id>=0 && id<sd->nextV){ return sd->RefsV[id]; } }
  240. elif(elemtype==TNS_MMESH_EDGE_BIT){ if(id>=0 && id<sd->nextE){ return sd->RefsE[id]; } }
  241. return 0;
  242. }
  243. int OPCHK_ViewportAndSceneExists(laPropPack *This, laStringSplitor *ss){
  244. if(!This || !This->EndInstance){ return 0; } laCanvasExtra* ex=This->EndInstance;
  245. laUiItem* ui=ex->ParentUi; tnsObject* root=ui?ui->PP.EndInstance:0;
  246. if(!ex->ViewingCamera || !root){ return 0; }
  247. return 1;
  248. }
  249. void la_DoObjectSelect(tnsObject* root, tnsObject* o, laCanvasExtra* e, int DeselectAll, int Select, int Toggle){
  250. if(DeselectAll){ tnsDeselectAllObjects(root); memAssignRef(root,&root->Active,0); }
  251. if(o){ tnsSelectObject(o, Select, o==root->Active?0:Toggle); memAssignRef(root,&root->Active,o); }
  252. }
  253. void la_DoMeshSelect(tnsMeshObject* mo, void* p, int WhatPrim, int DeselectAll, int Select, int Toggle){
  254. if(DeselectAll){ tnsMMeshDeselectAll(mo); }
  255. if(p){ if(WhatPrim==LA_CANVAS_SELECT_MODE_VERTS) tnsMMeshSelectVert(mo,p,Select,Toggle);
  256. elif(WhatPrim==LA_CANVAS_SELECT_MODE_EDGES) tnsMMeshSelectEdge(mo,p,Select,Toggle); }
  257. }
  258. #define LA_SELECT_MODE_BOX 1
  259. STRUCTURE(MSelectExtra){
  260. MSelectData* sd;
  261. tnsObject* root;
  262. tnsObject* mo;
  263. tnsCamera* cam;
  264. int Mode;
  265. int InSelect;
  266. laListHandle KnifeElements;
  267. void* PendingElem; int PendingElemType, BatchDirty;
  268. };
  269. int OPINV_Select(laOperator *a, laEvent *e){
  270. if(!a->This || !a->This->EndInstance){ return 0; }
  271. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  272. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  273. tnsMeshObject* mo=root->Active;
  274. int is_geo=0;
  275. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "toggle")){
  276. if(mo && mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  277. if(tnsMMeshAnySelected(mo)) tnsMMeshDeselectAll(mo); else tnsMMeshSelectAll(mo);
  278. tnsInvalidateMeshBatch(mo); is_geo=1;
  279. }else{
  280. if(tnsAnyObjectsSelected(root)) tnsDeselectAllObjects(root); else tnsSelectAllObjects(root);
  281. }
  282. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world", "Toggle selection",is_geo?TNS_HINT_GEOMETRY:TNS_HINT_TRANSFORM);
  283. return LA_FINISHED;
  284. }
  285. MSelectData* sd=la_InitSelectData(ex->OffScr->pColor[0]->Width, ex->OffScr->pColor[0]->Height, c);
  286. int DeselectAll=1;
  287. int Append=e->SpecialKeyBit&LA_KEY_SHIFT; if(Append) DeselectAll=0;
  288. if(mo && mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  289. la_PopulateSelectDataPrimitives(sd, mo, ex->ViewingCamera, ex->SelectMode);
  290. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "box")){
  291. MSelectExtra* se=memAcquire(sizeof(MSelectExtra));
  292. ex->OnX=e->x; ex->OnX=e->y;
  293. 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;
  294. }
  295. int elemtype,id=la_SelectGetClosest(sd, e->x-ui->L, e->y-ui->U, LA_RH,&elemtype)-1;
  296. void* p=la_SelectGetRef(sd,id,elemtype); printf("%d %d\n",id,elemtype);
  297. la_DoMeshSelect(mo, p, ex->SelectMode, DeselectAll, 1, 1); tnsMMeshEnsureSelection(mo,ex->SelectMode);
  298. tnsInvalidateMeshBatch(mo);
  299. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Mesh selection",TNS_HINT_GEOMETRY);
  300. }else{
  301. la_PopulateSelectDataObjects(sd,root,ex->ViewingCamera);
  302. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "box")){
  303. MSelectExtra* se=memAcquire(sizeof(MSelectExtra));
  304. ex->OnX=e->x; ex->OnX=e->y;
  305. a->CustomData=se; se->sd=sd; se->Mode=LA_SELECT_MODE_BOX; se->cam=c; ex->DrawCursor=1; se->root=root; return LA_RUNNING;
  306. }
  307. int elemtype,id=la_SelectGetClosest(sd, e->x-ui->L, e->y-ui->U, LA_RH*2,&elemtype); printf("%d\n",elemtype);
  308. void* p=la_SelectGetRef(sd,id,elemtype); if(p){ la_DoObjectSelect(root, p, ex, DeselectAll, 1, 1); }
  309. else{ la_DoObjectSelect(root, 0, ex, DeselectAll, 1, 1); }
  310. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Object selection",TNS_HINT_TRANSFORM);
  311. }
  312. la_FreeSelectData(sd);
  313. return LA_FINISHED_PASS;
  314. }
  315. int OPMOD_Select(laOperator *a, laEvent *e){
  316. if(!a->This || !a->This->EndInstance){ return 0; }
  317. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  318. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  319. tnsMeshObject* mo=root->Active;
  320. MSelectExtra* se=a->CustomData;
  321. if(e->Type==LA_L_MOUSE_DOWN){ se->InSelect=1; ex->DrawCursor=2; ex->ClickedX=e->x; ex->ClickedY=e->y; laRedrawCurrentPanel(); }
  322. if(e->Type&LA_MOUSE_EVENT){ ex->OnX=e->x; ex->OnY=e->y; laRedrawCurrentPanel(); }
  323. if(e->Type==LA_R_MOUSE_DOWN || (e->Type == LA_KEY_DOWN && e->key==LA_KEY_ESCAPE)){
  324. ex->DrawCursor=0; la_FreeSelectData(se->sd); memFree(se); laNotifyUsers("tns.world"); return LA_FINISHED;
  325. }
  326. int DeselectAll=1;
  327. int Append=e->SpecialKeyBit&LA_KEY_SHIFT; if(Append) DeselectAll=0;
  328. int Remove=e->SpecialKeyBit&LA_KEY_ALT; if(Remove) DeselectAll=0;
  329. int is_geo=0;
  330. if(se->InSelect && e->Type==LA_L_MOUSE_UP){
  331. if(mo && mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  332. la_DoMeshSelect(mo, 0, ex->SelectMode, DeselectAll, 0, 0);
  333. 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);
  334. for(int i=0;i<len;i++){
  335. int id=ids[i]-1; void* p=la_SelectGetRef(se->sd,id,ex->SelectMode==LA_CANVAS_SELECT_MODE_EDGES?TNS_MMESH_EDGE_BIT:0);
  336. la_DoMeshSelect(mo, p, ex->SelectMode, 0, !Remove, 0);
  337. }
  338. tnsMMeshEnsureSelection(mo,ex->SelectMode);
  339. tnsInvalidateMeshBatch(mo); is_geo=1;
  340. }else{
  341. la_DoObjectSelect(se->root, 0, ex, DeselectAll, 0, 0);
  342. int len; int* ids=la_SelectGetBox(se->sd, ex->ClickedX, ex->ClickedY, e->x-ui->L, e->y-ui->U, &len);
  343. for(int i=0;i<len;i++){
  344. int id=ids[i]; void* p=la_SelectGetRef(se->sd,id,0);
  345. if(p){ la_DoObjectSelect(se->root, p, ex, 0, !Remove, 0); }
  346. }
  347. }
  348. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Box selection",is_geo?TNS_HINT_GEOMETRY:TNS_HINT_TRANSFORM);
  349. ex->DrawCursor=0;
  350. la_FreeSelectData(se->sd); memFree(se);
  351. laRedrawCurrentPanel();
  352. return LA_FINISHED;
  353. }
  354. return LA_RUNNING;
  355. }
  356. #define LA_TRANSFORM_MODE_GRAB 1
  357. #define LA_TRANSFORM_MODE_ROTATE 2
  358. #define LA_TRANSFORM_MODE_SCALE 3
  359. STRUCTURE(MTOrigObject){
  360. tnsObject* o;
  361. tnsMatrix44d Global;
  362. tnsMatrix44d Local;
  363. int Discard;
  364. };
  365. STRUCTURE(MTOrigMVert){
  366. tnsVector3d p;
  367. tnsVector3d origp;
  368. tnsMVert* mv;
  369. };
  370. STRUCTURE(MTransformData){
  371. tnsMatrix44d Delta;
  372. tnsMatrix44d ViewProjection;
  373. tnsVector4d Up,Right,Foward;
  374. tnsVector4d TCenter;
  375. int CenterX,CenterY; real Initial;
  376. tnsObject* mo; tnsMatrix44d obmatinv;
  377. tnsCamera* c; tnsObject* root;
  378. int w,h;
  379. void* Originals; int next,max;
  380. int mode;
  381. int LockAxis[3];
  382. int UseLocal;
  383. real DeltaVal, UserDeltaVal;
  384. laStringEdit* Entry; int UseUserDelta;
  385. };
  386. MTransformData* la_InitTransformData(int w, int h, tnsCamera* c){
  387. MTransformData* td=memAcquireSimple(sizeof(MTransformData));
  388. tnsVector4d pu={0,1,0,0}, pr={1,0,0,0}, pf={0,0,1};
  389. tnsGetCameraMovingDeltas(c,w,h,1,0,pr); pr[2]=0; pr[3]=0;
  390. tnsGetCameraMovingDeltas(c,w,h,0,-1,pu); pu[2]=0; pu[3]=0;
  391. tnsMatrix44d inv; tnsInverse44d(inv,c->Base.GlobalTransform);
  392. tnsApplyRotation43d(td->Up,inv,pu);
  393. tnsApplyRotation43d(td->Right,inv,pr);
  394. tnsApplyRotation43d(td->Foward,inv,pf);
  395. tnsGetCameraViewProjection(td->ViewProjection, w,h,c);
  396. td->c=c; td->w=w; td->h=h;
  397. strBeginEdit(&td->Entry, "");
  398. return td;
  399. }
  400. void la_GetTransformInitialScale(MTransformData* td, laUiItem* ui, int x, int y){ td->Initial=tnsDistIdv2(x-ui->L,y-ui->U,td->CenterX,td->CenterY); }
  401. void la_GetTransformInitialRotation(MTransformData* td, laUiItem* ui, int x, int y){ td->Initial=atan2(y-ui->U-td->CenterY,x-ui->L-td->CenterX); }
  402. void la_GetTransformCenter2D(MTransformData* td){
  403. tnsVector4d vp; tnsApplyTransform44d(vp,td->ViewProjection,td->TCenter);
  404. if(td->c->CameraType==TNS_PRESPECTIVE_CAMERA){ tnsVectorMultiSelf3d(vp, 1/vp[3]); }
  405. td->CenterX = (vp[0]/2+0.5f)*td->w; td->CenterY=(-vp[1]/2+0.5f)*td->h;
  406. if(td->CenterX<0||td->CenterY<0) { td->CenterX=td->w/2; td->CenterY=td->h/2; }
  407. }
  408. int la_AddTransformObjectsRecursive(MTransformData* td, tnsObject*root){
  409. int any=0; for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  410. tnsObject* o=lip->p; if(o->ChildObjects.pFirst) any+=la_AddTransformObjectsRecursive(td,o);
  411. if(!(o->Flags&TNS_OBJECT_FLAGS_SELECTED)) continue;
  412. arrEnsureLength(&td->Originals, td->next, &td->max, sizeof(MTOrigObject));
  413. MTOrigObject* to=arrElement(td->Originals, td->next, sizeof(MTOrigObject)); td->next++; to->o=o;
  414. memcpy(to->Global, o->GlobalTransform, sizeof(tnsMatrix44d));
  415. memcpy(to->Local, o->SelfTransform, sizeof(tnsMatrix44d));
  416. tnsVectorAccum3d(td->TCenter,o->GLocation); any++;
  417. int discard=0; tnsObject* po=o; while(po=po->ParentObject){ if(po->Flags&TNS_OBJECT_FLAGS_SELECTED){ discard=1; break;} } if(discard) to->Discard=1;
  418. }
  419. return any;
  420. }
  421. int la_PopulateTransformObjects(MTransformData* td, tnsObject* root){
  422. arrEnsureLength(&td->Originals, 0, &td->max, sizeof(MTOrigObject));
  423. int any=la_AddTransformObjectsRecursive(td,root);
  424. tnsVectorMultiSelf3d(td->TCenter, 1.0f/any);
  425. la_GetTransformCenter2D(td);
  426. return any;
  427. }
  428. int la_PopulateTransformVerticies(MTransformData* td, tnsMeshObject* mo){
  429. int any=0; td->mo=mo;
  430. arrEnsureLength(&td->Originals, 0, &td->max, sizeof(MTOrigMVert));
  431. tnsInverse44d(td->obmatinv, mo->Base.GlobalTransform);
  432. for(tnsMVert* mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){
  433. if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  434. printf("v %d ",mv->i);
  435. arrEnsureLength(&td->Originals, td->next, &td->max, sizeof(MTOrigMVert));
  436. MTOrigMVert* to=arrElement(td->Originals, td->next, sizeof(MTOrigMVert)); td->next++; to->mv=mv;
  437. tnsApplyTransform43d(to->p, mo->Base.GlobalTransform, mv->p);
  438. memcpy(to->origp, mv->p, sizeof(tnsVector3d)); any++;
  439. tnsVectorAccum3d(td->TCenter,to->p);
  440. }
  441. printf(" [totmv %d]\n",mo->totmv);
  442. tnsVectorMultiSelf3d(td->TCenter, 1.0f/any);
  443. la_GetTransformCenter2D(td);
  444. return any;
  445. }
  446. void la_ApplyTranslation(MTransformData* td, int x, int y){
  447. tnsMatrix44d trans; tnsVector3d deltay,delta; tnsVector3d gp;
  448. tnsVectorMulti3d(delta, td->Right, x); tnsVectorMulti3d(deltay, td->Up, y); tnsVectorAccum3d(delta, deltay);
  449. tnsVector3d use_delta={LA_COLOR3(delta)}; real len;
  450. if(td->LockAxis[0]||td->LockAxis[1]||td->LockAxis[2]){ len=tnsLength3d(delta); }
  451. 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; }
  452. 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; }
  453. 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; }
  454. if(td->LockAxis[0]<0){ use_delta[0]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l*len/l:0); }
  455. if(td->LockAxis[1]<0){ use_delta[1]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l*len/l:0); }
  456. if(td->LockAxis[2]<0){ use_delta[2]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l*len/l:0); }
  457. td->DeltaVal=tnsLength3d(use_delta);
  458. if(td->UseUserDelta){
  459. tnsVectorMultiSelf3d(use_delta,1/tnsLength3d(use_delta)*td->UserDeltaVal);
  460. tnsVector3d lock={ td->LockAxis[0], td->LockAxis[1], td->LockAxis[2] };
  461. real dir=tnsDot3d(use_delta, lock, 0); tnsVectorMultiSelf3d(use_delta,(td->UserDeltaVal*dir<=0)?-1:1);
  462. td->DeltaVal=td->UserDeltaVal;
  463. }
  464. if(!td->mo){
  465. for(int i=0;i<td->next;i++){
  466. MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject)); memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
  467. if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
  468. tnsGlobalMatrixChanged(to->o, 0);
  469. if(td->UseLocal) tnsMoveObjectLocal(to->o, LA_COLOR3(use_delta)); else tnsMoveObjectGlobal(to->o, LA_COLOR3(use_delta));
  470. }
  471. }else{
  472. tnsMakeTranslationMatrix44d(trans, LA_COLOR3(use_delta));
  473. for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
  474. tnsApplyTransform43d(gp, trans, to->p); if(!td->UseLocal) tnsApplyTransform43d(to->mv->p, td->obmatinv, gp); else tnsVectorCopy3d(gp, to->mv->p);
  475. }
  476. tnsInvalidateMeshBatch(td->mo); tnsMMeshCalculateNormal(td->mo);
  477. }
  478. }
  479. void la_ApplyScale(MTransformData* td, int uix, int uiy){
  480. tnsMatrix44d trans; real d=tnsDistIdv2(uix,uiy,td->CenterX,td->CenterY); if(!td->Initial){ td->Initial=100; }
  481. real s=d/td->Initial; tnsVector3d gp;
  482. td->DeltaVal=s; if(td->UseUserDelta) td->DeltaVal=s=td->UserDeltaVal;
  483. if(!td->mo){
  484. for(int i=0;i<td->next;i++){
  485. MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject)); memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
  486. if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
  487. tnsGlobalMatrixChanged(to->o, 0); tnsScaleObject(to->o, s, LA_COLOR3(td->TCenter));
  488. }
  489. }else{
  490. tnsMakeScaleMatrix44d(trans,s,s,s);
  491. tnsMatrix44d t1,t2,t3; tnsMakeTranslationMatrix44d(t1,LA_COLOR3(td->TCenter)); tnsInverse44d(t2,t1);
  492. tnsMatrix44d final; tnsMultiply44d(t3,t1,trans); tnsMultiply44d(final,t3,t2);
  493. for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
  494. tnsApplyTransform43d(gp, final, to->p); tnsApplyTransform43d(to->mv->p, td->obmatinv, gp);
  495. }
  496. tnsInvalidateMeshBatch(td->mo); tnsMMeshCalculateNormal(td->mo);
  497. }
  498. }
  499. void la_ApplyRotation(MTransformData* td, int uix, int uiy){
  500. tnsMatrix44d trans; real a=atan2(uiy-td->CenterY,uix-td->CenterX);
  501. real angle=a-td->Initial; tnsVector3d gp; tnsVector3d LimFoward={0}; real* use_forward=td->Foward;
  502. if(td->LockAxis[0]||td->LockAxis[1]||td->LockAxis[2]){ use_forward=LimFoward; }
  503. if(td->LockAxis[0]){ LimFoward[0]=1; }
  504. if(td->LockAxis[1]){ LimFoward[1]=1; }
  505. if(td->LockAxis[2]){ LimFoward[2]=1; }
  506. if(td->UseUserDelta) angle=rad(td->UserDeltaVal); td->DeltaVal=deg(angle);
  507. if(!td->mo){
  508. for(int i=0;i<td->next;i++){
  509. MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject)); memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
  510. if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
  511. tnsGlobalMatrixChanged(to->o, 0); tnsRotateObjectGlobal(to->o,LA_COLOR3(use_forward),angle,LA_COLOR3(td->TCenter));
  512. }
  513. }else{
  514. tnsMakeRotationMatrix44d(trans, angle, LA_COLOR3(use_forward));
  515. tnsMatrix44d t1,t2,t3; tnsMakeTranslationMatrix44d(t1,LA_COLOR3(td->TCenter)); tnsInverse44d(t2,t1);
  516. tnsMatrix44d final; tnsMultiply44d(t3,t1,trans); tnsMultiply44d(final,t3,t2);
  517. for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
  518. tnsApplyTransform43d(gp, final, to->p); tnsApplyTransform43d(to->mv->p, td->obmatinv, gp);
  519. }
  520. tnsInvalidateMeshBatch(td->mo); tnsMMeshCalculateNormal(td->mo);
  521. }
  522. }
  523. void la_CancelTransformObjects(MTransformData* td){
  524. if(!td->mo){
  525. for(int i=0;i<td->next;i++){ MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject));
  526. if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
  527. memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
  528. tnsGlobalMatrixChanged(to->o, 1);
  529. }
  530. }else{
  531. for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert)); tnsVectorCopy3d(to->origp,to->mv->p); }
  532. tnsInvalidateMeshBatch(td->mo);
  533. }
  534. }
  535. void la_RecordTransformDifferences(MTransformData* td){
  536. if(!td->mo){
  537. for(int i=0;i<td->next;i++){ MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject));
  538. laRecordInstanceDifferences(to->o, "tns_object");
  539. } laPushDifferences(td->mode==LA_TRANSFORM_MODE_GRAB?"Moved objects":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotated objects":"Scaled objects", TNS_HINT_TRANSFORM);
  540. }else{
  541. laRecordInstanceDifferences(td->mo, "tns_mesh_object");
  542. laPushDifferences(td->mode==LA_TRANSFORM_MODE_GRAB?"Moved primitives":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotated primitives":"Scaled primitives", TNS_HINT_GEOMETRY);
  543. tnsInvalidateMeshBatch(td->mo);
  544. }
  545. }
  546. void la_FreeTransformData(MTransformData* td){
  547. free(td->Originals);
  548. strEndEdit(&td->Entry, 1);
  549. memFree(td);
  550. }
  551. void la_MakeTransformOperatorHint(laOperator* a, MTransformData* td){
  552. strSafeDestroy(&a->RuntimeHint);
  553. strSafePrint(&a->RuntimeHint, "%s ",
  554. td->mode==LA_TRANSFORM_MODE_GRAB?"Grab":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotate":td->mode==LA_TRANSFORM_MODE_SCALE?"Scale":"");
  555. char* entry=strGetEditString(td->Entry,0);
  556. strSafePrint(&a->RuntimeHint, "Delta: %.3lf [🔢 %s] 🆇🆈🆉 Lock axis: %s 🈳 %s ", td->DeltaVal, (entry&&entry[0])?entry:"Type...",
  557. td->LockAxis[0]?"X":td->LockAxis[1]?"Y":td->LockAxis[2]?"Z":"None",
  558. td->UseLocal?"Global/[Local]":"[Global]/Local");
  559. free(entry);
  560. if(td->mode==LA_TRANSFORM_MODE_GRAB){ strSafePrint(&a->RuntimeHint, "🡅🆇🆈🆉 Reverse: %s ",
  561. (td->LockAxis[0]<0||td->LockAxis[1]<0||td->LockAxis[2]<0)?"Yes":"No"); }
  562. if(td->mode!=LA_TRANSFORM_MODE_GRAB){ strSafePrint(&a->RuntimeHint,"🅶 Grab "); }
  563. if(td->mode!=LA_TRANSFORM_MODE_SCALE){ strSafePrint(&a->RuntimeHint,"🆂 Scale "); }
  564. if(td->mode!=LA_TRANSFORM_MODE_ROTATE){ strSafePrint(&a->RuntimeHint,"🆁 Rotate "); }
  565. }
  566. int la_InitTransform(laOperator* a, laEvent* e, int mode){
  567. if(!a->This || !a->This->EndInstance){ return 0; }
  568. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  569. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  570. tnsMeshObject* mo=root->Active;
  571. MTransformData* td=la_InitTransformData(ex->OffScr->pColor[0]->Width, ex->OffScr->pColor[0]->Height, c);
  572. a->CustomData = td;
  573. td->mode=mode;
  574. td->root=root;
  575. int ret=0;
  576. if(mo && mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  577. if(la_PopulateTransformVerticies(td, mo)){ ex->ClickedX=e->x; ex->ClickedY=e->y; ret=1; }
  578. }else{
  579. if(la_PopulateTransformObjects(td,root)){ ex->ClickedX=e->x; ex->ClickedY=e->y; ret=1; }
  580. }
  581. if(ret){
  582. if(mode==LA_TRANSFORM_MODE_SCALE){ la_GetTransformInitialScale(td,ui,e->x,e->y); ex->DrawCursor=LA_CANVAS_CURSOR_ARROW; }
  583. elif(mode==LA_TRANSFORM_MODE_ROTATE){ la_GetTransformInitialRotation(td,ui,e->x,e->y); ex->DrawCursor=LA_CANVAS_CURSOR_ARROW; }
  584. ex->TargetX=td->CenterX+ui->L; ex->TargetY=td->CenterY+ui->U; ex->OnX=e->x; ex->OnY=e->y;
  585. la_MakeTransformOperatorHint(a, td);
  586. laNotifyUsers("tns.world"); return 1;
  587. }
  588. return 0;
  589. }
  590. int OPINV_Grab(laOperator *a, laEvent *e){
  591. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB)) return LA_RUNNING; return LA_FINISHED_PASS;
  592. }
  593. int OPINV_Scale(laOperator *a, laEvent *e){
  594. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_SCALE)) return LA_RUNNING; return LA_FINISHED_PASS;
  595. }
  596. int OPINV_Rotate(laOperator *a, laEvent *e){
  597. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_ROTATE)) return LA_RUNNING; return LA_FINISHED_PASS;
  598. }
  599. int OPMOD_Transformation(laOperator *a, laEvent *e){
  600. if(!a->This || !a->This->EndInstance){ return 0; }
  601. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  602. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  603. tnsMeshObject* mo=root->Active;
  604. MTransformData* td=a->CustomData;
  605. if (e->Input=='x'||e->Input=='y'||e->Input=='z'||e->Input=='g'||e->Input=='s'||e->Input=='r'||
  606. e->Input=='X'||e->Input=='Y'||e->Input=='Z'||e->Input==' '){ /*pass*/ }
  607. else{ la_ProcessTextEdit(e, td->Entry, 0); }
  608. char* entered;
  609. if(entered=strGetEditString(td->Entry,0)){ int status;
  610. if((status=sscanf(entered,"%lf",&td->UserDeltaVal)) && status!=EOF) td->UseUserDelta=1; else td->UseUserDelta=0;
  611. td->UserDeltaVal=fabs(td->UserDeltaVal); for(char*pc=entered;*pc;pc++){ if(*pc=='-') td->UserDeltaVal=-td->UserDeltaVal; } free(entered);
  612. }
  613. if(e->Type==LA_KEY_DOWN){
  614. int Other=1; if(e->SpecialKeyBit&LA_KEY_SHIFT){ Other=-1; }
  615. if(e->key=='x'){ td->LockAxis[0]=Other*((Other<0&&td->LockAxis[0])?td->LockAxis[0]:!td->LockAxis[0]); td->LockAxis[1]=td->LockAxis[2]=0; }
  616. if(e->key=='y'){ td->LockAxis[1]=Other*((Other<0&&td->LockAxis[1])?td->LockAxis[1]:!td->LockAxis[1]); td->LockAxis[0]=td->LockAxis[2]=0; }
  617. if(e->key=='z'){ td->LockAxis[2]=Other*((Other<0&&td->LockAxis[2])?td->LockAxis[2]:!td->LockAxis[2]); td->LockAxis[0]=td->LockAxis[1]=0; }
  618. if(e->key=='g' && td->mode!=LA_TRANSFORM_MODE_GRAB){ td->mode=LA_TRANSFORM_MODE_GRAB; ex->DrawCursor=0; }
  619. 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; }
  620. 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; }
  621. if(e->key==' '){ td->UseLocal=!td->UseLocal; }
  622. }
  623. if(e->Type==LA_MOUSEMOVE || e->Type==LA_KEY_DOWN){
  624. switch(td->mode){
  625. case LA_TRANSFORM_MODE_GRAB: la_ApplyTranslation(td,e->x-ex->ClickedX, e->y-ex->ClickedY); break;
  626. case LA_TRANSFORM_MODE_SCALE: la_ApplyScale(td,e->x-ui->L, e->y-ui->U); break;
  627. case LA_TRANSFORM_MODE_ROTATE: la_ApplyRotation(td,e->x-ui->L, e->y-ui->U); break;
  628. default: break;
  629. }
  630. ex->OnX=e->x; ex->OnY=e->y;
  631. laNotifyUsers("tns.world");
  632. }
  633. if(e->Type==LA_L_MOUSE_DOWN || (e->Type==LA_KEY_DOWN && e->key==LA_KEY_ENTER)){ ex->DrawCursor=0;
  634. la_RecordTransformDifferences(td);
  635. laNotifyUsers("tns.world"); la_FreeTransformData(td); return LA_FINISHED;
  636. }
  637. if(e->Type==LA_R_MOUSE_DOWN || e->Type==LA_ESCAPE_DOWN){ ex->DrawCursor=0;
  638. la_CancelTransformObjects(td); laNotifyUsers("tns.world"); la_FreeTransformData(td); return LA_FINISHED;
  639. }
  640. la_MakeTransformOperatorHint(a, td);
  641. return LA_RUNNING;
  642. }
  643. int la_ParentableRecursive(tnsObject* root, tnsObject* parent){
  644. for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  645. tnsObject* o=lip->p; if((!o) || (!(o->Flags&TNS_OBJECT_FLAGS_SELECTED)) || (o==parent)) continue;
  646. if(!tnsCheckParentable(o,parent)) return 0;
  647. if(!la_ParentableRecursive(o,parent)) return 0;
  648. }return 1;
  649. }
  650. void la_MakeParentExecuteRecursive(tnsObject* root, tnsObject* parent, int Unparent, int KeepTransform){
  651. laListItemPointer* NextLip;
  652. for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=NextLip){ NextLip=lip->pNext;
  653. tnsObject* o=lip->p; if((!o) || (!(o->Flags&TNS_OBJECT_FLAGS_SELECTED)) || (o==parent)) continue;
  654. if(Unparent) tnsUnparentObject(o, KeepTransform);
  655. else tnsParentObject(o, parent, KeepTransform);
  656. la_MakeParentExecuteRecursive(o,parent,Unparent,KeepTransform);
  657. }
  658. laNotifyUsers("tns.world");
  659. }
  660. int OPINV_MakeParent(laOperator *a, laEvent *e){
  661. if(!a->This || !a->This->EndInstance){ return 0; }
  662. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  663. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  664. tnsObject* mo=root->Active;
  665. int Unparent=0,KeepTransform=1;
  666. char* action=strGetArgumentString(a->ExtraInstructionsP,"action");
  667. char* keep=strGetArgumentString(a->ExtraInstructionsP,"keep_transform");
  668. if(strSame(action,"unparent")){ Unparent=1; }
  669. if(strSame(keep,"false")){ KeepTransform=0; }
  670. if(!Unparent){ if((!mo) || (!(mo->Flags&TNS_OBJECT_FLAGS_SELECTED))) return LA_FINISHED;
  671. if(!la_ParentableRecursive(root,mo)){ laEnableMessagePanel(0,0,"It didn't work","There are loops in parenting",e->x,e->y,0,e); return LA_FINISHED; }
  672. }
  673. if(keep){
  674. la_MakeParentExecuteRecursive(root,mo,Unparent,KeepTransform);
  675. laRecordInstanceDifferences(&T->World, "tns_world"); laPushDifferences(Unparent?"Unparent":"Parent", TNS_HINT_TRANSFORM);
  676. return LA_FINISHED;
  677. }
  678. laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e);
  679. return LA_RUNNING;
  680. }
  681. void laui_MakeParent(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
  682. laColumn* c=laFirstColumn(uil);
  683. laShowItemFull(uil,c,pp,"_this_M_make_parent",0,"action=parent;keep_transform=true;text=Keep transform",0,0);
  684. laShowItemFull(uil,c,pp,"_this_M_make_parent",0,"action=parent;keep_transform=false;text=Directly",0,0);
  685. }
  686. void laui_Unparent(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
  687. laColumn* c=laFirstColumn(uil);
  688. laShowItemFull(uil,c,pp,"_this_M_unparent",0,"action=unparent;keep_transform=true;text=Keep transform",0,0);
  689. laShowItemFull(uil,c,pp,"_this_M_unparent",0,"action=unparent;keep_transform=false;text=Directly",0,0);
  690. }
  691. int la_ClearTransformationRecursive(tnsObject* root, int global,int location,int rotation,int scale){
  692. int any=0; for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  693. tnsObject* o=lip->p; if(!(o->Flags&TNS_OBJECT_FLAGS_SELECTED)) continue;
  694. if(location){
  695. if(global){ o->GLocation[0]=o->GLocation[1]=o->GLocation[2]=0;}
  696. else{ o->Location[0]=o->Location[1]=o->Location[2]=0; }
  697. }
  698. if(rotation){
  699. if(global){ o->GRotation[0]=o->GRotation[1]=o->GRotation[2]=0;}
  700. else{ o->Rotation[0]=o->Rotation[1]=o->Rotation[2]=0; }
  701. }
  702. if(scale){ if(global){ o->GScale=1;} else{ o->Scale=1; } }
  703. if(global) tnsGlobalTransformValueChanged(o); else tnsSelfTransformValueChanged(o);
  704. laRecordInstanceDifferences(o, "tns_object"); any++;
  705. any+=la_ClearTransformationRecursive(o,global,location,rotation,scale);
  706. } return any;
  707. }
  708. int OPINV_ClearTransformation(laOperator *a, laEvent *e){
  709. if(!a->This || !a->This->EndInstance){ return 0; }
  710. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  711. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  712. int global=0,location=0,rotation=0,scale=0;
  713. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"global"),"true")){ global=1; }
  714. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"location"),"true")){ location=1; }
  715. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"rotation"),"true")){ rotation=1; }
  716. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"scale"),"true")){ scale=1; }
  717. int any=0;
  718. if(location||rotation||scale){
  719. any=la_ClearTransformationRecursive(root,global,location,rotation,scale);
  720. if(any){ laPushDifferences("Clear Transformations", TNS_HINT_TRANSFORM); laNotifyUsers("tns.world"); }
  721. }
  722. return LA_FINISHED;
  723. }
  724. STRUCTURE(MEDupVert){
  725. int oi; tnsMVert* nmv; tnsMVert* omv; int IsBorder;
  726. };
  727. STRUCTURE(MEDupEdge){
  728. int oi; tnsMEdge* nme; tnsMEdge* ome; int IsBorder;
  729. };
  730. STRUCTURE(MEDupFace){
  731. int oi; tnsMFace* nmf; tnsMFace* omf;
  732. };
  733. STRUCTURE(MExtrudeExtra){
  734. MEDupVert* dv; int nextv,maxv;
  735. MEDupEdge* de; int nexte,maxe;
  736. MEDupFace* df; int nextf,maxf;
  737. tnsMeshObject* mo;
  738. int RemoveOriginalFaces;
  739. };
  740. int la_IsSelectionBorderVertex(tnsMVert* mv){
  741. if(!mv->elink.pFirst)
  742. return 0;
  743. int NearSelected=0, NearUnselected=0;
  744. for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){
  745. tnsMEdge* me=lip->p; if(!(me->fl&&me->fr)) return 1;
  746. tnsMVert* av=tnsMMeshEdgeAnotherVert(me,mv);
  747. if(me->fl->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { return 1; }
  748. if(me->fr->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { return 1; }
  749. if(NearUnselected && NearSelected) return 1;
  750. }
  751. return 0;
  752. }
  753. int la_IsSelectionBorderEdge(tnsMEdge* me){
  754. if(me->fl&&me->fr){
  755. if ((me->fl->flags&TNS_MESH_FLAG_SELECTED) && (!(me->fr->flags&TNS_MESH_FLAG_SELECTED))||
  756. (me->fr->flags&TNS_MESH_FLAG_SELECTED) && (!(me->fl->flags&TNS_MESH_FLAG_SELECTED))) return 1;
  757. else return (me->fr->flags==me->fl->flags&&me->fl->flags==0);
  758. } return 1;
  759. }
  760. MExtrudeExtra* la_InitExtrude(tnsMeshObject* mo){
  761. MExtrudeExtra* ee=memAcquireSimple(sizeof(MExtrudeExtra));
  762. arrEnsureLength(&ee->dv, ee->nextv, &ee->maxv, sizeof(MEDupVert));
  763. arrEnsureLength(&ee->de, ee->nexte, &ee->maxe, sizeof(MEDupEdge));
  764. arrEnsureLength(&ee->df, ee->nextf, &ee->maxf, sizeof(MEDupFace));
  765. ee->mo=mo;
  766. return ee;
  767. }
  768. void la_ExtrudeMakeDuplication(MExtrudeExtra* ee){
  769. tnsMeshObject* mo=ee->mo;
  770. for(tnsMVert* mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){ if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  771. arrEnsureLength(&ee->dv, ee->nextv, &ee->maxv, sizeof(MEDupVert));
  772. MEDupVert* dv=&ee->dv[ee->nextv];
  773. tnsMVert* nmv=tnsMMeshNewVert(mo); tnsVectorCopy3d(mv->p, &nmv->p); dv->oi=mv->i; mv->i=ee->nextv; dv->nmv=nmv; dv->omv=mv;
  774. dv->IsBorder=la_IsSelectionBorderVertex(mv);
  775. ee->nextv++;
  776. }
  777. for(tnsMEdge* me=mo->me.pFirst;me;me=me->Item.pNext){ if(!(me->flags&TNS_MESH_FLAG_SELECTED)) continue;
  778. arrEnsureLength(&ee->de, ee->nexte, &ee->maxe, sizeof(MEDupEdge));
  779. MEDupEdge* de=&ee->de[ee->nexte];
  780. tnsMEdge* nme=tnsMMeshNewEdge(mo); de->oi=me->i; me->i=ee->nexte; de->nme=nme; de->ome=me; de->IsBorder=la_IsSelectionBorderEdge(me);
  781. tnsMMeshEdgeAssignVerts(nme, ee->dv[me->vl->i].nmv, ee->dv[me->vr->i].nmv);
  782. if(de->IsBorder&&me->fl&&me->fr){ ee->RemoveOriginalFaces=1; }
  783. ee->nexte++;
  784. }
  785. for(tnsMFace* mf=mo->mf.pFirst;mf;mf=mf->Item.pNext){
  786. if(!(mf->flags&TNS_MESH_FLAG_SELECTED)) continue;
  787. arrEnsureLength(&ee->df, ee->nextf, &ee->maxf, sizeof(MEDupFace));
  788. MEDupFace* df=&ee->df[ee->nextf];
  789. tnsMFace* nmf=tnsMMeshNewFace(mo); df->oi=mf->i; mf->i=ee->nextf; df->nmf=nmf; df->omf=mf;
  790. for(laListItemPointer*lip=mf->l.pFirst;lip;lip=lip->pNext){
  791. tnsMEdge* ome=lip->p; tnsMMeshFaceAddEdge(nmf,ee->de[ome->i].nme);
  792. }
  793. ee->nextf++;
  794. }
  795. for(int i=0;i<ee->nextv;i++){ ee->dv[i].omv->i=ee->dv[i].oi; ee->dv[i].omv->flags&=(~TNS_MESH_FLAG_SELECTED); ee->dv[i].nmv->flags|=TNS_MESH_FLAG_SELECTED; }
  796. for(int i=0;i<ee->nexte;i++){ ee->de[i].ome->i=ee->de[i].oi; ee->de[i].ome->flags&=(~TNS_MESH_FLAG_SELECTED); ee->de[i].nme->flags|=TNS_MESH_FLAG_SELECTED; }
  797. for(int i=0;i<ee->nextf;i++){
  798. ee->df[i].omf->i=ee->df[i].oi;
  799. ee->df[i].omf->flags&=(~TNS_MESH_FLAG_SELECTED);
  800. ee->df[i].nmf->flags|=TNS_MESH_FLAG_SELECTED; }
  801. }
  802. void la_RemoveOriginalFaces(MExtrudeExtra* ee){
  803. tnsMeshObject* mo=ee->mo;
  804. if(ee->RemoveOriginalFaces){
  805. for(int i=0;i<ee->nextf;i++){ tnsMMeshRemoveFaceOnly(mo, ee->df[i].omf); }
  806. for(int i=0;i<ee->nexte;i++){ if(ee->de[i].IsBorder) continue; tnsMMeshRemoveEdgeFace(mo, ee->de[i].ome); }
  807. for(int i=0;i<ee->nextv;i++){ if(ee->dv[i].IsBorder) continue; tnsMMeshRemoveVertEdgeFace(mo, ee->dv[i].omv); }
  808. }
  809. }
  810. void la_ReconnectFaces(MExtrudeExtra* ee){
  811. tnsMeshObject* mo=ee->mo;
  812. for(int i=0;i<ee->nexte;i++){
  813. if(!ee->de[i].IsBorder) continue; MEDupEdge*de=&ee->de[i];
  814. tnsMMeshMakeFace4v(mo, de->ome->vl, de->ome->vr, de->nme->vr, de->nme->vl);
  815. }
  816. }
  817. void la_FinishExtrude(MExtrudeExtra* ee, int PushDifferences){
  818. tnsMMeshRefreshIndex(ee->mo);
  819. tnsInvalidateMeshBatch(ee->mo);
  820. if(PushDifferences){
  821. laRecordInstanceDifferences(ee->mo, "tns_mesh_object"); laPushDifferences("Extruded", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  822. }
  823. free(ee->dv); free(ee->de); free(ee->df); memFree(ee);
  824. }
  825. int OPINV_Extrude(laOperator *a, laEvent *e){
  826. if(!a->This || !a->This->EndInstance){ return 0; }
  827. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  828. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  829. tnsMeshObject* mo=root->Active; if(mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE) return 0;
  830. if(!tnsMMeshAnySelected(mo)) return LA_FINISHED;
  831. MExtrudeExtra* ee=la_InitExtrude(mo);
  832. la_ExtrudeMakeDuplication(ee);
  833. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"duplicate_only"), "true")){
  834. la_FinishExtrude(ee, 1);
  835. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB)) return LA_RUNNING; return LA_FINISHED;
  836. }
  837. la_RemoveOriginalFaces(ee);
  838. la_ReconnectFaces(ee);
  839. la_FinishExtrude(ee, 1);
  840. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB)) return LA_RUNNING; return LA_FINISHED;
  841. return LA_FINISHED;
  842. }
  843. int la_EdgeShouldDeleteVert(tnsMVert* mv){
  844. if(!mv->elink.pFirst) return 0;
  845. int NearSelected=0, NearUnselected=0;
  846. for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){
  847. tnsMEdge* me=lip->p;
  848. tnsMVert* av=tnsMMeshEdgeAnotherVert(me,mv);
  849. if(av->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { NearUnselected=1; }
  850. if(NearUnselected && NearSelected) return 0;
  851. }
  852. if(NearSelected&&(!NearUnselected)) return 1; return 0;
  853. }
  854. int la_FaceShouldDeleteVert(tnsMVert* mv){
  855. if(!mv->elink.pFirst) return 0;
  856. int NearSelected=0, NearUnselected=0, IsBorder=0;
  857. for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){
  858. tnsMEdge* me=lip->p;
  859. if(!(me->fl&&me->fr)){ IsBorder=1; }
  860. if(me->fl){ if(me->fl->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { NearUnselected=1; } }
  861. if(me->fr){ if(me->fr->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { NearUnselected=1; } }
  862. if(NearUnselected && NearSelected) return 0;
  863. }
  864. if((!NearUnselected) && IsBorder) return 1;
  865. return 1;
  866. }
  867. int la_FaceShouldDeleteEdge(tnsMEdge* me){
  868. if(me->fl&&me->fr){
  869. if ((me->fl->flags&TNS_MESH_FLAG_SELECTED) && (!(me->fr->flags&TNS_MESH_FLAG_SELECTED))||
  870. (me->fr->flags&TNS_MESH_FLAG_SELECTED) && (!(me->fl->flags&TNS_MESH_FLAG_SELECTED))) return 0;
  871. else return (me->fr->flags==me->fl->flags&&me->fl->flags==1);
  872. }else{
  873. if(me->fl&&me->fl->flags&TNS_MESH_FLAG_SELECTED&&!me->fr) return 1;
  874. if(me->fr&&me->fr->flags&TNS_MESH_FLAG_SELECTED&&!me->fl) return 1;
  875. } return 0;
  876. }
  877. void la_DeleteVertices(tnsMeshObject* mo){
  878. tnsMVert* nextmv; for(tnsMVert*mv=mo->mv.pFirst;mv;mv=nextmv){ nextmv=mv->Item.pNext; if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  879. tnsMMeshRemoveVertEdgeFace(mo, mv);
  880. }
  881. }
  882. void la_DeleteEdges(tnsMeshObject* mo){
  883. laListHandle lv={0};
  884. for(tnsMVert*mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){ if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  885. if(la_EdgeShouldDeleteVert(mv)) lstAppendPointer(&lv,mv);
  886. }
  887. tnsMEdge* nextme; for(tnsMEdge*me=mo->me.pFirst;me;me=nextme){ nextme=me->Item.pNext; if(!(me->flags&TNS_MESH_FLAG_SELECTED)) continue;
  888. tnsMMeshRemoveEdgeFace(mo, me);
  889. }
  890. tnsMVert* mv; while(mv=lstPopPointer(&lv)){ tnsMMeshRemoveVertEdgeFace(mo,mv); }
  891. }
  892. void la_DeleteFaces(tnsMeshObject* mo, int OnlyFaces){
  893. laListHandle lv={0}, le={0};
  894. if(OnlyFaces){
  895. tnsMFace* nextmf; for(tnsMFace*mf=mo->mf.pFirst;mf;mf=nextmf){ nextmf=mf->Item.pNext; if(!(mf->flags&TNS_MESH_FLAG_SELECTED)) continue;
  896. tnsMMeshRemoveFaceOnly(mo, mf);
  897. }
  898. }else{
  899. for(tnsMVert*mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){ if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  900. if(la_FaceShouldDeleteVert(mv)) lstAppendPointer(&lv,mv);
  901. }
  902. for(tnsMEdge*me=mo->me.pFirst;me;me=me->Item.pNext){ if(!(me->flags&TNS_MESH_FLAG_SELECTED)) continue;
  903. if(la_FaceShouldDeleteEdge(me)) lstAppendPointer(&le,me);
  904. }
  905. tnsMFace* nextmf; for(tnsMFace*mf=mo->mf.pFirst;mf;mf=nextmf){ nextmf=mf->Item.pNext; if(!(mf->flags&TNS_MESH_FLAG_SELECTED)) continue;
  906. tnsMMeshRemoveFaceOnly(mo, mf);
  907. }
  908. tnsMEdge* me; while(me=lstPopPointer(&le)){ tnsMMeshRemoveEdgeFace(mo,me); }
  909. tnsMVert* mv; while(mv=lstPopPointer(&lv)){ tnsMMeshRemoveVertEdgeFace(mo,mv); }
  910. }
  911. }
  912. int la_DeleteSelectedObjectsRecursive(tnsObject* root){
  913. int any=0; for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){ if(!lip->p) continue;
  914. tnsObject* o=lip->p; la_DeleteSelectedObjectsRecursive(lip->p);
  915. if(o->Flags&TNS_OBJECT_FLAGS_SELECTED){ tnsDestroyObject(o); any++; }
  916. }
  917. return any;
  918. }
  919. int OPINV_Delete(laOperator *a, laEvent *e){
  920. if(!a->This || !a->This->EndInstance){ return 0; }
  921. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  922. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  923. tnsMeshObject* mo=root->Active;
  924. if(mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){
  925. if(la_DeleteSelectedObjectsRecursive(root)){
  926. laRecordInstanceDifferences(&T->World, "tns_world"); laPushDifferences("Deleted objects", TNS_HINT_TRANSFORM); laNotifyUsers("tns.world");
  927. }
  928. }else{
  929. if(!tnsMMeshAnySelected(mo)) return LA_FINISHED;
  930. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"vertices")){
  931. la_DeleteVertices(mo);
  932. }elif(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"edges")){
  933. la_DeleteEdges(mo);
  934. }elif(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"faces")){
  935. la_DeleteFaces(mo,0);
  936. }elif(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"only_faces")){
  937. la_DeleteFaces(mo,1);
  938. }else{
  939. laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e);
  940. return LA_RUNNING;
  941. }
  942. tnsMMeshDeselectAll(mo);
  943. tnsMMeshRefreshIndex(mo);
  944. tnsInvalidateMeshBatch(mo);
  945. laRecordInstanceDifferences(mo, "tns_mesh_object"); laPushDifferences("Deleted primitives", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  946. }
  947. return LA_FINISHED;
  948. }
  949. void laui_Delete(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
  950. laColumn* c=laFirstColumn(uil);
  951. laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=vertices;text=Vertices",0,0);
  952. laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=edges;text=Edges",0,0);
  953. laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=faces;text=Faces",0,0);
  954. laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=only_faces;text=Only Faces",0,0);
  955. }
  956. STRUCTURE(MIslandInfo){
  957. laListItem Item;
  958. laListHandle v,e,f;int numv,nume,numf;
  959. int Paired,HasBranches;
  960. };
  961. STRUCTURE(MMakeData){
  962. laListHandle Islands; int NumIslands;
  963. };
  964. #define M_SHOULD_INCL_PRIM(m) \
  965. ((!(m->flags&TNS_MESH_FLAG_PICKED)) && (m->flags&TNS_MESH_FLAG_SELECTED))
  966. #define M_SHOULD_USE_OE(oe,sf) \
  967. (((!oe->fl)&&((!sf)||(oe->fr!=sf)))||((!oe->fr)&&((!sf)||(oe->fl!=sf))))
  968. MIslandInfo* la_NewMIsland(MMakeData* md){ MIslandInfo* ii=memAcquireSimple(sizeof(MIslandInfo)); lstAppendItem(&md->Islands, ii); md->NumIslands++; return ii; }
  969. void la_FillIslandFromVert(MIslandInfo* ii, tnsMVert* mv, int SelectMode){
  970. mv->flags|=TNS_MESH_FLAG_PICKED; lstAppendPointer(&ii->v,mv); ii->numv++; int connections=0;
  971. for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){ tnsMEdge* oe=lip->p; tnsMVert* ov=tnsMMeshEdgeAnotherVert(oe,mv);
  972. if(ov->flags&TNS_MESH_FLAG_SELECTED) connections++; else continue;
  973. if(SelectMode==LA_CANVAS_SELECT_MODE_EDGES){ if(!(oe->flags&TNS_MESH_FLAG_SELECTED)) continue; }
  974. if(M_SHOULD_INCL_PRIM(ov)){ la_FillIslandFromVert(ii,ov,SelectMode); } else { continue; }
  975. if(M_SHOULD_INCL_PRIM(oe)){ lstAppendPointer(&ii->e,oe); ii->nume++; oe->flags|=TNS_MESH_FLAG_PICKED; }
  976. if(oe->fl&&M_SHOULD_INCL_PRIM(oe->fl)){ lstAppendPointer(&ii->f,oe->fl); ii->numf++; oe->fl->flags|=TNS_MESH_FLAG_PICKED; }
  977. if(oe->fr&&M_SHOULD_INCL_PRIM(oe->fr)){ lstAppendPointer(&ii->f,oe->fr); ii->numf++; oe->fr->flags|=TNS_MESH_FLAG_PICKED; }
  978. }
  979. if(connections>2) ii->HasBranches=1;
  980. }
  981. void la_GetSelectionIslands(tnsMeshObject* mo, MMakeData* md, int SelectMode){
  982. tnsMMeshClearExtraFlags(mo);
  983. for(tnsMVert* mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){
  984. if(M_SHOULD_INCL_PRIM(mv)){ MIslandInfo* ii=la_NewMIsland(md); la_FillIslandFromVert(ii,mv,SelectMode); }
  985. }
  986. }
  987. void la_ClearIslands(MMakeData* md){ MIslandInfo* ii; while(ii=lstPopItem(&md->Islands)){ while(lstPopPointer(&ii->v)); memFree(ii); } }
  988. tnsMFace* la_MakeFacesFrom1Vert(tnsMeshObject* mo, tnsMVert* mv){
  989. tnsMEdge* oe1=0,*oe2=0; tnsMVert* ov1,*ov2;
  990. for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){
  991. tnsMEdge* oe=lip->p; if(oe->flags&TNS_MESH_FLAG_SELECTED) continue; if((!oe->fl)||(!oe->fr)){ if(!oe1)oe1=oe;elif(!oe2)oe2=oe;else return 0; /* more than 2 empty edges connected */ }
  992. } if(!oe1||!oe2) return 0;
  993. ov1=tnsMMeshEdgeAnotherVert(oe1,mv); ov2=tnsMMeshEdgeAnotherVert(oe2,mv);
  994. laListHandle vl={0}; lstAppendPointer(&vl,ov1); lstAppendPointer(&vl,mv); lstAppendPointer(&vl,ov2);
  995. tnsMFace* f=tnsMMeshMakeFaceN(mo, 3, &vl, 0);
  996. ov1->flags|=TNS_MESH_FLAG_SELECTED;ov2->flags|=TNS_MESH_FLAG_SELECTED; mv->flags&=(~TNS_MESH_FLAG_SELECTED);
  997. tnsMMeshEnsureSelectionFromVerts(mo);
  998. while(lstPopPointer(&vl)); return f;
  999. }
  1000. tnsMFace* la_MakeFacesFrom2Verts(tnsMeshObject* mo, tnsMVert* mv1, tnsMVert* mv2){
  1001. tnsMEdge* oe1=0,*oe2=0; tnsMVert* ov1,*ov2; tnsMFace* sf=0;
  1002. tnsMEdge* se=tnsMMeshVertShareEdge(mv1,mv2); if(se->fl && se->fr) return 0; sf=se->fl?se->fl:se->fr;
  1003. for(laListItemPointer* lip=mv1->elink.pFirst;lip;lip=lip->pNext){
  1004. tnsMEdge* oe=lip->p; if(oe->flags&TNS_MESH_FLAG_SELECTED) continue; if(M_SHOULD_USE_OE(oe,sf)){ if(!oe1)oe1=oe;else return 0; /* more than 1 empty edge connected */ }
  1005. }
  1006. for(laListItemPointer* lip=mv2->elink.pFirst;lip;lip=lip->pNext){
  1007. tnsMEdge* oe=lip->p; if(oe->flags&TNS_MESH_FLAG_SELECTED) continue; if(M_SHOULD_USE_OE(oe,sf)){ if(!oe2)oe2=oe;else return 0; /* more than 1 empty edge connected */ }
  1008. }
  1009. if(!oe1||!oe2) return 0;
  1010. ov1=tnsMMeshEdgeAnotherVert(oe1,mv1); ov2=tnsMMeshEdgeAnotherVert(oe2,mv2);
  1011. ov1->flags|=TNS_MESH_FLAG_SELECTED;ov2->flags|=TNS_MESH_FLAG_SELECTED; mv1->flags&=(~TNS_MESH_FLAG_SELECTED);mv2->flags&=(~TNS_MESH_FLAG_SELECTED);
  1012. laListHandle vl={0}; lstAppendPointer(&vl,ov1); lstAppendPointer(&vl,mv1); lstAppendPointer(&vl,mv2); lstAppendPointer(&vl,ov2);
  1013. tnsMFace* f=tnsMMeshMakeFaceN(mo, 4, &vl, 0); tnsMMeshEnsureSelectionFromVerts(mo);
  1014. while(lstPopPointer(&vl)); return f;
  1015. }
  1016. int la_IsEndingVert(tnsMVert* mv){
  1017. int sel=0; for(laListItemPointer*lip=mv->elink.pFirst;lip;lip=lip->pNext){ tnsMEdge* me=lip->p;
  1018. if(tnsMMeshEdgeAnotherVert(me,mv)->flags&TNS_MESH_FLAG_SELECTED){ sel++; if(sel>1) return 0; }
  1019. }
  1020. if(sel==1) return 1; return 0;
  1021. }
  1022. void la_EnsureIslandVertsSequence(MIslandInfo* ii){
  1023. laListHandle l={0}; tnsMVert* startv=((laListItemPointer*)ii->v.pFirst)->p; laListItemPointer* nextlip;
  1024. for(laListItemPointer*lip=ii->v.pFirst;lip;lip=lip->pNext){ if(la_IsEndingVert(lip->p)){ startv=lip->p; break; } } // otherwise a loop, doesn't matter.
  1025. lstRemovePointer(&ii->v, startv); lstAppendPointer(&l, startv);
  1026. while(ii->v.pFirst){
  1027. for(laListItemPointer*lip=ii->v.pFirst;lip;lip=lip->pNext){ nextlip=lip->pNext;
  1028. if(tnsMMeshVertShareEdge(startv, lip->p)){ startv=lip->p; lstRemoveItem(&ii->v,lip); lstAppendItem(&l, lip); break; }
  1029. }
  1030. }
  1031. memcpy(&ii->v, &l, sizeof(laListHandle));
  1032. }
  1033. MIslandInfo* la_GetNeighborIsland(tnsMVert* from, MMakeData* md){
  1034. int found=0; real dist=1e10; MIslandInfo* rii=0; for(MIslandInfo* ii=md->Islands.pFirst;ii;ii=ii->Item.pNext){ if(ii->Paired) continue;
  1035. found=1; tnsMVert* mv1=((laListItemPointer*)ii->v.pFirst)->p,*mv2=((laListItemPointer*)ii->v.pLast)->p;
  1036. real d1=tnsDist3dv(mv1->p, from->p),d2=tnsDist3dv(mv2->p, from->p);
  1037. if(d2<d1 && d2<dist){ lstReverse(&ii->v); } if(d1<dist || d2<dist){ rii=ii; }
  1038. }
  1039. if(rii) rii->Paired=1;
  1040. return rii;
  1041. }
  1042. int la_MakeFacesFromIslands(tnsMeshObject* mo, MMakeData* md){
  1043. int success=0;
  1044. if(!md->Islands.pFirst) return 0;
  1045. if(md->Islands.pFirst==md->Islands.pLast){
  1046. MIslandInfo* ii=md->Islands.pFirst; if(ii->HasBranches) return 0;
  1047. if(ii->numv==1){ laListItemPointer*lip=ii->v.pFirst; if(la_MakeFacesFrom1Vert(mo,lip->p)) success++; }
  1048. elif(ii->numv==2){ laListItemPointer*lip=ii->v.pFirst,*lip2=ii->v.pLast; if(la_MakeFacesFrom2Verts(mo,lip->p, lip2->p)) success++; }
  1049. else{ la_EnsureIslandVertsSequence(ii); if(tnsMMeshMakeFaceN(mo, ii->numv, &ii->v, 0)) success++; }
  1050. }else{
  1051. for(MIslandInfo* ii=md->Islands.pFirst;ii;ii=ii->Item.pNext){ if(ii->HasBranches) return 0; la_EnsureIslandVertsSequence(ii); }
  1052. laListHandle final={0}; int vcount=0;
  1053. MIslandInfo* ii=md->Islands.pFirst; ii->Paired=1; for(laListItemPointer* lip=ii->v.pFirst;lip;lip=lip->pNext){ lstAppendPointer(&final, lip->p); vcount++; }
  1054. while((ii=la_GetNeighborIsland(((laListItemPointer*)ii->v.pLast)->p, md))){
  1055. for(laListItemPointer* lip=ii->v.pFirst;lip;lip=lip->pNext){ lstAppendPointer(&final, lip->p); vcount++; }
  1056. }
  1057. tnsMEdge* fallback_e=0;
  1058. if(tnsMMeshMakeFaceN(mo,vcount,&final, &fallback_e) || fallback_e) success++;
  1059. while(lstPopPointer(&final));
  1060. }
  1061. return success;
  1062. }
  1063. int OPINV_Make(laOperator *a, laEvent *e){
  1064. if(!a->This || !a->This->EndInstance){ return 0; }
  1065. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1066. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  1067. tnsMeshObject* mo=root->Active;
  1068. if(!mo||mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
  1069. MMakeData md={0};
  1070. la_GetSelectionIslands(mo,&md,ex->SelectMode);
  1071. int success=la_MakeFacesFromIslands(mo,&md); if(success){ tnsMMeshCalculateNormal(mo); }
  1072. la_ClearIslands(&md);
  1073. tnsMMeshRefreshIndex(mo);
  1074. tnsMMeshEnsureSelection(mo,ex->SelectMode);
  1075. tnsInvalidateMeshBatch(mo);
  1076. if(laRecordInstanceDifferences(mo, "tns_mesh_object")) laPushDifferences("Make primitives", TNS_HINT_GEOMETRY);
  1077. laNotifyUsers("tns.world");
  1078. return LA_FINISHED;
  1079. }
  1080. int OPINV_Subdiv(laOperator *a, laEvent *e){
  1081. if(!a->This || !a->This->EndInstance){ return 0; }
  1082. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1083. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  1084. tnsMeshObject* mo=root->Active;
  1085. if(mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
  1086. laListHandle pending={0}; for(tnsMEdge* me=mo->me.pFirst;me;me=me->Item.pNext){ if(me->flags&TNS_MESH_FLAG_SELECTED) lstAppendPointer(&pending, me); }
  1087. if(!pending.pFirst) return LA_FINISHED;
  1088. tnsMEdge* me; while(me=lstPopPointer(&pending)){ tnsMVert* mv=tnsMMeshEdgeInsertVertAt(mo,me,0.5,0,0,0); mv->flags|=TNS_MESH_FLAG_SELECTED; }
  1089. tnsMMeshRefreshIndex(mo);
  1090. tnsMMeshEnsureSelection(mo,ex->SelectMode);
  1091. tnsInvalidateMeshBatch(mo);
  1092. if(laRecordInstanceDifferences(mo, "tns_mesh_object")) laPushDifferences("Subdivide edges", TNS_HINT_GEOMETRY);
  1093. laNotifyUsers("tns.world");
  1094. return LA_FINISHED;
  1095. }
  1096. int OPINV_Add(laOperator *a, laEvent *e){
  1097. if(!a->This || !a->This->EndInstance){ return 0; }
  1098. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1099. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  1100. tnsMeshObject* mo=root->Active; int ran=0; tnsObject* no=0;
  1101. if((!mo) || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){
  1102. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"PLANE")){ tnsDeselectAllObjects(root);
  1103. no=tnsCreateMeshPlane(root, "Plane",0,0,0,10); no->Flags|=TNS_OBJECT_FLAGS_SELECTED; memAssignRef(root,&root->Active,no); ran=1; }
  1104. else{ laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING; }
  1105. if(ran){ laRecordAndPush(0,"tns.world","Add object",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world"); }
  1106. }else{
  1107. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"PLANE")){
  1108. tnsMMeshDeselectAll(mo); tnsAddMMeshPlane(mo, 10); tnsMMeshEnsureSelection(mo,ex->SelectMode); ran=1;
  1109. }else{ laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING; }
  1110. if(ran){
  1111. tnsMMeshRefreshIndex(mo); tnsInvalidateMeshBatch(mo);
  1112. laRecordInstanceDifferences(mo, "tns_mesh_object"); laPushDifferences("Add primitives", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  1113. }
  1114. }
  1115. return LA_FINISHED;
  1116. }
  1117. void laui_Add(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
  1118. laColumn* c=laFirstColumn(uil);
  1119. laShowItemFull(uil,c,pp,"_this_M_add",0,"mode=PLANE;text=Plane",0,0);
  1120. }
  1121. int OPINV_Separate(laOperator *a, laEvent *e){
  1122. if(!a->This || !a->This->EndInstance){ return 0; }
  1123. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1124. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return LA_CANCELED;
  1125. tnsMeshObject* mo=root->Active; int ran=0;
  1126. if(mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){
  1127. return LA_CANCELED;
  1128. }
  1129. if(!tnsMMeshAnySelected(mo)) return LA_CANCELED;
  1130. MExtrudeExtra* ee=la_InitExtrude(mo);
  1131. la_ExtrudeMakeDuplication(ee);
  1132. ee->RemoveOriginalFaces=1;la_RemoveOriginalFaces(ee);
  1133. tnsMeshObject* no=tnsCreateMeshEmpty(mo->Base.ParentObject?mo->Base.ParentObject:mo->Base.InRoot, mo->Base.Name->Ptr, 0,0,0);
  1134. tnsCopyObjectTransformationsLocal(no,mo);
  1135. no->Mode=TNS_MESH_EDIT_MODE;
  1136. tnsMVert* nmv; for(tnsMVert* mv=mo->mv.pFirst;mv;mv=nmv){ nmv=mv->Item.pNext; if(!(mv->flags&TNS_MESH_FLAG_SELECTED))continue;
  1137. lstRemoveItem(&mo->mv, mv); lstAppendItem(&no->mv, mv); no->totmv++; mo->totmv--; }
  1138. tnsMEdge* nme; for(tnsMEdge* me=mo->me.pFirst;me;me=nme){ nme=me->Item.pNext; if(!(me->flags&TNS_MESH_FLAG_SELECTED))continue;
  1139. lstRemoveItem(&mo->me, me); lstAppendItem(&no->me, me); no->totme++; mo->totme--; }
  1140. tnsMFace* nmf; for(tnsMFace* mf=mo->mf.pFirst;mf;mf=nmf){ nmf=mf->Item.pNext; if(!(mf->flags&TNS_MESH_FLAG_SELECTED))continue;
  1141. lstRemoveItem(&mo->mf, mf); lstAppendItem(&no->mf, mf); no->totmf++; mo->totmf--; }
  1142. tnsMMeshRefreshIndex(no); tnsMeshLeaveEditMode(no);
  1143. la_FinishExtrude(ee, 0);
  1144. tnsMMeshRefreshIndex(mo); tnsInvalidateMeshBatch(mo);
  1145. laRecordAndPush(0,"tns.world","Separate mesh parts",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  1146. return LA_FINISHED;
  1147. }
  1148. void la_PopulateSelectedMeshObjects(tnsObject* root, laListHandle* l){
  1149. if(root->Type==TNS_OBJECT_MESH && root->Flags&TNS_OBJECT_FLAGS_SELECTED){ lstAppendPointer(l,root); }
  1150. for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  1151. la_PopulateSelectedMeshObjects(lip->p, l);
  1152. }
  1153. }
  1154. int OPINV_Combine(laOperator *a, laEvent *e){
  1155. if(!a->This || !a->This->EndInstance){ return 0; }
  1156. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1157. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return LA_CANCELED;
  1158. tnsMeshObject* mo=root->Active; int ran=0;
  1159. if(!mo || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode==TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
  1160. laListHandle pending={0}; la_PopulateSelectedMeshObjects(root,&pending);
  1161. tnsMeshObject* o; while(o=lstPopPointer(&pending)){ if(o==mo || o->Mode==TNS_MESH_EDIT_MODE) continue;
  1162. if(tnsMergeMeshObjects(mo, o)) ran++;
  1163. }
  1164. if(ran){
  1165. tnsMMeshRefreshIndex(mo); tnsInvalidateMeshBatch(mo);
  1166. laRecordAndPush(0,"tns.world","Merge mesh objects",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  1167. }
  1168. return LA_FINISHED;
  1169. }
  1170. int OPINV_Duplicate(laOperator *a, laEvent *e){
  1171. if(!a->This || !a->This->EndInstance){ return 0; }
  1172. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1173. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return LA_CANCELED;
  1174. tnsMeshObject* mo=root->Active; int ran=0;
  1175. if(!mo || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode==TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
  1176. laListHandle pending={0}; la_PopulateSelectedMeshObjects(root,&pending);
  1177. tnsMeshObject* o; tnsMeshObject* no;while(o=lstPopPointer(&pending)){ if(o->Mode==TNS_MESH_EDIT_MODE) continue;
  1178. if(no=tnsDuplicateMeshObjects(o)){ no->Base.Flags|=TNS_OBJECT_FLAGS_SELECTED; o->Base.Flags&=(~TNS_OBJECT_FLAGS_SELECTED);
  1179. if(mo==o){ memAssignRef(root,&root->Active,no); } ran++;
  1180. }
  1181. }
  1182. if(ran){
  1183. laRecordAndPush(0,"tns.world","Merge mesh objects",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  1184. if(la_InitTransform(a,e,LA_TRANSFORM_MODE_GRAB)) return LA_RUNNING; return LA_FINISHED;
  1185. }
  1186. return LA_FINISHED;
  1187. }
  1188. int OPINV_RecalculateNormals(laOperator *a, laEvent *e){
  1189. if(!a->This || !a->This->EndInstance){ return 0; }
  1190. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1191. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return LA_CANCELED;
  1192. tnsMeshObject* mo=root->Active; int ran=0;
  1193. if(!mo || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
  1194. ran=tnsMMeshCalculateNormal(mo);
  1195. if(ran){ tnsInvalidateMeshBatch(mo); laRecordAndPush(0,"tns.world","Recalculate Normals",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world"); }
  1196. return LA_FINISHED;
  1197. }
  1198. STRUCTURE(MKnifeElement){
  1199. laListItem Item;
  1200. void* p;
  1201. int Type;
  1202. };
  1203. void la_KnifeUpdateToolBatch(MSelectExtra* se,tnsObject* o){
  1204. if(se->root->ExtraBatch) tnsDeleteBatch(se->root->ExtraBatch); se->root->ExtraBatch=0;
  1205. int count=lstCountElements(&se->KnifeElements); if((!count) && (!se->PendingElem)) return;
  1206. float* points=calloc((count+1)*3,sizeof(real));
  1207. float* p=points; real tmp[3],trans[4];
  1208. for(MKnifeElement* ke=se->KnifeElements.pFirst;ke;ke=ke->Item.pNext){
  1209. if(ke->Type==TNS_MMESH_EDGE_BIT){ tnsMEdge* me=ke->p; tnsVectorSet3v(tmp,me->vl->p); tnsVectorAccum3d(tmp,me->vr->p);
  1210. tnsVectorMultiSelf3d(tmp,0.5); tnsApplyTransform43d(trans,o->GlobalTransform,tmp); tnsVectorSet3v(p,trans); }
  1211. else{ tnsMVert* mv=ke->p; tnsApplyTransform43d(trans,o->GlobalTransform,mv->p); tnsVectorSet3v(p,trans); }
  1212. p+=3;
  1213. }
  1214. if(se->PendingElem){
  1215. if(se->PendingElemType==TNS_MMESH_EDGE_BIT){ tnsMEdge* me=se->PendingElem; tnsVectorSet3v(tmp,me->vl->p); tnsVectorAccum3d(tmp,me->vr->p);
  1216. tnsVectorMultiSelf3d(tmp,0.5); tnsApplyTransform43d(trans,o->GlobalTransform,tmp); tnsVectorSet3v(p,trans); }
  1217. else{ tnsMVert* mv=se->PendingElem; tnsApplyTransform43d(trans,o->GlobalTransform,mv->p); tnsVectorSet3v(p,trans); }
  1218. }elif(count){
  1219. tnsVectorSet3v(p,p-3);
  1220. }
  1221. uint32_t elem=count;
  1222. tnsBatch* batch=tnsCreateBatch(count+1,3,points,0,0,0,0); tnsBatchCommand*c;
  1223. c=tnsCreateCommand(batch, "hovering_point", 1, 3, GL_POINTS, &elem, 0);
  1224. tnsCommandUseUniformColor(c,laAccentColor(LA_BT_SVERTEX));
  1225. if(count){
  1226. c=tnsCreateCommand(batch, "edges", count+1, 3, GL_LINE_STRIP, 0, 0);
  1227. tnsCommandUseUniformColor(c,laAccentColor(LA_BT_NORMAL));
  1228. c=tnsCreateCommand(batch, "points", count+1, 3, GL_POINTS, 0, 0);
  1229. tnsCommandUseUniformColor(c,laAccentColor(LA_BT_NORMAL));
  1230. }
  1231. se->root->ExtraBatch=batch;
  1232. free(points);
  1233. }
  1234. int la_KnifeIsDuplicated(MSelectExtra* se, void* ref){
  1235. for(MKnifeElement* ke=se->KnifeElements.pFirst;ke;ke=ke->Item.pNext){
  1236. if(ke->Type==TNS_MMESH_EDGE_BIT && ke->p==ref){ return 1; }
  1237. }
  1238. return 0;
  1239. }
  1240. void la_KnifeAppendCut(MSelectExtra* se){
  1241. MKnifeElement* ke=lstAppendPointerSized(&se->KnifeElements,se->PendingElem,sizeof(MKnifeElement));
  1242. ke->Type=se->PendingElemType;
  1243. }
  1244. int la_KnifeRegisterCuts(MSelectExtra* se, tnsMeshObject* mo){
  1245. if(!mo || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE) return 0;
  1246. if(!se->KnifeElements.pFirst) return 0;
  1247. tnsMVert* lastv=0,*newv=0; tnsMEdge* newme=0; int changed=0;
  1248. for(MKnifeElement* ke=se->KnifeElements.pFirst;ke;ke=ke->Item.pNext){
  1249. if(ke->Type==TNS_MMESH_EDGE_BIT){
  1250. newv=tnsMMeshEdgeInsertVertAt(mo,ke->p,0.5,0,0,0); changed=1;
  1251. }
  1252. else{ newv=ke->p; }
  1253. if(lastv){ if(tnsMMeshVertsShareFace(lastv,newv)) newme=tnsMMeshMakeEdge(mo, lastv, newv); changed=1; }
  1254. lastv=newv; newv->flags|=TNS_MESH_FLAG_SELECTED; if(newme){ newme->flags|=TNS_MESH_FLAG_SELECTED; }
  1255. }
  1256. if(changed){ tnsMMeshRefreshIndex(mo); tnsMMeshCalculateNormal(mo); }
  1257. return changed;
  1258. }
  1259. void la_KnifeFinish(MSelectExtra* se, tnsObject*o){
  1260. if(o->ExtraBatch) tnsDeleteBatch(o->ExtraBatch); o->ExtraBatch=0;
  1261. while(lstPopPointer(&se->KnifeElements));
  1262. la_FreeSelectData(se->sd); memFree(se);
  1263. }
  1264. int OPINV_Knife(laOperator *a, laEvent *e){
  1265. if(!a->This || !a->This->EndInstance){ return 0; }
  1266. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1267. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return LA_CANCELED;
  1268. tnsMeshObject* mo=root->Active; int ran=0;
  1269. if(!mo || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
  1270. MSelectExtra* se=memAcquire(sizeof(MSelectExtra));
  1271. MSelectData* sd=la_InitSelectData(ex->OffScr->pColor[0]->Width, ex->OffScr->pColor[0]->Height, c);
  1272. a->CustomData=se; se->sd=sd; se->root=root;
  1273. la_PopulateSelectDataPrimitives(sd,mo,c,LA_CANVAS_SELECT_MODE_KNIFE);
  1274. strSafeSet(&a->RuntimeHint, "◧ Set cut ◨ Cancel ⮨ Confirm");
  1275. return LA_RUNNING;
  1276. }
  1277. int OPMOD_Knife(laOperator *a, laEvent *e){
  1278. if(!a->This || !a->This->EndInstance || !a->CustomData){ return 0; }
  1279. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1280. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  1281. MSelectExtra* se=a->CustomData;
  1282. tnsMeshObject* mo=root->Active;
  1283. int changed=0;
  1284. if(e->Type==LA_R_MOUSE_DOWN || (e->Type == LA_KEY_DOWN && e->key==LA_KEY_ESCAPE)){
  1285. la_KnifeFinish(se,root); laNotifyUsers("tns.world"); return LA_FINISHED;
  1286. }
  1287. if(e->Type&LA_MOUSE_EVENT){
  1288. int elemtype,id=la_SelectGetClosest(se->sd, e->x-ui->L, e->y-ui->U, LA_RH,&elemtype)-1;
  1289. void* p=la_SelectGetRef(se->sd,id,elemtype); if(la_KnifeIsDuplicated(se,p)) p=0;
  1290. if(se->PendingElem!=p){ changed=1; }
  1291. se->PendingElem=p; se->PendingElemType=elemtype;
  1292. if(e->Type==LA_L_MOUSE_DOWN && p){ la_KnifeAppendCut(se); changed=1; }
  1293. }
  1294. if(e->Type==LA_KEY_DOWN && e->key==LA_KEY_ENTER){
  1295. if(la_KnifeRegisterCuts(se,mo)){ tnsMMeshEnsureSelection(mo,ex->SelectMode);
  1296. tnsInvalidateMeshBatch(mo); laRecordAndPush(0,"tns.world","Knife Cut",TNS_HINT_GEOMETRY);laNotifyUsers("tns.world");
  1297. }
  1298. la_KnifeFinish(se,root); return LA_FINISHED;
  1299. }
  1300. if(changed){
  1301. la_KnifeUpdateToolBatch(se,mo); laRedrawCurrentPanel();
  1302. }
  1303. return LA_RUNNING;
  1304. }
  1305. void la_RegisterModellingOperators(){
  1306. laPropContainer *pc; laProp *p;
  1307. laOperatorType *at;
  1308. laEnumProp *ep;
  1309. laCreateOperatorType("M_set_cursor", "Set Cursor", "Set cursor in the viewport", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_SetCursor, 0, 0, LA_EXTRA_TO_PANEL);
  1310. laCreateOperatorType("M_toggle_edit_mode", "Toggle Edit Mode", "Toggle edit mode of the active object", OPCHK_ThereIsActiveObject, 0, 0, OPINV_ToggleEdit, 0, 0, 0);
  1311. laCreateOperatorType("M_select", "Select", "Select things in the viewport", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Select, OPMOD_Select, 0, LA_EXTRA_TO_PANEL);
  1312. laCreateOperatorType("M_grab", "Grab", "Grab things and move around", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Grab, OPMOD_Transformation, 0, LA_EXTRA_TO_PANEL);
  1313. laCreateOperatorType("M_scale", "Scale", "Scale selected things", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Scale, OPMOD_Transformation, 0, LA_EXTRA_TO_PANEL);
  1314. laCreateOperatorType("M_rotate", "Rotate", "Rotation selected things", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Rotate, OPMOD_Transformation, 0, LA_EXTRA_TO_PANEL);
  1315. at=laCreateOperatorType("M_make_parent", "Make Parent", "Parent objects to active objects or unparent selected ones", 0, 0, 0, OPINV_MakeParent, OPMOD_FinishOnData, 0, 0);
  1316. at->UiDefine = laui_MakeParent;
  1317. at=laCreateOperatorType("M_unparent", "Unparent", "Unparent selected objects", 0, 0, 0, OPINV_MakeParent, OPMOD_FinishOnData, 0, 0);
  1318. at->UiDefine = laui_Unparent;
  1319. laCreateOperatorType("M_clear_transformations", "Clear Transformations", "Clear transformations in objects", 0, 0, 0, OPINV_ClearTransformation, 0, 0, 0);
  1320. laCreateOperatorType("M_extrude", "Extrude", "Extrude parts of the mesh", 0, 0, 0, OPINV_Extrude, OPMOD_Transformation, 0, 0);
  1321. at=laCreateOperatorType("M_delete", "Delete", "Delete parts of the mesh", 0, 0, 0, OPINV_Delete, OPMOD_FinishOnData, 0, 0);
  1322. at->UiDefine=laui_Delete;
  1323. laCreateOperatorType("M_make", "Make", "Make mesh primitive from selected ones", 0, 0, 0, OPINV_Make, 0, 0, 0);
  1324. laCreateOperatorType("M_subdiv", "Subdiv", "Subdivide edges", 0, 0, 0, OPINV_Subdiv, 0, 0, 0);
  1325. at=laCreateOperatorType("M_add", "Add", "Add mesh or primitives", 0, 0, 0, OPINV_Add, OPMOD_FinishOnData, 0, 0);
  1326. at->UiDefine=laui_Add;
  1327. laCreateOperatorType("M_separate", "Separate", "Separate mesh parts", 0, 0, 0, OPINV_Separate, 0, 0, 0);
  1328. laCreateOperatorType("M_combine", "Combine", "Combine mesh objects", 0, 0, 0, OPINV_Combine, 0, 0, 0);
  1329. laCreateOperatorType("M_duplicate", "Duplicate", "Duplicate objects", 0, 0, 0, OPINV_Duplicate, OPMOD_Transformation, 0, 0);
  1330. laCreateOperatorType("M_recalculate_normals", "Recalculate Normals", "Recalculate normals", 0, 0, 0, OPINV_RecalculateNormals, 0, 0, 0);
  1331. laCreateOperatorType("M_knife", "Knife", "Cut through edges", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Knife, OPMOD_Knife, 0, LA_EXTRA_TO_PANEL);
  1332. }