hschumann2/TempleOS-Source-Code
0847
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 