#help_index "Graphics/Sprite;Sprites" CSprite *SpriteSetSettings(CDC *dc=NULL,CSprite *head,I64 elem_num, I64 x=0,I64 y=0,CColorROPU32 *_color=NULL,I64 *_thick=NULL, I64 *_xx=NULL,I64 *_yy=NULL) { CSprite *res=head->next; I64 thick=1,xx=0,yy=0; CColorROPU32 color=BLACK; if (dc) DCRst(dc); while (elem_num-->0 && res!=head) { switch (res->type&SPG_TYPE_MASK) { case SPT_COLOR: color=res->c.color; if (dc) dc->color=color; break; case SPT_DITHER_COLOR: color=res->d.dither_color.u8[0]| res->d.dither_color.u8[1]<<COLORROP_BITS|ROPF_DITHER; if (dc) dc->color=color; break; case SPT_THICK: thick=res->t.thick; if (dc) dc->thick=thick; break; case SPT_SHIFT: xx+=res->p.x1; yy+=res->p.y1; x+=res->p.x1; y+=res->p.y1; break; case SPT_PLANAR_SYMMETRY: if (dc) { if (DCSymmetry3Set(dc,res->pp.x1+x,res->pp.y1+y,0, res->pp.x2+x,res->pp.y2+y,0, res->pp.x2+x,res->pp.y2+y,1)) dc->flags|=DCF_SYMMETRY; else dc->flags&=~DCF_SYMMETRY; } break; } res=res->next; } if (_color) *_color=color; if (_thick) *_thick=thick; if (_xx) *_xx=xx; if (_yy) *_yy=yy; return res; } Bool SpritePolyPtPlot(CSprite *head,I64 x,I64 y,I64) { CSprite *tmpg=CAlloc(SpriteElemQuedBaseSize(SPT_PT)); tmpg->type=SPT_PT; tmpg->p.x1=x; tmpg->p.y1=y; QueIns(tmpg,head->last); return TRUE; } CSprite *Sprite2SpriteQue(U8 *elems) { I64 s; CSprite *res=CAlloc(sizeof(CSprite)), *tmpg=elems-offset(CSprite.start),*tmpg1; QueInit(res); while (tmpg->type&SPG_TYPE_MASK) { tmpg1=MAlloc(SpriteElemSize(tmpg)+offset(CSprite.start)); s=SpriteElemSize(tmpg); MemCpy(&tmpg1->start,&tmpg->start,s); QueIns(tmpg1,res->last); tmpg(U8 *)+=s; } return res; } U8 *SpriteQue2Sprite(CSprite *head,I64 *_size=NULL) { I64 i,size=sprite_elem_base_sizes[SPT_END]; CSprite *tmpg=head->next; U8 *res,*dst; while (tmpg!=head) { size+=SpriteElemSize(tmpg); tmpg=tmpg->next; } if (_size) *_size=size; res=dst=MAlloc(size); tmpg=head->next; while (tmpg!=head) { i=SpriteElemSize(tmpg); MemCpy(dst,&tmpg->start,i); dst+=i; tmpg=tmpg->next; } *dst=SPT_END; return res; } U0 SpriteEdUpdate(CDoc *doc,CDocEntry *doc_ce,CSprite *head) { CDocBin *tmpb=doc_ce->bin_data; I64 size; Bool unlock=DocLock(doc); Free(tmpb->data); tmpb->data=SpriteQue2Sprite(head,&size); tmpb->size=size; if (unlock) DocUnlock(doc); } U0 SpriteSetOrigin(CSprite *head,I64 dx,I64 dy,I64 dz) { I64 i; I32 *ptr; CD3I32 *p; CSprite *tmpg=head->next; while (tmpg!=head) { if (Bt(&tmpg->type,SPf_SEL)) switch (tmpg->type&SPG_TYPE_MASK) { case SPT_ARROW: case SPT_LINE: case SPT_PLANAR_SYMMETRY: case SPT_RECT: case SPT_ROTATED_RECT: tmpg->pp.x2+=dx; tmpg->pp.y2+=dy; case SPT_PT: case SPT_FLOOD_FILL: case SPT_FLOOD_FILL_NOT: case SPT_TEXT: case SPT_TEXT_BOX: case SPT_TEXT_DIAMOND: case SPT_CIRCLE: case SPT_BITMAP: case SPT_ELLIPSE: case SPT_POLYGON: tmpg->p.x1+=dx; tmpg->p.y1+=dy; break; case SPT_POLYLINE: ptr=&tmpg->nu.u; for (i=0;i<tmpg->nu.num;i++) { ptr[i<<1]+=dx; ptr[i<<1+1]+=dy; } break; case SPT_POLYPT: tmpg->npu.x+=dx; tmpg->npu.y+=dy; break; case SPT_BSPLINE2: case SPT_BSPLINE3: case SPT_BSPLINE2_CLOSED: case SPT_BSPLINE3_CLOSED: p=&tmpg->nu.u; for (i=0;i<tmpg->nu.num;i++,p++) { p->x+=dx; p->y+=dy; p->z+=dz; } break; case SPT_MESH: p=&tmpg->mu.u; for (i=0;i<tmpg->mu.vertex_cnt;i++,p++) { p->x+=dx; p->y+=dy; p->z+=dz; } break; case SPT_SHIFTABLE_MESH: tmpg->pmu.x+=dx; tmpg->pmu.y+=dy; tmpg->pmu.z+=dz; break; } tmpg=tmpg->next; } } CSprite *SpriteTransformCircle(I64 *r,CSprite *tmpg) { I64 x,y,z; F64 m1,arg1,m2,radius=tmpg->pr.radius<<16; CSprite *tmpg1=CAlloc(SpriteElemQuedBaseSize(SPT_ELLIPSE)); tmpg1->type=SPT_ELLIPSE; x=tmpg->pr.x1; y=tmpg->pr.y1; z=0; Mat4x4MulXYZ(r,&x,&y,&z); tmpg1->pwha.x1=x; tmpg1->pwha.y1=y; x=radius; y=0; z=0; Mat4x4MulXYZ(r,&x,&y,&z); R2P(&m1,&arg1,x,y); x=0; y=radius; z=0; Mat4x4MulXYZ(r,&x,&y,&z); m2=Sqrt(x*x+y*y); tmpg1->pwha.width =ToI64(m1)/0x10000; tmpg1->pwha.height=ToI64(m2)/0x10000; tmpg1->pwha.angle=-arg1; tmpg1->type|=tmpg->type&SPF_SEL; return tmpg1; } CSprite *SpriteTransformEllipse(I64 *r,CSprite *tmpg) { I64 x,y,z; F64 m1,arg1,m2,arg2,s,c,x_radius=tmpg->pwha.width<<16, y_radius=tmpg->pwha.height<<16; CSprite *tmpg1=CAlloc(SpriteElemQuedBaseSize(tmpg->type&SPG_TYPE_MASK)); tmpg1->type=tmpg->type; if (tmpg->type&SPG_TYPE_MASK==SPT_POLYGON) tmpg1->pwhas.sides=tmpg->pwhas.sides; x=tmpg->pwha.x1; y=tmpg->pwha.y1; z=0; Mat4x4MulXYZ(r,&x,&y,&z); tmpg1->pwha.x1=x; tmpg1->pwha.y1=y; c=Cos(-tmpg->pwha.angle); s=Sin(-tmpg->pwha.angle); x=x_radius*c; y=x_radius*s; z=0; Mat4x4MulXYZ(r,&x,&y,&z); R2P(&m1,&arg1,x,y); x=-y_radius*s; y=y_radius*c; z=0; Mat4x4MulXYZ(r,&x,&y,&z); R2P(&m2,&arg2,x,y); m2*=Abs(Sin(arg2-arg1)); tmpg1->pwha.width=ToI64(m1)/0x10000; if (tmpg1->pwha.width<1) tmpg1->pwha.width=1; tmpg1->pwha.height=ToI64(m2)/0x10000; if (tmpg1->pwha.height<1) tmpg1->pwha.height=1; tmpg1->pwha.angle=-arg1; tmpg1->type|=tmpg->type&SPF_SEL; return tmpg1; } CSprite *SpriteTransformRect(I64 *r,CSprite *tmpg,F64 theta) { I64 x,y,z,w,h; F64 m1,arg1,m2,arg2,s,c, x_radius=(tmpg->pp.x2-tmpg->pp.x1)<<16, y_radius=(tmpg->pp.y2-tmpg->pp.y1)<<16; CSprite *tmpg1=CAlloc(SpriteElemQuedBaseSize(SPT_ROTATED_RECT)); tmpg1->type=SPT_ROTATED_RECT; x=tmpg->pp.x1; y=tmpg->pp.y1; z=0; Mat4x4MulXYZ(r,&x,&y,&z); tmpg1->ppa.x1=x; tmpg1->ppa.y1=y; c=Cos(-theta); s=Sin(-theta); x=x_radius*c; y=x_radius*s; z=0; Mat4x4MulXYZ(r,&x,&y,&z); R2P(&m1,&arg1,x,y); x=-y_radius*s; y=y_radius*c; z=0; Mat4x4MulXYZ(r,&x,&y,&z); R2P(&m2,&arg2,x,y); m2*=Abs(Sin(arg2-arg1)); w=ToI64(m1)/0x10000; if (w<1) w=1; h=ToI64(m2)/0x10000; if (h<1) h=1; tmpg1->ppa.x2=tmpg1->ppa.x1+w; tmpg1->ppa.y2=tmpg1->ppa.y1+h; tmpg1->ppa.angle=-arg1; tmpg1->type|=tmpg->type&SPF_SEL; return tmpg1; } CSprite *SpriteTransformBitMap(I64 *r,CSprite *tmpg) { CDC *img,*dc3; U8 *elems; I64 x,y,z,minx,maxx,miny,maxy,minz,maxz; CSprite *tmpg1; x=0; y=0; z=0; Mat4x4MulXYZ(r,&x,&y,&z); minx=maxx=x; miny=maxy=y; minz=maxz=z; x=0; y=tmpg->pwhu.height; z=0; Mat4x4MulXYZ(r,&x,&y,&z); if (x<minx) minx=x; if (x>maxx) maxx=x; if (y<minx) miny=y; if (y>maxx) maxy=y; if (z<minx) minz=z; if (z>maxx) maxz=z; x=tmpg->pwhu.width; y=0; z=0; Mat4x4MulXYZ(r,&x,&y,&z); if (x<minx) minx=x; if (x>maxx) maxx=x; if (y<minx) miny=y; if (y>maxx) maxy=y; if (z<minx) minz=z; if (z>maxx) maxz=z; x=tmpg->pwhu.width; y=tmpg->pwhu.height; z=0; Mat4x4MulXYZ(r,&x,&y,&z); if (x<minx) minx=x; if (x>maxx) maxx=x; if (y<minx) miny=y; if (y>maxx) maxy=y; if (z<minx) minz=z; if (z>maxx) maxz=z; dc3=DCNew(maxx-minx+1,maxy-miny+1); img=CAlloc(sizeof(CDC)); img->width=tmpg->pwhu.width; img->width_internal=(tmpg->pwhu.width+7)&~7; img->height=tmpg->pwhu.height; img->body=&tmpg->pwhu.u; img->dc_signature=DCS_SIGNATURE_VAL; dc3->color=TRANSPARENT; GrRect(dc3,0,0,maxx-minx+1,maxy-miny+1); Free(dc3->r); DCMat4x4Set(dc3,r); dc3->flags|=DCF_TRANSFORMATION; dc3->x=-minx; dc3->y=-miny; dc3->z=-minz; GrBlot3(dc3,0,0,0,img); Free(img); elems=DC2Sprite(dc3); dc3->r=NULL; DCDel(dc3); tmpg1=CAlloc(offset(CSprite.start)+MSize(elems)); MemCpy(tmpg1(U8 *)+offset(CSprite.start),elems,MSize(elems)); tmpg1->type=tmpg->type; x=tmpg->pwhu.x1; y=tmpg->pwhu.y1; z=0; Mat4x4MulXYZ(r,&x,&y,&z); tmpg1->pwhu.x1=x; tmpg1->pwhu.y1=y; x=0; y=0; z=0; Mat4x4MulXYZ(r,&x,&y,&z); tmpg1->pwhu.x1+=minx-x; tmpg1->pwhu.y1+=miny-y; return tmpg1; } U0 SpriteTransformQue(CSprite *head,I64 *r) { I64 i,j,k,num,x,y,z,x1,y1,z1,x2,y2,z2,x3,y3,z3; I32 *ptr; CD3I32 *p; CSprite *tmpg=head->next,head2,*tmpg1,*tmpg2,*tmpg3; while (tmpg!=head) { if (Bt(&tmpg->type,SPf_SEL)) switch (tmpg->type&SPG_TYPE_MASK) { case SPT_THICK: tmpg->t.thick*=Sqrt(Mat4x4NormSqr65536(r))/65536; if (tmpg->t.thick<0) tmpg->t.thick=0; break; case SPT_PLANAR_SYMMETRY: case SPT_ARROW: case SPT_LINE: x=tmpg->pp.x2; y=tmpg->pp.y2; z=0; Mat4x4MulXYZ(r,&x,&y,&z); tmpg->pp.x2=x; tmpg->pp.y2=y; case SPT_PT: case SPT_FLOOD_FILL: case SPT_FLOOD_FILL_NOT: case SPT_TEXT: case SPT_TEXT_BOX: case SPT_TEXT_DIAMOND: x=tmpg->p.x1; y=tmpg->p.y1; z=0; Mat4x4MulXYZ(r,&x,&y,&z); tmpg->p.x1=x; tmpg->p.y1=y; break; case SPT_BITMAP: tmpg1=SpriteTransformBitMap(r,tmpg); QueIns(tmpg1,tmpg); QueRem(tmpg); Free(tmpg); tmpg=tmpg1; break; case SPT_ROTATED_RECT: tmpg1=SpriteTransformRect(r,tmpg,tmpg->ppa.angle); QueIns(tmpg1,tmpg); QueRem(tmpg); Free(tmpg); tmpg=tmpg1; break; case SPT_RECT: tmpg1=SpriteTransformRect(r,tmpg,0); QueIns(tmpg1,tmpg); QueRem(tmpg); Free(tmpg); tmpg=tmpg1; break; case SPT_CIRCLE: tmpg1=SpriteTransformCircle(r,tmpg); QueIns(tmpg1,tmpg); QueRem(tmpg); Free(tmpg); tmpg=tmpg1; break; case SPT_ELLIPSE: case SPT_POLYGON: tmpg1=SpriteTransformEllipse(r,tmpg); QueIns(tmpg1,tmpg); QueRem(tmpg); Free(tmpg); tmpg=tmpg1; break; case SPT_POLYLINE: ptr=&tmpg->nu.u; for (i=0;i<tmpg->nu.num;i++) { x=ptr[i<<1]; y=ptr[i<<1+1]; z=0; Mat4x4MulXYZ(r,&x,&y,&z); ptr[i<<1]=x; ptr[i<<1+1]=y; } break; case SPT_POLYPT: QueInit(&head2); x=tmpg->npu.x; y=tmpg->npu.y; z=0; x1=x; y1=y; z1=z; //unrotated cur coordinates Mat4x4MulXYZ(r,&x,&y,&z); ptr=&tmpg->npu.u; k=tmpg->npu.num*3; x2=x; y2=y; z2=z; //rotated start coordinates x3=x; y3=y; z3=z; //lag 1 rotated coordinates for (i=0;i<k;i+=3) { j=BFieldExtU32(ptr,i,3); x1+=gr_x_offsets[j]; y1+=gr_y_offsets[j]; x=x1; y=y1; z=z1; Mat4x4MulXYZ(r,&x,&y,&z); Line(&head2,x3-x2,y3-y2,0,x-x2,y-y2,0,&SpritePolyPtPlot); x3=x; y3=y; z3=z; } num=0; tmpg1=head2.next; x3=0; y3=0; z3=0; while (tmpg1!=&head2) { tmpg2=tmpg1->next; if (tmpg1->p.x1==x3 && tmpg1->p.y1==y3) { QueRem(tmpg1); Free(tmpg1); } else { num++; x3=tmpg1->p.x1; y3=tmpg1->p.y1; } tmpg1=tmpg2; } tmpg3=CAlloc(SpriteElemQuedBaseSize(SPT_POLYPT)+(num*3+7)>>3); tmpg3->npu.x=x2; tmpg3->npu.y=y2; ptr=&tmpg3->npu.u; x3=0;y3=0; z3=0; i=0; tmpg1=head2.next; while (tmpg1!=&head2) { tmpg2=tmpg1->next; BFieldOrU32(ptr,i, polypt_map[SignI64(tmpg1->p.x1-x3)+1+ 3*(SignI64(tmpg1->p.y1-y3)+1)]); i+=3; x3=tmpg1->p.x1;y3=tmpg1->p.y1; QueRem(tmpg1); Free(tmpg1); tmpg1=tmpg2; } tmpg3->type=SPT_POLYPT|tmpg->type&SPF_SEL; tmpg3->npu.num=num; QueIns(tmpg3,tmpg); QueRem(tmpg); Free(tmpg); tmpg=tmpg3; break; case SPT_BSPLINE2: case SPT_BSPLINE3: case SPT_BSPLINE2_CLOSED: case SPT_BSPLINE3_CLOSED: p=&tmpg->nu.u; for (i=0;i<tmpg->nu.num;i++,p++) { x=p->x; y=p->y; z=p->z; Mat4x4MulXYZ(r,&x,&y,&z); p->x=x; p->y=y; p->z=z; } break; case SPT_SHIFTABLE_MESH: x=tmpg->pmu.x; y=tmpg->pmu.y; z=tmpg->pmu.z; Mat4x4MulXYZ(r,&x,&y,&z); tmpg->pmu.x=x; tmpg->pmu.y=y; tmpg->pmu.z=z; p=&tmpg->pmu.u; for (i=0;i<tmpg->pmu.vertex_cnt;i++,p++) { x=p->x; y=p->y; z=p->z; Mat4x4MulXYZ(r,&x,&y,&z); p->x=x; p->y=y; p->z=z; } break; case SPT_MESH: p=&tmpg->mu.u; for (i=0;i<tmpg->mu.vertex_cnt;i++,p++) { x=p->x; y=p->y; z=p->z; Mat4x4MulXYZ(r,&x,&y,&z); p->x=x; p->y=y; p->z=z; } break; } tmpg=tmpg->next; } } I64 SpriteQueSelCnt(CSprite *head,Bool val=TRUE) { I64 res=0; CSprite *tmpg=head->next; val=ToBool(val); while (tmpg!=head) { if (Bt(&tmpg->type,SPf_SEL)==val) res++; tmpg=tmpg->next; } return res; } I64 SpriteQueSelAll(CSprite *head,Bool val=TRUE) { I64 res=0; CSprite *tmpg=head->next; while (tmpg!=head) { BEqu(&tmpg->type,SPf_SEL,val); res++; tmpg=tmpg->next; } return res; } Bool SpriteEdText(CSprite **_head,I64 *_cur_elem_num) { Bool res; CSprite *head=*_head; U8 *elems=SpriteQue2Sprite(head); CDoc *doc=DocNew,*doc2,*old_put=DocPut; StrPrint(doc->filename.name,"AI:0x%X",doc); DocPrint(doc,"//$PURPLE$$TX+CX,\"Sprite Edit as Text\"$$FG$\n" "//$LK+PU+CX,\"Click for Help\"," "A=\"FI:::/Doc/SpriteEdText.DD.Z\"$\n\n"); Sprite2Code(doc,elems); Free(elems); while (TRUE) { if (res=PopUpPrint("DocEd(0x%X,0x%X);",doc,0)) { Fs->put_doc=doc2=DocNew; "$WW,1$"; if (elems=Code2Sprite(doc)) { DocDel(doc2); Fs->put_doc=old_put; QueDel(head); Free(head); head=Sprite2SpriteQue(elems); Free(elems); *_cur_elem_num=QueCnt(head); //TODO: Might want to improve this. break; } else { PopUpPrint("DocEd(0x%X,0x%X);",doc2,0); DocDel(doc2); Fs->put_doc=old_put; } } else break; } DocDel(doc); if (_head) *_head=head; return res; } #define SPED_SEL_UNSEL_ALL 0 #define SPED_SEL 2 #define SPED_SEL_RECTS 3 #define SPED_UNSEL 4 #define SPED_UNSEL_RECTS 5 #define SPED_SHIFT_PTS 6 #define SPED_SHIFT_RECTS 7 #define SPED_SHIFT_SEL 8 #define SPED_TRANSFORM_SEL 9 #define SPED_SET_ORIGIN 10 #define SPED_SHIFT_SUB_ORIGIN 11 #define SPED_TEXT_ED 12 #define SPED_INS_CLIP 13 #define SPED_MAIN_MENU 14 #define SPED_EXIT 15 U0 GrInit3() { DefineLstLoad("ST_SPRITE_ED_MENU","Select/Unselect All\0 \0Select\0" "Select Rects\0Unselect\0Unselect Rects\0Shift Points\0Shift Rects\0" "Shift Selected\0Transform Selected\0Set Origin\0" "Insert Shift SubOrigin\0Edit as Text\0Insert Clip\0Main Menu\0"); } GrInit3; I64 PopUpSpriteEd(CSprite **_head,I64 *_cur_elem_num) { U8 *st; CTask *pu_task; I64 res; CDoc *doc=DocNew; DocPrint(doc,"$PURPLE$$TX+CX,\"Sprite Edit Menu\"$\n" "$LK+PU+CX,\"Click for Help\",A=\"FI:::/Doc/SpriteEd.DD.Z\"$\n\n" "$LTBLUE$$MU-UL,\"Select/Unselect All\",LE=SPED_SEL_UNSEL_ALL$\n" "$MU-UL,\"Select Elems\",LE=SPED_SEL$\n" "$MU-UL,\"Select Elems with Rects\",LE=SPED_SEL_RECTS$\n" "$MU-UL,\"Unsel Elems\",LE=SPED_UNSEL$\n" "$MU-UL,\"Unsel Elems with Rects\",LE=SPED_UNSEL_RECTS$\n\n" "$MU-UL,\"Shift Points\",LE=SPED_SHIFT_PTS$\n" "$MU-UL,\"Shift Points with Rects\",LE=SPED_SHIFT_RECTS$\n" "$MU-UL,\"Shift Selected Elems\",LE=SPED_SHIFT_SEL$\n" "$MU-UL,\"Transform Selected Elems\",LE=SPED_TRANSFORM_SEL$\n\n" "$MU-UL,\"Set Origin\",LE=SPED_SET_ORIGIN$\n" "$MU-UL,\"Insert Shift SubOrigin\",LE=SPED_SHIFT_SUB_ORIGIN$\n\n" "$MU-UL,\"Edit as Text\",LE=SPED_TEXT_ED$\n" "$MU-UL,\"Insert Clip Sprite's\",LE=SPED_INS_CLIP$\n\n" "$PURPLE$$MU-UL,\"+] Sprite Main Menu\",LE=SPED_MAIN_MENU$$LTBLUE$\n" "$MU-UL,\"Exit Sprite\",LE=SPED_EXIT$\n" "$MU-UL,\"Abort Sprite\",LE=DOCM_CANCEL$"); st=MStrPrint("SpriteSideBarTask(0x%X,0x%X,0x%X);",Fs,_head,_cur_elem_num); PopUp(st,NULL,&pu_task); Free(st); res=PopUpMenu(doc); if (TaskValidate(pu_task)) { *_head=SpriteSideBar2SpriteQue(DocPut(pu_task),*_head,_cur_elem_num); Kill(pu_task); } DocDel(doc); return res; } #define SPEDT_SIMPLE_PT 0 #define SPEDT_WIDTH_HEIGHT 1 #define SPEDF_SEL 1 class CEdSprite { CEdSprite *next,*last; CSprite *g; I32 type,num,flags,xx,yy,zz; I32 *x,*y,*z,*w,*h; }; CEdSprite *EdSpriteNew(I64 type,CSprite *tmpg) { CEdSprite *res=CAlloc(sizeof(CEdSprite)); res->g=tmpg; if (tmpg->type&SPF_SEL) res->flags|=SPEDF_SEL; res->type=type; return res; } U0 SpritePtQueNew(U8 *elems,I64 x,I64 y,CEdSprite *head) { I64 i,num=0; I32 *ptr; CD3I32 *p; CEdSprite *tmpes; CSprite *tmpg=elems-offset(CSprite.start); QueInit(head); while (tmpg->type&SPG_TYPE_MASK) { switch (tmpg->type&SPG_TYPE_MASK) { case SPT_ELLIPSE: case SPT_POLYGON: tmpes=EdSpriteNew(SPEDT_WIDTH_HEIGHT,tmpg); tmpes->xx=x; tmpes->yy=y; tmpes->x=&tmpg->pwha.x1; tmpes->y=&tmpg->pwha.y1; tmpes->w=&tmpg->pwha.width; tmpes->h=&tmpg->pwha.height; tmpes->num=num; QueIns(tmpes,head->last); goto pq_x1_y1; case SPT_RECT: case SPT_ROTATED_RECT: case SPT_LINE: case SPT_ARROW: case SPT_PLANAR_SYMMETRY: tmpes=EdSpriteNew(SPEDT_SIMPLE_PT,tmpg); tmpes->xx=x; tmpes->yy=y; tmpes->x=&tmpg->pp.x2; tmpes->y=&tmpg->pp.y2; tmpes->num=num; QueIns(tmpes,head->last); case SPT_TEXT: case SPT_TEXT_BOX: case SPT_TEXT_DIAMOND: case SPT_PT: case SPT_BITMAP: case SPT_FLOOD_FILL: case SPT_FLOOD_FILL_NOT: case SPT_CIRCLE: pq_x1_y1: tmpes=EdSpriteNew(SPEDT_SIMPLE_PT,tmpg); tmpes->xx=x; tmpes->yy=y; tmpes->x=&tmpg->p.x1; tmpes->y=&tmpg->p.y1; tmpes->num=num; QueIns(tmpes,head->last); break; case SPT_SHIFT: x+=tmpg->p.x1; y+=tmpg->p.y1; break; case SPT_POLYLINE: ptr=&tmpg->nu.u; for (i=0;i<tmpg->nu.num;i++) { tmpes=EdSpriteNew(SPEDT_SIMPLE_PT,tmpg); tmpes->xx=x; tmpes->yy=y; tmpes->x=&ptr[i<<1]; tmpes->y=&ptr[i<<1+1]; tmpes->num=num; QueIns(tmpes,head->last); } break; case SPT_POLYPT: tmpes=EdSpriteNew(SPEDT_SIMPLE_PT,tmpg); tmpes->xx=x; tmpes->yy=y; tmpes->x=&tmpg->npu.x; tmpes->y=&tmpg->npu.y; tmpes->num=num; QueIns(tmpes,head->last); break; case SPT_BSPLINE2: case SPT_BSPLINE3: case SPT_BSPLINE2_CLOSED: case SPT_BSPLINE3_CLOSED: p=&tmpg->nu.u; for (i=0;i<tmpg->nu.num;i++) { tmpes=EdSpriteNew(SPEDT_SIMPLE_PT,tmpg); tmpes->xx=x; tmpes->yy=y; tmpes->x=&p[i].x; tmpes->y=&p[i].y; tmpes->z=&p[i].z; tmpes->num=num; QueIns(tmpes,head->last); } break; case SPT_MESH: break; case SPT_SHIFTABLE_MESH: tmpes=EdSpriteNew(SPEDT_SIMPLE_PT,tmpg); tmpes->xx=x; tmpes->yy=y; tmpes->x=&tmpg->pmu.x; tmpes->y=&tmpg->pmu.y; tmpes->z=&tmpg->pmu.z; tmpes->num=num; QueIns(tmpes,head->last); break; } tmpg(U8 *)+=SpriteElemSize(tmpg); num++; } } U0 SpriteCtrlPtsDraw(CDC *dc,CEdSprite *head) { I64 x,y; CEdSprite *tmpes; Refresh; DCFill(dc); if (Blink(20)) { tmpes=head->next; while (tmpes!=head) { switch (tmpes->type) { case SPEDT_SIMPLE_PT: x=*tmpes->x+tmpes->xx; y=*tmpes->y+tmpes->yy; break; case SPEDT_WIDTH_HEIGHT: x=*tmpes->w+*tmpes->x+tmpes->xx; y=*tmpes->h+*tmpes->y+tmpes->yy; break; } if (tmpes->flags&SPEDF_SEL) dc->color=RED; else dc->color=BLACK; GrRect(dc,x-2,y-2,4,4); dc->color=WHITE; GrRect(dc,x-1,y-1,2,2); tmpes=tmpes->next; } } } U0 SpriteCtrlPtsMove(CEdSprite *head,I64 dx,I64 dy) { CEdSprite *tmpes; tmpes=head->next; while (tmpes!=head) { if (tmpes->flags&SPEDF_SEL) switch (tmpes->type) { case SPEDT_SIMPLE_PT: if (tmpes->x) *tmpes->x+=dx; if (tmpes->y) *tmpes->y+=dy; break; case SPEDT_WIDTH_HEIGHT: if (tmpes->w) *tmpes->w+=dx; if (tmpes->h) *tmpes->h+=dy; break; } tmpes=tmpes->next; } } Bool SpriteSelUnselShiftPts(U8 *elems,I64 x,I64 y,I64 *_cur_elem_num,I64 mode) { I64 msg_code,arg1,arg2,xx,yy,xx2,yy2,dd,best_dd,cur_elem_num; Bool res=TRUE; CDC *dc=DCAlias; CEdSprite head,*tmpes,*best_es; SpritePtQueNew(elems,x,y,&head); cur_elem_num=0; if (head.next!=&head) { while (TRUE) { SpriteCtrlPtsDraw(dc,&head); //has Refresh switch (msg_code=ScanMsg(&arg1,&arg2, 1<<MSG_MS_R_UP|1<<MSG_MS_L_DOWN|1<<MSG_KEY_DOWN)) { case MSG_MS_L_DOWN: switch (mode) { case SPED_SEL: case SPED_UNSEL: case SPED_SHIFT_PTS: xx=arg1; yy=arg2; best_dd=I64_MAX; tmpes=head.next; while (tmpes!=&head) { switch (tmpes->type) { case SPEDT_SIMPLE_PT: dd=SqrI64(*tmpes->x+tmpes->xx-xx)+ SqrI64(*tmpes->y+tmpes->yy-yy); break; case SPEDT_WIDTH_HEIGHT: dd=SqrI64(*tmpes->x+*tmpes->w+tmpes->xx-xx)+ SqrI64(*tmpes->y+*tmpes->h+tmpes->yy-yy); break; } if (dd<best_dd) { best_dd=dd; best_es=tmpes; } tmpes=tmpes->next; } cur_elem_num=best_es->num; if (mode!=SPED_UNSEL) { best_es->flags|=SPEDF_SEL; best_es->g->type|=SPF_SEL; } else { best_es->flags&=~SPEDF_SEL; best_es->g->type&=~SPF_SEL; } break; start: xx2=xx=arg1; yy2=yy=arg2; while (TRUE) { SpriteCtrlPtsDraw(dc,&head); dc->color=ROPF_DITHER+WHITE<<16+RED; GrBorder(dc,xx,yy,xx2,yy2); if (msg_code=ScanMsg(&arg1,&arg2, 1<<MSG_MS_MOVE|1<<MSG_MS_L_UP)) { if (msg_code==MSG_MS_MOVE) { xx2=arg1; yy2=arg2; } else break; } } if (xx2<xx) SwapI64(&xx,&xx2); if (yy2<yy) SwapI64(&yy,&yy2); tmpes=head.next; while (tmpes!=&head) { switch (tmpes->type) { case SPEDT_SIMPLE_PT: if (xx<=*tmpes->x+tmpes->xx<=xx2 && yy<=*tmpes->y+tmpes->yy<=yy2) { if (mode!=SPED_UNSEL_RECTS) { tmpes->flags|=SPEDF_SEL; tmpes->g->type|=SPF_SEL; } else { tmpes->flags&=~SPEDF_SEL; tmpes->g->type&=~SPF_SEL; } } break; case SPEDT_WIDTH_HEIGHT: if (xx<=*tmpes->x+*tmpes->w+tmpes->xx<=xx2 && yy<=*tmpes->y+*tmpes->h+tmpes->yy<=yy2) { if (mode!=SPED_UNSEL_RECTS) { tmpes->flags|=SPEDF_SEL; tmpes->g->type|=SPF_SEL; } else { tmpes->flags&=~SPEDF_SEL; tmpes->g->type&=~SPF_SEL; } } break; } tmpes=tmpes->next; } case SPED_SEL_RECTS: case SPED_UNSEL_RECTS: break; case SPED_SHIFT_RECTS: do { SpriteCtrlPtsDraw(dc,&head); msg_code=ScanMsg(&arg1,&arg2, 1<<MSG_KEY_DOWN|1<<MSG_MS_L_DOWN); if (msg_code==MSG_KEY_DOWN) goto gs_key; } while (msg_code!=MSG_MS_L_DOWN); xx=arg1;yy=arg2; break; end: } switch (mode) { case SPED_SHIFT_PTS: case SPED_SHIFT_RECTS: do { SpriteCtrlPtsDraw(dc,&head); if (msg_code=ScanMsg(&arg1,&arg2, 1<<MSG_MS_MOVE|1<<MSG_MS_L_UP)) { SpriteCtrlPtsMove(&head,arg1-xx,arg2-yy); xx=arg1;yy=arg2; } } while (msg_code!=MSG_MS_L_UP); tmpes=head.next; while (tmpes!=&head) { tmpes->flags&=~SPEDF_SEL; tmpes->g->type&=~SPF_SEL; tmpes=tmpes->next; } break; } break; case MSG_KEY_DOWN: gs_key: switch (arg1.u8[0]) { case CH_SHIFT_ESC: res=FALSE; case CH_ESC: GetMsg(&arg1,&arg2,1<<MSG_KEY_UP); goto gs_done; case 'p': case 'P': mode&=~1; break; case 'r': case 'R': mode|=1; break; } break; case MSG_MS_R_UP: goto gs_done; } } gs_done: QueDel(&head,TRUE); } DCFill(dc); DCDel(dc); if (_cur_elem_num && res) *_cur_elem_num=cur_elem_num; return res; } I64 SpriteEd(CDoc *doc,CDocEntry *doc_ce,I64 x,I64 y, CSprite **_head,I64 *_cur_elem_num) { CDocEntry *doc_e2; CDocBin *tmpb; Bool unlock; I64 i,r[16],msg_code,arg1,arg2,xx,yy, old_de_flags; CSprite *head2,*next,*last,*tmpg,*insert_pt; old_de_flags=doc_ce->de_flags; tmpb=doc_ce->bin_data; DocUnlock(doc); SpriteQueSelAll(*_head,FALSE); do { if (winmgr.fps<10) doc_ce->de_flags|=DOCEF_DONT_DRAW; StrCpy(Fs->task_title,"Sprite Edit Menu"); i=PopUpSpriteEd(_head,_cur_elem_num); SpriteEdUpdate(doc,doc_ce,*_head); if (0<=i<SPED_EXIT) { StrCpy(Fs->task_title,DefineSub(i,"ST_SPRITE_ED_MENU")); switch (i) { case SPED_SEL_UNSEL_ALL: if (!SpriteQueSelCnt(*_head)) SpriteQueSelAll(*_head); else SpriteQueSelAll(*_head,FALSE); break; case SPED_SET_ORIGIN: SpriteQueSelAll(*_head); doc_ce->de_flags=old_de_flags; GetMsg(&arg1,&arg2,1<<MSG_MS_L_UP); SpriteSetOrigin(*_head,x-arg1,y-arg2,0); SpriteEdUpdate(doc,doc_ce,*_head); SpriteQueSelAll(*_head,FALSE); break; case SPED_SHIFT_SEL: if (!SpriteQueSelCnt(*_head)) SpriteQueSelAll(*_head); doc_ce->de_flags=old_de_flags; GetMsg(&arg1,&arg2,1<<MSG_MS_L_DOWN); xx=arg1; yy=arg2; do { msg_code=GetMsg(&arg1,&arg2, 1<<MSG_MS_L_UP+1<<MSG_MS_MOVE); SpriteSetOrigin(*_head,arg1-xx,arg2-yy,0); xx=arg1; yy=arg2; SpriteEdUpdate(doc,doc_ce,*_head); } while (msg_code!=MSG_MS_L_UP); if (!SpriteQueSelCnt(*_head,FALSE)) SpriteQueSelAll(*_head,FALSE); break; case SPED_SEL: case SPED_SEL_RECTS: case SPED_UNSEL: case SPED_UNSEL_RECTS: case SPED_SHIFT_PTS: case SPED_SHIFT_RECTS: RegOneTimePopUp(ARf_CSPRITE_PTS_RECTANGLES, "You can switch between points\n" "and rectangles with '$GREEN$p$FG$' and '$GREEN$r$FG$'.\n" "Press '$GREEN$r$FG$' after one rectangle\n" "to OR another rectangle.\n"); doc_ce->de_flags=old_de_flags; if (SpriteSelUnselShiftPts(tmpb->data,x,y,_cur_elem_num,i)) { QueDel(*_head); Free(*_head); *_head=Sprite2SpriteQue(tmpb->data); } else SpriteEdUpdate(doc,doc_ce,*_head); break; case SPED_TRANSFORM_SEL: if (!SpriteQueSelCnt(*_head)) SpriteQueSelAll(*_head); if (PopUpTransform(r)) { SpriteTransformQue(*_head,r); SpriteEdUpdate(doc,doc_ce,*_head); } if (!SpriteQueSelCnt(*_head,FALSE)) SpriteQueSelAll(*_head,FALSE); break; case SPED_SHIFT_SUB_ORIGIN: doc_ce->de_flags=old_de_flags; insert_pt=SpriteSetSettings(,*_head,*_cur_elem_num); tmpg=CAlloc(SpriteElemQuedBaseSize(SPT_SHIFT)); tmpg->type=SPT_SHIFT; tmpg->p.x1=0; tmpg->p.y1=0; QueIns(tmpg,insert_pt->last); GetMsg(&arg1,&arg2,1<<MSG_MS_L_DOWN); xx=arg1; yy=arg2; do { msg_code=GetMsg(&arg1,&arg2, 1<<MSG_MS_L_UP+1<<MSG_MS_MOVE); tmpg->p.x1=arg1-xx; tmpg->p.y1=arg2-yy; SpriteEdUpdate(doc,doc_ce,*_head); } while (msg_code!=MSG_MS_L_UP); *_cur_elem_num+=1; break; case SPED_INS_CLIP: RegOneTimePopUp(ARf_CSPRITE_INS_CLIP, "You will probably want to shift around\n" "the location of element groups. Use\n" "'Insert shift sub-origin' after picking the\n" "element to insert before. Or,\n" "use 'shift points'.\n"); insert_pt=SpriteSetSettings(,*_head,*_cur_elem_num); unlock=DocLock(sys_clip_doc); doc_e2=sys_clip_doc->head.next; while (doc_e2!=sys_clip_doc) { if (doc_e2->type_u8==DOCT_SPRITE) { head2=Sprite2SpriteQue(doc_e2->bin_data->data); if (head2->next!=head2) { tmpg=head2->next; while (tmpg!=head2) { *_cur_elem_num+=1; tmpg=tmpg->next; } next=head2->next; last=head2->last; insert_pt->last->next=next; next->last=insert_pt->last; insert_pt->last=last; last->next=insert_pt; } Free(head2); } doc_e2=doc_e2->next; } if (unlock) DocUnlock(sys_clip_doc); SpriteEdUpdate(doc,doc_ce,*_head); break; case SPED_TEXT_ED: if (SpriteEdText(_head,_cur_elem_num)) SpriteEdUpdate(doc,doc_ce,*_head); break; } } } while (i!=DOCM_CANCEL && i!=SPED_EXIT && i!=SPED_MAIN_MENU); doc_ce->de_flags=old_de_flags; switch (i) { case DOCM_CANCEL: return SPE_ABORT; case SPED_EXIT: return SPE_EXIT; case SPED_MAIN_MENU: return SPE_CONT; } } #help_index "Graphics/Sprite;Sprites;Graphics/Math/3D Transformation" public U8 *SpriteTransform(U8 *elems,I64 *r) {//Rotate Sprite using 4x4 matrix. Uses fixed-point. U8 *res; CSprite *head=Sprite2SpriteQue(elems); SpriteQueSelAll(head); SpriteTransformQue(head,r); res=SpriteQue2Sprite(head); QueDel(head); Free(head); return res; }