*/}}
1
0

la_tns_shape.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * LaGUI: A graphical application framework.
  3. * Copyright (C) 2022-2023 Wu Yiming
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "la_5.h"
  19. #include <math.h>
  20. extern LA MAIN;
  21. extern tnsMain *T;
  22. tnsShape* tnsNewShape(tnsShapeObject* so){
  23. tnsShape* s=memAcquireSimple(sizeof(tnsShape));
  24. lstAppendItem(&so->Shapes,s); return s;
  25. }
  26. tnsSPoint* tnsNewSPoint(tnsShape* s,real x, real y,real ldx,real ldy, real rdx,real rdy){
  27. tnsSPoint* sp=memAcquireSimple(sizeof(tnsSPoint));
  28. tnsVectorSet2(sp->p,x,y); tnsVectorSet2(sp->dl,ldx,ldy); tnsVectorSet2(sp->dr,rdx,rdy);
  29. lstAppendItem(&s->Points,sp); return sp;
  30. }
  31. void tnsShapeRefreshIndex(tnsShapeObject* so){
  32. u32bit i; for(tnsShape* s=so->Shapes.pFirst;s;s=s->Item.pNext){
  33. for(tnsSPoint* sp=s->Points.pFirst;sp;sp=sp->Item.pNext){ sp->i=i; i++; }
  34. }
  35. }
  36. int tnsShapePointAnySelected(tnsShape* s){
  37. for(tnsSPoint* sp=s->Points.pFirst;sp;sp=sp->Item.pNext){ if(sp->flags&TNS_MESH_FLAG_SELECTED) return 1; } return 0;
  38. }
  39. int tnsShapeAnySelected(tnsShapeObject* so){
  40. for(tnsShape* s=so->Shapes.pFirst;s;s=s->Item.pNext){ if(tnsShapePointAnySelected(s)) return 1; } return 0;
  41. }
  42. void tnsShapeDeselectAll(tnsShapeObject* so){
  43. for(tnsShape* s=so->Shapes.pFirst;s;s=s->Item.pNext){
  44. for(tnsSPoint* sp=s->Points.pFirst;sp;sp=sp->Item.pNext){ sp->flags&=(~TNS_MESH_FLAG_SELECTED); }
  45. }
  46. }
  47. void tnsShapeSelectAll(tnsShapeObject* so){
  48. for(tnsShape* s=so->Shapes.pFirst;s;s=s->Item.pNext){
  49. for(tnsSPoint* sp=s->Points.pFirst;sp;sp=sp->Item.pNext){ sp->flags|=TNS_MESH_FLAG_SELECTED; }
  50. }
  51. }
  52. void tnsShapeSelectPoint(tnsShapeObject* so, tnsSPoint* sp, int select, int toggle){
  53. if(!so) return;
  54. if(toggle) tnsShapeSelectPoint(so,sp,(sp->flags&TNS_MESH_FLAG_SELECTED?0:1),0);
  55. elif(select) sp->flags|=TNS_MESH_FLAG_SELECTED; else sp->flags&=(~TNS_MESH_FLAG_SELECTED);
  56. //if(!so->FirstSelectV) so->FirstSelectV=sp; so->LastSelectV=sp;
  57. }
  58. void tnsShapeSelectRingFrom(tnsShapeObject* so, tnsSPoint* sp, int select, int toggle){
  59. int has_idle=0; laListHandle spl={sp->Item.pPrev,sp->Item.pNext};
  60. while(spl.pFirst && ((laListItem*)spl.pFirst)->pPrev){ spl.pFirst=((laListItem*)spl.pFirst)->pPrev; }
  61. while(spl.pLast && ((laListItem*)spl.pLast)->pNext){ spl.pLast=((laListItem*)spl.pLast)->pNext; }
  62. if(toggle){
  63. for(tnsSPoint* isp=spl.pFirst;isp;isp=isp->Item.pNext){
  64. if(isp!=sp && (!(isp->flags&TNS_MESH_FLAG_SELECTED))) has_idle=1;
  65. if(has_idle){ break; }
  66. }
  67. if(has_idle){ select=1; }else{ select=0; }
  68. }
  69. for(tnsSPoint* isp=spl.pFirst;isp;isp=isp->Item.pNext){
  70. if(select){ isp->flags|=TNS_MESH_FLAG_SELECTED; }else{ isp->flags&=(~TNS_MESH_FLAG_SELECTED); }
  71. }
  72. }
  73. void tnsShapeEnterEditMode(tnsShapeObject* so){
  74. if(so->Mode==TNS_MESH_EDIT_MODE) return;
  75. so->Mode = TNS_MESH_EDIT_MODE;
  76. tnsInvalidateEvaluation(so);
  77. }
  78. void tnsShapeLeaveEditMode(tnsShapeObject* so){
  79. if(so->Mode==TNS_MESH_OBJECT_MODE) return;
  80. so->Mode = TNS_MESH_OBJECT_MODE;
  81. tnsInvalidateEvaluation(so);
  82. }
  83. tnsShapeObject* tnsDuplicateShapeObject(tnsShapeObject* from){
  84. if(from->Base.Type!=TNS_OBJECT_SHAPE) return 0;
  85. tnsShapeObject* to = memAcquireHyper(sizeof(tnsShapeObject));
  86. tnsInitObjectBase(to, from->Base.ParentObject?from->Base.ParentObject:from->Base.InRoot, from->Base.Name->Ptr, TNS_OBJECT_SHAPE,0,0,0,0,0,0,0,0,1);
  87. tnsCopyObjectTransformationsLocal(to,from);
  88. tnsMaterialSlot* new_current=0;
  89. for(tnsMaterialSlot* ms=from->Materials.pFirst;ms;ms=ms->Item.pNext){
  90. tnsMaterialSlot* nms=tnsNewMaterialSlot(to); nms->Index=ms->Index;
  91. memAssignRef(nms,&nms->Material,ms->Material);
  92. if(ms==from->CurrentMaterial) new_current=nms;
  93. }
  94. memAssignRef(to,&to->CurrentMaterial,new_current);
  95. if(!from->Shapes.pFirst){ return to; }
  96. for(tnsShape* s=from->Shapes.pFirst;s;s=s->Item.pNext){
  97. tnsShape* ns=tnsNewShape(to); for(tnsSPoint* sp=s->Points.pFirst;sp;sp=sp->Item.pNext){
  98. tnsSPoint* nsp=tnsNewSPoint(ns,sp->p[0],sp->p[1],sp->dl[0],sp->dl[1],sp->dr[0],sp->dr[1]); nsp->flags=sp->flags;
  99. }
  100. ns->flags=s->flags;ns->mat=s->mat;
  101. }
  102. return to;
  103. }
  104. void tnsInitShapeSquare(tnsShapeObject* so, real size){
  105. tnsShape* s=tnsNewShape(so);
  106. tnsNewSPoint(s,-size,-size,0,0,0,0)->flags|=TNS_MESH_FLAG_SELECTED;
  107. tnsNewSPoint(s,-size,size,0,0,0,0)->flags|=TNS_MESH_FLAG_SELECTED;
  108. tnsNewSPoint(s,size,size,0,0,0,0)->flags|=TNS_MESH_FLAG_SELECTED;
  109. tnsNewSPoint(s,size,-size,0,0,0,0)->flags|=TNS_MESH_FLAG_SELECTED;
  110. tnsShapeRefreshIndex(so);
  111. }
  112. void tns_DrawShape(tnsShape* s, real* override_color, int DrawEdit, real PointScale){
  113. if(!s->Points.pFirst) return; int HasSelection=0;
  114. NVGcontext* vg=MAIN.CurrentWindow->nvg;
  115. if(DrawEdit==2){
  116. nvgShapeAntiAlias(vg,0);
  117. for(tnsSPoint* sp=s->Points.pFirst;sp;sp=sp->Item.pNext){ nvgBeginPath(vg); nvgCircle(vg,sp->p[0],sp->p[1],PointScale*1);
  118. real color[4]={0,0,0,1}; TNS_ID_TO_COLOR(color,sp->i+1);
  119. nvgFillColor(vg,nvgRGBAf(LA_COLOR4(color))); nvgFill(vg);
  120. }
  121. nvgShapeAntiAlias(vg,1);
  122. return;
  123. }
  124. nvgBeginPath(vg);
  125. tnsSPoint* sp1=s->Points.pFirst; nvgMoveTo(vg,sp1->p[0],sp1->p[1]); if(sp1->flags&TNS_MESH_FLAG_SELECTED){HasSelection=1;}
  126. for(tnsSPoint* sp=sp1->Item.pNext;sp;sp=sp->Item.pNext){
  127. nvgLineTo(vg,sp->p[0],sp->p[1]); if(sp->flags&TNS_MESH_FLAG_SELECTED){HasSelection=1;}
  128. }
  129. nvgClosePath(vg);
  130. nvgFillColor(vg, override_color?nvgRGBAf(LA_COLOR4(override_color)):nvgRGBAf(0.8,0.8,0.8,1));
  131. nvgFill(vg);
  132. if(DrawEdit){
  133. tnsVector4d color; tnsVectorCopy4d(laAccentColor(LA_BT_VERTEX),color);
  134. real* ActiveColor=laAccentColor(LA_BT_SVERTEX);
  135. if(!HasSelection) color[3]*=0.4;
  136. nvgStrokeColor(vg,nvgRGBAf(LA_COLOR4(color)));
  137. nvgStrokeWidth(vg,PointScale*4); nvgStroke(vg);
  138. for(tnsSPoint* sp=s->Points.pFirst;sp;sp=sp->Item.pNext){ nvgBeginPath(vg); nvgCircle(vg,sp->p[0],sp->p[1],PointScale*5);
  139. nvgFillColor(vg,sp->flags&TNS_MESH_FLAG_SELECTED?nvgRGBAf(LA_COLOR4(ActiveColor)):nvgRGBAf(LA_COLOR4(color)));
  140. nvgFill(vg);
  141. }
  142. }
  143. }
  144. void tnsDrawShapeObjectShapes(tnsEvaluatedInstance* ei, la3DObjectDrawExtra* de, real* override_color, int DrawEdit){
  145. tnsShapeObject* so=ei->Object; NVGcontext* vg=MAIN.CurrentWindow->nvg;
  146. real sca[3]; tnsExtractScale44d(ei->Mat,sca);
  147. real rot[3]; tnsExtractXYZEuler44d(ei->Mat,rot);
  148. nvgSave(vg);
  149. if(de->Is3D){
  150. tnsVector4d pos; tnsApplyTransform44d(pos,de->mViewProj,&ei->Mat[12]);
  151. pos[0]/=pos[3]; pos[1]/=pos[3];
  152. nvgTranslate(vg,pos[0]*de->W/2,pos[1]*de->H/2);
  153. nvgScale(vg,LA_RH*sca[0],LA_RH*sca[1]); nvgRotate(vg,rot[2]);
  154. }else{
  155. nvgTranslate(vg,ei->Mat[12],-ei->Mat[13]);
  156. nvgScale(vg,sca[0],-sca[1]); nvgRotate(vg,rot[2]);
  157. }
  158. for(tnsShape*s=so->Shapes.pFirst;s;s=s->Item.pNext){
  159. tns_DrawShape(s,override_color,DrawEdit?DrawEdit:(so->Mode==TNS_MESH_EDIT_MODE),de->PointScale/sca[0]);
  160. }
  161. nvgRestore(vg);
  162. }
  163. void tnsDrawShapeObject(tnsEvaluatedInstance* ei, la3DObjectDrawExtra* de){
  164. tnsDrawShapeObjectShapes(ei,de,0,0);
  165. }
  166. void tnsDrawShapeObjectSelectionID(tnsEvaluatedInstance* ei, la3DObjectDrawExtra* de){
  167. int i=ei->InstanceSelectionID; real color[4]={0,0,0,1}; TNS_ID_TO_COLOR(color,i);
  168. tnsDrawShapeObjectShapes(ei,de,color,0);
  169. }
  170. void tnsDrawShapePointsSelectionID(tnsEvaluatedInstance* ei, la3DObjectDrawExtra* de){
  171. tnsDrawShapeObjectShapes(ei,de,0,2);
  172. }
  173. void tnsDrawShapeObjectOverlay(tnsEvaluatedInstance* ei, la3DObjectDrawExtra* de){
  174. int i=ei->InstanceSelectionID; real color[4]; tnsVectorCopy4d(laAccentColor(LA_BT_ACTIVE),color);
  175. if(ei->Object!=ei->Object->InRoot->Active){ color[3]=0.4; }else{ color[3]=0.7; }
  176. tnsDrawShapeObjectShapes(ei,de,color,0);
  177. }
  178. void tnsEvaluateShapeObject(tnsShapeObject* so, tnsEvaluateData* ed){
  179. int DrawTo=TNS_EVAL_LAYER_SOLID;
  180. if(so->Backdrop){ DrawTo=TNS_EVAL_LAYER_BACKDROP; }
  181. tnsAddEvaluatedInstance(ed,so,tnsDrawShapeObject,DrawTo,0,0,0);
  182. if(ed->FillSelectionID){
  183. tnsAddEvaluatedInstance(ed,so,tnsDrawShapeObjectSelectionID,TNS_EVAL_LAYER_SELECTION,0,1,so->Base.SelectID);
  184. }
  185. if(ed->FillOutline && (!ed->OverrideID)){
  186. if((so->Base.Flags&TNS_OBJECT_FLAGS_SELECTED) && (so->Mode!=TNS_MESH_EDIT_MODE)){
  187. tnsAddEvaluatedInstance(ed,so,tnsDrawShapeObjectOverlay,TNS_EVAL_LAYER_OVERLAY,0,0,0);
  188. }
  189. }
  190. }
  191. tnsShapeObject *tnsCreateShapeEmpty(tnsObject *under, char *Name, real AtX, real AtY, real AtZ){
  192. tnsShapeObject *so = memAcquireHyper(sizeof(tnsShapeObject));
  193. tnsInitObjectBase(&so->Base, under, Name, TNS_OBJECT_SHAPE, AtX, AtY, AtZ, 0, 0, 0, 1.0f, TNS_ROTATION_XYZ_EULER, 1.0f);
  194. return so;
  195. }
  196. tnsShapeObject *tnsCreateShapeSquare(tnsObject *under, char *Name, real AtX, real AtY, real AtZ, real size){
  197. tnsShapeObject *so=tnsCreateShapeEmpty(under, Name, AtX, AtY, AtZ);
  198. tnsInitShapeSquare(so, size);
  199. return so;
  200. }