*/}}

la_modelling.c 110 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073
  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. #include "nanovg.h"
  20. extern LA MAIN;
  21. extern struct _tnsMain *T;
  22. void tnsRemoveMaterial(tnsMaterial* mat);
  23. void tns_InvalidateMeshWithMaterial(tnsMaterial* m);
  24. void la_ReadGLocation(tnsOffscreen* off, int x, int y,float* xyz0){
  25. if(!off->pColor[2]){ tnsVectorSet3(xyz0,0,0,0); return; }
  26. glBindFramebuffer(GL_READ_FRAMEBUFFER, off->FboHandle);
  27. glReadBuffer(GL_COLOR_ATTACHMENT2); glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  28. glReadPixels(x,y,1,1, GL_RGBA, GL_FLOAT, xyz0);
  29. }
  30. int OPINV_SetCursor(laOperator *a, laEvent *e){
  31. if(!a->This || !a->This->EndInstance){ return 0; }
  32. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  33. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root || root->Type!=TNS_OBJECT_ROOT) return 0;
  34. float pos[4]; la_ReadGLocation(ex->OffScr, e->x-ui->L,ui->B-e->y,pos);
  35. if(pos[0]>-1e20){
  36. tnsVectorSet3v(root->GLocation,pos); laNotifyUsers("tns.world"); return LA_FINISHED_PASS;
  37. }else
  38. {
  39. if(!ex->ViewingCamera){ return LA_FINISHED_PASS; }
  40. real vv[4], gp[4]; tnsMatrix44d proj; tnsMatrix44d inv;
  41. real focus=ex->ViewingCamera->FocusDistance, _near=ex->ViewingCamera->ZMin, _far=ex->ViewingCamera->ZMax;
  42. tnsGetCameraViewProjection(proj,ui->R-ui->L,ui->B-ui->U,ex->ViewingCamera); tnsInverse44d(inv,proj);
  43. vv[0]=(real)(e->x-ui->L)/(real)(ui->R-ui->L)*2-1; vv[0]*=focus;
  44. vv[1]=(real)(ui->B-e->y)/(real)(ui->B-ui->U)*2-1; vv[1]*=focus;
  45. vv[2]=tnsGetRatiod(1/_near,1/_far,1/focus)*focus;
  46. vv[3]=focus;
  47. tnsApplyTransform44dTrue(gp, inv, vv);
  48. tnsVectorMultiSelf3d(gp,1/gp[3]);
  49. real vv0[3]={0,0,-1}, vv1[3], ray[3], p0[3]; real t; tnsMatrix44d inv2;
  50. tnsSelfTransformValueChanged(ex->ViewingCamera);tnsInverse44d(inv2,ex->ViewingCamera->Base.GlobalTransform);
  51. tnsApplyRotation43d(vv1,inv2,vv0);
  52. tnsVectorMulti3d(vv0,vv1,focus);
  53. tnsVectorAccum3d(vv0,ex->ViewingCamera->Base.GLocation);
  54. tnsVectorMinus3d(ray, gp, ex->ViewingCamera->Base.GLocation);
  55. tnsNormalizeSelf3d(ray);
  56. if(tnsIntersectPlaneRay(vv1,vv0,ex->ViewingCamera->Base.GLocation,ray,&t)){
  57. tnsVectorMultiSelf3d(ray,t); tnsVectorPlus3d(gp,ray,ex->ViewingCamera->Base.GLocation);
  58. }
  59. tnsVectorSet3v(root->GLocation,gp); laNotifyUsers("tns.world"); return LA_FINISHED_PASS;
  60. }
  61. return LA_FINISHED_PASS;
  62. }
  63. int OPCHK_ThereIsActiveObject(laPropPack *This, laStringSplitor *ss){
  64. if(!This || !This->EndInstance){ return 0; }
  65. laCanvasExtra* ex=This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  66. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  67. tnsMeshObject* mo=root->Active; if(!mo) return 0; return 1;
  68. }
  69. int OPINV_ToggleEdit(laOperator *a, laEvent *e){
  70. if(!a->This || !a->This->EndInstance){ return 0; }
  71. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  72. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  73. tnsObject* o=root->Active; if(!o) return 0;
  74. char* ObType=0;
  75. if(o->Type==TNS_OBJECT_MESH){ tnsMeshObject* mo=o; ObType="tns_mesh_object";
  76. if(mo->Mode==TNS_MESH_EDIT_MODE) tnsMeshLeaveEditMode(mo); else tnsMeshEnterEditMode(mo);
  77. }elif(o->Type==TNS_OBJECT_SHAPE){ tnsShapeObject* so=o; ObType="tns_shape_object";
  78. if(so->Mode==TNS_MESH_EDIT_MODE) tnsShapeLeaveEditMode(so); else tnsShapeEnterEditMode(so);
  79. }else{
  80. return LA_CANCELED;
  81. }
  82. laRecordInstanceDifferences(o, ObType); laPushDifferences("Toggle edit mode", TNS_HINT_GEOMETRY);
  83. laNotifyUsers("tns.world");
  84. return LA_FINISHED_PASS;
  85. }
  86. STRUCTURE(MSelectData){
  87. tnsOffscreen* FBO;
  88. tnsTexture* Color;
  89. void** RefsV; int nextV,maxV;
  90. void** RefsE; int nextE,maxE;
  91. };
  92. MSelectData* la_InitSelectData(int w, int h, tnsCamera* camera){
  93. MSelectData* sd=memAcquireSimple(sizeof(MSelectData));
  94. if (!sd->FBO || sd->FBO->pColor[0]->Height != h || sd->FBO->pColor[0]->Width != w){
  95. if (sd->FBO) tnsDelete2DOffscreen(sd->FBO);
  96. sd->FBO = tnsCreate2DOffscreen(GL_RGB8, w, h, 0, 0, 0); sd->Color=sd->FBO->pColor[0];
  97. }
  98. tnsDrawToOffscreen(sd->FBO, 1, 0);
  99. return sd;
  100. }
  101. void la_AssignObjectSelectIDRecursive(tnsObject* root, MSelectData* sd){
  102. for(laListItemPointer*lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  103. tnsObject* o=lip->p; if(!o) continue;
  104. arrEnsureLength(&sd->RefsV, sd->nextV, &sd->maxV, sizeof(tnsObject*));
  105. sd->RefsV[sd->nextV]=o; o->SelectID=sd->nextV; sd->nextV++;
  106. if(o->ChildObjects.pFirst){ la_AssignObjectSelectIDRecursive(o,sd); }
  107. }
  108. }
  109. void la_PopulateSelectDataObjects(MSelectData* sd, tnsObject* root, laCanvasExtra* e){
  110. tnsCamera* camera=e->ViewingCamera;
  111. arrEnsureLength(&sd->RefsV,0,&sd->maxV,sizeof(tnsObject*));
  112. sd->nextV++; // starting from 1;
  113. la_AssignObjectSelectIDRecursive(root, sd);
  114. if(sd->nextV==1) return; int w=sd->Color->Width, h=sd->Color->Height;
  115. tnsUnbindTexture(); tnsUniformUseTexture(T->immShader,0,0); tnsUseMultiplyColor(0);
  116. tnsEnableShaderv(T->SelectionShader);
  117. glDisableVertexAttribArray(T->SelectionShader->iColor); glVertexAttrib4f(T->SelectionShader->iColor,0,0,0,0);
  118. tnsViewportWithScissor(0,0,w,h);tnsResetViewMatrix();tnsResetModelMatrix();tnsResetProjectionMatrix();
  119. NVGcontext* vg=MAIN.CurrentWindow->nvg;
  120. la3DObjectDrawExtra de={0}; de.W=w; de.H=h; de.PointScale=1.0f/LA_RH;
  121. tnsMatrix44d mview,mproj; tnsRootObject* ro=root;
  122. if(ro && ro->Is2D){ la_SetCanvasOrtho(e,w,h); de.PointScale=e->ZoomX; }
  123. else{ tnsApplyCameraView(w, h, camera, mview,mproj); tnsMultiply44d(de.mViewProj,mproj,mview); de.Is3D=1; }
  124. la_BeginNVG(vg,e,w,h,ro->Is2D);
  125. glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST);
  126. tnsInvalidateEvaluation(root); tnsSetObjectTreeEvaluationArgs(root,root->Active,1,1,w,h); tnsEvaluateObjectTree(root,0,0);
  127. tnsDrawObjectTree(root,TNS_EVAL_LAYER_SELECTION,&de,0);
  128. tnsDrawObjectOrigins(root,root->Active,1); tnsFlush();
  129. glDisable(GL_DEPTH_TEST);
  130. nvgEndFrame(vg); tnsRestoreFromNanoVG(); tnsEnableShaderv(T->immShader);
  131. }
  132. void la_PopulateSelectVerts(MSelectData* sd, tnsMeshObject* mo){
  133. arrEnsureLength(&sd->RefsV,0,&sd->maxV,sizeof(tnsMVert*));
  134. if(mo->Base.Type!=TNS_OBJECT_MESH||!mo->mv.pFirst){ return; }
  135. for(tnsMVert* v=mo->mv.pFirst;v;v=v->Item.pNext){
  136. arrEnsureLength(&sd->RefsV, v->i, &sd->maxV, sizeof(tnsMVert*));
  137. sd->RefsV[v->i]=v; sd->nextV=TNS_MAX2(v->i, sd->nextV);
  138. }
  139. sd->nextV++;
  140. }
  141. void la_PopulateSelectEdges(MSelectData* sd, tnsMeshObject* mo){
  142. arrEnsureLength(&sd->RefsE,0,&sd->maxE,sizeof(tnsMEdge*));
  143. if(mo->Base.Type!=TNS_OBJECT_MESH||!mo->mv.pFirst){ return; }
  144. for(tnsMEdge* e=mo->me.pFirst;e;e=e->Item.pNext){
  145. arrEnsureLength(&sd->RefsE, e->i, &sd->maxE, sizeof(tnsObject*));
  146. sd->RefsE[e->i]=e; sd->nextE=TNS_MAX2(e->i, sd->nextE);
  147. }
  148. sd->nextE++;
  149. }
  150. void la_PopulateSelectPoints(MSelectData* sd, tnsShapeObject* so){
  151. sd->nextV=0;
  152. arrEnsureLength(&sd->RefsV,sd->nextV,&sd->maxV,sizeof(tnsSPoint*));
  153. if(so->Base.Type!=TNS_OBJECT_SHAPE||!so->Shapes.pFirst){ return; }
  154. for(tnsShape*s=so->Shapes.pFirst;s;s=s->Item.pNext){
  155. for(tnsSPoint*sp=s->Points.pFirst;sp;sp=sp->Item.pNext){
  156. arrEnsureLength(&sd->RefsV, sd->nextV+3, &sd->maxV, sizeof(tnsSPoint*));
  157. sd->RefsV[sd->nextV]=sp; sd->RefsV[sd->nextV+1]=sp; sd->RefsV[sd->nextV+2]=sp;
  158. sd->nextV+=3;
  159. }
  160. }
  161. sd->nextV++;
  162. }
  163. void la_PopulateSelectDataPrimitives(MSelectData* sd, tnsObject* o, tnsCamera* camera, int WhatPrim, tnsObject* root, laCanvasExtra* e){
  164. int DoVerts=(WhatPrim==LA_CANVAS_SELECT_MODE_VERTS),DoEdges=(WhatPrim==LA_CANVAS_SELECT_MODE_EDGES);
  165. int Knife=(WhatPrim==LA_CANVAS_SELECT_MODE_KNIFE);
  166. tnsMeshObject* mo=o; tnsShapeObject* so=o;
  167. if(o->Type==TNS_OBJECT_MESH){
  168. if(DoVerts || Knife){ la_PopulateSelectVerts(sd,mo); }
  169. if(DoEdges || Knife){ la_PopulateSelectEdges(sd,mo); }
  170. }elif(o->Type==TNS_OBJECT_SHAPE){
  171. la_PopulateSelectPoints(sd,so);
  172. }
  173. int w=sd->Color->Width, h=sd->Color->Height;
  174. tnsUnbindTexture(); tnsUniformUseTexture(T->immShader,0,0); tnsUseMultiplyColor(0);
  175. tnsEnableShaderv(T->SelectionShader);
  176. tnsViewportWithScissor(0,0,w,h);tnsResetViewMatrix();tnsResetModelMatrix();tnsResetProjectionMatrix();
  177. NVGcontext* vg=MAIN.CurrentWindow->nvg;
  178. la3DObjectDrawExtra de={0}; de.W=w; de.H=h; de.PointScale=1.0f/LA_RH;
  179. tnsMatrix44d mview,mproj; tnsRootObject* ro=root;
  180. if(ro && ro->Is2D){ la_SetCanvasOrtho(e,w,h); de.PointScale=e->ZoomX; }
  181. else{ tnsApplyCameraView(w, h, camera, mview,mproj); tnsMultiply44d(de.mViewProj,mproj,mview); de.Is3D=1; }
  182. la_BeginNVG(vg,e,w,h,ro->Is2D);
  183. glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  184. tnsPushMatrix(); tnsApplyModelMatrix(o->GlobalTransform);glEnable(GL_DEPTH_TEST);
  185. if(o->Type==TNS_OBJECT_MESH){
  186. if(!e->SelectThrough){
  187. glDepthMask(GL_TRUE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  188. tnsUniformUseOffset(T->SelectionShader,0);
  189. tnsDrawBatch(mo->Batch,"body",0,0);
  190. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  191. }
  192. }
  193. glDepthMask(GL_FALSE);
  194. tnsUniformUseOffset(T->SelectionShader,1);
  195. if(o->Type==TNS_OBJECT_MESH){
  196. if(DoEdges || Knife){ tnsDrawBatch(mo->Batch, "edges_select",0,0); }
  197. if(DoVerts || Knife){ tnsDrawBatch(mo->Batch, "verts_select",0,0); }
  198. }elif(o->Type==TNS_OBJECT_SHAPE){
  199. tnsEvaluatedInstance ei; memcpy(&ei.Mat,o->GlobalTransform,sizeof(tnsMatrix44d)); ei.Object=o;
  200. tnsDrawShapePointsSelectionID(&ei,&de);
  201. }
  202. tnsUniformUseOffset(T->SelectionShader,0);
  203. tnsPopMatrix();
  204. glDisable(GL_DEPTH_TEST);
  205. nvgEndFrame(vg); tnsRestoreFromNanoVG(); tnsEnableShaderv(T->immShader);
  206. }
  207. void la_PadSelectionBuffer(uint8_t* buf, int w, int h, int sx, int sy, int ex, int ey, int real_endx){
  208. if(!sx&&!sy&&!ex&&!ey) return;
  209. uint8_t* pad=calloc(1,sizeof(uint8_t)*4*w*h);
  210. for(int i=0;i<h;i++){
  211. if(i<sy || i>=h-ey){ memset(&pad[i*w*4],0,w*4); continue; }
  212. for(int j=0;j<w;j++){
  213. if(j<sx || j>=w-sx){ memset(&pad[(i*w+j)*4],0,4); continue; }
  214. memcpy(&pad[(i*w+j)*4], &buf[((i-sy)*(real_endx-sx)+j-sx)*4], 4);
  215. }
  216. }
  217. memcpy(buf,pad,sizeof(uint8_t)*4*w*h);
  218. free(pad);
  219. }
  220. uint8_t* la_ReadSelection(MSelectData* sd, u8bit* buf, int x, int y, int w, int h){
  221. glFlush(); glFinish(); glGetError();
  222. glBindFramebuffer(GL_READ_FRAMEBUFFER, sd->FBO->FboHandle);
  223. glReadBuffer(GL_COLOR_ATTACHMENT0);
  224. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  225. glReadPixels(x,y,w,h, GL_RGBA, GL_UNSIGNED_BYTE, buf);
  226. return buf;
  227. }
  228. uint8_t* la_ReadSelectionRadius(MSelectData* sd, int uix, int uiy, int radius){
  229. int w=radius*2; int vh=sd->Color->Height,vw=sd->Color->Width;
  230. uint8_t* buf=calloc(1,sizeof(uint8_t)*4*w*w);
  231. int startx=uix-radius, starty=vh-uiy-radius, endx=uix+radius, endy=vh-uiy+radius;
  232. TNS_CLAMP(startx,0,vw);TNS_CLAMP(endx,0,vw);TNS_CLAMP(starty,0,vh);TNS_CLAMP(endy,0,vh);
  233. int _startx=TNS_MAX2(startx,0), _starty=TNS_MAX2(starty,0), _endx=TNS_MIN2(endx,vw), _endy=TNS_MIN2(endy,vh);
  234. la_ReadSelection(sd, buf, _startx, _starty, _endx-_startx, _endy-_starty);
  235. la_PadSelectionBuffer(buf, w, w, _startx-startx, _starty-starty, endx-_endx, endy-_endy,_endx);
  236. return buf;
  237. }
  238. uint8_t* la_ReadSelectionBox(MSelectData* sd, int uix, int uiy, int uix2, int uiy2){
  239. int vh=sd->Color->Height,vw=sd->Color->Width;
  240. if(uix2<uix) LA_SWAP(int,uix,uix2); if(uiy2<uiy) LA_SWAP(int,uiy,uiy2);
  241. TNS_CLAMP(uix,0,vw);TNS_CLAMP(uix2,0,vw);TNS_CLAMP(uiy,0,vh);TNS_CLAMP(uiy2,0,vh);
  242. int w=uix2-uix, h=uiy2-uiy;
  243. uint8_t* buf=calloc(1,sizeof(uint8_t)*4*w*h);
  244. int startx=uix, starty=vh-uiy2, endx=uix+w, endy=starty+h;
  245. int _startx=TNS_MAX2(startx,0), _starty=TNS_MAX2(starty,0), _endx=TNS_MIN2(endx,vw), _endy=TNS_MIN2(endy,vh);
  246. la_ReadSelection(sd, buf, _startx, _starty, _endx-_startx, _endy-_starty);
  247. la_PadSelectionBuffer(buf, w, h, _startx-startx, _starty-starty, endx-_endx, endy-_endy,_endx);
  248. return buf;
  249. }
  250. int la_SelectGetClosest(MSelectData* sd, int uix, int uiy, int radius, int *ElemType){
  251. *ElemType=0; uint8_t* buf=la_ReadSelectionRadius(sd, uix, uiy, radius); if(!buf) return 0;
  252. int w=radius*2; int MinD=INT_MAX,MinDe=INT_MAX; int MinID=0,MinIDe=0, d, elemtype=0;
  253. for(int i=0;i<w;i++){
  254. for(int j=0;j<w;j++){
  255. uint8_t* p=&buf[(i*w+j)*4]; int id=(p[0])|(p[1]<<8)|((p[2]<<16)&(~TNS_MMESH_TYPE_BIT)); if(!id){continue;}
  256. d=tnsDistIdv2(i,j, radius, radius); elemtype=((p[2]<<16)&TNS_MMESH_TYPE_BIT);
  257. if(elemtype==TNS_MMESH_EDGE_BIT){ if(d<MinDe){ MinDe=d; MinIDe=id; } }
  258. elif(d<MinD){ MinD=d; MinID=id; }
  259. //printf("%d ",buf[(i*w+j)*4]);
  260. }
  261. //printf("\n");
  262. }
  263. //printf("%d %d\n",MinID, MinIDe);
  264. free(buf);
  265. if(MinID && MinIDe){ if(MinD<MinDe*5){ *ElemType=0; return MinID; } }
  266. if(MinIDe){ *ElemType=TNS_MMESH_EDGE_BIT; return MinIDe; }
  267. if(MinID){ *ElemType=0; return MinID; }
  268. *ElemType=0; return 0;
  269. }
  270. int* la_SelectGetBox(MSelectData* sd, int uix, int uiy, int uix2, int uiy2, int* r_length){
  271. uint8_t* buf=la_ReadSelectionBox(sd, uix, uiy, uix2, uiy2); if(!buf) return 0;
  272. int vh=sd->Color->Height,vw=sd->Color->Width;
  273. if(uix2<uix) LA_SWAP(int,uix,uix2); if(uiy2<uiy) LA_SWAP(int,uiy,uiy2);
  274. TNS_CLAMP(uix,0,vw);TNS_CLAMP(uix2,0,vw);TNS_CLAMP(uiy,0,vh);TNS_CLAMP(uiy2,0,vh);
  275. int w=uix2-uix, h=uiy2-uiy;
  276. int* ids=0; int next=0,max=0;
  277. arrEnsureLength(&ids, next, &max, sizeof(int));
  278. for(int i=0;i<h;i++){
  279. for(int j=0;j<w;j++){
  280. uint8_t* p=&buf[(i*w+j)*4]; int id=(p[0])|(p[1]<<8)|((p[2]<<16)&(~TNS_MMESH_TYPE_BIT));
  281. if(id){ int found=0;
  282. for(int a=0;a<next;a++){ if(ids[a]==id){ found=1; break; } }
  283. if(!found){
  284. arrEnsureLength(&ids, next, &max, sizeof(int)); ids[next]=id; next++; }
  285. }
  286. }
  287. }
  288. free(buf);
  289. *r_length=next;
  290. return ids;
  291. }
  292. void la_FreeSelectData(MSelectData* sd){
  293. tnsDelete2DOffscreen(sd->FBO);
  294. free(sd->RefsV);
  295. free(sd->RefsE);
  296. memFree(sd);
  297. }
  298. void* la_SelectGetRef(MSelectData* sd, int id, int elemtype){
  299. if(!elemtype){ if(id>=0 && id<sd->nextV){ return sd->RefsV[id]; } }
  300. elif(elemtype==TNS_MMESH_EDGE_BIT){ if(id>=0 && id<sd->nextE){ return sd->RefsE[id]; } }
  301. return 0;
  302. }
  303. int OPCHK_ViewportAndSceneExists(laPropPack *This, laStringSplitor *ss){
  304. if(!This || !This->EndInstance){ return 0; } laCanvasExtra* ex=This->EndInstance;
  305. laUiItem* ui=ex->ParentUi; tnsObject* root=ui?ui->PP.EndInstance:0;
  306. if(!ex->ViewingCamera || !root){ return 0; }
  307. return 1;
  308. }
  309. void la_DoObjectSelect(tnsObject* root, tnsObject* o, laCanvasExtra* e, int DeselectAll, int Select, int Toggle){
  310. if(DeselectAll){ tnsDeselectAllObjects(root); memAssignRef(root,&root->Active,0); }
  311. if(o){ tnsSelectObject(o, Select, o==root->Active?0:Toggle); memAssignRef(root,&root->Active,o); }
  312. }
  313. void la_DoMeshSelect(tnsMeshObject* mo, void* p, int WhatPrim, int DeselectAll, int Select, int Toggle){
  314. if(DeselectAll){ tnsMMeshDeselectAll(mo); }
  315. if(p){ if(WhatPrim==LA_CANVAS_SELECT_MODE_VERTS) tnsMMeshSelectVert(mo,p,Select,Toggle);
  316. elif(WhatPrim==LA_CANVAS_SELECT_MODE_EDGES) tnsMMeshSelectEdge(mo,p,Select,Toggle); }
  317. }
  318. void la_DoShapeSelect(tnsShapeObject* so, void* p, int lr, int DeselectAll, int Select, int Toggle){
  319. if(DeselectAll){ tnsShapeDeselectAll(so); } if(p) tnsShapeSelectPoint(so,p,Select,Toggle,lr);
  320. }
  321. #define LA_SELECT_MODE_BOX 1
  322. STRUCTURE(MSelectExtra){
  323. MSelectData* sd;
  324. tnsObject* root;
  325. tnsObject* mo;
  326. tnsCamera* cam;
  327. int Mode;
  328. int InSelect;
  329. laListHandle KnifeElements;
  330. void* PendingElem; int PendingElemType, BatchDirty;
  331. int IsLoop;
  332. };
  333. int OPINV_Select(laOperator *a, laEvent *e){
  334. if(!a->This || !a->This->EndInstance){ return 0; }
  335. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  336. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  337. tnsObject* o=root->Active; tnsMeshObject* mo=o; tnsShapeObject* so=o;
  338. int is_geo=0, SelectMode=ex->SelectMode, ring_band=0;
  339. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "toggle")){
  340. if(o && o->Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  341. if(tnsMMeshAnySelected(mo)) tnsMMeshDeselectAll(mo); else tnsMMeshSelectAll(mo);
  342. tnsInvalidateMeshBatch(mo); is_geo=1;
  343. }elif(o && o->Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){ is_geo=1;
  344. if(tnsShapeAnySelected(so)) tnsShapeDeselectAll(so); else tnsShapeSelectAll(so);
  345. //tnsInvalidateMeshBatch(mo);
  346. }else{
  347. if(tnsAnyObjectsSelected(root)) tnsDeselectAllObjects(root); else tnsSelectAllObjects(root);
  348. }
  349. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world", "Toggle selection",is_geo?TNS_HINT_GEOMETRY:TNS_HINT_TRANSFORM);
  350. return LA_FINISHED;
  351. }
  352. int spk=e->SpecialKeyBit & (LA_KEY_CTRL|LA_KEY_ALT);
  353. if(spk==LA_KEY_ALT){ ring_band=1; SelectMode=LA_CANVAS_SELECT_MODE_EDGES; }
  354. elif(spk==(LA_KEY_CTRL|LA_KEY_ALT)){ ring_band=2; SelectMode=LA_CANVAS_SELECT_MODE_EDGES; }
  355. MSelectData* sd=la_InitSelectData(ex->OffScr->pColor[0]->Width, ex->OffScr->pColor[0]->Height, c);
  356. int DeselectAll=1;
  357. int Append=e->SpecialKeyBit&LA_KEY_SHIFT; if(Append) DeselectAll=0;
  358. if(o&&o->Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  359. la_PopulateSelectDataPrimitives(sd, mo, ex->ViewingCamera, SelectMode, root, ex);
  360. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "box")){
  361. MSelectExtra* se=memAcquire(sizeof(MSelectExtra));
  362. ex->OnX=e->x; ex->OnX=e->y;
  363. 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;
  364. }
  365. int elemtype,id=la_SelectGetClosest(sd, e->x-ui->L, e->y-ui->U, LA_RH,&elemtype)-1;
  366. void* p=la_SelectGetRef(sd,id,elemtype);
  367. la_DoMeshSelect(mo, p, SelectMode, DeselectAll, 1, 1); tnsMMeshEnsureSelection(mo,ex->SelectMode);
  368. if(ring_band && p){
  369. tnsMMeshSelectRingBandFrom(mo,p,ring_band,1,Append); tnsMMeshEnsureSelection(mo,ex->SelectMode);
  370. }
  371. tnsInvalidateMeshBatch(mo);
  372. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Mesh selection",TNS_HINT_GEOMETRY);
  373. }elif(o&&o->Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){
  374. la_PopulateSelectDataPrimitives(sd, mo, ex->ViewingCamera, SelectMode, root, ex);
  375. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "box")){
  376. MSelectExtra* se=memAcquire(sizeof(MSelectExtra));
  377. ex->OnX=e->x; ex->OnX=e->y;
  378. 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;
  379. }
  380. int elemtype,id=la_SelectGetClosest(sd, e->x-ui->L, e->y-ui->U, LA_RH,&elemtype)-1;
  381. void* p=la_SelectGetRef(sd,id,elemtype);
  382. la_DoShapeSelect(mo, p, id%3, DeselectAll, 1, 1);
  383. if(ring_band && p){ tnsShapeSelectRingFrom(mo,p,1,Append); }
  384. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Shape selection",TNS_HINT_GEOMETRY);
  385. }else{
  386. la_PopulateSelectDataObjects(sd,root,ex);
  387. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "box")){
  388. MSelectExtra* se=memAcquire(sizeof(MSelectExtra));
  389. ex->OnX=e->x; ex->OnX=e->y;
  390. a->CustomData=se; se->sd=sd; se->Mode=LA_SELECT_MODE_BOX; se->cam=c; ex->DrawCursor=1; se->root=root; return LA_RUNNING;
  391. }
  392. int elemtype,id=la_SelectGetClosest(sd, e->x-ui->L, e->y-ui->U, LA_RH*2,&elemtype);
  393. void* p=la_SelectGetRef(sd,id,elemtype); if(p){ la_DoObjectSelect(root, p, ex, DeselectAll, 1, 1); }
  394. else{ la_DoObjectSelect(root, 0, ex, DeselectAll, 1, 1); }
  395. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Object selection",TNS_HINT_TRANSFORM);
  396. }
  397. la_FreeSelectData(sd);
  398. return LA_FINISHED_PASS;
  399. }
  400. int OPMOD_Select(laOperator *a, laEvent *e){
  401. if(!a->This || !a->This->EndInstance){ return 0; }
  402. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  403. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  404. tnsObject* o=root->Active; tnsMeshObject* mo=o; tnsShapeObject* so=o;
  405. MSelectExtra* se=a->CustomData;
  406. if(e->Type==LA_L_MOUSE_DOWN){ se->InSelect=1; ex->DrawCursor=2; ex->ClickedX=e->x; ex->ClickedY=e->y; laRedrawCurrentPanel(); }
  407. if(e->Type&LA_MOUSE_EVENT){ ex->OnX=e->x; ex->OnY=e->y; laRedrawCurrentPanel(); }
  408. if(e->Type==LA_R_MOUSE_DOWN || (e->Type == LA_KEY_DOWN && e->key==LA_KEY_ESCAPE)){
  409. ex->DrawCursor=0; la_FreeSelectData(se->sd); memFree(se); laNotifyUsers("tns.world"); return LA_FINISHED;
  410. }
  411. int DeselectAll=1;
  412. int Append=e->SpecialKeyBit&LA_KEY_SHIFT; if(Append) DeselectAll=0;
  413. int Remove=e->SpecialKeyBit&LA_KEY_ALT; if(Remove) DeselectAll=0;
  414. int is_geo=0;
  415. if(se->InSelect && e->Type==LA_L_MOUSE_UP){
  416. if(o && o->Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){ is_geo=1;
  417. la_DoMeshSelect(mo, 0, ex->SelectMode, DeselectAll, 0, 0);
  418. 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);
  419. for(int i=0;i<len;i++){
  420. int id=ids[i]-1; void* p=la_SelectGetRef(se->sd,id,ex->SelectMode==LA_CANVAS_SELECT_MODE_EDGES?TNS_MMESH_EDGE_BIT:0);
  421. la_DoMeshSelect(mo, p, ex->SelectMode, 0, !Remove, 0);
  422. }
  423. tnsMMeshEnsureSelection(mo,ex->SelectMode);
  424. tnsInvalidateMeshBatch(mo);
  425. }elif(o && o->Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){ is_geo=1;
  426. la_DoShapeSelect(so, 0, 0, DeselectAll, 0, 0);
  427. 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);
  428. for(int i=0;i<len;i++){
  429. int id=ids[i]-1; void* p=la_SelectGetRef(se->sd,id,ex->SelectMode==LA_CANVAS_SELECT_MODE_EDGES?TNS_MMESH_EDGE_BIT:0);
  430. la_DoShapeSelect(so, p, id%3, 0, !Remove, 0);
  431. }
  432. }else{
  433. la_DoObjectSelect(se->root, 0, ex, DeselectAll, 0, 0);
  434. int len; int* ids=la_SelectGetBox(se->sd, ex->ClickedX, ex->ClickedY, e->x-ui->L, e->y-ui->U, &len);
  435. for(int i=0;i<len;i++){
  436. int id=ids[i]; void* p=la_SelectGetRef(se->sd,id,0);
  437. if(p){ la_DoObjectSelect(se->root, p, ex, 0, !Remove, 0); }
  438. }
  439. }
  440. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Box selection",is_geo?TNS_HINT_GEOMETRY:TNS_HINT_TRANSFORM);
  441. ex->DrawCursor=0;
  442. la_FreeSelectData(se->sd); memFree(se);
  443. laRedrawCurrentPanel();
  444. return LA_FINISHED;
  445. }
  446. return LA_RUNNING;
  447. }
  448. int OPINV_SelectLinked(laOperator *a, laEvent *e){
  449. if(!a->This || !a->This->EndInstance){ return 0; }
  450. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  451. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  452. tnsObject* o=root->Active; tnsMeshObject* mo=o; tnsShapeObject* so=o;
  453. if(o&&o->Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  454. tnsMMeshSelectLinked(mo); tnsInvalidateMeshBatch(mo);
  455. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Mesh selection",TNS_HINT_GEOMETRY);
  456. }elif(o&&o->Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){
  457. tnsShapeSelectLinked(so);
  458. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world","Shape selection",TNS_HINT_GEOMETRY);
  459. }
  460. return LA_FINISHED_PASS;
  461. }
  462. #define LA_TRANSFORM_MODE_GRAB 1
  463. #define LA_TRANSFORM_MODE_ROTATE 2
  464. #define LA_TRANSFORM_MODE_SCALE 3
  465. #define LA_TRANSFORM_RESTORE_LOC 1
  466. #define LA_TRANSFORM_RESTORE_ROT 2
  467. #define LA_TRANSFORM_RESTORE_SCA 3
  468. STRUCTURE(MTOrigObject){
  469. tnsObject* o;
  470. tnsMatrix44d Global;
  471. tnsMatrix44d Local;
  472. int Discard;
  473. };
  474. STRUCTURE(MTOrigMVert){
  475. tnsVector3d p;
  476. tnsVector3d origp;
  477. tnsMVert* mv;
  478. };
  479. STRUCTURE(MTOrigSPoint){
  480. tnsVector2d p,pl,pr;
  481. tnsVector2d origp,origdl,origdr;
  482. tnsSPoint* sp;
  483. };
  484. STRUCTURE(MTransformData){
  485. tnsMatrix44d Delta;
  486. tnsMatrix44d ViewProjection;
  487. tnsVector4d Up,Right,Foward;
  488. tnsVector4d TCenter,TLCenter;
  489. int CenterX,CenterY; real Initial;
  490. tnsObject* mo; tnsShapeObject* so;
  491. tnsMatrix44d obmatinv,deltainv;
  492. tnsCamera* c; tnsObject* root;
  493. int w,h;
  494. void* Originals; int next,max;
  495. int mode;
  496. int LockAxis[3];
  497. int UseLocal;
  498. real DeltaVal, UserDeltaVal;
  499. laStringEdit* Entry; int UseUserDelta;
  500. int CanvasDeltaMode;
  501. int Is2D; real zoomx,zoomy;
  502. };
  503. MTransformData* la_InitTransformData(int w, int h, tnsCamera* c, int CanvasDeltaMode, int Is2D,real zoomx,real zoomy){
  504. MTransformData* td=memAcquireSimple(sizeof(MTransformData));
  505. tnsVector4d pu={0,1,0,0}, pr={1,0,0,0}, pf={0,0,1};
  506. tnsGetCameraMovingDeltas(c,w,h,1,0,pr); pr[2]=0; pr[3]=0;
  507. tnsGetCameraMovingDeltas(c,w,h,0,-1,pu); pu[2]=0; pu[3]=0;
  508. tnsMatrix44d inv; tnsInverse44d(inv,c->Base.GlobalTransform);
  509. tnsApplyRotation43d(td->Up,inv,pu);
  510. tnsApplyRotation43d(td->Right,inv,pr);
  511. tnsApplyRotation43d(td->Foward,inv,pf);
  512. tnsGetCameraViewProjection(td->ViewProjection, w,h,c);
  513. td->c=c; td->w=w; td->h=h; td->CanvasDeltaMode=CanvasDeltaMode;
  514. strBeginEdit(&td->Entry, "");
  515. td->Is2D=Is2D; td->zoomx=zoomx; td->zoomy=zoomy;
  516. return td;
  517. }
  518. void la_GetTransformInitialScale(MTransformData* td, laUiItem* ui, int x, int y){ td->Initial=tnsDistIdv2(x-ui->L,y-ui->U,td->CenterX,td->CenterY); }
  519. void la_GetTransformInitialRotation(MTransformData* td, laUiItem* ui, int x, int y){ td->Initial=atan2(y-ui->U-td->CenterY,x-ui->L-td->CenterX); }
  520. void la_GetTransformCenter2D(MTransformData* td){
  521. if(td->Is2D||td->so){
  522. { td->CenterX=td->w/2; td->CenterY=td->h/2; } return;
  523. }
  524. tnsVector4d vp; tnsApplyTransform44d(vp,td->ViewProjection,td->TCenter);
  525. if(td->c->CameraType==TNS_CAMERA_PERSP){ tnsVectorMultiSelf3d(vp, 1/vp[3]); }
  526. td->CenterX = (vp[0]/2+0.5f)*td->w; td->CenterY=(-vp[1]/2+0.5f)*td->h;
  527. if(td->CenterX<0||td->CenterY<0) { td->CenterX=td->w/2; td->CenterY=td->h/2; }
  528. }
  529. int la_AddTransformObjectsRecursive(MTransformData* td, tnsObject*root){
  530. int any=0; for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  531. tnsObject* o=lip->p; if(o->ChildObjects.pFirst) any+=la_AddTransformObjectsRecursive(td,o);
  532. if(!(o->Flags&TNS_OBJECT_FLAGS_SELECTED)) continue;
  533. arrEnsureLength(&td->Originals, td->next, &td->max, sizeof(MTOrigObject));
  534. MTOrigObject* to=arrElement(td->Originals, td->next, sizeof(MTOrigObject)); td->next++; to->o=o;
  535. memcpy(to->Global, o->GlobalTransform, sizeof(tnsMatrix44d));
  536. memcpy(to->Local, o->SelfTransform, sizeof(tnsMatrix44d));
  537. tnsVectorAccum3d(td->TCenter,o->GLocation); any++;
  538. 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;
  539. }
  540. return any;
  541. }
  542. int la_PopulateTransformObjects(MTransformData* td, tnsObject* root){
  543. arrEnsureLength(&td->Originals, 0, &td->max, sizeof(MTOrigObject));
  544. int any=la_AddTransformObjectsRecursive(td,root);
  545. tnsVectorMultiSelf3d(td->TCenter, 1.0f/any);
  546. la_GetTransformCenter2D(td);
  547. return any;
  548. }
  549. int la_PopulateTransformVerticies(MTransformData* td, tnsMeshObject* mo){
  550. int any=0; td->mo=mo; td->next=0;
  551. arrEnsureLength(&td->Originals, 0, &td->max, sizeof(MTOrigMVert));
  552. tnsInverse44d(td->obmatinv, mo->Base.GlobalTransform);
  553. tnsInverse44d(td->deltainv, mo->Base.DeltaTransform);
  554. for(tnsMVert* mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){
  555. if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  556. //printf("v %d ",mv->i);
  557. arrEnsureLength(&td->Originals, td->next, &td->max, sizeof(MTOrigMVert));
  558. MTOrigMVert* to=arrElement(td->Originals, td->next, sizeof(MTOrigMVert)); td->next++; to->mv=mv;
  559. tnsApplyTransform43d(to->p, mo->Base.GlobalTransform, mv->p);
  560. memcpy(to->origp, mv->p, sizeof(tnsVector3d)); any++;
  561. tnsVectorAccum3d(td->TCenter,to->p);
  562. tnsVectorAccum3d(td->TLCenter,mv->p);
  563. }
  564. //printf(" [totmv %d]\n",mo->totmv);
  565. tnsVectorMultiSelf3d(td->TCenter, 1.0f/any);
  566. tnsVectorMultiSelf3d(td->TLCenter, 1.0f/any);
  567. la_GetTransformCenter2D(td);
  568. return any;
  569. }
  570. int la_PopulateTransformPoints(MTransformData* td, tnsShapeObject* so){
  571. int any=0; td->so=so; td->next=0;
  572. arrEnsureLength(&td->Originals, 0, &td->max, sizeof(MTOrigSPoint));
  573. tnsInverse44d(td->obmatinv, so->Base.GlobalTransform);
  574. tnsInverse44d(td->deltainv, so->Base.DeltaTransform);
  575. for(tnsShape* s=so->Shapes.pFirst;s;s=s->Item.pNext){
  576. for(tnsSPoint* sp=s->Points.pFirst;sp;sp=sp->Item.pNext){
  577. if(!(sp->flags&TNS_SPOINT_SELECTED)) continue;
  578. int addl=0,addr=0,addmain=0;
  579. if(sp->flags&TNS_MESH_FLAG_SELECTED) addmain=1;
  580. elif(sp->flags&TNS_SPOINT_BEZIER){
  581. if(sp->flags&TNS_SPOINT_SELECTED_L) addl=1; if(sp->flags&TNS_SPOINT_SELECTED_R) addr=1;
  582. if(sp->flags&TNS_SPOINT_ALIGNED){ if(addl&&addr){ addmain=1; } }
  583. }
  584. arrEnsureLength(&td->Originals, td->next, &td->max, sizeof(MTOrigSPoint));
  585. MTOrigSPoint* to=arrElement(td->Originals, td->next, sizeof(MTOrigSPoint)); td->next++; to->sp=sp;
  586. tnsVector3d tp; tnsVector3d fp={sp->p[0],sp->p[1],0},
  587. fpl={sp->p[0]+sp->dl[0],sp->p[1]+sp->dl[1],0},fpr={sp->p[0]+sp->dr[0],sp->p[1]+sp->dr[1],0};
  588. tnsApplyTransform43d(tp, so->Base.GlobalTransform, fp); tnsVectorSet2v(to->p,tp);
  589. tnsApplyTransform43d(tp, so->Base.GlobalTransform, fpl); tnsVectorSet2v(to->pl,tp);
  590. tnsApplyTransform43d(tp, so->Base.GlobalTransform, fpr); tnsVectorSet2v(to->pr,tp);
  591. tnsVectorSet2v(to->origp,sp->p); tnsVectorSet2v(to->origdl,sp->dl); tnsVectorSet2v(to->origdr,sp->dr);
  592. any++;
  593. tnsVectorAccum2d(td->TCenter,to->p);
  594. tnsVectorAccum2d(td->TLCenter,sp->p);
  595. }
  596. }
  597. tnsVectorMultiSelf2d(td->TCenter, 1.0f/any);
  598. tnsVectorMultiSelf2d(td->TLCenter, 1.0f/any);
  599. la_GetTransformCenter2D(td);
  600. return any;
  601. }
  602. void la_ApplyTranslation(MTransformData* td, int x, int y){
  603. tnsMatrix44d trans; tnsVector3d deltay,delta; tnsVector3d gp; tnsVector3d use_delta;
  604. if(td->Is2D || td->so){
  605. use_delta[0]=x*(td->Is2D?td->zoomx:(1.0f/LA_RH)); use_delta[1]=-y*(td->Is2D?td->zoomy:(1.0f/LA_RH)); use_delta[2]=0;
  606. if(td->LockAxis[0]){ use_delta[1]=0; } if(td->LockAxis[1]){ use_delta[0]=0; }
  607. }else{
  608. tnsVectorMulti3d(delta, td->Right, x); tnsVectorMulti3d(deltay, td->Up, y); tnsVectorAccum3d(delta, deltay);
  609. tnsVectorSet3v(use_delta,delta); real len;
  610. if(td->LockAxis[0]||td->LockAxis[1]||td->LockAxis[2]){ len=tnsLength3d(delta); }
  611. 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; }
  612. 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; }
  613. 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; }
  614. if(td->LockAxis[0]<0){ use_delta[0]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l*len/l:0); }
  615. if(td->LockAxis[1]<0){ use_delta[1]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l*len/l:0); }
  616. if(td->LockAxis[2]<0){ use_delta[2]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l*len/l:0); }
  617. }
  618. td->DeltaVal=tnsLength3d(use_delta);
  619. if(td->UseUserDelta){
  620. tnsVectorMultiSelf3d(use_delta,1/tnsLength3d(use_delta)*td->UserDeltaVal);
  621. tnsVector3d lock={ td->LockAxis[0], td->LockAxis[1], td->LockAxis[2] };
  622. real dir=tnsDot3d(use_delta, lock, 0); tnsVectorMultiSelf3d(use_delta,(td->UserDeltaVal*dir<=0)?-1:1);
  623. td->DeltaVal=td->UserDeltaVal;
  624. }
  625. if(td->mo){
  626. tnsMakeTranslationMatrix44d(trans, LA_COLOR3(use_delta)); tnsMatrix44d final;
  627. if(!td->UseLocal) tnsMultiply44d(final,td->obmatinv,trans);
  628. else tnsMultiply44d(final,trans,td->obmatinv);
  629. for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
  630. tnsApplyTransform43d(to->mv->p, final, to->p);
  631. }
  632. tnsInvalidateMeshBatch(td->mo); tnsMMeshCalculateNormal(td->mo);
  633. }elif(td->so){
  634. tnsMakeTranslationMatrix44d(trans, LA_COLOR3(use_delta)); tnsMatrix44d final;
  635. if(!td->UseLocal) tnsMultiply44d(final,td->obmatinv,trans);
  636. else tnsMultiply44d(final,trans,td->obmatinv);
  637. for(int i=0;i<td->next;i++){ MTOrigSPoint* to=arrElement(td->Originals, i, sizeof(MTOrigSPoint));
  638. tnsVector3d fp={to->p[0],to->p[1],0}, tp, tpl, tpr, fpl={to->pl[0],to->pl[1],0},fpr={to->pr[0],to->pr[1],0};
  639. if((to->sp->flags&TNS_SPOINT_BEZIER) && (!(to->sp->flags&TNS_MESH_FLAG_SELECTED))){
  640. if(to->sp->flags&TNS_SPOINT_SELECTED_L){ tnsApplyTransform43d(tpl, final, fpl); tnsVectorMinus2d(to->sp->dl,tpl,to->sp->p);
  641. if(to->sp->flags&TNS_SPOINT_ALIGNED){ real len=tnsLength2d(to->origdr);
  642. tnsVectorMulti2d(to->sp->dr,to->sp->dl,-1*len/tnsLength2d(to->sp->dl));
  643. }
  644. }
  645. if(to->sp->flags&TNS_SPOINT_SELECTED_R){ tnsApplyTransform43d(tpr, final, fpr); tnsVectorMinus2d(to->sp->dr,tpr,to->sp->p);
  646. if(to->sp->flags&TNS_SPOINT_ALIGNED){ real len=tnsLength2d(to->origdl);
  647. tnsVectorMulti2d(to->sp->dl,to->sp->dr,-1*len/tnsLength2d(to->sp->dr));
  648. }
  649. }
  650. }else{
  651. tnsApplyTransform43d(tp, final, fp); tnsVectorSet2v(to->sp->p,tp);
  652. }
  653. }
  654. }else{
  655. for(int i=0;i<td->next;i++){
  656. MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject)); memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
  657. if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
  658. if(td->CanvasDeltaMode) tnsGlobalMatrixChangedForDelta(to->o, 0); else tnsGlobalMatrixChanged(to->o, 0);
  659. if(td->UseLocal){
  660. if(td->CanvasDeltaMode) tnsMoveObjectDelta(to->o, LA_COLOR3(use_delta));
  661. else tnsMoveObjectLocal(to->o, LA_COLOR3(use_delta));
  662. }else{
  663. if(td->CanvasDeltaMode) tnsMoveObjectGlobalForDelta(to->o, LA_COLOR3(use_delta));
  664. else tnsMoveObjectGlobal(to->o, LA_COLOR3(use_delta));
  665. }
  666. }
  667. }
  668. }
  669. void la_ApplyScale(MTransformData* td, int uix, int uiy){
  670. tnsMatrix44d trans; real d=tnsDistIdv2(uix,uiy,td->CenterX,td->CenterY); if(!td->Initial){ td->Initial=100; }
  671. real s=d/td->Initial; tnsVector3d gp;
  672. td->DeltaVal=s; if(td->UseUserDelta) td->DeltaVal=s=td->UserDeltaVal;
  673. tnsMatrix44d t1,t2,t3,final;
  674. if(td->mo || td->so){
  675. tnsVector3d use_delta={s,s,s};\
  676. if(td->LockAxis[0]>0){ use_delta[1]=use_delta[2]=1;}
  677. if(td->LockAxis[1]>0){ use_delta[0]=use_delta[2]=1;}
  678. if(td->LockAxis[2]>0){ use_delta[0]=use_delta[1]=1;}
  679. if(td->LockAxis[0]<0){ use_delta[0]=1; }
  680. if(td->LockAxis[1]<0){ use_delta[1]=1; }
  681. if(td->LockAxis[2]<0){ use_delta[2]=1; }
  682. tnsMakeScaleMatrix44d(trans,LA_COLOR3(use_delta));
  683. tnsMakeTranslationMatrix44d(t1,LA_COLOR3(td->TCenter)); tnsInverse44d(t2,t1);
  684. tnsMultiply44d(t3,t1,trans); tnsMultiply44d(t1,t3,t2);
  685. if(!td->UseLocal) tnsMultiply44d(final,td->obmatinv,t1);
  686. else tnsMultiply44d(final,t1,td->obmatinv);
  687. }
  688. if(td->mo){
  689. for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
  690. tnsApplyTransform43d(to->mv->p, final, to->p);
  691. }
  692. tnsInvalidateMeshBatch(td->mo); tnsMMeshCalculateNormal(td->mo);
  693. }elif(td->so){
  694. for(int i=0;i<td->next;i++){ MTOrigSPoint* to=arrElement(td->Originals, i, sizeof(MTOrigSPoint));
  695. tnsVector3d fp={to->p[0],to->p[1],0}, tp, tpl, tpr, fpl={to->pl[0],to->pl[1],0},fpr={to->pr[0],to->pr[1],0};
  696. int domain=0;
  697. if(to->sp->flags&TNS_MESH_FLAG_SELECTED){
  698. tnsApplyTransform43d(tp, final, fp); tnsVectorSet2v(to->sp->p,tp); domain=1;
  699. }
  700. if((to->sp->flags&TNS_SPOINT_BEZIER)){
  701. if((to->sp->flags&TNS_SPOINT_SELECTED_L) || domain){ tnsApplyTransform43d(tpl, final, fpl); tnsVectorMinus2d(to->sp->dl,tpl,to->sp->p);
  702. if((to->sp->flags&TNS_SPOINT_ALIGNED) && (!domain)){ real len=tnsLength2d(to->origdr);
  703. tnsVectorMulti2d(to->sp->dr,to->sp->dl,-1*len/tnsLength2d(to->sp->dl));
  704. }
  705. }
  706. if((to->sp->flags&TNS_SPOINT_SELECTED_R) || domain){ tnsApplyTransform43d(tpr, final, fpr); tnsVectorMinus2d(to->sp->dr,tpr,to->sp->p);
  707. if((to->sp->flags&TNS_SPOINT_ALIGNED) && (!domain)){ real len=tnsLength2d(to->origdl);
  708. tnsVectorMulti2d(to->sp->dl,to->sp->dr,-1*len/tnsLength2d(to->sp->dr));
  709. }
  710. }
  711. }
  712. }
  713. }else{
  714. for(int i=0;i<td->next;i++){
  715. MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject)); memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
  716. if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
  717. if(td->CanvasDeltaMode) tnsGlobalMatrixChangedForDelta(to->o, 0); else tnsGlobalMatrixChanged(to->o, 0);
  718. if(td->CanvasDeltaMode) tnsScaleObjectDelta(to->o,s,s,s,LA_COLOR3(td->TCenter));
  719. else tnsScaleObject(to->o, s,s,s, LA_COLOR3(td->TCenter));
  720. }
  721. }
  722. }
  723. void la_ApplyRotation(MTransformData* td, int uix, int uiy){
  724. tnsMatrix44d trans; real a=atan2(uiy-td->CenterY,uix-td->CenterX);
  725. real angle=a-td->Initial; tnsVector3d gp; tnsVector3d LimFoward={0}; real* use_forward=td->Foward;
  726. tnsMatrix44d t1,t2,t3,final;
  727. if(td->Is2D || td->so){ use_forward=LimFoward; LimFoward[2]=1; }
  728. if(td->LockAxis[0]||td->LockAxis[1]||td->LockAxis[2]){ use_forward=LimFoward; }
  729. if(td->LockAxis[0]){ LimFoward[0]=1; LimFoward[2]=0; }
  730. if(td->LockAxis[1]){ LimFoward[1]=1; LimFoward[2]=0; }
  731. if(td->LockAxis[2]){ LimFoward[2]=1; }
  732. if(td->UseUserDelta) angle=rad(td->UserDeltaVal); td->DeltaVal=deg(angle);
  733. if(td->mo||td->so){
  734. tnsMakeRotationMatrix44d(trans, angle, LA_COLOR3(use_forward));
  735. tnsMakeTranslationMatrix44d(t1,LA_COLOR3(td->UseLocal?td->TLCenter:td->TCenter)); tnsInverse44d(t2,t1);
  736. tnsMultiply44d(t3,t1,trans); tnsMultiply44d(t1,t3,t2);
  737. if(!td->UseLocal) tnsMultiply44d(final,td->obmatinv,t1);
  738. else tnsMultiply44d(final,t1,td->obmatinv);
  739. }
  740. if(td->mo){
  741. for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
  742. tnsApplyTransform43d(to->mv->p, final, to->p);
  743. }
  744. tnsInvalidateMeshBatch(td->mo); tnsMMeshCalculateNormal(td->mo);
  745. }elif(td->so){
  746. for(int i=0;i<td->next;i++){ MTOrigSPoint* to=arrElement(td->Originals, i, sizeof(MTOrigSPoint));
  747. tnsVector3d fp={to->p[0],to->p[1],0}, tp, tpl, tpr, fpl={to->pl[0],to->pl[1],0},fpr={to->pr[0],to->pr[1],0};
  748. int domain=0;
  749. if(to->sp->flags&TNS_MESH_FLAG_SELECTED){
  750. tnsApplyTransform43d(tp, final, fp); tnsVectorSet2v(to->sp->p,tp); domain=1;
  751. }
  752. if((to->sp->flags&TNS_SPOINT_BEZIER)){
  753. if((to->sp->flags&TNS_SPOINT_SELECTED_L) || domain){ tnsApplyTransform43d(tpl, final, fpl); tnsVectorMinus2d(to->sp->dl,tpl,to->sp->p);
  754. if((to->sp->flags&TNS_SPOINT_ALIGNED) && (!domain)){ real len=tnsLength2d(to->origdr);
  755. tnsVectorMulti2d(to->sp->dr,to->sp->dl,-1*len/tnsLength2d(to->sp->dl));
  756. }
  757. }
  758. if((to->sp->flags&TNS_SPOINT_SELECTED_R) || domain){ tnsApplyTransform43d(tpr, final, fpr); tnsVectorMinus2d(to->sp->dr,tpr,to->sp->p);
  759. if((to->sp->flags&TNS_SPOINT_ALIGNED) && (!domain)){ real len=tnsLength2d(to->origdl);
  760. tnsVectorMulti2d(to->sp->dl,to->sp->dr,-1*len/tnsLength2d(to->sp->dr));
  761. }
  762. }
  763. }
  764. }
  765. }else{
  766. for(int i=0;i<td->next;i++){
  767. MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject)); memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
  768. if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
  769. if(td->CanvasDeltaMode) tnsGlobalMatrixChangedForDelta(to->o, 0); else tnsGlobalMatrixChanged(to->o, 0);
  770. if(td->UseLocal){
  771. if(td->CanvasDeltaMode) tnsRotateObjectDelta(to->o,LA_COLOR3(use_forward),angle);
  772. else tnsRotateObjectLocal(to->o,LA_COLOR3(use_forward),angle);
  773. }else{
  774. if(td->CanvasDeltaMode) tnsRotateObjectGlobalForDelta(to->o,LA_COLOR3(use_forward),angle,LA_COLOR3(td->TCenter));
  775. else tnsRotateObjectGlobal(to->o,LA_COLOR3(use_forward),angle,LA_COLOR3(td->TCenter));
  776. }
  777. }
  778. }
  779. }
  780. void la_CancelTransformObjects(MTransformData* td){
  781. if(td->mo){
  782. for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert)); tnsVectorCopy3d(to->origp,to->mv->p); }
  783. tnsInvalidateMeshBatch(td->mo);
  784. }elif(td->so){
  785. for(int i=0;i<td->next;i++){ MTOrigSPoint* to=arrElement(td->Originals, i, sizeof(MTOrigSPoint));
  786. tnsVectorCopy2d(to->origp,to->sp->p); tnsVectorCopy2d(to->origdl,to->sp->dl); tnsVectorCopy2d(to->origdr,to->sp->dr);
  787. }
  788. }else{
  789. for(int i=0;i<td->next;i++){ MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject));
  790. if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
  791. memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
  792. if(td->CanvasDeltaMode) tnsGlobalMatrixChangedForDelta(to->o, 1);
  793. else tnsGlobalMatrixChanged(to->o, 1);
  794. }
  795. }
  796. }
  797. void la_RecordTransformDifferences(MTransformData* td){
  798. if(td->mo){
  799. laRecordInstanceDifferences(td->mo, "tns_mesh_object");
  800. laPushDifferences(td->mode==LA_TRANSFORM_MODE_GRAB?"Moved primitives":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotated primitives":"Scaled primitives", TNS_HINT_GEOMETRY);
  801. tnsInvalidateMeshBatch(td->mo);
  802. }elif(td->so){
  803. laRecordInstanceDifferences(td->so, "tns_shape_object");
  804. laPushDifferences(td->mode==LA_TRANSFORM_MODE_GRAB?"Moved points":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotated points":"Scaled points", TNS_HINT_GEOMETRY);
  805. }else{
  806. for(int i=0;i<td->next;i++){ MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject));
  807. laRecordInstanceDifferences(to->o, "tns_object");
  808. } laPushDifferences(td->mode==LA_TRANSFORM_MODE_GRAB?"Moved objects":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotated objects":"Scaled objects", TNS_HINT_TRANSFORM);
  809. }
  810. }
  811. void la_FreeTransformData(MTransformData* td){
  812. free(td->Originals);
  813. strEndEdit(&td->Entry, 1);
  814. memFree(td);
  815. }
  816. void la_MakeTransformOperatorHint(laOperator* a, MTransformData* td){
  817. strSafeDestroy(&a->RuntimeHint);
  818. strSafePrint(&a->RuntimeHint, "%s ",
  819. td->mode==LA_TRANSFORM_MODE_GRAB?"Grab":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotate":td->mode==LA_TRANSFORM_MODE_SCALE?"Scale":"");
  820. char* entry=strGetEditString(td->Entry,0);
  821. strSafePrint(&a->RuntimeHint, "Delta: %.3lf [🔢 %s] 🆇🆈🆉 Lock axis: %s 🈳 %s ", td->DeltaVal, (entry&&entry[0])?entry:"Type...",
  822. td->LockAxis[0]?"X":td->LockAxis[1]?"Y":td->LockAxis[2]?"Z":"None",
  823. td->UseLocal?"Global/[Local]":"[Global]/Local");
  824. free(entry);
  825. if(td->mode==LA_TRANSFORM_MODE_GRAB){ strSafePrint(&a->RuntimeHint, "🡅🆇🆈🆉 Reverse: %s ",
  826. (td->LockAxis[0]<0||td->LockAxis[1]<0||td->LockAxis[2]<0)?"Yes":"No"); }
  827. if(td->mode!=LA_TRANSFORM_MODE_GRAB){ strSafePrint(&a->RuntimeHint,"🅶 Grab "); }
  828. if(td->mode!=LA_TRANSFORM_MODE_SCALE){ strSafePrint(&a->RuntimeHint,"🆂 Scale "); }
  829. if(td->mode!=LA_TRANSFORM_MODE_ROTATE){ strSafePrint(&a->RuntimeHint,"🆁 Rotate "); }
  830. }
  831. void la_RestoreTransform(tnsObject* ob, int restore_type, int restore_delta){
  832. if(restore_delta){
  833. if(restore_type==LA_TRANSFORM_RESTORE_LOC){ tnsVectorSet3(ob->DLocation,0,0,0); }
  834. elif(restore_type==LA_TRANSFORM_RESTORE_ROT){ tnsVectorSet3(ob->DRotation,0,0,0); }
  835. elif(restore_type==LA_TRANSFORM_RESTORE_SCA){ tnsVectorSet3(ob->DScale,1,1,1); }
  836. tnsDeltaTransformValueChanged(ob);
  837. }else{
  838. if(restore_type==LA_TRANSFORM_RESTORE_LOC){ tnsVectorSet3(ob->Location,0,0,0); }
  839. elif(restore_type==LA_TRANSFORM_RESTORE_ROT){ tnsVectorSet3(ob->Rotation,0,0,0); }
  840. elif(restore_type==LA_TRANSFORM_RESTORE_SCA){ tnsVectorSet3(ob->Scale,1,1,1); }
  841. tnsSelfTransformValueChanged(ob);
  842. }
  843. }
  844. int la_InitTransform(laOperator* a, laEvent* e, int mode, int restore_type, int restore_delta){
  845. if(!a->This || !a->This->EndInstance){ return 0; }
  846. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  847. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  848. tnsObject* o=root->Active; tnsRootObject*ro=root;
  849. tnsMeshObject* mo=o; tnsShapeObject* so=o;
  850. MTransformData* td=la_InitTransformData(
  851. ex->OffScr->pColor[0]->Width, ex->OffScr->pColor[0]->Height, c, ex->DeltaMode,
  852. ro->Is2D, ex->ZoomX,ex->ZoomY);
  853. a->CustomData = td;
  854. td->mode=mode;
  855. td->root=root;
  856. int ret=0;
  857. if(o && o->Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  858. if(la_PopulateTransformVerticies(td, mo)){ ex->ClickedX=e->x; ex->ClickedY=e->y; ret=1; }
  859. }elif(o && o->Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){
  860. if(la_PopulateTransformPoints(td, so)){ ex->ClickedX=e->x; ex->ClickedY=e->y; ret=1; }
  861. }else{
  862. if(la_PopulateTransformObjects(td,root)){ ex->ClickedX=e->x; ex->ClickedY=e->y; ret=1; }
  863. if(ret && restore_type){
  864. for(int i=0;i<td->next;i++){ MTOrigObject* ob=arrElement(td->Originals, i, sizeof(MTOrigObject));
  865. la_RestoreTransform(ob->o,restore_type,restore_delta);
  866. }
  867. la_RecordTransformDifferences(td); laNotifyUsers("tns.world"); la_FreeTransformData(td);
  868. return 0;
  869. }
  870. }
  871. if(ret){
  872. if(mode==LA_TRANSFORM_MODE_SCALE){ la_GetTransformInitialScale(td,ui,e->x,e->y); ex->DrawCursor=LA_CANVAS_CURSOR_ARROW; }
  873. elif(mode==LA_TRANSFORM_MODE_ROTATE){ la_GetTransformInitialRotation(td,ui,e->x,e->y); ex->DrawCursor=LA_CANVAS_CURSOR_ARROW; }
  874. ex->TargetX=td->CenterX+ui->L; ex->TargetY=td->CenterY+ui->U; ex->OnX=e->x; ex->OnY=e->y;
  875. la_MakeTransformOperatorHint(a, td);
  876. laNotifyUsers("tns.world"); return 1;
  877. }
  878. return 0;
  879. }
  880. int OPINV_Grab(laOperator *a, laEvent *e){
  881. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB,0,0)) return LA_RUNNING; return LA_FINISHED_PASS;
  882. }
  883. int OPINV_Scale(laOperator *a, laEvent *e){
  884. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_SCALE,0,0)) return LA_RUNNING; return LA_FINISHED_PASS;
  885. }
  886. int OPINV_Rotate(laOperator *a, laEvent *e){
  887. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_ROTATE,0,0)) return LA_RUNNING; return LA_FINISHED_PASS;
  888. }
  889. int OPMOD_Transformation(laOperator *a, laEvent *e){
  890. if(!a->This || !a->This->EndInstance){ return 0; }
  891. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  892. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  893. tnsMeshObject* mo=root->Active;
  894. MTransformData* td=a->CustomData;
  895. if (e->Input=='x'||e->Input=='y'||e->Input=='z'||e->Input=='g'||e->Input=='s'||e->Input=='r'||
  896. e->Input=='X'||e->Input=='Y'||e->Input=='Z'||e->Input==' '){ /*pass*/ }
  897. else{ la_ProcessTextEdit(e, td->Entry, 0); }
  898. char* entered;
  899. if(entered=strGetEditString(td->Entry,0)){ int status;
  900. if((status=sscanf(entered,"%lf",&td->UserDeltaVal)) && status!=EOF) td->UseUserDelta=1; else td->UseUserDelta=0;
  901. td->UserDeltaVal=fabs(td->UserDeltaVal); for(char*pc=entered;*pc;pc++){ if(*pc=='-') td->UserDeltaVal=-td->UserDeltaVal; } free(entered);
  902. }
  903. if(e->Type==LA_KEY_DOWN){
  904. int Other=1; if(e->SpecialKeyBit&LA_KEY_SHIFT){ Other=-1; }
  905. 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; }
  906. 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; }
  907. 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; }
  908. if(e->key=='g' && td->mode!=LA_TRANSFORM_MODE_GRAB){ td->mode=LA_TRANSFORM_MODE_GRAB; ex->DrawCursor=0; }
  909. 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; }
  910. 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; }
  911. if(e->key==' '){ td->UseLocal=!td->UseLocal; }
  912. }
  913. if(e->Type==LA_MOUSEMOVE || e->Type==LA_KEY_DOWN){
  914. switch(td->mode){
  915. case LA_TRANSFORM_MODE_GRAB: la_ApplyTranslation(td,e->x-ex->ClickedX, e->y-ex->ClickedY); break;
  916. case LA_TRANSFORM_MODE_SCALE: la_ApplyScale(td,e->x-ui->L, e->y-ui->U); break;
  917. case LA_TRANSFORM_MODE_ROTATE: la_ApplyRotation(td,e->x-ui->L, e->y-ui->U); break;
  918. default: break;
  919. }
  920. ex->OnX=e->x; ex->OnY=e->y;
  921. laNotifyUsers("tns.world");
  922. }
  923. if(e->Type==LA_L_MOUSE_DOWN || (e->Type==LA_KEY_DOWN && e->key==LA_KEY_ENTER)){ ex->DrawCursor=0;
  924. la_RecordTransformDifferences(td);
  925. laNotifyUsers("tns.world"); la_FreeTransformData(td); return LA_FINISHED;
  926. }
  927. if(e->Type==LA_R_MOUSE_DOWN || e->Type==LA_ESCAPE_DOWN){ ex->DrawCursor=0;
  928. la_CancelTransformObjects(td); laNotifyUsers("tns.world"); la_FreeTransformData(td); return LA_FINISHED;
  929. }
  930. la_MakeTransformOperatorHint(a, td);
  931. return LA_RUNNING;
  932. }
  933. int OPINV_ClearTransformation(laOperator *a, laEvent *e){
  934. laCanvasExtra* ex=a->This->EndInstance; int restore=0;
  935. char* channel=strGetArgumentString(a->ExtraInstructionsP,"channel");
  936. if(channel){
  937. if(channel[0]=='L' || channel[0]=='l'){ restore=LA_TRANSFORM_RESTORE_LOC; }
  938. if(channel[0]=='R' || channel[0]=='r'){ restore=LA_TRANSFORM_RESTORE_ROT; }
  939. if(channel[0]=='S' || channel[0]=='s'){ restore=LA_TRANSFORM_RESTORE_SCA; }
  940. }else{
  941. laEnableOperatorPanel(a,a->This,e->x,e->y,150,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING;
  942. }
  943. char* dt=strGetArgumentString(a->ExtraInstructionsP,"delta");
  944. int delta=dt?strSame(dt,"true"):ex->DeltaMode;
  945. la_InitTransform(a,e,0,restore,delta);
  946. return LA_FINISHED;
  947. }
  948. void laui_ClearTransformation(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
  949. laColumn* c=laFirstColumn(uil), *cl,*cr; laSplitColumn(uil,c,0.6); cl=laLeftColumn(c,0); cr=laRightColumn(c,0);
  950. laShowItemFull(uil,cl,pp,"_this_M_clear_transformations",0,"channel=loc;text=Location",0,0);
  951. laShowItemFull(uil,cl,pp,"_this_M_clear_transformations",0,"channel=rot;text=Rotation",0,0);
  952. laShowItemFull(uil,cl,pp,"_this_M_clear_transformations",0,"channel=sca;text=Scale",0,0);
  953. laShowItemFull(uil,cr,pp,"_this_M_clear_transformations",0,"channel=loc;text=Delta;delta=true",0,0);
  954. laShowItemFull(uil,cr,pp,"_this_M_clear_transformations",0,"channel=rot;text=Delta;delta=true",0,0);
  955. laShowItemFull(uil,cr,pp,"_this_M_clear_transformations",0,"channel=sca;text=Delta;delta=true",0,0);
  956. }
  957. int la_ParentableRecursive(tnsObject* root, tnsObject* parent){
  958. for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  959. tnsObject* o=lip->p; if((!o) || (!(o->Flags&TNS_OBJECT_FLAGS_SELECTED)) || (o==parent)) continue;
  960. if(!tnsCheckParentable(o,parent)) return 0;
  961. if(!la_ParentableRecursive(o,parent)) return 0;
  962. }return 1;
  963. }
  964. void la_MakeParentExecuteRecursive(tnsObject* root, tnsObject* parent, int Unparent, int KeepTransform){
  965. laListItemPointer* NextLip;
  966. if(root->Type!=TNS_OBJECT_ROOT){
  967. if((root->Flags&TNS_OBJECT_FLAGS_SELECTED)&&root->InRoot==parent->InRoot){
  968. if(Unparent) tnsUnparentObject(root, KeepTransform);
  969. elif(root!=parent) tnsParentObject(root, parent, KeepTransform);
  970. }
  971. }
  972. for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=NextLip){ NextLip=lip->pNext;
  973. tnsObject* o=lip->p; if(!o) continue; la_MakeParentExecuteRecursive(o,parent,Unparent,KeepTransform);
  974. }
  975. laNotifyUsers("tns.world");
  976. }
  977. int OPINV_MakeParent(laOperator *a, laEvent *e){
  978. if(!a->This || !a->This->EndInstance){ return 0; }
  979. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  980. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  981. tnsObject* mo=root->Active;
  982. int Unparent=0,KeepTransform=1;
  983. char* action=strGetArgumentString(a->ExtraInstructionsP,"action");
  984. char* keep=strGetArgumentString(a->ExtraInstructionsP,"keep_transform");
  985. if(strSame(action,"unparent")){ Unparent=1; }
  986. if(strSame(keep,"false")){ KeepTransform=0; }
  987. if(!Unparent){ if((!mo) || (!(mo->Flags&TNS_OBJECT_FLAGS_SELECTED))) return LA_FINISHED;
  988. 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; }
  989. }
  990. if(keep){
  991. la_MakeParentExecuteRecursive(root,mo,Unparent,KeepTransform);
  992. laRecordInstanceDifferences(T->World, "tns_world"); laPushDifferences(Unparent?"Unparent":"Parent", TNS_HINT_TRANSFORM);
  993. return LA_FINISHED;
  994. }
  995. laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e);
  996. return LA_RUNNING;
  997. }
  998. void laui_MakeParent(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
  999. laColumn* c=laFirstColumn(uil);
  1000. laShowItemFull(uil,c,pp,"_this_M_make_parent",0,"action=parent;keep_transform=true;text=Keep transform",0,0);
  1001. laShowItemFull(uil,c,pp,"_this_M_make_parent",0,"action=parent;keep_transform=false;text=Directly",0,0);
  1002. }
  1003. void laui_Unparent(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
  1004. laColumn* c=laFirstColumn(uil);
  1005. laShowItemFull(uil,c,pp,"_this_M_unparent",0,"action=unparent;keep_transform=true;text=Keep transform",0,0);
  1006. laShowItemFull(uil,c,pp,"_this_M_unparent",0,"action=unparent;keep_transform=false;text=Directly",0,0);
  1007. }
  1008. STRUCTURE(MEDupVert){
  1009. int oi; tnsMVert* nmv; tnsMVert* omv; int IsBorder;
  1010. };
  1011. STRUCTURE(MEDupEdge){
  1012. int oi; tnsMEdge* nme; tnsMEdge* ome; int IsBorder;
  1013. };
  1014. STRUCTURE(MEDupFace){
  1015. int oi; tnsMFace* nmf; tnsMFace* omf;
  1016. };
  1017. STRUCTURE(MExtrudeExtra){
  1018. MEDupVert* dv; int nextv,maxv;
  1019. MEDupEdge* de; int nexte,maxe;
  1020. MEDupFace* df; int nextf,maxf;
  1021. tnsMeshObject* mo;
  1022. int RemoveOriginalFaces;
  1023. };
  1024. int la_IsSelectionBorderVertex(tnsMVert* mv){
  1025. if(!mv->elink.pFirst)
  1026. return 0;
  1027. int NearSelected=0, NearUnselected=0;
  1028. for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){
  1029. tnsMEdge* me=lip->p; if(!(me->fl&&me->fr)) return 1;
  1030. tnsMVert* av=tnsMMeshEdgeAnotherVert(me,mv);
  1031. if(me->fl->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { return 1; }
  1032. if(me->fr->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { return 1; }
  1033. if(NearUnselected && NearSelected) return 1;
  1034. }
  1035. return 0;
  1036. }
  1037. int la_IsSelectionBorderEdge(tnsMEdge* me){
  1038. if(me->fl&&me->fr){
  1039. if ((me->fl->flags&TNS_MESH_FLAG_SELECTED) && (!(me->fr->flags&TNS_MESH_FLAG_SELECTED))||
  1040. (me->fr->flags&TNS_MESH_FLAG_SELECTED) && (!(me->fl->flags&TNS_MESH_FLAG_SELECTED))) return 1;
  1041. else return (me->fr->flags==me->fl->flags&&me->fl->flags==0);
  1042. } return 1;
  1043. }
  1044. MExtrudeExtra* la_InitExtrude(tnsMeshObject* mo){
  1045. MExtrudeExtra* ee=memAcquireSimple(sizeof(MExtrudeExtra));
  1046. arrEnsureLength(&ee->dv, ee->nextv, &ee->maxv, sizeof(MEDupVert));
  1047. arrEnsureLength(&ee->de, ee->nexte, &ee->maxe, sizeof(MEDupEdge));
  1048. arrEnsureLength(&ee->df, ee->nextf, &ee->maxf, sizeof(MEDupFace));
  1049. ee->mo=mo;
  1050. return ee;
  1051. }
  1052. void la_ExtrudeMakeDuplication(MExtrudeExtra* ee){
  1053. tnsMeshObject* mo=ee->mo;
  1054. for(tnsMVert* mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){ if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  1055. arrEnsureLength(&ee->dv, ee->nextv, &ee->maxv, sizeof(MEDupVert));
  1056. MEDupVert* dv=&ee->dv[ee->nextv];
  1057. tnsMVert* nmv=tnsMMeshNewVert(mo); tnsVectorCopy3d(mv->p, &nmv->p); dv->oi=mv->i; mv->i=ee->nextv; dv->nmv=nmv; dv->omv=mv;
  1058. dv->IsBorder=la_IsSelectionBorderVertex(mv);
  1059. ee->nextv++;
  1060. }
  1061. for(tnsMEdge* me=mo->me.pFirst;me;me=me->Item.pNext){ if(!(me->flags&TNS_MESH_FLAG_SELECTED)) continue;
  1062. arrEnsureLength(&ee->de, ee->nexte, &ee->maxe, sizeof(MEDupEdge));
  1063. MEDupEdge* de=&ee->de[ee->nexte];
  1064. tnsMEdge* nme=tnsMMeshNewEdge(mo); de->oi=me->i; me->i=ee->nexte; de->nme=nme; de->ome=me; de->IsBorder=la_IsSelectionBorderEdge(me);
  1065. tnsMMeshEdgeAssignVerts(nme, ee->dv[me->vl->i].nmv, ee->dv[me->vr->i].nmv);
  1066. if(de->IsBorder&&me->fl&&me->fr){ ee->RemoveOriginalFaces=1; }
  1067. ee->nexte++;
  1068. }
  1069. for(tnsMFace* mf=mo->mf.pFirst;mf;mf=mf->Item.pNext){
  1070. if(!(mf->flags&TNS_MESH_FLAG_SELECTED)) continue;
  1071. arrEnsureLength(&ee->df, ee->nextf, &ee->maxf, sizeof(MEDupFace));
  1072. MEDupFace* df=&ee->df[ee->nextf];
  1073. tnsMFace* nmf=tnsMMeshNewFace(mo); df->oi=mf->i; mf->i=ee->nextf; df->nmf=nmf; df->omf=mf; nmf->mat=mf->mat;
  1074. for(laListItemPointer*lip=mf->l.pFirst;lip;lip=lip->pNext){
  1075. tnsMEdge* ome=lip->p; tnsMMeshFaceAddEdge(nmf,ee->de[ome->i].nme);
  1076. }
  1077. ee->nextf++;
  1078. }
  1079. 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; }
  1080. 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; }
  1081. for(int i=0;i<ee->nextf;i++){
  1082. ee->df[i].omf->i=ee->df[i].oi;
  1083. ee->df[i].omf->flags&=(~TNS_MESH_FLAG_SELECTED);
  1084. ee->df[i].nmf->flags|=TNS_MESH_FLAG_SELECTED; }
  1085. }
  1086. void la_RemoveOriginalFaces(MExtrudeExtra* ee){
  1087. tnsMeshObject* mo=ee->mo;
  1088. if(ee->RemoveOriginalFaces){
  1089. for(int i=0;i<ee->nextf;i++){ tnsMMeshRemoveFaceOnly(mo, ee->df[i].omf); }
  1090. for(int i=0;i<ee->nexte;i++){ if(ee->de[i].IsBorder) continue; tnsMMeshRemoveEdgeFace(mo, ee->de[i].ome); }
  1091. for(int i=0;i<ee->nextv;i++){ if(ee->dv[i].IsBorder) continue; tnsMMeshRemoveVertEdgeFace(mo, ee->dv[i].omv); }
  1092. }
  1093. }
  1094. void la_ReconnectFaces(MExtrudeExtra* ee){
  1095. tnsMeshObject* mo=ee->mo;
  1096. for(int i=0;i<ee->nexte;i++){
  1097. if(!ee->de[i].IsBorder) continue; MEDupEdge*de=&ee->de[i];
  1098. tnsMMeshMakeFace4v(mo, de->ome->vl, de->ome->vr, de->nme->vr, de->nme->vl);
  1099. }
  1100. }
  1101. void la_FinishExtrude(MExtrudeExtra* ee, int PushDifferences){
  1102. tnsMMeshRefreshIndex(ee->mo);
  1103. tnsInvalidateMeshBatch(ee->mo);
  1104. if(PushDifferences){
  1105. laRecordInstanceDifferences(ee->mo, "tns_mesh_object"); laPushDifferences("Extruded", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  1106. }
  1107. free(ee->dv); free(ee->de); free(ee->df); memFree(ee);
  1108. }
  1109. int OPINV_Extrude(laOperator *a, laEvent *e){
  1110. if(!a->This || !a->This->EndInstance){ return 0; }
  1111. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1112. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  1113. tnsMeshObject* mo=root->Active; tnsShapeObject* so=mo; if(!mo) return 0;
  1114. if(mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  1115. if(!tnsMMeshAnySelected(mo)) return LA_FINISHED;
  1116. MExtrudeExtra* ee=la_InitExtrude(mo);
  1117. la_ExtrudeMakeDuplication(ee);
  1118. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"duplicate_only"), "true")){
  1119. la_FinishExtrude(ee, 1);
  1120. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB,0,0)) return LA_RUNNING; return LA_FINISHED;
  1121. }
  1122. la_RemoveOriginalFaces(ee);
  1123. la_ReconnectFaces(ee);
  1124. la_FinishExtrude(ee, 1);
  1125. }elif(so->Base.Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){
  1126. int duponly=strSame(strGetArgumentString(a->ExtraInstructionsP,"duplicate_only"), "true");
  1127. tnsShapeExtrudeSelected(so,duponly);
  1128. }else{
  1129. return LA_CANCELED;
  1130. }
  1131. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB,0,0)) return LA_RUNNING; return LA_FINISHED;
  1132. return LA_FINISHED;
  1133. }
  1134. int la_EdgeShouldDeleteVert(tnsMVert* mv){
  1135. if(!mv->elink.pFirst) return 0;
  1136. int NearSelected=0, NearUnselected=0;
  1137. for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){
  1138. tnsMEdge* me=lip->p;
  1139. tnsMVert* av=tnsMMeshEdgeAnotherVert(me,mv);
  1140. if(av->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { NearUnselected=1; }
  1141. if(NearUnselected && NearSelected) return 0;
  1142. }
  1143. if(NearSelected&&(!NearUnselected)) return 1; return 0;
  1144. }
  1145. int la_FaceShouldDeleteVert(tnsMVert* mv){
  1146. if(!mv->elink.pFirst) return 0;
  1147. int NearSelected=0, NearUnselected=0, IsBorder=0;
  1148. for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){
  1149. tnsMEdge* me=lip->p;
  1150. if(!(me->fl&&me->fr)){ IsBorder=1; }
  1151. if(me->fl){ if(me->fl->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { NearUnselected=1; } }
  1152. if(me->fr){ if(me->fr->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { NearUnselected=1; } }
  1153. if(NearUnselected && NearSelected) return 0;
  1154. }
  1155. if((!NearUnselected) && IsBorder) return 1;
  1156. return 1;
  1157. }
  1158. int la_FaceShouldDeleteEdge(tnsMEdge* me){
  1159. if(me->fl&&me->fr){
  1160. if ((me->fl->flags&TNS_MESH_FLAG_SELECTED) && (!(me->fr->flags&TNS_MESH_FLAG_SELECTED))||
  1161. (me->fr->flags&TNS_MESH_FLAG_SELECTED) && (!(me->fl->flags&TNS_MESH_FLAG_SELECTED))) return 0;
  1162. else return (me->fr->flags==me->fl->flags&&me->fl->flags==1);
  1163. }else{
  1164. if(me->fl&&me->fl->flags&TNS_MESH_FLAG_SELECTED&&!me->fr) return 1;
  1165. if(me->fr&&me->fr->flags&TNS_MESH_FLAG_SELECTED&&!me->fl) return 1;
  1166. } return 0;
  1167. }
  1168. void la_DeleteVertices(tnsMeshObject* mo){
  1169. tnsMVert* nextmv; for(tnsMVert*mv=mo->mv.pFirst;mv;mv=nextmv){ nextmv=mv->Item.pNext; if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  1170. tnsMMeshRemoveVertEdgeFace(mo, mv);
  1171. }
  1172. }
  1173. void la_DeleteEdges(tnsMeshObject* mo){
  1174. laListHandle lv={0};
  1175. for(tnsMVert*mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){ if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  1176. if(la_EdgeShouldDeleteVert(mv)) lstAppendPointer(&lv,mv);
  1177. }
  1178. tnsMEdge* nextme; for(tnsMEdge*me=mo->me.pFirst;me;me=nextme){ nextme=me->Item.pNext; if(!(me->flags&TNS_MESH_FLAG_SELECTED)) continue;
  1179. tnsMMeshRemoveEdgeFace(mo, me);
  1180. }
  1181. tnsMVert* mv; while(mv=lstPopPointer(&lv)){ tnsMMeshRemoveVertEdgeFace(mo,mv); }
  1182. }
  1183. void la_DeleteFaces(tnsMeshObject* mo, int OnlyFaces){
  1184. laListHandle lv={0}, le={0};
  1185. if(OnlyFaces){
  1186. tnsMFace* nextmf; for(tnsMFace*mf=mo->mf.pFirst;mf;mf=nextmf){ nextmf=mf->Item.pNext; if(!(mf->flags&TNS_MESH_FLAG_SELECTED)) continue;
  1187. tnsMMeshRemoveFaceOnly(mo, mf);
  1188. }
  1189. }else{
  1190. for(tnsMVert*mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){ if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  1191. if(la_FaceShouldDeleteVert(mv)) lstAppendPointer(&lv,mv);
  1192. }
  1193. for(tnsMEdge*me=mo->me.pFirst;me;me=me->Item.pNext){ if(!(me->flags&TNS_MESH_FLAG_SELECTED)) continue;
  1194. if(la_FaceShouldDeleteEdge(me)) lstAppendPointer(&le,me);
  1195. }
  1196. tnsMFace* nextmf; for(tnsMFace*mf=mo->mf.pFirst;mf;mf=nextmf){ nextmf=mf->Item.pNext; if(!(mf->flags&TNS_MESH_FLAG_SELECTED)) continue;
  1197. tnsMMeshRemoveFaceOnly(mo, mf);
  1198. }
  1199. tnsMEdge* me; while(me=lstPopPointer(&le)){ tnsMMeshRemoveEdgeFace(mo,me); }
  1200. tnsMVert* mv; while(mv=lstPopPointer(&lv)){ tnsMMeshRemoveVertEdgeFace(mo,mv); }
  1201. }
  1202. }
  1203. void la_DeletePoints(tnsShapeObject* so, int SplitShape){
  1204. for(tnsShape* s=so->Shapes.pFirst;s;s=s->Item.pNext){
  1205. tnsSPoint* NextSP; for(tnsSPoint* sp=s->Points.pFirst;sp;sp=NextSP){ NextSP=sp->Item.pNext;
  1206. if(!(sp->flags&TNS_MESH_FLAG_SELECTED)) continue;
  1207. tnsShapeRemovePoint(so,s,sp,SplitShape);
  1208. }
  1209. }
  1210. tnsShapeRefreshIndex(so);
  1211. }
  1212. int la_DeleteSelectedObjectsRecursive(tnsObject* root){
  1213. int any=0; for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){ if(!lip->p) continue;
  1214. tnsObject* o=lip->p; la_DeleteSelectedObjectsRecursive(lip->p);
  1215. if(o->Flags&TNS_OBJECT_FLAGS_SELECTED){ tnsDestroyObject(o); any++; }
  1216. }
  1217. return any;
  1218. }
  1219. STRUCTURE(MDeleteData){
  1220. int _PAD;
  1221. int Context;
  1222. };
  1223. int OPINV_Delete(laOperator *a, laEvent *e){
  1224. if(!a->This || !a->This->EndInstance){ return 0; }
  1225. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1226. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  1227. tnsMeshObject* mo=root->Active; tnsShapeObject* so=mo; if(!mo) return 0;
  1228. if(mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  1229. if(!tnsMMeshAnySelected(mo)) return LA_FINISHED;
  1230. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"vertices")){
  1231. la_DeleteVertices(mo);
  1232. }elif(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"edges")){
  1233. la_DeleteEdges(mo);
  1234. }elif(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"faces")){
  1235. la_DeleteFaces(mo,0);
  1236. }elif(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"only_faces")){
  1237. la_DeleteFaces(mo,1);
  1238. }else{
  1239. MDeleteData* md=memAcquire(sizeof(MDeleteData)); a->CustomData=md; md->Context=TNS_OBJECT_MESH;
  1240. laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING;
  1241. }
  1242. tnsMMeshDeselectAll(mo);
  1243. tnsMMeshRefreshIndex(mo);
  1244. tnsInvalidateMeshBatch(mo);
  1245. laRecordInstanceDifferences(mo, "tns_mesh_object"); laPushDifferences("Deleted primitives", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  1246. }elif(so->Base.Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){
  1247. if(!tnsShapeAnySelected(so)) return LA_FINISHED;
  1248. char* split=strGetArgumentString(a->ExtraInstructionsP, "split");
  1249. if(split){
  1250. int SplitShapes=strSame(split,"TRUE"); la_DeletePoints(so,SplitShapes);
  1251. }else{
  1252. MDeleteData* md=memAcquire(sizeof(MDeleteData)); a->CustomData=md; md->Context=TNS_OBJECT_SHAPE;
  1253. laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING;
  1254. }
  1255. laRecordInstanceDifferences(so, "tns_shape_object"); laPushDifferences("Deleted points", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  1256. }else{
  1257. if(la_DeleteSelectedObjectsRecursive(root)){
  1258. laRecordInstanceDifferences(T->World, "tns_world"); laPushDifferences("Deleted objects", TNS_HINT_TRANSFORM); laNotifyUsers("tns.world");
  1259. }
  1260. }
  1261. return LA_FINISHED;
  1262. }
  1263. void laui_Delete(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
  1264. laColumn* c=laFirstColumn(uil); laUiItem* b;
  1265. b=laOnConditionThat(uil,c,laEqual(laPropExpression(actinst,"context"),laIntExpression(TNS_OBJECT_MESH)));{
  1266. laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=vertices;text=Vertices",0,0);
  1267. laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=edges;text=Edges",0,0);
  1268. laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=faces;text=Faces",0,0);
  1269. laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=only_faces;text=Only Faces",0,0);
  1270. }laEndCondition(uil,b);
  1271. b=laOnConditionThat(uil,c,laEqual(laPropExpression(actinst,"context"),laIntExpression(TNS_OBJECT_SHAPE)));{
  1272. laShowItemFull(uil,c,pp,"_this_M_delete",0,"split=FALSE;",0,0);
  1273. laShowItemFull(uil,c,pp,"_this_M_delete",0,"split=TRUE;text=Delet and Split",0,0);
  1274. }laEndCondition(uil,b);
  1275. }
  1276. STRUCTURE(MIslandInfo){
  1277. laListItem Item;
  1278. laListHandle v,e,f;int numv,nume,numf;
  1279. int Paired,HasBranches;
  1280. };
  1281. STRUCTURE(MMakeData){
  1282. laListHandle Islands; int NumIslands;
  1283. };
  1284. #define M_SHOULD_INCL_PRIM(m) \
  1285. ((!(m->flags&TNS_MESH_FLAG_PICKED)) && (m->flags&TNS_MESH_FLAG_SELECTED))
  1286. #define M_SHOULD_USE_OE(oe,sf) \
  1287. (((!oe->fl)&&((!sf)||(oe->fr!=sf)))||((!oe->fr)&&((!sf)||(oe->fl!=sf))))
  1288. MIslandInfo* la_NewMIsland(MMakeData* md){ MIslandInfo* ii=memAcquireSimple(sizeof(MIslandInfo)); lstAppendItem(&md->Islands, ii); md->NumIslands++; return ii; }
  1289. void la_FillIslandFromVert(MIslandInfo* ii, tnsMVert* mv, int SelectMode){
  1290. mv->flags|=TNS_MESH_FLAG_PICKED; lstAppendPointer(&ii->v,mv); ii->numv++; int connections=0;
  1291. for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){ tnsMEdge* oe=lip->p; tnsMVert* ov=tnsMMeshEdgeAnotherVert(oe,mv);
  1292. if(ov->flags&TNS_MESH_FLAG_SELECTED) connections++; else continue;
  1293. if(SelectMode==LA_CANVAS_SELECT_MODE_EDGES){ if(!(oe->flags&TNS_MESH_FLAG_SELECTED)) continue; }
  1294. if(M_SHOULD_INCL_PRIM(ov)){ la_FillIslandFromVert(ii,ov,SelectMode); } else { continue; }
  1295. if(M_SHOULD_INCL_PRIM(oe)){ lstAppendPointer(&ii->e,oe); ii->nume++; oe->flags|=TNS_MESH_FLAG_PICKED; }
  1296. if(oe->fl&&M_SHOULD_INCL_PRIM(oe->fl)){ lstAppendPointer(&ii->f,oe->fl); ii->numf++; oe->fl->flags|=TNS_MESH_FLAG_PICKED; }
  1297. if(oe->fr&&M_SHOULD_INCL_PRIM(oe->fr)){ lstAppendPointer(&ii->f,oe->fr); ii->numf++; oe->fr->flags|=TNS_MESH_FLAG_PICKED; }
  1298. }
  1299. if(connections>2) ii->HasBranches=1;
  1300. }
  1301. void la_GetSelectionIslands(tnsMeshObject* mo, MMakeData* md, int SelectMode){
  1302. tnsMMeshClearExtraFlags(mo);
  1303. for(tnsMVert* mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){
  1304. if(M_SHOULD_INCL_PRIM(mv)){ MIslandInfo* ii=la_NewMIsland(md); la_FillIslandFromVert(ii,mv,SelectMode); }
  1305. }
  1306. }
  1307. void la_ClearIslands(MMakeData* md){ MIslandInfo* ii; while(ii=lstPopItem(&md->Islands)){ while(lstPopPointer(&ii->v)); memFree(ii); } }
  1308. tnsMFace* la_MakeFacesFrom1Vert(tnsMeshObject* mo, tnsMVert* mv){
  1309. tnsMEdge* oe1=0,*oe2=0; tnsMVert* ov1,*ov2;
  1310. for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){
  1311. 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 */ }
  1312. } if(!oe1||!oe2) return 0;
  1313. ov1=tnsMMeshEdgeAnotherVert(oe1,mv); ov2=tnsMMeshEdgeAnotherVert(oe2,mv);
  1314. laListHandle vl={0}; lstAppendPointer(&vl,ov1); lstAppendPointer(&vl,mv); lstAppendPointer(&vl,ov2);
  1315. tnsMFace* f=tnsMMeshMakeFaceN(mo, 3, &vl, 0);
  1316. ov1->flags|=TNS_MESH_FLAG_SELECTED;ov2->flags|=TNS_MESH_FLAG_SELECTED; mv->flags&=(~TNS_MESH_FLAG_SELECTED);
  1317. tnsMMeshEnsureSelectionFromVerts(mo);
  1318. while(lstPopPointer(&vl)); return f;
  1319. }
  1320. tnsMFace* la_MakeFacesFrom2Verts(tnsMeshObject* mo, tnsMVert* mv1, tnsMVert* mv2){
  1321. tnsMEdge* oe1=0,*oe2=0; tnsMVert* ov1,*ov2; tnsMFace* sf=0;
  1322. tnsMEdge* se=tnsMMeshVertsShareEdge(mv1,mv2); if(se->fl && se->fr) return 0; sf=se->fl?se->fl:se->fr;
  1323. for(laListItemPointer* lip=mv1->elink.pFirst;lip;lip=lip->pNext){
  1324. 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 */ }
  1325. }
  1326. for(laListItemPointer* lip=mv2->elink.pFirst;lip;lip=lip->pNext){
  1327. 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 */ }
  1328. }
  1329. if(!oe1||!oe2) return 0;
  1330. ov1=tnsMMeshEdgeAnotherVert(oe1,mv1); ov2=tnsMMeshEdgeAnotherVert(oe2,mv2);
  1331. ov1->flags|=TNS_MESH_FLAG_SELECTED;ov2->flags|=TNS_MESH_FLAG_SELECTED; mv1->flags&=(~TNS_MESH_FLAG_SELECTED);mv2->flags&=(~TNS_MESH_FLAG_SELECTED);
  1332. laListHandle vl={0}; int vcount=3;
  1333. lstAppendPointer(&vl,ov1); lstAppendPointer(&vl,mv1); lstAppendPointer(&vl,mv2); if(ov2!=ov1){ lstAppendPointer(&vl,ov2); vcount=4; }
  1334. tnsMFace* f=tnsMMeshMakeFaceN(mo, vcount, &vl, 0); tnsMMeshEnsureSelectionFromVerts(mo);
  1335. while(lstPopPointer(&vl)); return f;
  1336. }
  1337. int la_IsEndingVert(tnsMVert* mv){
  1338. int sel=0; for(laListItemPointer*lip=mv->elink.pFirst;lip;lip=lip->pNext){ tnsMEdge* me=lip->p;
  1339. if(tnsMMeshEdgeAnotherVert(me,mv)->flags&TNS_MESH_FLAG_SELECTED){ sel++; if(sel>1) return 0; }
  1340. }
  1341. if(sel==1) return 1; return 0;
  1342. }
  1343. void la_EnsureIslandVertsSequence(MIslandInfo* ii){
  1344. laListHandle l={0}; tnsMVert* startv=((laListItemPointer*)ii->v.pFirst)->p; laListItemPointer* nextlip;
  1345. 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.
  1346. lstRemovePointer(&ii->v, startv); lstAppendPointer(&l, startv);
  1347. while(ii->v.pFirst){
  1348. for(laListItemPointer*lip=ii->v.pFirst;lip;lip=lip->pNext){ nextlip=lip->pNext;
  1349. if(tnsMMeshVertsShareEdge(startv, lip->p)){ startv=lip->p; lstRemoveItem(&ii->v,lip); lstAppendItem(&l, lip); break; }
  1350. }
  1351. }
  1352. memcpy(&ii->v, &l, sizeof(laListHandle));
  1353. }
  1354. MIslandInfo* la_GetNeighborIsland(tnsMVert* from, MMakeData* md){
  1355. int found=0; real dist=1e10; MIslandInfo* rii=0; for(MIslandInfo* ii=md->Islands.pFirst;ii;ii=ii->Item.pNext){ if(ii->Paired) continue;
  1356. found=1; tnsMVert* mv1=((laListItemPointer*)ii->v.pFirst)->p,*mv2=((laListItemPointer*)ii->v.pLast)->p;
  1357. real d1=tnsDist3dv(mv1->p, from->p),d2=tnsDist3dv(mv2->p, from->p);
  1358. if(d2<d1 && d2<dist){ lstReverse(&ii->v); } if(d1<dist || d2<dist){ rii=ii; }
  1359. }
  1360. if(rii) rii->Paired=1;
  1361. return rii;
  1362. }
  1363. int la_MakeFacesFromIslands(tnsMeshObject* mo, MMakeData* md){
  1364. int success=0;
  1365. if(!md->Islands.pFirst) return 0;
  1366. if(md->Islands.pFirst==md->Islands.pLast){
  1367. MIslandInfo* ii=md->Islands.pFirst; if(ii->HasBranches) return 0;
  1368. if(ii->numv==1){ laListItemPointer*lip=ii->v.pFirst; if(la_MakeFacesFrom1Vert(mo,lip->p)) success++; }
  1369. elif(ii->numv==2){ laListItemPointer*lip=ii->v.pFirst,*lip2=ii->v.pLast; if(la_MakeFacesFrom2Verts(mo,lip->p, lip2->p)) success++; }
  1370. else{ la_EnsureIslandVertsSequence(ii); if(tnsMMeshMakeFaceN(mo, ii->numv, &ii->v, 0)) success++; }
  1371. }else{
  1372. for(MIslandInfo* ii=md->Islands.pFirst;ii;ii=ii->Item.pNext){ if(ii->HasBranches) return 0; la_EnsureIslandVertsSequence(ii); }
  1373. laListHandle final={0}; int vcount=0;
  1374. MIslandInfo* ii=md->Islands.pFirst; ii->Paired=1; for(laListItemPointer* lip=ii->v.pFirst;lip;lip=lip->pNext){ lstAppendPointer(&final, lip->p); vcount++; }
  1375. while((ii=la_GetNeighborIsland(((laListItemPointer*)ii->v.pLast)->p, md))){
  1376. for(laListItemPointer* lip=ii->v.pFirst;lip;lip=lip->pNext){ lstAppendPointer(&final, lip->p); vcount++; }
  1377. }
  1378. tnsMEdge* fallback_e=0;
  1379. if(tnsMMeshMakeFaceN(mo,vcount,&final, &fallback_e) || fallback_e) success++;
  1380. while(lstPopPointer(&final));
  1381. }
  1382. return success;
  1383. }
  1384. int OPINV_Make(laOperator *a, laEvent *e){
  1385. if(!a->This || !a->This->EndInstance){ return 0; }
  1386. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1387. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  1388. tnsMeshObject* mo=root->Active; tnsShapeObject*so=mo;
  1389. if(!mo){ return LA_CANCELED; }
  1390. if(mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  1391. MMakeData md={0};
  1392. la_GetSelectionIslands(mo,&md,ex->SelectMode);
  1393. int success=la_MakeFacesFromIslands(mo,&md); if(success){ tnsMMeshCalculateNormal(mo); }
  1394. la_ClearIslands(&md);
  1395. tnsMMeshRefreshIndex(mo);
  1396. tnsMMeshEnsureSelection(mo,ex->SelectMode);
  1397. tnsInvalidateMeshBatch(mo);
  1398. if(laRecordInstanceDifferences(mo, "tns_mesh_object")) laPushDifferences("Make primitives", TNS_HINT_GEOMETRY);
  1399. laNotifyUsers("tns.world");
  1400. }elif(so->Base.Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){
  1401. if(tnsShapeConnectSelected(so)){
  1402. laRecordInstanceDifferences(so, "tns_shape_object"); laPushDifferences("Connect shapes", TNS_HINT_GEOMETRY);
  1403. laNotifyUsers("tns.world");
  1404. }
  1405. }
  1406. return LA_FINISHED;
  1407. }
  1408. int OPINV_Subdiv(laOperator *a, laEvent *e){
  1409. if(!a->This || !a->This->EndInstance){ return 0; }
  1410. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1411. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  1412. tnsMeshObject* mo=root->Active;
  1413. if(mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
  1414. laListHandle pending={0}; for(tnsMEdge* me=mo->me.pFirst;me;me=me->Item.pNext){ if(me->flags&TNS_MESH_FLAG_SELECTED) lstAppendPointer(&pending, me); }
  1415. if(!pending.pFirst) return LA_FINISHED;
  1416. tnsMEdge* me; while(me=lstPopPointer(&pending)){ tnsMVert* mv=tnsMMeshEdgeInsertVertAt(mo,me,0.5,0,0,0); mv->flags|=TNS_MESH_FLAG_SELECTED; }
  1417. tnsMMeshRefreshIndex(mo);
  1418. tnsMMeshEnsureSelection(mo,ex->SelectMode);
  1419. tnsInvalidateMeshBatch(mo);
  1420. if(laRecordInstanceDifferences(mo, "tns_mesh_object")) laPushDifferences("Subdivide edges", TNS_HINT_GEOMETRY);
  1421. laNotifyUsers("tns.world");
  1422. return LA_FINISHED;
  1423. }
  1424. #define LA_ADD_CTX_OBJECT 0
  1425. #define LA_ADD_CTX_MESH 1
  1426. #define LA_ADD_CTX_SHAPE 2
  1427. STRUCTURE(laObjectAddData){
  1428. int Context;
  1429. };
  1430. int OPINV_Add(laOperator *a, laEvent *e){
  1431. if(!a->This || !a->This->EndInstance){ return 0; }
  1432. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1433. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  1434. tnsMeshObject* mo=root->Active; tnsShapeObject* so=mo;int ran=0; tnsObject* no=0;
  1435. laObjectAddData *ad=memAcquire(sizeof(laObjectAddData));a->CustomData=ad;
  1436. char* str=strGetArgumentString(a->ExtraInstructionsP, "mode");
  1437. if((!mo) || (mo->Base.Type==TNS_OBJECT_MESH && mo->Mode!=TNS_MESH_EDIT_MODE) ||
  1438. (so->Base.Type==TNS_OBJECT_SHAPE && so->Mode!=TNS_MESH_EDIT_MODE)){ ad->Context=LA_ADD_CTX_OBJECT;
  1439. if(strSame(str,"PLANE")){ tnsDeselectAllObjects(root);
  1440. no=tnsCreateMeshPlane(root, "Plane",0,0,0,1); no->Flags|=TNS_OBJECT_FLAGS_SELECTED; memAssignRef(root,&root->Active,no); ran=1; }
  1441. elif(strSame(str,"INSTANCER")){ tnsDeselectAllObjects(root);
  1442. no=tnsCreateInstancer(root, "Instancer",0,0,0); no->Flags|=TNS_OBJECT_FLAGS_SELECTED; memAssignRef(root,&root->Active,no); ran=1; }
  1443. elif(strSame(str,"SQUARE")){ tnsDeselectAllObjects(root);
  1444. no=tnsCreateShapeSquare(root, "Square",0,0,0,1); no->Flags|=TNS_OBJECT_FLAGS_SELECTED; memAssignRef(root,&root->Active,no); ran=1; }
  1445. else{ laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING; }
  1446. if(ran){ laRecordAndPush(0,"tns.world","Add object",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world"); }
  1447. }elif(mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){ ad->Context=LA_ADD_CTX_MESH;
  1448. if(strSame(str,"PLANE")){
  1449. tnsMMeshDeselectAll(mo); tnsAddMMeshPlane(mo, 1); tnsMMeshEnsureSelection(mo,ex->SelectMode); ran=1;
  1450. }else{ laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING; }
  1451. if(ran){
  1452. tnsMMeshRefreshIndex(mo); tnsInvalidateMeshBatch(mo);
  1453. laRecordInstanceDifferences(mo, "tns_mesh_object"); laPushDifferences("Add primitives", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  1454. }
  1455. }elif(so->Base.Type==TNS_OBJECT_SHAPE && so->Mode==TNS_MESH_EDIT_MODE){ ad->Context=LA_ADD_CTX_SHAPE;
  1456. if(strSame(str,"SQUARE")){
  1457. tnsShapeDeselectAll(so); tnsInitShapeSquare(so,1); ran=1;
  1458. }else{ laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING; }
  1459. if(ran){
  1460. laRecordInstanceDifferences(so, "tns_shape_object"); laPushDifferences("Add shape", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  1461. }
  1462. }
  1463. return LA_FINISHED;
  1464. }
  1465. void laui_Add(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
  1466. laColumn* c=laFirstColumn(uil);
  1467. laUiItem* b=laOnConditionThat(uil,c,laEqual(laPropExpression(actinst,"context"),laIntExpression(LA_ADD_CTX_OBJECT)));{
  1468. laShowLabel(uil,c,"Empty",0,0)->Flags|=LA_TEXT_MONO|LA_UI_FLAGS_DISABLED;
  1469. laShowItemFull(uil,c,pp,"_this_M_add",0,"mode=INSTANCER;text=Instancer",0,0);
  1470. laShowLabel(uil,c,"Primitives",0,0)->Flags|=LA_TEXT_MONO|LA_UI_FLAGS_DISABLED;
  1471. laShowItemFull(uil,c,pp,"_this_M_add",0,"mode=PLANE;text=Plane",0,0);
  1472. laShowLabel(uil,c,"Shapes",0,0)->Flags|=LA_TEXT_MONO|LA_UI_FLAGS_DISABLED;
  1473. laShowItemFull(uil,c,pp,"_this_M_add",0,"mode=SQUARE;text=Square",0,0);
  1474. }laEndCondition(uil,b);
  1475. b=laOnConditionThat(uil,c,laEqual(laPropExpression(actinst,"context"),laIntExpression(LA_ADD_CTX_MESH)));{
  1476. laShowLabel(uil,c,"Primitives",0,0)->Flags|=LA_TEXT_MONO|LA_UI_FLAGS_DISABLED;
  1477. laShowItemFull(uil,c,pp,"_this_M_add",0,"mode=PLANE;text=Plane",0,0);
  1478. }laEndCondition(uil,b);
  1479. b=laOnConditionThat(uil,c,laEqual(laPropExpression(actinst,"context"),laIntExpression(LA_ADD_CTX_SHAPE)));{
  1480. laShowLabel(uil,c,"Shapes",0,0)->Flags|=LA_TEXT_MONO|LA_UI_FLAGS_DISABLED;
  1481. laShowItemFull(uil,c,pp,"_this_M_add",0,"mode=SQUARE;text=Square",0,0);
  1482. }laEndCondition(uil,b);
  1483. }
  1484. int OPINV_Separate(laOperator *a, laEvent *e){
  1485. if(!a->This || !a->This->EndInstance){ return 0; }
  1486. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1487. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return LA_CANCELED;
  1488. tnsMeshObject* mo=root->Active; int ran=0;
  1489. if(mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){
  1490. return LA_CANCELED;
  1491. }
  1492. if(!tnsMMeshAnySelected(mo)) return LA_CANCELED;
  1493. MExtrudeExtra* ee=la_InitExtrude(mo);
  1494. la_ExtrudeMakeDuplication(ee);
  1495. ee->RemoveOriginalFaces=1;la_RemoveOriginalFaces(ee);
  1496. tnsMeshObject* no=tnsCreateMeshEmpty(mo->Base.ParentObject?mo->Base.ParentObject:mo->Base.InRoot, mo->Base.Name->Ptr, 0,0,0);
  1497. tnsCopyObjectTransformationsLocal(no,mo);
  1498. no->Mode=TNS_MESH_EDIT_MODE;
  1499. tnsMVert* nmv; for(tnsMVert* mv=mo->mv.pFirst;mv;mv=nmv){ nmv=mv->Item.pNext; if(!(mv->flags&TNS_MESH_FLAG_SELECTED))continue;
  1500. lstRemoveItem(&mo->mv, mv); lstAppendItem(&no->mv, mv); no->totmv++; mo->totmv--; }
  1501. tnsMEdge* nme; for(tnsMEdge* me=mo->me.pFirst;me;me=nme){ nme=me->Item.pNext; if(!(me->flags&TNS_MESH_FLAG_SELECTED))continue;
  1502. lstRemoveItem(&mo->me, me); lstAppendItem(&no->me, me); no->totme++; mo->totme--; }
  1503. tnsMFace* nmf; for(tnsMFace* mf=mo->mf.pFirst;mf;mf=nmf){ nmf=mf->Item.pNext; if(!(mf->flags&TNS_MESH_FLAG_SELECTED))continue;
  1504. lstRemoveItem(&mo->mf, mf); lstAppendItem(&no->mf, mf); no->totmf++; mo->totmf--; }
  1505. tnsMMeshRefreshIndex(no); tnsMeshLeaveEditMode(no);
  1506. la_FinishExtrude(ee, 0);
  1507. tnsMMeshRefreshIndex(mo); tnsInvalidateMeshBatch(mo);
  1508. laRecordAndPush(0,"tns.world","Separate mesh parts",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  1509. return LA_FINISHED;
  1510. }
  1511. void la_PopulateSelectedObjects(tnsObject* root, laListHandle* l, int FilterType){
  1512. if(root->Flags&TNS_OBJECT_FLAGS_SELECTED){ if(root->Type && ((!FilterType) || root->Type==FilterType)) lstAppendPointer(l,root); }
  1513. for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  1514. la_PopulateSelectedObjects(lip->p, l, FilterType);
  1515. }
  1516. }
  1517. int OPINV_Combine(laOperator *a, laEvent *e){
  1518. if(!a->This || !a->This->EndInstance){ return 0; }
  1519. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1520. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return LA_CANCELED;
  1521. tnsMeshObject* mo=root->Active; int ran=0;
  1522. if(!mo || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode==TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
  1523. laListHandle pending={0}; la_PopulateSelectedObjects(root,&pending,TNS_OBJECT_MESH);
  1524. tnsMeshObject* o; while(o=lstPopPointer(&pending)){ if(o==mo || o->Mode==TNS_MESH_EDIT_MODE) continue;
  1525. if(tnsMergeMeshObjects(mo, o)) ran++;
  1526. }
  1527. if(ran){
  1528. tnsMMeshRefreshIndex(mo); tnsInvalidateMeshBatch(mo);
  1529. laRecordAndPush(0,"tns.world","Merge mesh objects",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  1530. }
  1531. return LA_FINISHED;
  1532. }
  1533. int OPINV_Duplicate(laOperator *a, laEvent *e){
  1534. if(!a->This || !a->This->EndInstance){ return 0; }
  1535. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1536. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return LA_CANCELED;
  1537. tnsMeshObject* mo=root->Active; tnsShapeObject* so=mo; int ran=0;
  1538. if(!mo || (mo->Base.Type==TNS_OBJECT_MESH&&mo->Mode==TNS_MESH_EDIT_MODE)||
  1539. (so->Base.Type==TNS_OBJECT_SHAPE&&so->Mode==TNS_MESH_EDIT_MODE)){ return LA_CANCELED; }
  1540. laListHandle pending={0}; la_PopulateSelectedObjects(root,&pending,0);
  1541. tnsMeshObject* o; tnsMeshObject* no; laListItemPointer* lip;
  1542. for(lip=pending.pFirst;lip;lip=lip->pNext){ o=lip->p; o->Base.EditDuplicateTemp=0; if (o->Mode == TNS_MESH_EDIT_MODE) continue;
  1543. if(o->Base.Type==TNS_OBJECT_MESH) no = tnsDuplicateMeshObject(o);
  1544. elif(o->Base.Type==TNS_OBJECT_SHAPE) no = tnsDuplicateShapeObject(o);
  1545. elif(o->Base.Type==TNS_OBJECT_INSTANCER) no = tnsDuplicateShapeObject(o);
  1546. if(no){ o->Base.EditDuplicateTemp=no;
  1547. no->Base.Flags |= TNS_OBJECT_FLAGS_SELECTED; o->Base.Flags &= (~TNS_OBJECT_FLAGS_SELECTED);
  1548. if (mo == o) { memAssignRef(root, &root->Active, no); } ran++;
  1549. }
  1550. }
  1551. for (lip = pending.pFirst;lip;lip=lip->pNext){ o=lip->p; no = o->Base.EditDuplicateTemp;
  1552. tnsObject* NewParent=o->Base.ParentObject?o->Base.ParentObject->EditDuplicateTemp:0;
  1553. if(NewParent){ tnsUnparentObject(no,1); tnsParentObject(no,NewParent,1); }
  1554. }
  1555. while(o=lstPopPointer(&pending)){ o->Base.EditDuplicateTemp=0; }
  1556. if(ran){
  1557. laRecordAndPush(0,"tns.world","Duplicated objects",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  1558. if(la_InitTransform(a,e,LA_TRANSFORM_MODE_GRAB,0,0)) return LA_RUNNING; return LA_FINISHED;
  1559. }
  1560. return LA_FINISHED;
  1561. }
  1562. int OPINV_RecalculateNormals(laOperator *a, laEvent *e){
  1563. if(!a->This || !a->This->EndInstance){ return 0; }
  1564. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1565. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return LA_CANCELED;
  1566. tnsMeshObject* mo=root->Active; int ran=0;
  1567. if(!mo || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
  1568. ran=tnsMMeshCalculateNormal(mo);
  1569. if(ran){ tnsInvalidateMeshBatch(mo); laRecordAndPush(0,"tns.world","Recalculate Normals",TNS_HINT_GEOMETRY); laNotifyUsers("tns.world"); }
  1570. return LA_FINISHED;
  1571. }
  1572. STRUCTURE(MKnifeElement){
  1573. laListItem Item;
  1574. void* p;
  1575. int Type;
  1576. };
  1577. void la_KnifeUpdateToolBatch(MSelectExtra* se,tnsMeshObject* o){
  1578. if(o->ExtraBatch) tnsDeleteBatch(o->ExtraBatch); o->ExtraBatch=0;
  1579. int count=lstCountElements(&se->KnifeElements); if((!count) && (!se->PendingElem)) return;
  1580. float* points=calloc((count+1)*3,sizeof(real));
  1581. float* p=points; real tmp[3],trans[4];
  1582. for(MKnifeElement* ke=se->KnifeElements.pFirst;ke;ke=ke->Item.pNext){
  1583. if(ke->Type==TNS_MMESH_EDGE_BIT){ tnsMEdge* me=ke->p; tnsVectorSet3v(tmp,me->vl->p); tnsVectorAccum3d(tmp,me->vr->p);
  1584. tnsVectorMultiSelf3d(tmp,0.5); tnsVectorSet3v(p,tmp); }
  1585. else{ tnsMVert* mv=ke->p; tnsVectorSet3v(p,mv->p); }
  1586. p+=3;
  1587. }
  1588. if(se->PendingElem){
  1589. if(se->PendingElemType==TNS_MMESH_EDGE_BIT){ tnsMEdge* me=se->PendingElem; tnsVectorSet3v(tmp,me->vl->p); tnsVectorAccum3d(tmp,me->vr->p);
  1590. tnsVectorMultiSelf3d(tmp,0.5); tnsVectorSet3v(p,trans); }
  1591. else{ tnsMVert* mv=se->PendingElem; tnsVectorSet3v(p,mv->p); }
  1592. }elif(count){
  1593. tnsVectorSet3v(p,p-3);
  1594. }
  1595. uint32_t elem=count;
  1596. tnsBatch* batch=tnsCreateBatch(count+1,3,points,0,0,0,0); tnsBatchCommand*c;
  1597. c=tnsCreateCommand(batch, "hovering_point", 1, 3, GL_POINTS, &elem, 0);
  1598. tnsCommandUseUniformColor(c,laAccentColor(LA_BT_SVERTEX));
  1599. tnsCommandUseWidth(c, 8);
  1600. if(count){
  1601. c=tnsCreateCommand(batch, "edges", count+(se->IsLoop?0:1), 3, se->IsLoop?GL_LINE_LOOP:GL_LINE_STRIP, 0, 0);
  1602. tnsCommandUseUniformColor(c,laAccentColor(LA_BT_NORMAL));
  1603. tnsCommandUseWidth(c, 2);
  1604. c=tnsCreateCommand(batch, "points", count, 3, GL_POINTS, 0, 0);
  1605. tnsCommandUseUniformColor(c,laAccentColor(LA_BT_NORMAL));
  1606. tnsCommandUseWidth(c, 6);
  1607. }
  1608. o->ExtraBatch=batch;
  1609. free(points);
  1610. }
  1611. int la_KnifeIsDuplicated(MSelectExtra* se, void* ref){
  1612. for(MKnifeElement* ke=se->KnifeElements.pFirst;ke;ke=ke->Item.pNext){
  1613. if(ke->Type==TNS_MMESH_EDGE_BIT && ke->p==ref){ return 1; }
  1614. }
  1615. return 0;
  1616. }
  1617. void la_KnifeAppendCut(MSelectExtra* se){
  1618. MKnifeElement* ke=lstAppendPointerSized(&se->KnifeElements,se->PendingElem,sizeof(MKnifeElement));
  1619. ke->Type=se->PendingElemType;
  1620. }
  1621. int la_KnifeRegisterCuts(MSelectExtra* se, tnsMeshObject* mo, int TryClose){
  1622. if(!mo || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE) return 0;
  1623. if(!se->KnifeElements.pFirst) return 0;
  1624. tnsMVert* lastv=0,*newv=0,*firstv=0; tnsMEdge* newme=0; int changed=0; tnsMFace* mf=0;
  1625. for(MKnifeElement* ke=se->KnifeElements.pFirst;ke;ke=ke->Item.pNext){
  1626. if(ke->Type==TNS_MMESH_EDGE_BIT){
  1627. newv=tnsMMeshEdgeInsertVertAt(mo,ke->p,0.5,0,0,0); changed=1;
  1628. }
  1629. else{ newv=ke->p; }
  1630. if(lastv){ if(tnsMMeshVertsShareFace(lastv,newv)) newme=tnsMMeshMakeEdge(mo, lastv, newv); changed=1; }
  1631. lastv=newv; if(!firstv) firstv=newv; newv->flags|=TNS_MESH_FLAG_SELECTED;
  1632. if(newme){ newme->flags|=TNS_MESH_FLAG_SELECTED; }
  1633. }
  1634. if(TryClose){ if((mf=tnsMMeshVertsShareFace(lastv,firstv))&&mf->looplen==6) newme=tnsMMeshMakeEdge(mo, lastv, firstv); changed=1; }
  1635. if(changed){ tnsMMeshRefreshIndex(mo); tnsMMeshCalculateNormal(mo); }
  1636. return changed;
  1637. }
  1638. void la_KnifeFinish(MSelectExtra* se, tnsMeshObject*o){
  1639. if(o->ExtraBatch) tnsDeleteBatch(o->ExtraBatch); o->ExtraBatch=0;
  1640. while(lstPopPointer(&se->KnifeElements));
  1641. la_FreeSelectData(se->sd); memFree(se);
  1642. }
  1643. void la_KnifeRefreshLoopCuts(MSelectExtra* se, tnsObject* o,tnsMEdge* me){
  1644. if(!me) return;
  1645. tnsMMeshClearExtraFlags(o);
  1646. laListHandle lst={0}; lstAppendPointer(&lst,me); me->flags|=TNS_MESH_FLAG_PICKED;
  1647. tnsMMeshExpandBandList(o, me, &lst);
  1648. if(lst.pFirst==lst.pLast){ while(lstPopPointer(&lst)); return; }
  1649. tnsMEdge* mme; while((mme=lstPopPointer(&lst))){
  1650. MKnifeElement* ke=lstAppendPointerSized(&se->KnifeElements,mme,sizeof(MKnifeElement));
  1651. ke->Type=TNS_MMESH_EDGE_BIT;
  1652. }
  1653. }
  1654. void la_KnifeSortLoopCuts(MSelectExtra* se){
  1655. laListHandle lst={0};MKnifeElement* ke=se->KnifeElements.pFirst,*NextKe;
  1656. if(!ke) return;
  1657. lstRemoveItem(&se->KnifeElements,ke); lstAppendItem(&lst,ke);
  1658. for(ke=se->KnifeElements.pFirst;ke;ke=NextKe){
  1659. NextKe=ke->Item.pNext; tnsMEdge* me=ke->p,*firste=((MKnifeElement*)lst.pFirst)->p,*laste=((MKnifeElement*)lst.pLast)->p;
  1660. if(tnsMMeshEdgeShareFace(me,firste) && (!tnsMMeshEdgeShareVert(me,firste))){
  1661. lstRemoveItem(&se->KnifeElements,ke); lstPushItem(&lst,ke); ke=se->KnifeElements.pFirst; continue; }
  1662. if(tnsMMeshEdgeShareFace(me,laste) && (!tnsMMeshEdgeShareVert(me,laste))){
  1663. lstRemoveItem(&se->KnifeElements,ke); lstAppendItem(&lst,ke); ke=se->KnifeElements.pFirst; continue; }
  1664. }
  1665. if(se->KnifeElements.pFirst){ /* something went wrong */ while(lstPopPointer(&se->KnifeElements)); while(lstPopPointer(&lst)); }
  1666. se->KnifeElements.pFirst=lst.pFirst; se->KnifeElements.pLast=lst.pLast;
  1667. }
  1668. int OPINV_Knife(laOperator *a, laEvent *e){
  1669. if(!a->This || !a->This->EndInstance){ return 0; }
  1670. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1671. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return LA_CANCELED;
  1672. tnsMeshObject* mo=root->Active; int ran=0;
  1673. if(!mo || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
  1674. MSelectExtra* se=memAcquire(sizeof(MSelectExtra));
  1675. MSelectData* sd=la_InitSelectData(ex->OffScr->pColor[0]->Width, ex->OffScr->pColor[0]->Height, c);
  1676. a->CustomData=se; se->sd=sd; se->root=root;
  1677. int SelectMode=LA_CANVAS_SELECT_MODE_KNIFE;
  1678. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "loop_cut")){
  1679. se->IsLoop=1; SelectMode=LA_CANVAS_SELECT_MODE_EDGES; }
  1680. la_PopulateSelectDataPrimitives(sd,mo,c,SelectMode,root,ex);
  1681. if(se->IsLoop){ strSafePrint(&a->RuntimeHint,"◧ Cut ◨ Cancel"); }
  1682. else{ strSafePrint(&a->RuntimeHint,"◧ Place Cut ◨ Cancel ⮨ Confirm"); }
  1683. return LA_RUNNING;
  1684. }
  1685. int OPMOD_Knife(laOperator *a, laEvent *e){
  1686. if(!a->This || !a->This->EndInstance || !a->CustomData){ return 0; }
  1687. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1688. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  1689. MSelectExtra* se=a->CustomData;
  1690. tnsMeshObject* mo=root->Active;
  1691. int changed=0;
  1692. if(e->Type==LA_R_MOUSE_DOWN || (e->Type == LA_KEY_DOWN && e->key==LA_KEY_ESCAPE)){
  1693. la_KnifeFinish(se,mo); laNotifyUsers("tns.world"); return LA_FINISHED;
  1694. }
  1695. if(e->Type&LA_MOUSE_EVENT){
  1696. int elemtype,id=la_SelectGetClosest(se->sd, e->x-ui->L, e->y-ui->U, LA_RH,&elemtype)-1;
  1697. void* p=la_SelectGetRef(se->sd,id,elemtype);
  1698. if(se->IsLoop){
  1699. if(se->PendingElem!=p){ changed=1; while(lstPopPointer(&se->KnifeElements));
  1700. se->PendingElem=p; la_KnifeRefreshLoopCuts(se, mo, se->PendingElem);
  1701. la_KnifeSortLoopCuts(se);
  1702. }
  1703. }else{
  1704. if(la_KnifeIsDuplicated(se,p)) p=0;
  1705. if(se->PendingElem!=p){ changed=1; }
  1706. se->PendingElem=p; se->PendingElemType=elemtype;
  1707. if(e->Type==LA_L_MOUSE_DOWN && p){ la_KnifeAppendCut(se); changed=1; }
  1708. }
  1709. }
  1710. if((e->Type==LA_KEY_DOWN && e->key==LA_KEY_ENTER) || (se->IsLoop && e->Type==LA_L_MOUSE_DOWN)){
  1711. if(la_KnifeRegisterCuts(se,mo,se->IsLoop)){ tnsMMeshEnsureSelection(mo,ex->SelectMode);
  1712. tnsInvalidateMeshBatch(mo); laNotifyUsers("tns.world");
  1713. laRecordAndPush(0,"tns.world",se->IsLoop?"Loop Cut":"Knife Cut",TNS_HINT_GEOMETRY);
  1714. }
  1715. la_KnifeFinish(se,mo); return LA_FINISHED;
  1716. }
  1717. if(changed){
  1718. la_KnifeUpdateToolBatch(se,mo); laRedrawCurrentPanel();
  1719. }
  1720. return LA_RUNNING;
  1721. }
  1722. #define LA_MERGE_MODE_CENTER 0
  1723. #define LA_MERGE_MODE_FIRST 1
  1724. #define LA_MERGE_MODE_LAST 2
  1725. int la_MergeGetCenter(tnsMeshObject* mo, int SelectMode, int MergeMode, real* center){
  1726. real pos[3]={0},tmp[3]={0}; int count=0;
  1727. tnsMVert* usev=0; tnsMEdge* usee=0;
  1728. if(MergeMode!=LA_MERGE_MODE_CENTER){
  1729. if(MergeMode==LA_MERGE_MODE_FIRST){ usev=mo->FirstSelectV; usee=mo->FirstSelectE; }
  1730. elif(MergeMode==LA_MERGE_MODE_LAST){ usev=mo->LastSelectV; usee=mo->LastSelectE; }
  1731. if(SelectMode==LA_CANVAS_SELECT_MODE_VERTS && usev){ tnsVectorCopy3d(usev->p,center); return 1; }
  1732. elif(SelectMode==LA_CANVAS_SELECT_MODE_EDGES && usee){
  1733. tnsVectorAccum3d(pos,usee->vl->p);tnsVectorAccum3d(pos,usee->vr->p);
  1734. tnsVectorMultiSelf3d(pos,0.5f); tnsVectorCopy3d(pos,center); return 1;
  1735. }
  1736. }
  1737. for(tnsMVert* mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){ if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  1738. tnsVectorAccum3d(pos,mv->p); count++;
  1739. }
  1740. if(!count) return 0;
  1741. tnsVectorMultiSelf3d(pos,1.0f/count); tnsVectorCopy3d(pos,center);
  1742. return 1;
  1743. }
  1744. void la_MergeSelected(tnsMeshObject* mo, real* center, int* count_success, int* count_fail){
  1745. tnsMVert* fmv=0,*NextMv=0; int success=0,fail=0,has_success=0;
  1746. do{ fail=0; has_success=0;
  1747. for(tnsMVert* mv=mo->mv.pFirst;mv;mv=NextMv){ NextMv=mv->Item.pNext;
  1748. if((!(mv->flags&TNS_MESH_FLAG_SELECTED))||mv==fmv) continue; if(!fmv){ fmv=mv; success++; continue; }
  1749. if(tnsMMeshMergeVerts(mo,fmv,mv)){ success++; has_success=1; }else{ fail++; }
  1750. }
  1751. }while(has_success&&fail);
  1752. if(count_success){ *count_success=success; } if(count_fail){ *count_fail=fail; }
  1753. if(!fmv) return; tnsVectorCopy3d(center,fmv->p);
  1754. tnsMMeshRefreshIndex(mo);
  1755. }
  1756. int OPINV_Merge(laOperator *a, laEvent *e){
  1757. if(!a->This || !a->This->EndInstance){ return 0; }
  1758. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  1759. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return LA_CANCELED;
  1760. tnsMeshObject* mo=root->Active; int ran=0;
  1761. if(!mo || mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){ return LA_CANCELED; }
  1762. char* arg=strGetArgumentString(a->ExtraInstructionsP, "towards");
  1763. if(arg){
  1764. int MergeMode=LA_MERGE_MODE_CENTER; real center[3];
  1765. if(strSame(arg,"FIRST")){ MergeMode=LA_MERGE_MODE_FIRST; }
  1766. elif(strSame(arg,"LAST")){ MergeMode=LA_MERGE_MODE_LAST; }
  1767. if(!(la_MergeGetCenter(mo,ex->SelectMode,MergeMode,center))){
  1768. laEnableMessagePanel(a, 0, "Can't perform merging:", "No vertices selected.", e->x, e->y, 0, e);
  1769. return LA_FINISHED;
  1770. }
  1771. int success,fail;
  1772. la_MergeSelected(mo,center,&success,&fail); //printf("succeeded: %d failed:%d\n",success,fail);
  1773. if(fail){
  1774. char* msg[256]; sprintf(msg,"Succeeded: %d vertices, failed: %d vertices.",success,fail);
  1775. laEnableMessagePanel(a, 0, "Merging partially succeeded.", msg, e->x, e->y, 0, e);
  1776. }
  1777. if(success){
  1778. tnsMMeshEnsureSelection(mo,ex->SelectMode); tnsInvalidateMeshBatch(mo); laNotifyUsers("tns.world");
  1779. laRecordAndPush(0,"tns.world","Merge vertices",TNS_HINT_GEOMETRY);
  1780. }
  1781. }else{
  1782. laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING;
  1783. }
  1784. return LA_FINISHED;
  1785. }
  1786. void laui_Merge(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
  1787. laColumn* c=laFirstColumn(uil);
  1788. laShowItemFull(uil,c,pp,"_this_M_merge",0,"towards=CENTER;text=Center",0,0);
  1789. laShowItemFull(uil,c,pp,"_this_M_merge",0,"towards=FIRST;text=First",0,0);
  1790. laShowItemFull(uil,c,pp,"_this_M_merge",0,"towards=LAST;text=Last",0,0);
  1791. }
  1792. int OPINV_NewRootObject(laOperator *a, laEvent *e){
  1793. int use_2d=0;
  1794. if(strSame(strGetArgumentString(&a->ExtraInstructionsP,"type"),"2d")){ use_2d=1; }
  1795. tnsCreateRootObject("Root", use_2d); laNotifyUsers("tns.world.root_objects"); laNotifyUsers("tns.world.active_root");
  1796. laRecordDifferences(0,"tns.world"); laPushDifferences("New root object",0);
  1797. return LA_FINISHED;
  1798. }
  1799. int OPCHK_RemoveRootObjects(laPropPack *This, laStringSplitor *ss){
  1800. if(This && This->EndInstance){
  1801. if(la_EnsureSubTarget(This->LastPs->p,0)!=TNS_PC_OBJECT_ROOT) return 0;
  1802. if(((tnsObject*)This->EndInstance)->Type!=TNS_OBJECT_ROOT) return 0;
  1803. }else{ if(!T->World->ActiveRoot) return 0; }
  1804. return 1;
  1805. }
  1806. int OPINV_RemoveRootObject(laOperator *a, laEvent *e){
  1807. tnsObject* root=0;
  1808. if(a->This && a->This->EndInstance){ root=a->This->EndInstance; }
  1809. else{ root=T->World->ActiveRoot; }
  1810. laNotifyDetached(root,root->Item.pNext?root->Item.pNext:root->Item.pPrev);
  1811. tnsDestroyRootObject(root);
  1812. laNotifyUsers("tns.world.root_objects"); laNotifyUsers("tns.world.active_root");
  1813. laRecordDifferences(0,"tns.world"); laPushDifferences("Removed root object",0);
  1814. return LA_FINISHED;
  1815. }
  1816. int OPINV_NewMaterial(laOperator *a, laEvent *e){
  1817. tnsMaterial* mat=tnsCreateMaterial("Material"); laNotifyUsers("tns.world.materials");
  1818. if(!a->This && a->This->EndInstance) return LA_CANCELED;
  1819. laPropContainer* pc=la_EnsureSubTarget(a->This->LastPs->p,a->This->EndInstance);
  1820. if(pc==TNS_PC_OBJECT_MESH){
  1821. tnsMeshObject* mo=a->This->EndInstance; if(mo->CurrentMaterial){
  1822. memAssignRef(mo->CurrentMaterial,&mo->CurrentMaterial->Material,mat);
  1823. tnsInvalidateMeshBatch(mo);
  1824. laRecordInstanceDifferences(mo,"tns_mesh_object"); laNotifyInstanceUsers(mo);
  1825. }
  1826. }elif(pc==TNS_PC_OBJECT_SHAPE){
  1827. tnsShapeObject* so=a->This->EndInstance; if(so->CurrentMaterial){
  1828. memAssignRef(so->CurrentMaterial,&so->CurrentMaterial->Material,mat);
  1829. tnsInvalidateMeshBatch(so);
  1830. laRecordInstanceDifferences(so,"tns_shape_object"); laNotifyInstanceUsers(so);
  1831. }
  1832. }
  1833. laDetachedTrySet("material",mat);
  1834. laRecordDifferences(0,"tns.world.materials"); laPushDifferences("New material",0);
  1835. return LA_FINISHED;
  1836. }
  1837. int OPCHK_RemoveMaterial(laPropPack *This, laStringSplitor *ss){
  1838. if(This && This->EndInstance){ if(la_EnsureSubTarget(This->LastPs->p,0)==TNS_PC_MATERIAL) return 1; }
  1839. return 0;
  1840. }
  1841. int OPINV_RemoveMaterial(laOperator *a, laEvent *e){
  1842. if(!a->This || !a->This->EndInstance){ return LA_FINISHED; }
  1843. tnsMaterial* mat=a->This->EndInstance;
  1844. laNotifyDetached(mat,mat->Item.pNext?mat->Item.pNext:mat->Item.pPrev);
  1845. tnsRemoveMaterial(mat); laNotifyUsers("tns.world");
  1846. laRecordDifferences(0,"tns.world"); laPushDifferences("Removed material",0);
  1847. return LA_FINISHED;
  1848. }
  1849. int OPCHK_NewMaterialSlot(laPropPack *This, laStringSplitor *ss){
  1850. if(This && This->EndInstance){ laPropContainer* pc=la_EnsureSubTarget(This->LastPs->p,This->EndInstance);
  1851. if(pc==TNS_PC_OBJECT_MESH||pc==TNS_PC_OBJECT_SHAPE) return 1;
  1852. } return 0;
  1853. }
  1854. int OPINV_NewMaterialSlot(laOperator *a, laEvent *e){
  1855. if(!a->This || !a->This->EndInstance){ return LA_FINISHED; } tnsObject* o=a->This->EndInstance;
  1856. tnsNewMaterialSlot(o); laNotifyInstanceUsers(o);
  1857. laRecordDifferences(0,"tns.world.objects"); laPushDifferences("New material slot",0);
  1858. return LA_FINISHED;
  1859. }
  1860. int OPCHK_RemoveMaterialSlot(laPropPack *This, laStringSplitor *ss){
  1861. if(This && This->EndInstance){ if(la_EnsureSubTarget(This->LastPs->p,0)==TNS_PC_MATERIAL_SLOT) return 1; } return 0;
  1862. }
  1863. int OPINV_RemoveMaterialSlot(laOperator *a, laEvent *e){
  1864. if(!a->This || !a->This->EndInstance){ return LA_FINISHED; } tnsMaterialSlot* ms=a->This->EndInstance;
  1865. laNotifyInstanceUsers(ms->Parent); tnsRemoveMaterialSlot(ms->Parent,ms);
  1866. laRecordDifferences(0,"tns.world.objects"); laPushDifferences("Remove material slot",0);
  1867. return LA_FINISHED;
  1868. }
  1869. int OPCHK_AssignMaterialSlot(laPropPack *This, laStringSplitor *ss){
  1870. if(This && This->EndInstance){ laPropContainer* pc=la_EnsureSubTarget(This->LastPs->p,This->EndInstance);
  1871. if(pc==TNS_PC_OBJECT_MESH){
  1872. tnsMeshObject* mo=This->EndInstance; if(mo->Mode==TNS_MESH_EDIT_MODE && mo->CurrentMaterial) return 1;
  1873. }elif(pc==TNS_PC_OBJECT_SHAPE){
  1874. tnsShapeObject* so=This->EndInstance; if(so->Mode==TNS_MESH_EDIT_MODE && so->CurrentMaterial) return 1;
  1875. }
  1876. } return 0;
  1877. }
  1878. int OPINV_AssignMaterialSlot(laOperator *a, laEvent *e){
  1879. if(!a->This || !a->This->EndInstance){ return LA_FINISHED; } tnsObject* o=a->This->EndInstance;
  1880. laPropContainer* pc=la_EnsureSubTarget(a->This->LastPs->p,a->This->EndInstance);
  1881. if(pc==TNS_PC_OBJECT_MESH){ tnsMeshObject* mo=o;
  1882. tnsMaterialSlot* ms=mo->CurrentMaterial;
  1883. if(mo->Mode!=TNS_MESH_EDIT_MODE || !ms) return LA_FINISHED;
  1884. tnsAssignMaterialSlot(mo,ms); tnsInvalidateMeshBatch(mo); laRecordInstanceDifferences(mo,"tns_mesh_object");
  1885. }elif(pc==TNS_PC_OBJECT_SHAPE){ tnsShapeObject* so=o;
  1886. tnsMaterialSlot* ms=so->CurrentMaterial;
  1887. if(so->Mode!=TNS_MESH_EDIT_MODE || !ms) return LA_FINISHED;
  1888. tnsAssignMaterialSlot(so,ms); laRecordInstanceDifferences(so,"tns_shape_object");
  1889. }
  1890. laNotifyInstanceUsers(o); laNotifyUsers("tns.world");
  1891. laPushDifferences("Assign material slot",0);
  1892. return LA_FINISHED;
  1893. }
  1894. int OPCHK_RefreshMaterialShader(laPropPack *This, laStringSplitor *ss){
  1895. if(This && This->EndInstance){
  1896. if(la_EnsureSubTarget(This->LastPs->p,This->EndInstance)==TNS_PC_MATERIAL){ return 1; }
  1897. } return 0;
  1898. }
  1899. int OPINV_RefreshMaterialShader(laOperator *a, laEvent *e){
  1900. if(!a->This || !a->This->EndInstance){ return LA_FINISHED; }
  1901. tnsMaterial* m=a->This->EndInstance;
  1902. if(m->AsLibrary){ tnsRefreshMaterialLibraries(); return LA_FINISHED; }
  1903. tnsEnsureMaterialShader(m,1); tns_InvalidateMeshWithMaterial(m); laNotifyUsers("tns.world");
  1904. return LA_FINISHED;
  1905. }
  1906. void la_RegisterModellingOperators(){
  1907. laPropContainer *pc; laProp *p;
  1908. laOperatorType *at; laEnumProp *ep;
  1909. laCreateOperatorType("M_new_root", "New Root", "Create a new root object", 0, 0, 0, OPINV_NewRootObject, 0, '+', 0);
  1910. laCreateOperatorType("M_remove_root", "Remove Root", "Remove root object", OPCHK_RemoveRootObjects, 0, 0, OPINV_RemoveRootObject, 0 ,L'🗴', 0);
  1911. laCreateOperatorType("M_new_material", "New Material", "Create a new material", 0, 0, 0, OPINV_NewMaterial, 0, '+', 0);
  1912. laCreateOperatorType("M_remove_material", "Remove Material", "Remove a material", OPCHK_RemoveMaterial, 0, 0, OPINV_RemoveMaterial, 0 ,L'🗴', 0);
  1913. laCreateOperatorType("M_new_material_slot", "New Material Slot", "Create a new material slot", OPCHK_NewMaterialSlot, 0, 0, OPINV_NewMaterialSlot, 0, '+', 0);
  1914. laCreateOperatorType("M_remove_material_slot", "Remove Material Slot", "Remove a material slot", OPCHK_RemoveMaterialSlot, 0, 0, OPINV_RemoveMaterialSlot, 0 ,L'🗴', 0);
  1915. laCreateOperatorType("M_assign_material_slot", "Assign Material Slot", "Assign faces to a material slot", OPCHK_AssignMaterialSlot, 0, 0, OPINV_AssignMaterialSlot, 0 ,L'🖌', 0);
  1916. laCreateOperatorType("M_refresh_material_shader", "Refresh Material Shader", "Refresh material shader", OPCHK_RefreshMaterialShader, 0, 0, OPINV_RefreshMaterialShader, 0 ,L'🗘', 0);
  1917. laCreateOperatorType("M_set_cursor", "Set Cursor", "Set cursor in the viewport", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_SetCursor, 0, 0, LA_EXTRA_TO_PANEL);
  1918. laCreateOperatorType("M_toggle_edit_mode", "Toggle Edit Mode", "Toggle edit mode of the active object", OPCHK_ThereIsActiveObject, 0, 0, OPINV_ToggleEdit, 0, 0, 0);
  1919. laCreateOperatorType("M_select", "Select", "Select things in the viewport", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Select, OPMOD_Select, 0, LA_EXTRA_TO_PANEL);
  1920. laCreateOperatorType("M_grab", "Grab", "Grab things and move around", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Grab, OPMOD_Transformation, 0, LA_EXTRA_TO_PANEL);
  1921. laCreateOperatorType("M_scale", "Scale", "Scale selected things", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Scale, OPMOD_Transformation, 0, LA_EXTRA_TO_PANEL);
  1922. laCreateOperatorType("M_rotate", "Rotate", "Rotation selected things", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Rotate, OPMOD_Transformation, 0, LA_EXTRA_TO_PANEL);
  1923. at=laCreateOperatorType("M_clear_transformations", "Clear Transformations", "Clear object transformations", 0, 0, 0, OPINV_ClearTransformation, OPMOD_FinishOnData, 0, 0);
  1924. at->UiDefine=laui_ClearTransformation;
  1925. 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);
  1926. at->UiDefine = laui_MakeParent;
  1927. at=laCreateOperatorType("M_unparent", "Unparent", "Unparent selected objects", 0, 0, 0, OPINV_MakeParent, OPMOD_FinishOnData, 0, 0);
  1928. at->UiDefine = laui_Unparent;
  1929. laCreateOperatorType("M_extrude", "Extrude", "Extrude parts of the mesh", 0, 0, 0, OPINV_Extrude, OPMOD_Transformation, 0, 0);
  1930. at=laCreateOperatorType("M_delete", "Delete", "Delete parts of the mesh", 0, 0, OPEXT_FreeUserData, OPINV_Delete, OPMOD_FinishOnData, 0, 0);
  1931. pc = laDefineOperatorProps(at, 1);
  1932. laAddIntProperty(pc,"context","Context","Delete menu context",0,0,0,0,0,0,0,0,offsetof(MDeleteData,Context),0,0,0,0,0,0,0,0,0,0,0);
  1933. at->UiDefine=laui_Delete;
  1934. laCreateOperatorType("M_make", "Make", "Make mesh primitive from selected ones", 0, 0, 0, OPINV_Make, 0, 0, 0);
  1935. laCreateOperatorType("M_subdiv", "Subdiv", "Subdivide edges", 0, 0, 0, OPINV_Subdiv, 0, 0, 0);
  1936. at=laCreateOperatorType("M_add", "Add", "Add mesh or primitives", 0, 0, OPEXT_FreeUserData, OPINV_Add, OPMOD_FinishOnData, 0, 0);
  1937. at->UiDefine=laui_Add; pc = laDefineOperatorProps(at, 1);
  1938. p=laAddEnumProperty(pc,"context","Context","Context of adding",0,0,0,0,0,offsetof(laObjectAddData,Context),0,0,0,0,0,0,0,0,0,0);
  1939. laAddEnumItemAs(p,"OBJECT","Object","Object context",LA_ADD_CTX_OBJECT,0);
  1940. laAddEnumItemAs(p,"MESH","Mesh","Mesh context",LA_ADD_CTX_MESH,0);
  1941. laAddEnumItemAs(p,"SHAPE","Shape","Shape context",LA_ADD_CTX_SHAPE,0);
  1942. laCreateOperatorType("M_select_linked", "Select Linked", "Select linked geometry or shapes", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_SelectLinked, 0, 0, LA_EXTRA_TO_PANEL);
  1943. laCreateOperatorType("M_separate", "Separate", "Separate mesh parts", 0, 0, 0, OPINV_Separate, 0, 0, 0);
  1944. laCreateOperatorType("M_combine", "Combine", "Combine mesh objects", 0, 0, 0, OPINV_Combine, 0, 0, 0);
  1945. laCreateOperatorType("M_duplicate", "Duplicate", "Duplicate objects", 0, 0, 0, OPINV_Duplicate, OPMOD_Transformation, 0, 0);
  1946. laCreateOperatorType("M_recalculate_normals", "Recalculate Normals", "Recalculate normals", 0, 0, 0, OPINV_RecalculateNormals, 0, 0, 0);
  1947. laCreateOperatorType("M_knife", "Knife", "Cut through edges", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Knife, OPMOD_Knife, 0, LA_EXTRA_TO_PANEL);
  1948. at=laCreateOperatorType("M_merge", "Merge", "Merge vertices", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Merge, OPMOD_FinishOnData, 0, LA_EXTRA_TO_PANEL);
  1949. at->UiDefine=laui_Merge;
  1950. }