Team Ai
Datasetpublic

hschumann2/TempleOS-Source-Code

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes847downloads
SpriteEd.txt1185 linesDownload Raw Back to Gr
1 2#help_index "Graphics/Sprite;Sprites"3 4CSprite *SpriteSetSettings(CDC *dc=NULL,CSprite *head,I64 elem_num,5        I64 x=0,I64 y=0,CColorROPU32 *_color=NULL,I64 *_thick=NULL,6        I64 *_xx=NULL,I64 *_yy=NULL)7{8  CSprite *res=head->next;9  I64 thick=1,xx=0,yy=0;10  CColorROPU32 color=BLACK;11  if (dc) DCRst(dc);12  while (elem_num-->0 && res!=head) {13    switch (res->type&SPG_TYPE_MASK) {14      case SPT_COLOR:15        color=res->c.color;16        if (dc) dc->color=color;17        break;18      case SPT_DITHER_COLOR:19        color=res->d.dither_color.u8[0]|20              res->d.dither_color.u8[1]<<COLORROP_BITS|ROPF_DITHER;21        if (dc) dc->color=color;22        break;23      case SPT_THICK:24        thick=res->t.thick;25        if (dc) dc->thick=thick;26        break;27      case SPT_SHIFT:28        xx+=res->p.x1;29        yy+=res->p.y1;30        x+=res->p.x1;31        y+=res->p.y1;32        break;33      case SPT_PLANAR_SYMMETRY:34        if (dc) {35          if (DCSymmetry3Set(dc,res->pp.x1+x,res->pp.y1+y,0,36                res->pp.x2+x,res->pp.y2+y,0,37                res->pp.x2+x,res->pp.y2+y,1))38            dc->flags|=DCF_SYMMETRY;39          else40            dc->flags&=~DCF_SYMMETRY;41        }42        break;43    }44    res=res->next;45  }46  if (_color) *_color=color;47  if (_thick) *_thick=thick;48  if (_xx) *_xx=xx;49  if (_yy) *_yy=yy;50  return res;51}52 53Bool SpritePolyPtPlot(CSprite *head,I64 x,I64 y,I64)54{55  CSprite *tmpg=CAlloc(SpriteElemQuedBaseSize(SPT_PT));56  tmpg->type=SPT_PT;57  tmpg->p.x1=x;58  tmpg->p.y1=y;59  QueIns(tmpg,head->last);60  return TRUE;61}62 63CSprite *Sprite2SpriteQue(U8 *elems)64{65  I64 s;66  CSprite *res=CAlloc(sizeof(CSprite)),67        *tmpg=elems-offset(CSprite.start),*tmpg1;68  QueInit(res);69  while (tmpg->type&SPG_TYPE_MASK) {70    tmpg1=MAlloc(SpriteElemSize(tmpg)+offset(CSprite.start));71    s=SpriteElemSize(tmpg);72    MemCpy(&tmpg1->start,&tmpg->start,s);73    QueIns(tmpg1,res->last);74    tmpg(U8 *)+=s;75  }76  return res;77}78 79U8 *SpriteQue2Sprite(CSprite *head,I64 *_size=NULL)80{81  I64 i,size=sprite_elem_base_sizes[SPT_END];82  CSprite *tmpg=head->next;83  U8 *res,*dst;84  while (tmpg!=head) {85    size+=SpriteElemSize(tmpg);86    tmpg=tmpg->next;87  }88  if (_size) *_size=size;89  res=dst=MAlloc(size);90  tmpg=head->next;91  while (tmpg!=head) {92    i=SpriteElemSize(tmpg);93    MemCpy(dst,&tmpg->start,i);94    dst+=i;95    tmpg=tmpg->next;96  }97  *dst=SPT_END;98  return res;99}100 101U0 SpriteEdUpdate(CDoc *doc,CDocEntry *doc_ce,CSprite *head)102{103  CDocBin *tmpb=doc_ce->bin_data;104  I64 size;105  Bool unlock=DocLock(doc);106  Free(tmpb->data);107  tmpb->data=SpriteQue2Sprite(head,&size);108  tmpb->size=size;109  if (unlock)110    DocUnlock(doc);111}112 113U0 SpriteSetOrigin(CSprite *head,I64 dx,I64 dy,I64 dz)114{115  I64 i;116  I32 *ptr;117  CD3I32 *p;118  CSprite *tmpg=head->next;119  while (tmpg!=head) {120    if (Bt(&tmpg->type,SPf_SEL))121      switch (tmpg->type&SPG_TYPE_MASK) {122        case SPT_ARROW:123        case SPT_LINE:124        case SPT_PLANAR_SYMMETRY:125        case SPT_RECT:126        case SPT_ROTATED_RECT:127          tmpg->pp.x2+=dx;128          tmpg->pp.y2+=dy;129        case SPT_PT:130        case SPT_FLOOD_FILL:131        case SPT_FLOOD_FILL_NOT:132        case SPT_TEXT:133        case SPT_TEXT_BOX:134        case SPT_TEXT_DIAMOND:135        case SPT_CIRCLE:136        case SPT_BITMAP:137        case SPT_ELLIPSE:138        case SPT_POLYGON:139          tmpg->p.x1+=dx;140          tmpg->p.y1+=dy;141          break;142        case SPT_POLYLINE:143          ptr=&tmpg->nu.u;144          for (i=0;i<tmpg->nu.num;i++) {145            ptr[i<<1]+=dx;146            ptr[i<<1+1]+=dy;147          }148          break;149        case SPT_POLYPT:150          tmpg->npu.x+=dx;151          tmpg->npu.y+=dy;152          break;153        case SPT_BSPLINE2:154        case SPT_BSPLINE3:155        case SPT_BSPLINE2_CLOSED:156        case SPT_BSPLINE3_CLOSED:157          p=&tmpg->nu.u;158          for (i=0;i<tmpg->nu.num;i++,p++) {159            p->x+=dx;160            p->y+=dy;161            p->z+=dz;162          }163          break;164        case SPT_MESH:165          p=&tmpg->mu.u;166          for (i=0;i<tmpg->mu.vertex_cnt;i++,p++) {167            p->x+=dx;168            p->y+=dy;169            p->z+=dz;170          }171          break;172        case SPT_SHIFTABLE_MESH:173          tmpg->pmu.x+=dx;174          tmpg->pmu.y+=dy;175          tmpg->pmu.z+=dz;176          break;177      }178    tmpg=tmpg->next;179  }180}181 182CSprite *SpriteTransformCircle(I64 *r,CSprite *tmpg)183{184  I64 x,y,z;185  F64 m1,arg1,m2,radius=tmpg->pr.radius<<16;186  CSprite *tmpg1=CAlloc(SpriteElemQuedBaseSize(SPT_ELLIPSE));187  tmpg1->type=SPT_ELLIPSE;188 189  x=tmpg->pr.x1; y=tmpg->pr.y1; z=0;190  Mat4x4MulXYZ(r,&x,&y,&z);191  tmpg1->pwha.x1=x;192  tmpg1->pwha.y1=y;193 194  x=radius; y=0; z=0;195  Mat4x4MulXYZ(r,&x,&y,&z);196  R2P(&m1,&arg1,x,y);197 198  x=0; y=radius; z=0;199  Mat4x4MulXYZ(r,&x,&y,&z);200  m2=Sqrt(x*x+y*y);201 202  tmpg1->pwha.width =ToI64(m1)/0x10000;203  tmpg1->pwha.height=ToI64(m2)/0x10000;204  tmpg1->pwha.angle=-arg1;205 206  tmpg1->type|=tmpg->type&SPF_SEL;207  return tmpg1;208}209 210CSprite *SpriteTransformEllipse(I64 *r,CSprite *tmpg)211{212  I64 x,y,z;213  F64 m1,arg1,m2,arg2,s,c,x_radius=tmpg->pwha.width<<16,214        y_radius=tmpg->pwha.height<<16;215  CSprite *tmpg1=CAlloc(SpriteElemQuedBaseSize(tmpg->type&SPG_TYPE_MASK));216  tmpg1->type=tmpg->type;217  if (tmpg->type&SPG_TYPE_MASK==SPT_POLYGON)218    tmpg1->pwhas.sides=tmpg->pwhas.sides;219 220  x=tmpg->pwha.x1; y=tmpg->pwha.y1; z=0;221  Mat4x4MulXYZ(r,&x,&y,&z);222  tmpg1->pwha.x1=x;223  tmpg1->pwha.y1=y;224 225  c=Cos(-tmpg->pwha.angle);226  s=Sin(-tmpg->pwha.angle);227 228  x=x_radius*c;229  y=x_radius*s;230  z=0;231  Mat4x4MulXYZ(r,&x,&y,&z);232  R2P(&m1,&arg1,x,y);233 234  x=-y_radius*s;235  y=y_radius*c;236  z=0;237  Mat4x4MulXYZ(r,&x,&y,&z);238  R2P(&m2,&arg2,x,y);239  m2*=Abs(Sin(arg2-arg1));240 241  tmpg1->pwha.width=ToI64(m1)/0x10000;242  if (tmpg1->pwha.width<1) tmpg1->pwha.width=1;243  tmpg1->pwha.height=ToI64(m2)/0x10000;244  if (tmpg1->pwha.height<1) tmpg1->pwha.height=1;245  tmpg1->pwha.angle=-arg1;246 247  tmpg1->type|=tmpg->type&SPF_SEL;248  return tmpg1;249}250 251CSprite *SpriteTransformRect(I64 *r,CSprite *tmpg,F64 theta)252{253  I64 x,y,z,w,h;254  F64 m1,arg1,m2,arg2,s,c,255        x_radius=(tmpg->pp.x2-tmpg->pp.x1)<<16,256        y_radius=(tmpg->pp.y2-tmpg->pp.y1)<<16;257  CSprite *tmpg1=CAlloc(SpriteElemQuedBaseSize(SPT_ROTATED_RECT));258  tmpg1->type=SPT_ROTATED_RECT;259 260  x=tmpg->pp.x1; y=tmpg->pp.y1; z=0;261  Mat4x4MulXYZ(r,&x,&y,&z);262  tmpg1->ppa.x1=x;263  tmpg1->ppa.y1=y;264 265  c=Cos(-theta);266  s=Sin(-theta);267 268  x=x_radius*c;269  y=x_radius*s;270  z=0;271  Mat4x4MulXYZ(r,&x,&y,&z);272  R2P(&m1,&arg1,x,y);273 274  x=-y_radius*s;275  y=y_radius*c;276  z=0;277  Mat4x4MulXYZ(r,&x,&y,&z);278  R2P(&m2,&arg2,x,y);279  m2*=Abs(Sin(arg2-arg1));280 281  w=ToI64(m1)/0x10000;282  if (w<1) w=1;283  h=ToI64(m2)/0x10000;284  if (h<1) h=1;285  tmpg1->ppa.x2=tmpg1->ppa.x1+w;286  tmpg1->ppa.y2=tmpg1->ppa.y1+h;287  tmpg1->ppa.angle=-arg1;288 289  tmpg1->type|=tmpg->type&SPF_SEL;290  return tmpg1;291}292 293CSprite *SpriteTransformBitMap(I64 *r,CSprite *tmpg)294{295  CDC *img,*dc3;296  U8 *elems;297  I64 x,y,z,minx,maxx,miny,maxy,minz,maxz;298  CSprite *tmpg1;299 300  x=0; y=0; z=0;301  Mat4x4MulXYZ(r,&x,&y,&z);302  minx=maxx=x;303  miny=maxy=y;304  minz=maxz=z;305 306  x=0; y=tmpg->pwhu.height; z=0;307  Mat4x4MulXYZ(r,&x,&y,&z);308  if (x<minx) minx=x;309  if (x>maxx) maxx=x;310  if (y<minx) miny=y;311  if (y>maxx) maxy=y;312  if (z<minx) minz=z;313  if (z>maxx) maxz=z;314 315  x=tmpg->pwhu.width; y=0; z=0;316  Mat4x4MulXYZ(r,&x,&y,&z);317  if (x<minx) minx=x;318  if (x>maxx) maxx=x;319  if (y<minx) miny=y;320  if (y>maxx) maxy=y;321  if (z<minx) minz=z;322  if (z>maxx) maxz=z;323 324  x=tmpg->pwhu.width; y=tmpg->pwhu.height; z=0;325  Mat4x4MulXYZ(r,&x,&y,&z);326  if (x<minx) minx=x;327  if (x>maxx) maxx=x;328  if (y<minx) miny=y;329  if (y>maxx) maxy=y;330  if (z<minx) minz=z;331  if (z>maxx) maxz=z;332 333  dc3=DCNew(maxx-minx+1,maxy-miny+1);334 335  img=CAlloc(sizeof(CDC));336  img->width=tmpg->pwhu.width;337  img->width_internal=(tmpg->pwhu.width+7)&~7;338  img->height=tmpg->pwhu.height;339  img->body=&tmpg->pwhu.u;340  img->dc_signature=DCS_SIGNATURE_VAL;341 342  dc3->color=TRANSPARENT;343  GrRect(dc3,0,0,maxx-minx+1,maxy-miny+1);344 345  Free(dc3->r);346  DCMat4x4Set(dc3,r);347  dc3->flags|=DCF_TRANSFORMATION;348 349  dc3->x=-minx;350  dc3->y=-miny;351  dc3->z=-minz;352  GrBlot3(dc3,0,0,0,img);353  Free(img);354 355  elems=DC2Sprite(dc3);356  dc3->r=NULL;357  DCDel(dc3);358  tmpg1=CAlloc(offset(CSprite.start)+MSize(elems));359  MemCpy(tmpg1(U8 *)+offset(CSprite.start),elems,MSize(elems));360  tmpg1->type=tmpg->type;361 362  x=tmpg->pwhu.x1; y=tmpg->pwhu.y1; z=0;363  Mat4x4MulXYZ(r,&x,&y,&z);364  tmpg1->pwhu.x1=x;365  tmpg1->pwhu.y1=y;366 367  x=0; y=0; z=0;368  Mat4x4MulXYZ(r,&x,&y,&z);369  tmpg1->pwhu.x1+=minx-x;370  tmpg1->pwhu.y1+=miny-y;371 372  return tmpg1;373}374 375U0 SpriteTransformQue(CSprite *head,I64 *r)376{377  I64 i,j,k,num,x,y,z,x1,y1,z1,x2,y2,z2,x3,y3,z3;378  I32 *ptr;379  CD3I32 *p;380  CSprite *tmpg=head->next,head2,*tmpg1,*tmpg2,*tmpg3;381  while (tmpg!=head) {382    if (Bt(&tmpg->type,SPf_SEL))383      switch (tmpg->type&SPG_TYPE_MASK) {384        case SPT_THICK:385          tmpg->t.thick*=Sqrt(Mat4x4NormSqr65536(r))/65536;386          if (tmpg->t.thick<0) tmpg->t.thick=0;387          break;388        case SPT_PLANAR_SYMMETRY:389        case SPT_ARROW:390        case SPT_LINE:391          x=tmpg->pp.x2; y=tmpg->pp.y2; z=0;392          Mat4x4MulXYZ(r,&x,&y,&z);393          tmpg->pp.x2=x;394          tmpg->pp.y2=y;395        case SPT_PT:396        case SPT_FLOOD_FILL:397        case SPT_FLOOD_FILL_NOT:398        case SPT_TEXT:399        case SPT_TEXT_BOX:400        case SPT_TEXT_DIAMOND:401          x=tmpg->p.x1; y=tmpg->p.y1; z=0;402          Mat4x4MulXYZ(r,&x,&y,&z);403          tmpg->p.x1=x;404          tmpg->p.y1=y;405          break;406        case SPT_BITMAP:407          tmpg1=SpriteTransformBitMap(r,tmpg);408          QueIns(tmpg1,tmpg);409          QueRem(tmpg);410          Free(tmpg);411          tmpg=tmpg1;412          break;413        case SPT_ROTATED_RECT:414          tmpg1=SpriteTransformRect(r,tmpg,tmpg->ppa.angle);415          QueIns(tmpg1,tmpg);416          QueRem(tmpg);417          Free(tmpg);418          tmpg=tmpg1;419          break;420        case SPT_RECT:421          tmpg1=SpriteTransformRect(r,tmpg,0);422          QueIns(tmpg1,tmpg);423          QueRem(tmpg);424          Free(tmpg);425          tmpg=tmpg1;426          break;427        case SPT_CIRCLE:428          tmpg1=SpriteTransformCircle(r,tmpg);429          QueIns(tmpg1,tmpg);430          QueRem(tmpg);431          Free(tmpg);432          tmpg=tmpg1;433          break;434        case SPT_ELLIPSE:435        case SPT_POLYGON:436          tmpg1=SpriteTransformEllipse(r,tmpg);437          QueIns(tmpg1,tmpg);438          QueRem(tmpg);439          Free(tmpg);440          tmpg=tmpg1;441          break;442        case SPT_POLYLINE:443          ptr=&tmpg->nu.u;444          for (i=0;i<tmpg->nu.num;i++) {445            x=ptr[i<<1]; y=ptr[i<<1+1]; z=0;446            Mat4x4MulXYZ(r,&x,&y,&z);447            ptr[i<<1]=x;448            ptr[i<<1+1]=y;449          }450          break;451        case SPT_POLYPT:452          QueInit(&head2);453          x=tmpg->npu.x; y=tmpg->npu.y; z=0;454          x1=x; y1=y; z1=z;  //unrotated cur coordinates455          Mat4x4MulXYZ(r,&x,&y,&z);456          ptr=&tmpg->npu.u;457          k=tmpg->npu.num*3;458          x2=x; y2=y; z2=z;  //rotated start coordinates459          x3=x; y3=y; z3=z;  //lag 1 rotated coordinates460          for (i=0;i<k;i+=3) {461            j=BFieldExtU32(ptr,i,3);462            x1+=gr_x_offsets[j];463            y1+=gr_y_offsets[j];464            x=x1; y=y1; z=z1;465            Mat4x4MulXYZ(r,&x,&y,&z);466            Line(&head2,x3-x2,y3-y2,0,x-x2,y-y2,0,&SpritePolyPtPlot);467            x3=x; y3=y; z3=z;468          }469 470          num=0;471          tmpg1=head2.next;472          x3=0; y3=0; z3=0;473          while (tmpg1!=&head2) {474            tmpg2=tmpg1->next;475            if (tmpg1->p.x1==x3 && tmpg1->p.y1==y3) {476              QueRem(tmpg1);477              Free(tmpg1);478            } else {479              num++;480              x3=tmpg1->p.x1;481              y3=tmpg1->p.y1;482            }483            tmpg1=tmpg2;484          }485 486          tmpg3=CAlloc(SpriteElemQuedBaseSize(SPT_POLYPT)+(num*3+7)>>3);487          tmpg3->npu.x=x2;488          tmpg3->npu.y=y2;489          ptr=&tmpg3->npu.u;490          x3=0;y3=0; z3=0;491          i=0;492          tmpg1=head2.next;493          while (tmpg1!=&head2) {494            tmpg2=tmpg1->next;495            BFieldOrU32(ptr,i,496                  polypt_map[SignI64(tmpg1->p.x1-x3)+1+497                  3*(SignI64(tmpg1->p.y1-y3)+1)]);498            i+=3;499            x3=tmpg1->p.x1;y3=tmpg1->p.y1;500            QueRem(tmpg1);501            Free(tmpg1);502            tmpg1=tmpg2;503          }504          tmpg3->type=SPT_POLYPT|tmpg->type&SPF_SEL;505          tmpg3->npu.num=num;506          QueIns(tmpg3,tmpg);507          QueRem(tmpg);508          Free(tmpg);509          tmpg=tmpg3;510          break;511        case SPT_BSPLINE2:512        case SPT_BSPLINE3:513        case SPT_BSPLINE2_CLOSED:514        case SPT_BSPLINE3_CLOSED:515          p=&tmpg->nu.u;516          for (i=0;i<tmpg->nu.num;i++,p++) {517            x=p->x; y=p->y; z=p->z;518            Mat4x4MulXYZ(r,&x,&y,&z);519            p->x=x;520            p->y=y;521            p->z=z;522          }523          break;524        case SPT_SHIFTABLE_MESH:525          x=tmpg->pmu.x; y=tmpg->pmu.y; z=tmpg->pmu.z;526          Mat4x4MulXYZ(r,&x,&y,&z);527          tmpg->pmu.x=x;528          tmpg->pmu.y=y;529          tmpg->pmu.z=z;530          p=&tmpg->pmu.u;531          for (i=0;i<tmpg->pmu.vertex_cnt;i++,p++) {532            x=p->x; y=p->y; z=p->z;533            Mat4x4MulXYZ(r,&x,&y,&z);534            p->x=x;535            p->y=y;536            p->z=z;537          }538          break;539        case SPT_MESH:540          p=&tmpg->mu.u;541          for (i=0;i<tmpg->mu.vertex_cnt;i++,p++) {542            x=p->x; y=p->y; z=p->z;543            Mat4x4MulXYZ(r,&x,&y,&z);544            p->x=x;545            p->y=y;546            p->z=z;547          }548          break;549      }550    tmpg=tmpg->next;551  }552}553 554I64 SpriteQueSelCnt(CSprite *head,Bool val=TRUE)555{556  I64 res=0;557  CSprite *tmpg=head->next;558  val=ToBool(val);559  while (tmpg!=head) {560    if (Bt(&tmpg->type,SPf_SEL)==val)561      res++;562    tmpg=tmpg->next;563  }564  return res;565}566 567I64 SpriteQueSelAll(CSprite *head,Bool val=TRUE)568{569  I64 res=0;570  CSprite *tmpg=head->next;571  while (tmpg!=head) {572    BEqu(&tmpg->type,SPf_SEL,val);573    res++;574    tmpg=tmpg->next;575  }576  return res;577}578 579Bool SpriteEdText(CSprite **_head,I64 *_cur_elem_num)580{581  Bool res;582  CSprite *head=*_head;583  U8 *elems=SpriteQue2Sprite(head);584  CDoc *doc=DocNew,*doc2,*old_put=DocPut;585  StrPrint(doc->filename.name,"AI:0x%X",doc);586  DocPrint(doc,"//$PURPLE$$TX+CX,\"Sprite Edit as Text\"$$FG$\n"587        "//$LK+PU+CX,\"Click for Help\","588        "A=\"FI:::/Doc/SpriteEdText.DD.Z\"$\n\n");589  Sprite2Code(doc,elems);590  Free(elems);591  while (TRUE) {592    if (res=PopUpPrint("DocEd(0x%X,0x%X);",doc,0)) {593      Fs->put_doc=doc2=DocNew;594      "$WW,1$";595      if (elems=Code2Sprite(doc)) {596        DocDel(doc2);597        Fs->put_doc=old_put;598        QueDel(head);599        Free(head);600        head=Sprite2SpriteQue(elems);601        Free(elems);602        *_cur_elem_num=QueCnt(head); //TODO: Might want to improve this.603        break;604      } else {605        PopUpPrint("DocEd(0x%X,0x%X);",doc2,0);606        DocDel(doc2);607        Fs->put_doc=old_put;608      }609    } else610      break;611  }612  DocDel(doc);613  if (_head) *_head=head;614  return res;615}616 617#define SPED_SEL_UNSEL_ALL      0618#define SPED_SEL                2619#define SPED_SEL_RECTS          3620#define SPED_UNSEL              4621#define SPED_UNSEL_RECTS        5622#define SPED_SHIFT_PTS          6623#define SPED_SHIFT_RECTS        7624#define SPED_SHIFT_SEL          8625#define SPED_TRANSFORM_SEL      9626#define SPED_SET_ORIGIN         10627#define SPED_SHIFT_SUB_ORIGIN   11628#define SPED_TEXT_ED            12629#define SPED_INS_CLIP           13630#define SPED_MAIN_MENU          14631#define SPED_EXIT               15632 633U0 GrInit3()634{635  DefineLstLoad("ST_SPRITE_ED_MENU","Select/Unselect All\0 \0Select\0"636        "Select Rects\0Unselect\0Unselect Rects\0Shift Points\0Shift Rects\0"637        "Shift Selected\0Transform Selected\0Set Origin\0"638        "Insert Shift SubOrigin\0Edit as Text\0Insert Clip\0Main Menu\0");639}640GrInit3;641 642I64 PopUpSpriteEd(CSprite **_head,I64 *_cur_elem_num)643{644  U8 *st;645  CTask *pu_task;646  I64 res;647  CDoc *doc=DocNew;648  DocPrint(doc,"$PURPLE$$TX+CX,\"Sprite Edit Menu\"$\n"649        "$LK+PU+CX,\"Click for Help\",A=\"FI:::/Doc/SpriteEd.DD.Z\"$\n\n"650        "$LTBLUE$$MU-UL,\"Select/Unselect All\",LE=SPED_SEL_UNSEL_ALL$\n"651        "$MU-UL,\"Select Elems\",LE=SPED_SEL$\n"652        "$MU-UL,\"Select Elems with Rects\",LE=SPED_SEL_RECTS$\n"653        "$MU-UL,\"Unsel Elems\",LE=SPED_UNSEL$\n"654        "$MU-UL,\"Unsel Elems with Rects\",LE=SPED_UNSEL_RECTS$\n\n"655        "$MU-UL,\"Shift Points\",LE=SPED_SHIFT_PTS$\n"656        "$MU-UL,\"Shift Points with Rects\",LE=SPED_SHIFT_RECTS$\n"657        "$MU-UL,\"Shift Selected Elems\",LE=SPED_SHIFT_SEL$\n"658        "$MU-UL,\"Transform Selected Elems\",LE=SPED_TRANSFORM_SEL$\n\n"659        "$MU-UL,\"Set Origin\",LE=SPED_SET_ORIGIN$\n"660        "$MU-UL,\"Insert Shift SubOrigin\",LE=SPED_SHIFT_SUB_ORIGIN$\n\n"661        "$MU-UL,\"Edit as Text\",LE=SPED_TEXT_ED$\n"662        "$MU-UL,\"Insert Clip Sprite's\",LE=SPED_INS_CLIP$\n\n"663        "$PURPLE$$MU-UL,\"+] Sprite Main Menu\",LE=SPED_MAIN_MENU$$LTBLUE$\n"664        "$MU-UL,\"Exit  Sprite\",LE=SPED_EXIT$\n"665        "$MU-UL,\"Abort Sprite\",LE=DOCM_CANCEL$");666  st=MStrPrint("SpriteSideBarTask(0x%X,0x%X,0x%X);",Fs,_head,_cur_elem_num);667  PopUp(st,NULL,&pu_task);668  Free(st);669  res=PopUpMenu(doc);670  if (TaskValidate(pu_task)) {671    *_head=SpriteSideBar2SpriteQue(DocPut(pu_task),*_head,_cur_elem_num);672    Kill(pu_task);673  }674  DocDel(doc);675  return res;676}677 678#define SPEDT_SIMPLE_PT         0679#define SPEDT_WIDTH_HEIGHT      1680 681#define SPEDF_SEL               1682 683class CEdSprite684{685  CEdSprite *next,*last;686  CSprite *g;687  I32 type,num,flags,xx,yy,zz;688  I32 *x,*y,*z,*w,*h;689};690 691CEdSprite *EdSpriteNew(I64 type,CSprite *tmpg)692{693  CEdSprite *res=CAlloc(sizeof(CEdSprite));694  res->g=tmpg;695  if (tmpg->type&SPF_SEL)696    res->flags|=SPEDF_SEL;697  res->type=type;698  return res;699}700 701U0 SpritePtQueNew(U8 *elems,I64 x,I64 y,CEdSprite *head)702{703  I64 i,num=0;704  I32 *ptr;705  CD3I32 *p;706  CEdSprite *tmpes;707  CSprite *tmpg=elems-offset(CSprite.start);708  QueInit(head);709  while (tmpg->type&SPG_TYPE_MASK) {710    switch (tmpg->type&SPG_TYPE_MASK) {711      case SPT_ELLIPSE:712      case SPT_POLYGON:713        tmpes=EdSpriteNew(SPEDT_WIDTH_HEIGHT,tmpg);714        tmpes->xx=x;715        tmpes->yy=y;716        tmpes->x=&tmpg->pwha.x1;717        tmpes->y=&tmpg->pwha.y1;718        tmpes->w=&tmpg->pwha.width;719        tmpes->h=&tmpg->pwha.height;720        tmpes->num=num;721        QueIns(tmpes,head->last);722        goto pq_x1_y1;723      case SPT_RECT:724      case SPT_ROTATED_RECT:725      case SPT_LINE:726      case SPT_ARROW:727      case SPT_PLANAR_SYMMETRY:728        tmpes=EdSpriteNew(SPEDT_SIMPLE_PT,tmpg);729        tmpes->xx=x;730        tmpes->yy=y;731        tmpes->x=&tmpg->pp.x2;732        tmpes->y=&tmpg->pp.y2;733        tmpes->num=num;734        QueIns(tmpes,head->last);735      case SPT_TEXT:736      case SPT_TEXT_BOX:737      case SPT_TEXT_DIAMOND:738      case SPT_PT:739      case SPT_BITMAP:740      case SPT_FLOOD_FILL:741      case SPT_FLOOD_FILL_NOT:742      case SPT_CIRCLE:743pq_x1_y1:744        tmpes=EdSpriteNew(SPEDT_SIMPLE_PT,tmpg);745        tmpes->xx=x;746        tmpes->yy=y;747        tmpes->x=&tmpg->p.x1;748        tmpes->y=&tmpg->p.y1;749        tmpes->num=num;750        QueIns(tmpes,head->last);751        break;752      case SPT_SHIFT:753        x+=tmpg->p.x1;754        y+=tmpg->p.y1;755        break;756      case SPT_POLYLINE:757        ptr=&tmpg->nu.u;758        for (i=0;i<tmpg->nu.num;i++) {759          tmpes=EdSpriteNew(SPEDT_SIMPLE_PT,tmpg);760          tmpes->xx=x;761          tmpes->yy=y;762          tmpes->x=&ptr[i<<1];763          tmpes->y=&ptr[i<<1+1];764          tmpes->num=num;765          QueIns(tmpes,head->last);766        }767        break;768      case SPT_POLYPT:769        tmpes=EdSpriteNew(SPEDT_SIMPLE_PT,tmpg);770        tmpes->xx=x;771        tmpes->yy=y;772        tmpes->x=&tmpg->npu.x;773        tmpes->y=&tmpg->npu.y;774        tmpes->num=num;775        QueIns(tmpes,head->last);776        break;777      case SPT_BSPLINE2:778      case SPT_BSPLINE3:779      case SPT_BSPLINE2_CLOSED:780      case SPT_BSPLINE3_CLOSED:781        p=&tmpg->nu.u;782        for (i=0;i<tmpg->nu.num;i++) {783          tmpes=EdSpriteNew(SPEDT_SIMPLE_PT,tmpg);784          tmpes->xx=x;785          tmpes->yy=y;786          tmpes->x=&p[i].x;787          tmpes->y=&p[i].y;788          tmpes->z=&p[i].z;789          tmpes->num=num;790          QueIns(tmpes,head->last);791        }792        break;793      case SPT_MESH:794        break;795      case SPT_SHIFTABLE_MESH:796        tmpes=EdSpriteNew(SPEDT_SIMPLE_PT,tmpg);797        tmpes->xx=x;798        tmpes->yy=y;799        tmpes->x=&tmpg->pmu.x;800        tmpes->y=&tmpg->pmu.y;801        tmpes->z=&tmpg->pmu.z;802        tmpes->num=num;803        QueIns(tmpes,head->last);804        break;805    }806    tmpg(U8 *)+=SpriteElemSize(tmpg);807    num++;808  }809}810 811U0 SpriteCtrlPtsDraw(CDC *dc,CEdSprite *head)812{813  I64 x,y;814  CEdSprite *tmpes;815  Refresh;816  DCFill(dc);817  if (Blink(20)) {818    tmpes=head->next;819    while (tmpes!=head) {820      switch (tmpes->type) {821        case SPEDT_SIMPLE_PT:822          x=*tmpes->x+tmpes->xx;823          y=*tmpes->y+tmpes->yy;824          break;825        case SPEDT_WIDTH_HEIGHT:826          x=*tmpes->w+*tmpes->x+tmpes->xx;827          y=*tmpes->h+*tmpes->y+tmpes->yy;828          break;829      }830      if (tmpes->flags&SPEDF_SEL)831        dc->color=RED;832      else833        dc->color=BLACK;834      GrRect(dc,x-2,y-2,4,4);835      dc->color=WHITE;836      GrRect(dc,x-1,y-1,2,2);837      tmpes=tmpes->next;838    }839  }840}841 842U0 SpriteCtrlPtsMove(CEdSprite *head,I64 dx,I64 dy)843{844  CEdSprite *tmpes;845  tmpes=head->next;846  while (tmpes!=head) {847    if (tmpes->flags&SPEDF_SEL)848      switch (tmpes->type) {849        case SPEDT_SIMPLE_PT:850          if (tmpes->x) *tmpes->x+=dx;851          if (tmpes->y) *tmpes->y+=dy;852          break;853        case SPEDT_WIDTH_HEIGHT:854          if (tmpes->w) *tmpes->w+=dx;855          if (tmpes->h) *tmpes->h+=dy;856          break;857      }858    tmpes=tmpes->next;859  }860}861 862Bool SpriteSelUnselShiftPts(U8 *elems,I64 x,I64 y,I64 *_cur_elem_num,I64 mode)863{864  I64 msg_code,arg1,arg2,xx,yy,xx2,yy2,dd,best_dd,cur_elem_num;865  Bool res=TRUE;866  CDC *dc=DCAlias;867  CEdSprite head,*tmpes,*best_es;868 869  SpritePtQueNew(elems,x,y,&head);870  cur_elem_num=0;871  if (head.next!=&head) {872    while (TRUE) {873      SpriteCtrlPtsDraw(dc,&head); //has Refresh874      switch (msg_code=ScanMsg(&arg1,&arg2,875            1<<MSG_MS_R_UP|1<<MSG_MS_L_DOWN|1<<MSG_KEY_DOWN)) {876        case MSG_MS_L_DOWN:877          switch (mode) {878            case SPED_SEL:879            case SPED_UNSEL:880            case SPED_SHIFT_PTS:881              xx=arg1; yy=arg2;882              best_dd=I64_MAX;883              tmpes=head.next;884              while (tmpes!=&head) {885                switch (tmpes->type) {886                  case SPEDT_SIMPLE_PT:887                    dd=SqrI64(*tmpes->x+tmpes->xx-xx)+888                          SqrI64(*tmpes->y+tmpes->yy-yy);889                    break;890                  case SPEDT_WIDTH_HEIGHT:891                    dd=SqrI64(*tmpes->x+*tmpes->w+tmpes->xx-xx)+892                          SqrI64(*tmpes->y+*tmpes->h+tmpes->yy-yy);893                    break;894                }895                if (dd<best_dd) {896                  best_dd=dd;897                  best_es=tmpes;898                }899                tmpes=tmpes->next;900              }901              cur_elem_num=best_es->num;902              if (mode!=SPED_UNSEL) {903                best_es->flags|=SPEDF_SEL;904                best_es->g->type|=SPF_SEL;905              } else {906                best_es->flags&=~SPEDF_SEL;907                best_es->g->type&=~SPF_SEL;908              }909              break;910            start:911              xx2=xx=arg1; yy2=yy=arg2;912              while (TRUE) {913                SpriteCtrlPtsDraw(dc,&head);914                dc->color=ROPF_DITHER+WHITE<<16+RED;915                GrBorder(dc,xx,yy,xx2,yy2);916                if (msg_code=ScanMsg(&arg1,&arg2,917                      1<<MSG_MS_MOVE|1<<MSG_MS_L_UP)) {918                  if (msg_code==MSG_MS_MOVE) {919                    xx2=arg1; yy2=arg2;920                  } else921                    break;922                }923              }924              if (xx2<xx) SwapI64(&xx,&xx2);925              if (yy2<yy) SwapI64(&yy,&yy2);926              tmpes=head.next;927              while (tmpes!=&head) {928                switch (tmpes->type) {929                  case SPEDT_SIMPLE_PT:930                    if (xx<=*tmpes->x+tmpes->xx<=xx2 &&931                          yy<=*tmpes->y+tmpes->yy<=yy2) {932                      if (mode!=SPED_UNSEL_RECTS) {933                        tmpes->flags|=SPEDF_SEL;934                        tmpes->g->type|=SPF_SEL;935                      } else {936                        tmpes->flags&=~SPEDF_SEL;937                        tmpes->g->type&=~SPF_SEL;938                      }939                    }940                    break;941                  case SPEDT_WIDTH_HEIGHT:942                    if (xx<=*tmpes->x+*tmpes->w+tmpes->xx<=xx2 &&943                          yy<=*tmpes->y+*tmpes->h+tmpes->yy<=yy2) {944                      if (mode!=SPED_UNSEL_RECTS) {945                        tmpes->flags|=SPEDF_SEL;946                        tmpes->g->type|=SPF_SEL;947                      } else {948                        tmpes->flags&=~SPEDF_SEL;949                        tmpes->g->type&=~SPF_SEL;950                      }951                    }952                    break;953                }954                tmpes=tmpes->next;955              }956              case SPED_SEL_RECTS:957              case SPED_UNSEL_RECTS:958                break;959              case SPED_SHIFT_RECTS:960                do {961                  SpriteCtrlPtsDraw(dc,&head);962                  msg_code=ScanMsg(&arg1,&arg2,963                        1<<MSG_KEY_DOWN|1<<MSG_MS_L_DOWN);964                  if (msg_code==MSG_KEY_DOWN) goto gs_key;965                } while (msg_code!=MSG_MS_L_DOWN);966                xx=arg1;yy=arg2;967                break;968            end:969          }970          switch (mode) {971            case SPED_SHIFT_PTS:972            case SPED_SHIFT_RECTS:973              do {974                SpriteCtrlPtsDraw(dc,&head);975                if (msg_code=ScanMsg(&arg1,&arg2,976                      1<<MSG_MS_MOVE|1<<MSG_MS_L_UP)) {977                  SpriteCtrlPtsMove(&head,arg1-xx,arg2-yy);978                  xx=arg1;yy=arg2;979                }980              } while (msg_code!=MSG_MS_L_UP);981              tmpes=head.next;982              while (tmpes!=&head) {983                tmpes->flags&=~SPEDF_SEL;984                tmpes->g->type&=~SPF_SEL;985                tmpes=tmpes->next;986              }987              break;988          }989          break;990        case MSG_KEY_DOWN:991gs_key:992          switch (arg1.u8[0]) {993            case CH_SHIFT_ESC:994              res=FALSE;995            case CH_ESC:996              GetMsg(&arg1,&arg2,1<<MSG_KEY_UP);997              goto gs_done;998            case 'p':999            case 'P':1000              mode&=~1;1001              break;1002            case 'r':1003            case 'R':1004              mode|=1;1005              break;1006          }1007          break;1008        case MSG_MS_R_UP:1009          goto gs_done;1010      }1011    }1012gs_done:1013    QueDel(&head,TRUE);1014  }1015  DCFill(dc);1016  DCDel(dc);1017  if (_cur_elem_num && res)1018    *_cur_elem_num=cur_elem_num;1019  return res;1020}1021 1022I64 SpriteEd(CDoc *doc,CDocEntry *doc_ce,I64 x,I64 y,1023        CSprite **_head,I64 *_cur_elem_num)1024{1025  CDocEntry *doc_e2;1026  CDocBin *tmpb;1027  Bool unlock;1028  I64 i,r[16],msg_code,arg1,arg2,xx,yy,1029        old_de_flags;1030  CSprite *head2,*next,*last,*tmpg,*insert_pt;1031 1032  old_de_flags=doc_ce->de_flags;1033  tmpb=doc_ce->bin_data;1034  DocUnlock(doc);1035  SpriteQueSelAll(*_head,FALSE);1036  do {1037    if (winmgr.fps<10)1038      doc_ce->de_flags|=DOCEF_DONT_DRAW;1039    StrCpy(Fs->task_title,"Sprite Edit Menu");1040    i=PopUpSpriteEd(_head,_cur_elem_num);1041    SpriteEdUpdate(doc,doc_ce,*_head);1042    if (0<=i<SPED_EXIT) {1043      StrCpy(Fs->task_title,DefineSub(i,"ST_SPRITE_ED_MENU"));1044      switch (i) {1045        case SPED_SEL_UNSEL_ALL:1046          if (!SpriteQueSelCnt(*_head))1047            SpriteQueSelAll(*_head);1048          else1049            SpriteQueSelAll(*_head,FALSE);1050          break;1051        case SPED_SET_ORIGIN:1052          SpriteQueSelAll(*_head);1053          doc_ce->de_flags=old_de_flags;1054          GetMsg(&arg1,&arg2,1<<MSG_MS_L_UP);1055          SpriteSetOrigin(*_head,x-arg1,y-arg2,0);1056          SpriteEdUpdate(doc,doc_ce,*_head);1057          SpriteQueSelAll(*_head,FALSE);1058          break;1059        case SPED_SHIFT_SEL:1060          if (!SpriteQueSelCnt(*_head))1061            SpriteQueSelAll(*_head);1062          doc_ce->de_flags=old_de_flags;1063          GetMsg(&arg1,&arg2,1<<MSG_MS_L_DOWN);1064          xx=arg1; yy=arg2;1065          do {1066            msg_code=GetMsg(&arg1,&arg2,1067                  1<<MSG_MS_L_UP+1<<MSG_MS_MOVE);1068            SpriteSetOrigin(*_head,arg1-xx,arg2-yy,0);1069            xx=arg1; yy=arg2;1070            SpriteEdUpdate(doc,doc_ce,*_head);1071          } while (msg_code!=MSG_MS_L_UP);1072          if (!SpriteQueSelCnt(*_head,FALSE))1073            SpriteQueSelAll(*_head,FALSE);1074          break;1075        case SPED_SEL:1076        case SPED_SEL_RECTS:1077        case SPED_UNSEL:1078        case SPED_UNSEL_RECTS:1079        case SPED_SHIFT_PTS:1080        case SPED_SHIFT_RECTS:1081          RegOneTimePopUp(ARf_CSPRITE_PTS_RECTANGLES,1082                "You can switch between points\n"1083                "and rectangles with '$GREEN$p$FG$' and '$GREEN$r$FG$'.\n"1084                "Press '$GREEN$r$FG$' after one rectangle\n"1085                "to OR another rectangle.\n");1086          doc_ce->de_flags=old_de_flags;1087          if (SpriteSelUnselShiftPts(tmpb->data,x,y,_cur_elem_num,i)) {1088            QueDel(*_head);1089            Free(*_head);1090            *_head=Sprite2SpriteQue(tmpb->data);1091          } else1092            SpriteEdUpdate(doc,doc_ce,*_head);1093          break;1094        case SPED_TRANSFORM_SEL:1095          if (!SpriteQueSelCnt(*_head))1096            SpriteQueSelAll(*_head);1097          if (PopUpTransform(r)) {1098            SpriteTransformQue(*_head,r);1099            SpriteEdUpdate(doc,doc_ce,*_head);1100          }1101          if (!SpriteQueSelCnt(*_head,FALSE))1102            SpriteQueSelAll(*_head,FALSE);1103          break;1104        case SPED_SHIFT_SUB_ORIGIN:1105          doc_ce->de_flags=old_de_flags;1106          insert_pt=SpriteSetSettings(,*_head,*_cur_elem_num);1107          tmpg=CAlloc(SpriteElemQuedBaseSize(SPT_SHIFT));1108          tmpg->type=SPT_SHIFT;1109          tmpg->p.x1=0;1110          tmpg->p.y1=0;1111          QueIns(tmpg,insert_pt->last);1112          GetMsg(&arg1,&arg2,1<<MSG_MS_L_DOWN);1113          xx=arg1; yy=arg2;1114          do {1115            msg_code=GetMsg(&arg1,&arg2,1116                  1<<MSG_MS_L_UP+1<<MSG_MS_MOVE);1117            tmpg->p.x1=arg1-xx;1118            tmpg->p.y1=arg2-yy;1119            SpriteEdUpdate(doc,doc_ce,*_head);1120          } while (msg_code!=MSG_MS_L_UP);1121          *_cur_elem_num+=1;1122          break;1123        case SPED_INS_CLIP:1124          RegOneTimePopUp(ARf_CSPRITE_INS_CLIP,1125                "You will probably want to shift around\n"1126                "the location of element groups.  Use\n"1127                "'Insert shift sub-origin' after picking the\n"1128                "element to insert before.  Or,\n"1129                "use 'shift points'.\n");1130          insert_pt=SpriteSetSettings(,*_head,*_cur_elem_num);1131          unlock=DocLock(sys_clip_doc);1132          doc_e2=sys_clip_doc->head.next;1133          while (doc_e2!=sys_clip_doc) {1134            if (doc_e2->type_u8==DOCT_SPRITE) {1135              head2=Sprite2SpriteQue(doc_e2->bin_data->data);1136              if (head2->next!=head2) {1137                tmpg=head2->next;1138                while (tmpg!=head2) {1139                  *_cur_elem_num+=1;1140                  tmpg=tmpg->next;1141                }1142                next=head2->next;1143                last=head2->last;1144                insert_pt->last->next=next;1145                next->last=insert_pt->last;1146                insert_pt->last=last;1147                last->next=insert_pt;1148              }1149              Free(head2);1150            }1151            doc_e2=doc_e2->next;1152          }1153          if (unlock)1154            DocUnlock(sys_clip_doc);1155          SpriteEdUpdate(doc,doc_ce,*_head);1156          break;1157        case SPED_TEXT_ED:1158          if (SpriteEdText(_head,_cur_elem_num))1159            SpriteEdUpdate(doc,doc_ce,*_head);1160          break;1161      }1162    }1163  } while (i!=DOCM_CANCEL && i!=SPED_EXIT && i!=SPED_MAIN_MENU);1164  doc_ce->de_flags=old_de_flags;1165 1166  switch (i) {1167    case DOCM_CANCEL:   return SPE_ABORT;1168    case SPED_EXIT:     return SPE_EXIT;1169    case SPED_MAIN_MENU:        return SPE_CONT;1170  }1171}1172 1173#help_index "Graphics/Sprite;Sprites;Graphics/Math/3D Transformation"1174public U8 *SpriteTransform(U8 *elems,I64 *r)1175{//Rotate Sprite using 4x4 matrix. Uses fixed-point.1176  U8 *res;1177  CSprite *head=Sprite2SpriteQue(elems);1178  SpriteQueSelAll(head);1179  SpriteTransformQue(head,r);1180  res=SpriteQue2Sprite(head);1181  QueDel(head);1182  Free(head);1183  return res;1184}1185