*/}}

la_modelling.c 46 KB

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