*/}}

la_modelling.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944
  1. #include "../la_5.h"
  2. extern LA MAIN;
  3. extern struct _tnsMain *T;
  4. int OPCHK_ThereIsActiveObject(laPropPack *This, laStringSplitor *ss){
  5. if(!This || !This->EndInstance){ return 0; }
  6. laCanvasExtra* ex=This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  7. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  8. tnsMeshObject* mo=root->Active; if(!mo) return 0; return 1;
  9. }
  10. int OPINV_ToggleEdit(laOperator *a, laEvent *e){
  11. if(!a->This || !a->This->EndInstance){ return 0; }
  12. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  13. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  14. tnsMeshObject* mo=root->Active; if(!mo) return 0;
  15. if(mo->Base.Type!=TNS_OBJECT_MESH) return LA_CANCELED;
  16. if(mo->Mode==TNS_MESH_EDIT_MODE) tnsMeshLeaveEditMode(mo); else tnsMeshEnterEditMode(mo);
  17. laRecordInstanceDifferences(mo, "tns_mesh_object"); laPushDifferences("Toggle edit mode", TNS_HINT_GEOMETRY);
  18. laNotifyUsers("tns.world");
  19. return LA_FINISHED_PASS;
  20. }
  21. STRUCTURE(MSelectData){
  22. tnsOffscreen* FBO;
  23. tnsTexture* Color;
  24. void** Refs; int next,max;
  25. };
  26. MSelectData* la_InitSelectData(int w, int h, tnsCamera* camera){
  27. MSelectData* sd=memAcquireSimple(sizeof(MSelectData));
  28. if (!sd->FBO || sd->FBO->pColor[0]->Height != h || sd->FBO->pColor[0]->Width != w){
  29. if (sd->FBO) tnsDelete2DOffscreen(sd->FBO);
  30. sd->FBO = tnsCreate2DOffscreen(GL_RGB, w, h, 0, 1); sd->Color=sd->FBO->pColor[0];
  31. }
  32. tnsDrawToOffscreen(sd->FBO, 1, 0);
  33. return sd;
  34. }
  35. void la_AssignObjectSelectIDRecursive(tnsObject* root, MSelectData* sd){
  36. for(laListItemPointer*lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  37. tnsObject* o=lip->p; if(!o) continue;
  38. arrEnsureLength(&sd->Refs, sd->next, &sd->max, sizeof(tnsObject*));
  39. sd->Refs[sd->next]=o; o->SelectID=sd->next; sd->next++;
  40. if(o->ChildObjects.pFirst){ la_AssignObjectSelectIDRecursive(o,sd); }
  41. }
  42. }
  43. void la_PopulateSelectDataObjects(MSelectData* sd, tnsObject* root, tnsCamera* camera){
  44. arrEnsureLength(&sd->Refs,0,&sd->max,sizeof(tnsObject*));
  45. sd->next++; // starting from 1;
  46. la_AssignObjectSelectIDRecursive(root, sd);
  47. if(sd->next==1) return; int w=sd->Color->Width, h=sd->Color->Height;
  48. tnsUnbindTexture(); tnsUniformUseTexture(T->immShader,0,0); tnsUseMultiplyColor(0);
  49. tnsEnableShaderv(T->SelectionShader);
  50. glDisableVertexAttribArray(T->SelectionShader->iColor); glVertexAttrib4f(T->SelectionShader->iColor,0,0,0,0);
  51. tnsViewportWithScissor(0,0,w,h);tnsResetViewMatrix();tnsResetModelMatrix();tnsResetProjectionMatrix();
  52. tnsApplyCameraView(w,h,camera);
  53. glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  54. glEnable(GL_DEPTH_TEST);
  55. tnsDrawObjectTree(root,0,0,0);
  56. glDisable(GL_DEPTH_TEST);
  57. }
  58. void la_PopulateSelectVerts(MSelectData* sd, tnsMeshObject* mo){
  59. arrEnsureLength(&sd->Refs,0,&sd->max,sizeof(tnsMVert*));
  60. if(mo->Base.Type!=TNS_OBJECT_MESH||!mo->mv.pFirst){ return; }
  61. for(tnsMVert* v=mo->mv.pFirst;v;v=v->Item.pNext){
  62. arrEnsureLength(&sd->Refs, v->i, &sd->max, sizeof(tnsObject*));
  63. sd->Refs[v->i]=v; sd->next=TNS_MAX2(v->i, sd->next);
  64. }
  65. sd->next++;
  66. }
  67. void la_PopulateSelectEdges(MSelectData* sd, tnsMeshObject* mo){
  68. arrEnsureLength(&sd->Refs,0,&sd->max,sizeof(tnsMEdge*));
  69. if(mo->Base.Type!=TNS_OBJECT_MESH||!mo->mv.pFirst){ return; }
  70. for(tnsMEdge* e=mo->me.pFirst;e;e=e->Item.pNext){
  71. arrEnsureLength(&sd->Refs, e->i, &sd->max, sizeof(tnsObject*));
  72. sd->Refs[e->i]=e; sd->next=TNS_MAX2(e->i, sd->next);
  73. }
  74. sd->next++;
  75. }
  76. void la_PopulateSelectDataPrimitives(MSelectData* sd, tnsMeshObject* mo, tnsCamera* camera, int WhatPrim){
  77. if(WhatPrim==LA_CANVAS_SELECT_MODE_VERTS){ la_PopulateSelectVerts(sd,mo); }
  78. elif(WhatPrim==LA_CANVAS_SELECT_MODE_EDGES){ la_PopulateSelectEdges(sd,mo); }
  79. int w=sd->Color->Width, h=sd->Color->Height;
  80. tnsUnbindTexture(); tnsUniformUseTexture(T->immShader,0,0); tnsUseMultiplyColor(0);
  81. tnsEnableShaderv(T->SelectionShader);
  82. tnsViewportWithScissor(0,0,w,h);tnsResetViewMatrix();tnsResetModelMatrix();tnsResetProjectionMatrix();
  83. tnsApplyCameraView(w,h,camera);
  84. glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  85. glEnable(GL_DEPTH_TEST);
  86. tnsPushMatrix(); tnsApplyObjectMatrix(mo);
  87. tnsDrawBatch(mo->Batch, (WhatPrim==LA_CANVAS_SELECT_MODE_VERTS)?"verts_select":"edges_select",0,0);
  88. tnsPopMatrix();
  89. glDisable(GL_DEPTH_TEST);
  90. }
  91. void la_PadSelectionBuffer(uint8_t* buf, int w, int h, int sx, int sy, int ex, int ey, int real_endx){
  92. if(!sx&&!sy&&!ex&&!ey) return;
  93. uint8_t* pad=calloc(1,sizeof(uint8_t)*4*w*h);
  94. for(int i=0;i<h;i++){
  95. if(i<sy || i>=h-ey){ memset(&pad[i*w*4],0,w*4); continue; }
  96. for(int j=0;j<w;j++){
  97. if(j<sx || j>=w-sx){ memset(&pad[(i*w+j)*4],0,4); continue; }
  98. memcpy(&pad[(i*w+j)*4], &buf[((i-sy)*(real_endx-sx)+j-sx)*4], 4);
  99. }
  100. }
  101. memcpy(buf,pad,sizeof(uint8_t)*4*w*h);
  102. free(pad);
  103. }
  104. uint8_t* la_ReadSelection(MSelectData* sd, u8bit* buf, int x, int y, int w, int h){
  105. glFlush(); glFinish();
  106. glGetError();
  107. glBindFramebuffer(GL_READ_FRAMEBUFFER, sd->FBO->FboHandle);
  108. glReadBuffer(GL_COLOR_ATTACHMENT0);
  109. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  110. glReadPixels(x,y,w,h, GL_RGBA, GL_UNSIGNED_BYTE, buf);
  111. return buf;
  112. }
  113. uint8_t* la_ReadSelectionRadius(MSelectData* sd, int uix, int uiy, int radius){
  114. int w=radius*2; int vh=sd->Color->Height,vw=sd->Color->Width;
  115. uint8_t* buf=calloc(1,sizeof(uint8_t)*4*w*w);
  116. int startx=uix-radius, starty=vh-uiy-radius, endx=uix+radius, endy=vh-uiy+radius;
  117. TNS_CLAMP(startx,0,vw);TNS_CLAMP(endx,0,vw);TNS_CLAMP(starty,0,vh);TNS_CLAMP(endy,0,vh);
  118. int _startx=TNS_MAX2(startx,0), _starty=TNS_MAX2(starty,0), _endx=TNS_MIN2(endx,vw), _endy=TNS_MIN2(endy,vh);
  119. la_ReadSelection(sd, buf, _startx, _starty, _endx-_startx, _endy-_starty);
  120. la_PadSelectionBuffer(buf, w, w, _startx-startx, _starty-starty, endx-_endx, endy-_endy,_endx);
  121. return buf;
  122. }
  123. uint8_t* la_ReadSelectionBox(MSelectData* sd, int uix, int uiy, int uix2, int uiy2){
  124. int vh=sd->Color->Height,vw=sd->Color->Width;
  125. if(uix2<uix) LA_SWAP(int,uix,uix2); if(uiy2<uiy) LA_SWAP(int,uiy,uiy2);
  126. TNS_CLAMP(uix,0,vw);TNS_CLAMP(uix2,0,vw);TNS_CLAMP(uiy,0,vh);TNS_CLAMP(uiy2,0,vh);
  127. int w=uix2-uix, h=uiy2-uiy;
  128. uint8_t* buf=calloc(1,sizeof(uint8_t)*4*w*h);
  129. int startx=uix, starty=vh-uiy2, endx=uix+w, endy=starty+h;
  130. int _startx=TNS_MAX2(startx,0), _starty=TNS_MAX2(starty,0), _endx=TNS_MIN2(endx,vw), _endy=TNS_MIN2(endy,vh);
  131. la_ReadSelection(sd, buf, _startx, _starty, _endx-_startx, _endy-_starty);
  132. la_PadSelectionBuffer(buf, w, h, _startx-startx, _starty-starty, endx-_endx, endy-_endy,_endx);
  133. return buf;
  134. }
  135. int la_SelectGetClosest(MSelectData* sd, int uix, int uiy, int radius){
  136. uint8_t* buf=la_ReadSelectionRadius(sd, uix, uiy, radius); if(!buf) return 0;
  137. int w=radius*2; int MinD=INT_MAX; int MinID=0, d;
  138. for(int i=0;i<w;i++){
  139. for(int j=0;j<w;j++){
  140. uint8_t* p=&buf[(i*w+j)*4]; int id=(p[0])|(p[1]<<8)|(p[2]<<16);
  141. if(id && (d=tnsDistIdv2(i,j, radius, radius))<MinD ){ MinD=d; MinID=id; }
  142. printf("%d ",buf[(i*w+j)*4]);
  143. }
  144. printf("\n");
  145. }
  146. free(buf);
  147. return MinID;
  148. }
  149. int* la_SelectGetBox(MSelectData* sd, int uix, int uiy, int uix2, int uiy2, int* r_length){
  150. uint8_t* buf=la_ReadSelectionBox(sd, uix, uiy, uix2, uiy2); if(!buf) return 0;
  151. int vh=sd->Color->Height,vw=sd->Color->Width;
  152. if(uix2<uix) LA_SWAP(int,uix,uix2); if(uiy2<uiy) LA_SWAP(int,uiy,uiy2);
  153. TNS_CLAMP(uix,0,vw);TNS_CLAMP(uix2,0,vw);TNS_CLAMP(uiy,0,vh);TNS_CLAMP(uiy2,0,vh);
  154. int w=uix2-uix, h=uiy2-uiy;
  155. int* ids=0; int next=0,max=0;
  156. arrEnsureLength(&ids, next, &max, sizeof(int));
  157. for(int i=0;i<h;i++){
  158. for(int j=0;j<w;j++){
  159. uint8_t* p=&buf[(i*w+j)*4]; int id=(p[0])|(p[1]<<8)|(p[2]<<16);
  160. if(id){ int found=0;
  161. for(int a=0;a<next;a++){ if(ids[a]==id){ found=1; break; } }
  162. if(!found){
  163. arrEnsureLength(&ids, next, &max, sizeof(int)); ids[next]=id; next++; }
  164. }
  165. }
  166. }
  167. free(buf);
  168. *r_length=next;
  169. return ids;
  170. }
  171. void la_FreeSelectData(MSelectData* sd){
  172. tnsDelete2DOffscreen(sd->FBO);
  173. free(sd->Refs);
  174. memFree(sd);
  175. }
  176. int OPCHK_ViewportAndSceneExists(laPropPack *This, laStringSplitor *ss){
  177. if(!This || !This->EndInstance){ return 0; } laCanvasExtra* ex=This->EndInstance;
  178. laUiItem* ui=ex->ParentUi; tnsObject* root=ui?ui->PP.EndInstance:0;
  179. if(!ex->ViewingCamera || !root){ return 0; }
  180. return 1;
  181. }
  182. void la_DoObjectSelect(tnsObject* root, tnsObject* o, laCanvasExtra* e, int DeselectAll, int Select, int Toggle){
  183. if(DeselectAll){ tnsDeselectAllObjects(root); memAssignRef(root,&root->Active,0); }
  184. if(o){ tnsSelectObject(o, Select, o==root->Active?0:Toggle); memAssignRef(root,&root->Active,o); }
  185. }
  186. void la_DoMeshSelect(tnsMeshObject* mo, void* p, int WhatPrim, int DeselectAll, int Select, int Toggle){
  187. if(DeselectAll){ tnsMMeshDeselectAll(mo); }
  188. if(p){ if(WhatPrim==LA_CANVAS_SELECT_MODE_VERTS) tnsMMeshSelectVert(mo,p,Select,Toggle);
  189. elif(WhatPrim==LA_CANVAS_SELECT_MODE_EDGES) tnsMMeshSelectEdge(mo,p,Select,Toggle); }
  190. }
  191. #define LA_SELECT_MODE_BOX 1
  192. STRUCTURE(MSelectExtra){
  193. MSelectData* sd;
  194. tnsObject* root;
  195. tnsObject* mo;
  196. tnsCamera* cam;
  197. int Mode;
  198. int InSelect;
  199. };
  200. int OPINV_Select(laOperator *a, laEvent *e){
  201. if(!a->This || !a->This->EndInstance){ return 0; }
  202. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  203. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  204. tnsMeshObject* mo=root->Active;
  205. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "toggle")){
  206. if(mo && mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  207. if(tnsMMeshAnySelected(mo)) tnsMMeshDeselectAll(mo); else tnsMMeshSelectAll(mo);
  208. tnsInvaliateMeshBatch(mo);
  209. }else{
  210. if(tnsAnyObjectsSelected(root)) tnsDeselectAllObjects(root); else tnsSelectAllObjects(root);
  211. }
  212. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world");
  213. return LA_FINISHED;
  214. }
  215. MSelectData* sd=la_InitSelectData(ex->OffScr->pColor[0]->Width, ex->OffScr->pColor[0]->Height, c);
  216. int DeselectAll=1;
  217. int Append=e->SpecialKeyBit&LA_KEY_SHIFT; if(Append) DeselectAll=0;
  218. if(mo && mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  219. la_PopulateSelectDataPrimitives(sd, mo, ex->ViewingCamera, ex->SelectMode);
  220. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "box")){
  221. MSelectExtra* se=memAcquire(sizeof(MSelectExtra));
  222. ex->OnX=e->x; ex->OnX=e->y;
  223. 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;
  224. }
  225. int id=la_SelectGetClosest(sd, e->x-ui->L, e->y-ui->U, LA_RH)-1;
  226. void* p; if(id>=0 && id<sd->next){ p=sd->Refs[id]; }
  227. la_DoMeshSelect(mo, p, ex->SelectMode, DeselectAll, 1, 1); tnsMMeshEnsureSelection(mo,ex->SelectMode);
  228. tnsInvaliateMeshBatch(mo);
  229. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world");
  230. }else{
  231. la_PopulateSelectDataObjects(sd,root,ex->ViewingCamera);
  232. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"), "box")){
  233. MSelectExtra* se=memAcquire(sizeof(MSelectExtra));
  234. ex->OnX=e->x; ex->OnX=e->y;
  235. a->CustomData=se; se->sd=sd; se->Mode=LA_SELECT_MODE_BOX; se->cam=c; ex->DrawCursor=1; se->root=root; return LA_RUNNING;
  236. }
  237. int id=la_SelectGetClosest(sd, e->x-ui->L, e->y-ui->U, LA_RH*2);
  238. if(id && id<sd->next){ la_DoObjectSelect(root, sd->Refs[id], ex, DeselectAll, 1, 1); }
  239. else{ la_DoObjectSelect(root, 0, ex, DeselectAll, 1, 1); }
  240. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world");
  241. }
  242. la_FreeSelectData(sd);
  243. return LA_FINISHED_PASS;
  244. }
  245. int OPMOD_Select(laOperator *a, laEvent *e){
  246. if(!a->This || !a->This->EndInstance){ return 0; }
  247. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  248. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return;
  249. tnsMeshObject* mo=root->Active;
  250. MSelectExtra* se=a->CustomData;
  251. if(e->Type==LA_L_MOUSE_DOWN){ se->InSelect=1; ex->DrawCursor=2; ex->ClickedX=e->x; ex->ClickedY=e->y; laRedrawCurrentPanel(); }
  252. if(e->Type&LA_MOUSE_EVENT){ ex->OnX=e->x; ex->OnY=e->y; laRedrawCurrentPanel(); }
  253. if(e->Type==LA_R_MOUSE_DOWN || (e->Type == LA_KEY_DOWN && e->key==LA_KEY_ESCAPE)){
  254. ex->DrawCursor=0; la_FreeSelectData(se->sd); laNotifyUsers("tns.world"); return LA_FINISHED;
  255. }
  256. int DeselectAll=1;
  257. int Append=e->SpecialKeyBit&LA_KEY_SHIFT; if(Append) DeselectAll=0;
  258. int Remove=e->SpecialKeyBit&LA_KEY_ALT; if(Remove) DeselectAll=0;
  259. if(se->InSelect && e->Type==LA_L_MOUSE_UP){
  260. if(mo && mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  261. la_DoMeshSelect(mo, 0, ex->SelectMode, DeselectAll, 0, 0);
  262. 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);
  263. for(int i=0;i<len;i++){
  264. int id=ids[i]-1; void* p; if(id>=0 && id<se->sd->next){ p=se->sd->Refs[id]; }
  265. la_DoMeshSelect(mo, p, ex->SelectMode, 0, !Remove, 0);
  266. }
  267. tnsMMeshEnsureSelection(mo,ex->SelectMode);
  268. tnsInvaliateMeshBatch(mo);
  269. }else{
  270. la_DoObjectSelect(se->root, 0, ex, DeselectAll, 0, 0);
  271. int len; int* ids=la_SelectGetBox(se->sd, ex->ClickedX, ex->ClickedY, e->x-ui->L, e->y-ui->U, &len);
  272. for(int i=0;i<len;i++){
  273. int id=ids[i]; if(id && id<se->sd->next){ la_DoObjectSelect(se->root, se->sd->Refs[id], ex, 0, !Remove, 0); }
  274. }
  275. }
  276. laNotifyUsers("tns.world"); laRecordAndPush(0,"tns.world");
  277. ex->DrawCursor=0;
  278. la_FreeSelectData(se->sd);
  279. laRedrawCurrentPanel();
  280. return LA_FINISHED;
  281. }
  282. return LA_RUNNING;
  283. }
  284. #define LA_TRANSFORM_MODE_GRAB 1
  285. #define LA_TRANSFORM_MODE_ROTATE 2
  286. #define LA_TRANSFORM_MODE_SCALE 3
  287. STRUCTURE(MTOrigObject){
  288. tnsObject* o;
  289. tnsMatrix44d Global;
  290. tnsMatrix44d Local;
  291. int Discard;
  292. };
  293. STRUCTURE(MTOrigMVert){
  294. tnsVector3d p;
  295. tnsVector3d origp;
  296. tnsMVert* mv;
  297. };
  298. STRUCTURE(MTransformData){
  299. tnsMatrix44d Delta;
  300. tnsMatrix44d ViewProjection;
  301. tnsVector4d Up,Right,Foward;
  302. tnsVector4d TCenter;
  303. int CenterX,CenterY; real Initial;
  304. tnsObject* mo; tnsMatrix44d obmatinv;
  305. tnsCamera* c; tnsObject* root;
  306. int w,h;
  307. void* Originals; int next,max;
  308. int mode;
  309. int LockAxis[3];
  310. int Local;
  311. real DeltaVal, UserDeltaVal;
  312. laStringEdit* Entry; int UseUserDelta;
  313. };
  314. MTransformData* la_InitTransformData(int w, int h, tnsCamera* c){
  315. MTransformData* td=memAcquireSimple(sizeof(MTransformData));
  316. tnsVector4d pu={0,1,0,0}, pr={1,0,0,0}, pf={0,0,1};
  317. tnsGetCameraMovingDeltas(c,w,h,1,0,pr); pr[2]=0; pr[3]=0;
  318. tnsGetCameraMovingDeltas(c,w,h,0,-1,pu); pu[2]=0; pu[3]=0;
  319. tnsMatrix44d inv; tnsInverse44d(inv,c->Base.GlobalTransform);
  320. tnsApplyRotation43d(td->Up,inv,pu);
  321. tnsApplyRotation43d(td->Right,inv,pr);
  322. tnsApplyRotation43d(td->Foward,inv,pf);
  323. tnsGetCameraViewProjection(td->ViewProjection, w,h,c);
  324. td->c=c; td->w=w; td->h=h;
  325. strBeginEdit(&td->Entry, "");
  326. return td;
  327. }
  328. void la_GetTransformInitialScale(MTransformData* td, laUiItem* ui, int x, int y){ td->Initial=tnsDistIdv2(x-ui->L,y-ui->U,td->CenterX,td->CenterY); }
  329. void la_GetTransformInitialRotation(MTransformData* td, laUiItem* ui, int x, int y){ td->Initial=atan2(y-ui->U-td->CenterY,x-ui->L-td->CenterX); }
  330. void la_GetTransformCenter2D(MTransformData* td){
  331. tnsVector4d vp; tnsApplyTransform44d(vp,td->ViewProjection,td->TCenter);
  332. if(td->c->CameraType==TNS_PRESPECTIVE_CAMERA){ tnsVectorMultiSelf3d(vp, 1/vp[3]); }
  333. td->CenterX = (vp[0]/2+0.5f)*td->w; td->CenterY=(-vp[1]/2+0.5f)*td->h;
  334. if(td->CenterX<0||td->CenterY<0) { td->CenterX=td->w/2; td->CenterY=td->h/2; }
  335. }
  336. int la_AddTransformObjectsRecursive(MTransformData* td, tnsObject*root){
  337. int any=0; for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  338. tnsObject* o=lip->p; if(o->ChildObjects.pFirst) any+=la_AddTransformObjectsRecursive(td,o);
  339. if(!o->Flags&TNS_OBJECT_FLAGS_SELECTED) continue;
  340. arrEnsureLength(&td->Originals, td->next, &td->max, sizeof(MTOrigObject));
  341. MTOrigObject* to=arrElement(td->Originals, td->next, sizeof(MTOrigObject)); td->next++; to->o=o;
  342. memcpy(to->Global, o->GlobalTransform, sizeof(tnsMatrix44d));
  343. memcpy(to->Local, o->SelfTransform, sizeof(tnsMatrix44d));
  344. tnsVectorAccum3d(td->TCenter,o->GLocation); any++;
  345. 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;
  346. }
  347. return any;
  348. }
  349. int la_PopulateTransformObjects(MTransformData* td, tnsObject* root){
  350. arrEnsureLength(&td->Originals, 0, &td->max, sizeof(MTOrigObject));
  351. int any=la_AddTransformObjectsRecursive(td,root);
  352. tnsVectorMultiSelf3d(td->TCenter, 1.0f/any);
  353. la_GetTransformCenter2D(td);
  354. return any;
  355. }
  356. int la_PopulateTransformVerticies(MTransformData* td, tnsMeshObject* mo){
  357. int any=0; td->mo=mo;
  358. arrEnsureLength(&td->Originals, 0, &td->max, sizeof(MTOrigMVert));
  359. tnsInverse44d(td->obmatinv, mo->Base.GlobalTransform);
  360. for(tnsMVert* mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){
  361. if(!mv->flags&TNS_MESH_FLAG_SELECTED) continue;
  362. arrEnsureLength(&td->Originals, td->next, &td->max, sizeof(MTOrigMVert));
  363. MTOrigMVert* to=arrElement(td->Originals, td->next, sizeof(MTOrigMVert)); td->next++; to->mv=mv;
  364. tnsApplyTransform43d(to->p, mo->Base.GlobalTransform, mv->p);
  365. memcpy(to->origp, mv->p, sizeof(tnsVector3d)); any++;
  366. tnsVectorAccum3d(td->TCenter,to->p);
  367. }
  368. tnsVectorMultiSelf3d(td->TCenter, 1.0f/any);
  369. la_GetTransformCenter2D(td);
  370. return any;
  371. }
  372. void la_ApplyTranslation(MTransformData* td, int x, int y){
  373. tnsMatrix44d trans; tnsVector3d deltay,delta; tnsVector3d gp;
  374. tnsVectorMulti3d(delta, td->Right, x); tnsVectorMulti3d(deltay, td->Up, y); tnsVectorAccum3d(delta, deltay);
  375. tnsVector3d use_delta={LA_COLOR3(delta)}; real len;
  376. if(td->LockAxis[0]||td->LockAxis[1]||td->LockAxis[2]){ len=tnsLength3d(delta); }
  377. 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; }
  378. 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; }
  379. 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; }
  380. if(td->LockAxis[0]<0){ use_delta[0]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l:0); }
  381. if(td->LockAxis[1]<0){ use_delta[1]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l:0); }
  382. if(td->LockAxis[2]<0){ use_delta[2]=0; real l=tnsLength3d(use_delta); tnsVectorMultiSelf3d(use_delta, l?len/l:0); }
  383. td->DeltaVal=tnsLength3d(use_delta);
  384. if(td->UseUserDelta){
  385. tnsVectorMultiSelf3d(use_delta,1/tnsLength3d(use_delta)*td->UserDeltaVal);
  386. tnsVector3d lock={ td->LockAxis[0], td->LockAxis[1], td->LockAxis[2] };
  387. real dir=tnsDot3d(use_delta, lock, 0); tnsVectorMultiSelf3d(use_delta,(td->UserDeltaVal*dir<=0)?-1:1);
  388. td->DeltaVal=td->UserDeltaVal;
  389. }
  390. if(!td->mo){
  391. for(int i=0;i<td->next;i++){
  392. MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject)); memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
  393. if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
  394. tnsGlobalMatrixChanged(to->o, 0); tnsMoveObjectGlobal(to->o, LA_COLOR3(use_delta));
  395. }
  396. }else{
  397. tnsMakeTranslationMatrix44d(trans, LA_COLOR3(use_delta));
  398. for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
  399. tnsApplyTransform43d(gp, trans, to->p); tnsApplyTransform43d(to->mv->p, td->obmatinv, gp);
  400. }
  401. tnsInvaliateMeshBatch(td->mo);
  402. }
  403. }
  404. void la_ApplyScale(MTransformData* td, int uix, int uiy){
  405. tnsMatrix44d trans; real d=tnsDistIdv2(uix,uiy,td->CenterX,td->CenterY); if(!td->Initial){ td->Initial=100; }
  406. real s=d/td->Initial; tnsVector3d gp;
  407. td->DeltaVal=s; if(td->UseUserDelta) td->DeltaVal=s=td->UserDeltaVal;
  408. if(!td->mo){
  409. for(int i=0;i<td->next;i++){
  410. MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject)); memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
  411. if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
  412. tnsGlobalMatrixChanged(to->o, 0); tnsScaleObject(to->o, s, LA_COLOR3(td->TCenter));
  413. }
  414. }else{
  415. tnsMakeScaleMatrix44d(trans,s,s,s);
  416. tnsMatrix44d t1,t2,t3; tnsMakeTranslationMatrix44d(t1,LA_COLOR3(td->TCenter)); tnsInverse44d(t2,t1);
  417. tnsMatrix44d final; tnsMultiply44d(t3,t1,trans); tnsMultiply44d(final,t3,t2);
  418. for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
  419. tnsApplyTransform43d(gp, final, to->p); tnsApplyTransform43d(to->mv->p, td->obmatinv, gp);
  420. }
  421. tnsInvaliateMeshBatch(td->mo);
  422. }
  423. }
  424. void la_ApplyRotation(MTransformData* td, int uix, int uiy){
  425. tnsMatrix44d trans; real a=atan2(uiy-td->CenterY,uix-td->CenterX);
  426. real angle=a-td->Initial; tnsVector3d gp; tnsVector3d LimFoward={0}; real* use_forward=td->Foward;
  427. if(td->LockAxis[0]||td->LockAxis[1]||td->LockAxis[2]){ use_forward=LimFoward; }
  428. if(td->LockAxis[0]){ LimFoward[0]=1; }
  429. if(td->LockAxis[1]){ LimFoward[1]=1; }
  430. if(td->LockAxis[2]){ LimFoward[2]=1; }
  431. if(td->UseUserDelta) angle=rad(td->UserDeltaVal); td->DeltaVal=deg(angle);
  432. if(!td->mo){
  433. for(int i=0;i<td->next;i++){
  434. MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject)); memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
  435. if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
  436. tnsGlobalMatrixChanged(to->o, 0); tnsRotateObjectGlobal(to->o,LA_COLOR3(use_forward),angle,LA_COLOR3(td->TCenter));
  437. }
  438. }else{
  439. tnsMakeRotationMatrix44d(trans, angle, LA_COLOR3(use_forward));
  440. tnsMatrix44d t1,t2,t3; tnsMakeTranslationMatrix44d(t1,LA_COLOR3(td->TCenter)); tnsInverse44d(t2,t1);
  441. tnsMatrix44d final; tnsMultiply44d(t3,t1,trans); tnsMultiply44d(final,t3,t2);
  442. for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert));
  443. tnsApplyTransform43d(gp, final, to->p); tnsApplyTransform43d(to->mv->p, td->obmatinv, gp);
  444. }
  445. tnsInvaliateMeshBatch(td->mo);
  446. }
  447. }
  448. void la_CancelTransformObjects(MTransformData* td){
  449. if(!td->mo){
  450. for(int i=0;i<td->next;i++){ MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject));
  451. if(to->Discard){ tnsSelfMatrixChanged(to->o,1); continue; }
  452. memcpy(to->o->GlobalTransform, to->Global,sizeof(tnsMatrix44d));
  453. tnsGlobalMatrixChanged(to->o, 1);
  454. }
  455. }else{
  456. for(int i=0;i<td->next;i++){ MTOrigMVert* to=arrElement(td->Originals, i, sizeof(MTOrigMVert)); tnsVectorCopy3d(to->origp,to->mv->p); }
  457. tnsInvaliateMeshBatch(td->mo);
  458. }
  459. }
  460. void la_RecordTransformDifferences(MTransformData* td){
  461. if(!td->mo){
  462. for(int i=0;i<td->next;i++){ MTOrigObject* to=arrElement(td->Originals, i, sizeof(MTOrigObject));
  463. laRecordInstanceDifferences(to->o, "tns_object");
  464. } laPushDifferences("Object Transformation", TNS_HINT_TRANSFORM);
  465. }else{
  466. laRecordInstanceDifferences(td->mo, "tns_mesh_object"); laPushDifferences("Mesh transformation", TNS_HINT_GEOMETRY);
  467. tnsInvaliateMeshBatch(td->mo);
  468. }
  469. }
  470. void la_FreeTransformData(MTransformData* td){
  471. free(td->Originals);
  472. strEndEdit(&td->Entry, 1);
  473. memFree(td);
  474. }
  475. void la_MakeTransformOperatorHint(laOperator* a, MTransformData* td){
  476. strSafeDestroy(&a->RuntimeHint);
  477. strSafePrint(&a->RuntimeHint, "%s ",
  478. td->mode==LA_TRANSFORM_MODE_GRAB?"Grab":td->mode==LA_TRANSFORM_MODE_ROTATE?"Rotate":td->mode==LA_TRANSFORM_MODE_SCALE?"Scale":"");
  479. char* entry=strGetEditString(td->Entry,0);
  480. strSafePrint(&a->RuntimeHint, "Delta: %.3lf [🔢 %s] 🆇🆈🆉 Lock axis: %s ", td->DeltaVal, (entry&&entry[0])?entry:"Type...",
  481. td->LockAxis[0]?"X":td->LockAxis[1]?"Y":td->LockAxis[2]?"Z":"None");
  482. free(entry);
  483. if(td->mode==LA_TRANSFORM_MODE_GRAB){ strSafePrint(&a->RuntimeHint, "🡅🆇🆈🆉 Reverse: %s ",
  484. (td->LockAxis[0]<0||td->LockAxis[1]<0||td->LockAxis[2]<0)?"Yes":"No"); }
  485. if(td->mode!=LA_TRANSFORM_MODE_GRAB){ strSafePrint(&a->RuntimeHint,"🅶 Grab "); }
  486. if(td->mode!=LA_TRANSFORM_MODE_SCALE){ strSafePrint(&a->RuntimeHint,"🆂 Scale "); }
  487. if(td->mode!=LA_TRANSFORM_MODE_ROTATE){ strSafePrint(&a->RuntimeHint,"🆁 Rotate "); }
  488. }
  489. int la_InitTransform(laOperator* a, laEvent* e, int mode){
  490. if(!a->This || !a->This->EndInstance){ return 0; }
  491. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  492. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  493. tnsMeshObject* mo=root->Active;
  494. MTransformData* td=la_InitTransformData(ex->OffScr->pColor[0]->Width, ex->OffScr->pColor[0]->Height, c);
  495. a->CustomData = td;
  496. td->mode=mode;
  497. td->root=root;
  498. int ret=0;
  499. if(mo && mo->Base.Type==TNS_OBJECT_MESH && mo->Mode==TNS_MESH_EDIT_MODE){
  500. if(la_PopulateTransformVerticies(td, mo)){ ex->ClickedX=e->x; ex->ClickedY=e->y; ret=1; }
  501. }else{
  502. if(la_PopulateTransformObjects(td,root)){ ex->ClickedX=e->x; ex->ClickedY=e->y; ret=1; }
  503. }
  504. if(ret){
  505. if(mode==LA_TRANSFORM_MODE_SCALE){ la_GetTransformInitialScale(td,ui,e->x,e->y); ex->DrawCursor=LA_CANVAS_CURSOR_ARROW; }
  506. elif(mode==LA_TRANSFORM_MODE_ROTATE){ la_GetTransformInitialRotation(td,ui,e->x,e->y); ex->DrawCursor=LA_CANVAS_CURSOR_ARROW; }
  507. ex->TargetX=td->CenterX+ui->L; ex->TargetY=td->CenterY+ui->U; ex->OnX=e->x; ex->OnY=e->y;
  508. la_MakeTransformOperatorHint(a, td);
  509. laNotifyUsers("tns.world"); return 1;
  510. }
  511. return 0;
  512. }
  513. int OPINV_Grab(laOperator *a, laEvent *e){
  514. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB)) return LA_RUNNING; return LA_FINISHED_PASS;
  515. }
  516. int OPINV_Scale(laOperator *a, laEvent *e){
  517. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_SCALE)) return LA_RUNNING; return LA_FINISHED_PASS;
  518. }
  519. int OPINV_Rotate(laOperator *a, laEvent *e){
  520. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_ROTATE)) return LA_RUNNING; return LA_FINISHED_PASS;
  521. }
  522. int OPMOD_Transformation(laOperator *a, laEvent *e){
  523. if(!a->This || !a->This->EndInstance){ return 0; }
  524. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  525. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  526. tnsMeshObject* mo=root->Active;
  527. MTransformData* td=a->CustomData;
  528. if (e->Input=='x'||e->Input=='y'||e->Input=='z'||e->Input=='g'||e->Input=='s'||e->Input=='r'||
  529. e->Input=='X'||e->Input=='Y'||e->Input=='Z'){ /*pass*/ }
  530. else{ la_ProcessTextEdit(e, td->Entry, 0); }
  531. char* entered;
  532. if(entered=strGetEditString(td->Entry,0)){ int status;
  533. if((status=sscanf(entered,"%lf",&td->UserDeltaVal)) && status!=EOF) td->UseUserDelta=1; else td->UseUserDelta=0;
  534. td->UserDeltaVal=fabs(td->UserDeltaVal); for(char*pc=entered;*pc;pc++){ if(*pc=='-') td->UserDeltaVal=-td->UserDeltaVal; } free(entered);
  535. }
  536. if(e->Type==LA_KEY_DOWN){
  537. int Other=1; if(e->SpecialKeyBit&LA_KEY_SHIFT){ Other=-1; }
  538. 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; }
  539. 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; }
  540. 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; }
  541. if(e->key=='g' && td->mode!=LA_TRANSFORM_MODE_GRAB){ td->mode=LA_TRANSFORM_MODE_GRAB; ex->DrawCursor=0; }
  542. 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; }
  543. 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; }
  544. }
  545. if(e->Type==LA_MOUSEMOVE || e->Type==LA_KEY_DOWN){
  546. switch(td->mode){
  547. case LA_TRANSFORM_MODE_GRAB: la_ApplyTranslation(td,e->x-ex->ClickedX, e->y-ex->ClickedY); break;
  548. case LA_TRANSFORM_MODE_SCALE: la_ApplyScale(td,e->x-ui->L, e->y-ui->U); break;
  549. case LA_TRANSFORM_MODE_ROTATE: la_ApplyRotation(td,e->x-ui->L, e->y-ui->U); break;
  550. default: break;
  551. }
  552. ex->OnX=e->x; ex->OnY=e->y;
  553. laNotifyUsers("tns.world");
  554. }
  555. if(e->Type==LA_L_MOUSE_DOWN || (e->Type==LA_KEY_DOWN && e->key==LA_KEY_ENTER)){ ex->DrawCursor=0;
  556. la_RecordTransformDifferences(td);
  557. laNotifyUsers("tns.world"); la_FreeTransformData(td); return LA_FINISHED;
  558. }
  559. if(e->Type==LA_R_MOUSE_DOWN || e->Type==LA_ESCAPE_DOWN){ ex->DrawCursor=0;
  560. la_CancelTransformObjects(td); laNotifyUsers("tns.world"); la_FreeTransformData(td); return LA_FINISHED;
  561. }
  562. la_MakeTransformOperatorHint(a, td);
  563. return LA_RUNNING;
  564. }
  565. int la_ParentableRecursive(tnsObject* root, tnsObject* parent){
  566. for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  567. tnsObject* o=lip->p; if(!o || !o->Flags&TNS_OBJECT_FLAGS_SELECTED || o==parent) continue;
  568. if(!tnsCheckParentable(o,parent)) return 0;
  569. if(!la_ParentableRecursive(o,parent)) return 0;
  570. }return 1;
  571. }
  572. void la_MakeParentExecuteRecursive(tnsObject* root, tnsObject* parent, int Unparent, int KeepTransform){
  573. for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  574. tnsObject* o=lip->p; if(!o || !o->Flags&TNS_OBJECT_FLAGS_SELECTED) continue;
  575. if(Unparent) tnsUnparentObject(o, KeepTransform);
  576. else tnsParentObject(o, parent, KeepTransform);
  577. la_MakeParentExecuteRecursive(o,parent,Unparent,KeepTransform);
  578. }
  579. laNotifyUsers("tns.world");
  580. }
  581. int OPINV_MakeParent(laOperator *a, laEvent *e){
  582. if(!a->This || !a->This->EndInstance){ return 0; }
  583. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  584. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  585. tnsObject* mo=root->Active;
  586. int Unparent=0,KeepTransform=1;
  587. char* action=strGetArgumentString(a->ExtraInstructionsP,"action");
  588. char* keep=strGetArgumentString(a->ExtraInstructionsP,"keep_transform");
  589. if(strSame(action,"unparent")){ Unparent=1; }
  590. if(strSame(keep,"false")){ KeepTransform=0; }
  591. if(!Unparent){ if(!mo || !mo->Flags&TNS_OBJECT_FLAGS_SELECTED) return LA_FINISHED;
  592. 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;
  593. }
  594. if(keep){
  595. la_MakeParentExecuteRecursive(root,mo,Unparent,KeepTransform);
  596. laRecordInstanceDifferences(&T->World, "tns_world"); laPushDifferences(Unparent?"Unparent":"Parent", TNS_HINT_TRANSFORM);
  597. return LA_FINISHED;
  598. }
  599. laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e);
  600. return LA_RUNNING;
  601. }
  602. void laui_MakeParent(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
  603. laColumn* c=laFirstColumn(uil);
  604. laShowItemFull(uil,c,pp,"_this_M_make_parent",0,"action=parent;keep_transform=true;text=Keep transform",0,0);
  605. laShowItemFull(uil,c,pp,"_this_M_make_parent",0,"action=parent;keep_transform=false;text=Directly",0,0);
  606. }
  607. void laui_Unparent(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
  608. laColumn* c=laFirstColumn(uil);
  609. laShowItemFull(uil,c,pp,"_this_M_unparent",0,"action=unparent;keep_transform=true;text=Keep transform",0,0);
  610. laShowItemFull(uil,c,pp,"_this_M_unparent",0,"action=unparent;keep_transform=false;text=Directly",0,0);
  611. }
  612. int la_ClearTransformationRecursive(tnsObject* root, int global,int location,int rotation,int scale){
  613. int any=0; for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){
  614. tnsObject* o=lip->p; if(!o->Flags&TNS_OBJECT_FLAGS_SELECTED) continue;
  615. if(location){
  616. if(global){ o->GLocation[0]=o->GLocation[1]=o->GLocation[2]=0;}
  617. else{ o->Location[0]=o->Location[1]=o->Location[2]=0; }
  618. }
  619. if(rotation){
  620. if(global){ o->GRotation[0]=o->GRotation[1]=o->GRotation[2]=0;}
  621. else{ o->Rotation[0]=o->Rotation[1]=o->Rotation[2]=0; }
  622. }
  623. if(scale){ if(global){ o->GScale=1;} else{ o->Scale=1; } }
  624. if(global) tnsGlobalTransformValueChanged(o); else tnsSelfTransformValueChanged(o);
  625. laRecordInstanceDifferences(o, "tns_object"); any++;
  626. any+=la_ClearTransformationRecursive(o,global,location,rotation,scale);
  627. } return any;
  628. }
  629. int OPINV_ClearTransformation(laOperator *a, laEvent *e){
  630. if(!a->This || !a->This->EndInstance){ return 0; }
  631. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  632. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  633. int global=0,location=0,rotation=0,scale=0;
  634. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"global"),"true")){ global=1; }
  635. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"location"),"true")){ location=1; }
  636. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"rotation"),"true")){ rotation=1; }
  637. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"scale"),"true")){ scale=1; }
  638. int any=0;
  639. if(location||rotation||scale){
  640. any=la_ClearTransformationRecursive(root,global,location,rotation,scale);
  641. if(any){ laPushDifferences("Clear Transformations", TNS_HINT_TRANSFORM); laNotifyUsers("tns.world"); }
  642. }
  643. return LA_FINISHED;
  644. }
  645. STRUCTURE(MEDupVert){
  646. int oi; tnsMVert* nmv; tnsMVert* omv; int IsBorder;
  647. };
  648. STRUCTURE(MEDupEdge){
  649. int oi; tnsMEdge* nme; tnsMEdge* ome; int IsBorder;
  650. };
  651. STRUCTURE(MEDupFace){
  652. int oi; tnsMFace* nmf; tnsMFace* omf;
  653. };
  654. STRUCTURE(MExtrudeExtra){
  655. MEDupVert* dv; int nextv,maxv;
  656. MEDupEdge* de; int nexte,maxe;
  657. MEDupFace* df; int nextf,maxf;
  658. tnsMeshObject* mo;
  659. int RemoveOriginalFaces;
  660. };
  661. int la_IsSelectionBorderVertex(tnsMVert* mv){
  662. if(!mv->elink.pFirst)
  663. return 0;
  664. int NearSelected=0, NearUnselected=0;
  665. for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){
  666. tnsMEdge* me=lip->p; if(!(me->fl&&me->fr)) return 1;
  667. tnsMVert* av=tnsMMeshEdgeAnotherVert(me,mv);
  668. if(me->fl->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { return 1; }
  669. if(me->fr->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { return 1; }
  670. if(NearUnselected && NearSelected) return 1;
  671. }
  672. return 0;
  673. }
  674. int la_IsSelectionBorderEdge(tnsMEdge* me){
  675. if(me->fl&&me->fr){
  676. if ((me->fl->flags&TNS_MESH_FLAG_SELECTED) && (!(me->fr->flags&TNS_MESH_FLAG_SELECTED))||
  677. (me->fr->flags&TNS_MESH_FLAG_SELECTED) && (!(me->fl->flags&TNS_MESH_FLAG_SELECTED))) return 1;
  678. else return (me->fr->flags==me->fl->flags&&me->fl->flags==0);
  679. } return 1;
  680. }
  681. MExtrudeExtra* la_InitExtrude(tnsMeshObject* mo){
  682. MExtrudeExtra* ee=memAcquireSimple(sizeof(MExtrudeExtra));
  683. arrEnsureLength(&ee->dv, ee->nextv, &ee->maxv, sizeof(MEDupVert));
  684. arrEnsureLength(&ee->de, ee->nexte, &ee->maxe, sizeof(MEDupEdge));
  685. arrEnsureLength(&ee->df, ee->nextf, &ee->maxf, sizeof(MEDupFace));
  686. ee->mo=mo;
  687. return ee;
  688. }
  689. void la_ExtrudeMakeDuplication(MExtrudeExtra* ee){
  690. tnsMeshObject* mo=ee->mo;
  691. for(tnsMVert* mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){ if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  692. arrEnsureLength(&ee->dv, ee->nextv, &ee->maxv, sizeof(MEDupVert));
  693. MEDupVert* dv=&ee->dv[ee->nextv];
  694. tnsMVert* nmv=tnsMMeshNewVert(mo); tnsVectorCopy3d(mv->p, &nmv->p); dv->oi=mv->i; mv->i=ee->nextv; dv->nmv=nmv; dv->omv=mv;
  695. dv->IsBorder=la_IsSelectionBorderVertex(mv);
  696. ee->nextv++;
  697. }
  698. for(tnsMEdge* me=mo->me.pFirst;me;me=me->Item.pNext){ if(!(me->flags&TNS_MESH_FLAG_SELECTED)) continue;
  699. arrEnsureLength(&ee->de, ee->nexte, &ee->maxe, sizeof(MEDupEdge));
  700. MEDupEdge* de=&ee->de[ee->nexte];
  701. tnsMEdge* nme=tnsMMeshNewEdge(mo); de->oi=me->i; me->i=ee->nexte; de->nme=nme; de->ome=me; de->IsBorder=la_IsSelectionBorderEdge(me);
  702. tnsMMeshEdgeAssignVerts(nme, ee->dv[me->vl->i].nmv, ee->dv[me->vr->i].nmv);
  703. if(de->IsBorder&&me->fl&&me->fr){ ee->RemoveOriginalFaces=1; }
  704. ee->nexte++;
  705. }
  706. for(tnsMFace* mf=mo->mf.pFirst;mf;mf=mf->Item.pNext){
  707. if(!(mf->flags&TNS_MESH_FLAG_SELECTED)) continue;
  708. arrEnsureLength(&ee->df, ee->nextf, &ee->maxf, sizeof(MEDupFace));
  709. MEDupFace* df=&ee->df[ee->nextf];
  710. tnsMFace* nmf=tnsMMeshNewFace(mo); df->oi=mf->i; mf->i=ee->nextf; df->nmf=nmf; df->omf=mf;
  711. for(laListItemPointer*lip=mf->l.pFirst;lip;lip=lip->pNext){
  712. tnsMEdge* ome=lip->p; tnsMMeshFaceAddEdge(nmf,ee->de[ome->i].nme);
  713. }
  714. ee->nextf++;
  715. }
  716. 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; }
  717. 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; }
  718. for(int i=0;i<ee->nextf;i++){
  719. ee->df[i].omf->i=ee->df[i].oi;
  720. ee->df[i].omf->flags&=(~TNS_MESH_FLAG_SELECTED);
  721. ee->df[i].nmf->flags|=TNS_MESH_FLAG_SELECTED; }
  722. }
  723. void la_ReconnectFaces(MExtrudeExtra* ee){
  724. tnsMeshObject* mo=ee->mo;
  725. if(ee->RemoveOriginalFaces){
  726. for(int i=0;i<ee->nextf;i++){ tnsMMeshRemoveFaceOnly(mo, ee->df[i].omf); }
  727. for(int i=0;i<ee->nexte;i++){ if(ee->de[i].IsBorder) continue; tnsMMeshRemoveEdgeFace(mo, ee->de[i].ome); }
  728. for(int i=0;i<ee->nextv;i++){ if(ee->dv[i].IsBorder) continue; tnsMMeshRemoveVertEdgeFace(mo, ee->dv[i].omv); }
  729. }
  730. for(int i=0;i<ee->nexte;i++){
  731. if(!ee->de[i].IsBorder) continue; MEDupEdge*de=&ee->de[i];
  732. tnsMMeshMakeFace4v(mo, de->ome->vl, de->ome->vr, de->nme->vr, de->nme->vl);
  733. }
  734. }
  735. void la_FinishExtrude(MExtrudeExtra* ee){
  736. tnsMMeshRefreshIndex(ee->mo);
  737. tnsInvaliateMeshBatch(ee->mo);
  738. laRecordInstanceDifferences(ee->mo, "tns_mesh_object"); laPushDifferences("Extruded", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  739. free(ee->dv); free(ee->de); free(ee->df); memFree(ee);
  740. }
  741. int OPINV_Extrude(laOperator *a, laEvent *e){
  742. if(!a->This || !a->This->EndInstance){ return 0; }
  743. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  744. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  745. tnsMeshObject* mo=root->Active; if(mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE) return 0;
  746. if(!tnsMMeshAnySelected(mo)) return LA_FINISHED;
  747. MExtrudeExtra* ee=la_InitExtrude(mo);
  748. la_ExtrudeMakeDuplication(ee);
  749. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"duplicate_only"), "true")){
  750. la_FinishExtrude(ee);
  751. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB)) return LA_RUNNING; return LA_FINISHED;
  752. }
  753. la_ReconnectFaces(ee);
  754. la_FinishExtrude(ee);
  755. if(la_InitTransform(a, e, LA_TRANSFORM_MODE_GRAB)) return LA_RUNNING; return LA_FINISHED;
  756. return LA_FINISHED;
  757. }
  758. int la_EdgeShouldDeleteVert(tnsMVert* mv){
  759. if(!mv->elink.pFirst) return 0;
  760. int NearSelected=0, NearUnselected=0;
  761. for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){
  762. tnsMEdge* me=lip->p;
  763. tnsMVert* av=tnsMMeshEdgeAnotherVert(me,mv);
  764. if(av->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { NearUnselected=1; }
  765. if(NearUnselected && NearSelected) return 1;
  766. }
  767. return 0;
  768. }
  769. int la_FaceShouldDeleteVert(tnsMVert* mv){
  770. if(!mv->elink.pFirst) return 0;
  771. int NearSelected=0, NearUnselected=0, IsBorder=0;
  772. for(laListItemPointer* lip=mv->elink.pFirst;lip;lip=lip->pNext){
  773. tnsMEdge* me=lip->p;
  774. if(!(me->fl&&me->fr)){ IsBorder=1; }
  775. if(me->fl){ if(me->fl->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { NearUnselected=1; } }
  776. if(me->fr){ if(me->fr->flags&TNS_MESH_FLAG_SELECTED){ NearSelected=1; } else { NearUnselected=1; } }
  777. if(NearUnselected && NearSelected) return 0;
  778. }
  779. if((!NearUnselected) && IsBorder) return 1;
  780. return 1;
  781. }
  782. int la_FaceShouldDeleteEdge(tnsMEdge* me){
  783. if(me->fl&&me->fr){
  784. if ((me->fl->flags&TNS_MESH_FLAG_SELECTED) && (!(me->fr->flags&TNS_MESH_FLAG_SELECTED))||
  785. (me->fr->flags&TNS_MESH_FLAG_SELECTED) && (!(me->fl->flags&TNS_MESH_FLAG_SELECTED))) return 0;
  786. else return (me->fr->flags==me->fl->flags&&me->fl->flags==1);
  787. }else{
  788. if(me->fl&&me->fl->flags&TNS_MESH_FLAG_SELECTED&&!me->fr) return 1;
  789. if(me->fr&&me->fr->flags&TNS_MESH_FLAG_SELECTED&&!me->fl) return 1;
  790. } return 0;
  791. }
  792. void la_DeleteVertices(tnsMeshObject* mo){
  793. tnsMVert* nextmv; for(tnsMVert*mv=mo->mv.pFirst;mv;mv=nextmv){ nextmv=mv->Item.pNext; if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  794. tnsMMeshRemoveVertEdgeFace(mo, mv);
  795. }
  796. }
  797. void la_DeleteEdges(tnsMeshObject* mo){
  798. laListHandle lv={0};
  799. for(tnsMVert*mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){ if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  800. if(la_EdgeShouldDeleteVert(mv)) lstAppendPointer(&lv,mv);
  801. }
  802. tnsMEdge* nextme; for(tnsMEdge*me=mo->me.pFirst;me;me=nextme){ nextme=me->Item.pNext; if(!(me->flags&TNS_MESH_FLAG_SELECTED)) continue;
  803. tnsMMeshRemoveEdgeFace(mo, me);
  804. }
  805. tnsMVert* mv; while(mv=lstPopPointer(&lv)){ tnsMMeshRemoveVertEdgeFace(mo,mv); }
  806. }
  807. void la_DeleteFaces(tnsMeshObject* mo, int OnlyFaces){
  808. laListHandle lv={0}, le={0};
  809. if(OnlyFaces){
  810. tnsMFace* nextmf; for(tnsMFace*mf=mo->mf.pFirst;mf;mf=nextmf){ nextmf=mf->Item.pNext; if(!(mf->flags&TNS_MESH_FLAG_SELECTED)) continue;
  811. tnsMMeshRemoveFaceOnly(mo, mf);
  812. }
  813. }else{
  814. for(tnsMVert*mv=mo->mv.pFirst;mv;mv=mv->Item.pNext){ if(!(mv->flags&TNS_MESH_FLAG_SELECTED)) continue;
  815. if(la_FaceShouldDeleteVert(mv)) lstAppendPointer(&lv,mv);
  816. }
  817. for(tnsMEdge*me=mo->me.pFirst;me;me=me->Item.pNext){ if(!(me->flags&TNS_MESH_FLAG_SELECTED)) continue;
  818. if(la_FaceShouldDeleteEdge(me)) lstAppendPointer(&le,me);
  819. }
  820. tnsMFace* nextmf; for(tnsMFace*mf=mo->mf.pFirst;mf;mf=nextmf){ nextmf=mf->Item.pNext; if(!(mf->flags&TNS_MESH_FLAG_SELECTED)) continue;
  821. tnsMMeshRemoveFaceOnly(mo, mf);
  822. }
  823. tnsMEdge* me; while(me=lstPopPointer(&le)){ tnsMMeshRemoveEdgeFace(mo,me); }
  824. tnsMVert* mv; while(mv=lstPopPointer(&lv)){ tnsMMeshRemoveVertEdgeFace(mo,mv); }
  825. }
  826. }
  827. int la_DeleteSelectedObjectsRecursive(tnsObject* root){
  828. int any=0; for(laListItemPointer* lip=root->ChildObjects.pFirst;lip;lip=lip->pNext){ if(!lip->p) continue;
  829. tnsObject* o=lip->p; la_DeleteSelectedObjectsRecursive(lip->p);
  830. if(o->Flags&TNS_OBJECT_FLAGS_SELECTED){ tnsDestroyObject(o); any++; }
  831. }
  832. return any;
  833. }
  834. int OPINV_Delete(laOperator *a, laEvent *e){
  835. if(!a->This || !a->This->EndInstance){ return 0; }
  836. laCanvasExtra* ex=a->This->EndInstance; tnsCamera*c=ex->ViewingCamera; laUiItem* ui=ex->ParentUi;
  837. tnsObject*root=ui?ui->PP.EndInstance:0; if(!root) return 0;
  838. tnsMeshObject* mo=root->Active;
  839. if(mo->Base.Type!=TNS_OBJECT_MESH || mo->Mode!=TNS_MESH_EDIT_MODE){
  840. if(la_DeleteSelectedObjectsRecursive(root)){
  841. laRecordInstanceDifferences(&T->World, "tns_world"); laPushDifferences("Deleted objects", TNS_HINT_TRANSFORM); laNotifyUsers("tns.world");
  842. }
  843. }else{
  844. if(!tnsMMeshAnySelected(mo)) return LA_FINISHED;
  845. if(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"vertices")){
  846. la_DeleteVertices(mo);
  847. }elif(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"edges")){
  848. la_DeleteEdges(mo);
  849. }elif(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"faces")){
  850. la_DeleteFaces(mo,0);
  851. }elif(strSame(strGetArgumentString(a->ExtraInstructionsP, "mode"),"only_faces")){
  852. la_DeleteFaces(mo,1);
  853. }else{
  854. laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e);
  855. return LA_RUNNING;
  856. }
  857. tnsMMeshDeselectAll(mo);
  858. tnsMMeshRefreshIndex(mo);
  859. tnsInvaliateMeshBatch(mo);
  860. laRecordInstanceDifferences(mo, "tns_mesh_object"); laPushDifferences("Deleted primitives", TNS_HINT_GEOMETRY); laNotifyUsers("tns.world");
  861. }
  862. return LA_FINISHED;
  863. }
  864. void laui_Delete(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColumn *extracol, int context){
  865. laColumn* c=laFirstColumn(uil);
  866. laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=vertices;text=Vertices",0,0);
  867. laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=edges;text=Edges",0,0);
  868. laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=faces;text=Faces",0,0);
  869. laShowItemFull(uil,c,pp,"_this_M_delete",0,"mode=only_faces;text=Only Faces",0,0);
  870. }
  871. void la_RegisterModellingOperators(){
  872. laPropContainer *pc; laProp *p;
  873. laOperatorType *at;
  874. laEnumProp *ep;
  875. laCreateOperatorType("M_toggle_edit_mode", "Toggle Edit Mode", "Toggle edit mode of the active object", OPCHK_ThereIsActiveObject, 0, 0, OPINV_ToggleEdit, 0, 0, 0);
  876. laCreateOperatorType("M_select", "Select", "Select things in the viewport", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Select, OPMOD_Select, 0, LA_EXTRA_TO_PANEL);
  877. laCreateOperatorType("M_grab", "Grab", "Grab things and move around", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Grab, OPMOD_Transformation, 0, LA_EXTRA_TO_PANEL);
  878. laCreateOperatorType("M_scale", "Scale", "Scale selected things", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Scale, OPMOD_Transformation, 0, LA_EXTRA_TO_PANEL);
  879. laCreateOperatorType("M_rotate", "Rotate", "Rotation selected things", OPCHK_ViewportAndSceneExists, 0, 0, OPINV_Rotate, OPMOD_Transformation, 0, LA_EXTRA_TO_PANEL);
  880. 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);
  881. at->UiDefine = laui_MakeParent;
  882. at=laCreateOperatorType("M_unparent", "Unparent", "Unparent selected objects", 0, 0, 0, OPINV_MakeParent, OPMOD_FinishOnData, 0, 0);
  883. at->UiDefine = laui_Unparent;
  884. laCreateOperatorType("M_clear_transformations", "Clear Transformations", "Clear transformations in objects", 0, 0, 0, OPINV_ClearTransformation, 0, 0, 0);
  885. laCreateOperatorType("M_extrude", "Extrude", "Extrude parts of the mesh", 0, 0, 0, OPINV_Extrude, OPMOD_Transformation, 0, 0);
  886. at=laCreateOperatorType("M_delete", "Delete", "Delete parts of the mesh", 0, 0, 0, OPINV_Delete, OPMOD_FinishOnData, 0, 0);
  887. at->UiDefine=laui_Delete;
  888. }