329 lines
6.4 KiB
HolyC
329 lines
6.4 KiB
HolyC
|
//This is a whimsical program which demonstrates some techniques.
|
|||
|
|
|||
|
#define BORDER 20
|
|||
|
|
|||
|
#define PTY_PT 0
|
|||
|
#define PTY_CIRCLE 1
|
|||
|
#define PTY_LINE 2
|
|||
|
#define PTY_SPRITE 3
|
|||
|
#define PTY_NUM 4
|
|||
|
|
|||
|
extern class PObj;
|
|||
|
|
|||
|
class PPt
|
|||
|
{
|
|||
|
CD3I32 p;
|
|||
|
};
|
|||
|
|
|||
|
class PCircle
|
|||
|
{
|
|||
|
PObj *p;
|
|||
|
I64 radius;
|
|||
|
};
|
|||
|
|
|||
|
class PLine
|
|||
|
{
|
|||
|
PObj *p1,*p2;
|
|||
|
};
|
|||
|
|
|||
|
class PCSprite
|
|||
|
{
|
|||
|
PObj *p;
|
|||
|
U8 *img;
|
|||
|
I64 *r,
|
|||
|
*dr; //Rounding error might eventually screw this up
|
|||
|
}
|
|||
|
|
|||
|
class PObj
|
|||
|
{
|
|||
|
PObj *next,*last;
|
|||
|
I64 type,color;
|
|||
|
union {
|
|||
|
PPt p;
|
|||
|
PCircle c;
|
|||
|
PLine l;
|
|||
|
PCSprite g;
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
class PickFrame
|
|||
|
{
|
|||
|
PObj o_head;
|
|||
|
I64 o_cnts[PTY_NUM];
|
|||
|
I64 cx,cy;
|
|||
|
};
|
|||
|
|
|||
|
#define IMGS_NUM 3
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<1>",BI=1$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<2>",BI=2$
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$SP,"<3>",BI=3$
|
|||
|
|
|||
|
|
|||
|
U8 *imgs[IMGS_NUM]={$IB,"<1>",BI=1$,$IB,"<2>",BI=2$,$IB,"<3>",BI=3$};
|
|||
|
|
|||
|
U0 DrawIt(CTask *task,CDC *dc)
|
|||
|
{
|
|||
|
I64 *r,*old_r;
|
|||
|
PickFrame *pf=FramePtr("PickFrame",task);
|
|||
|
PObj *tmpo=pf->o_head.next;
|
|||
|
|
|||
|
pf->cx=task->pix_width>>1;
|
|||
|
pf->cy=task->pix_height>>1;
|
|||
|
|
|||
|
DCDepthBufAlloc(dc);
|
|||
|
|
|||
|
dc->color=LTRED;
|
|||
|
dc->thick=3;
|
|||
|
GrBorder(dc,BORDER,BORDER,2*pf->cx-BORDER,2*pf->cy-BORDER);
|
|||
|
|
|||
|
while (tmpo!=&pf->o_head) {
|
|||
|
dc->color=tmpo->color;
|
|||
|
switch (tmpo->type) {
|
|||
|
case PTY_PT:
|
|||
|
GrLine(dc,pf->cx+tmpo->p.p.x+2,pf->cy+tmpo->p.p.y+2,
|
|||
|
pf->cx+tmpo->p.p.x-2,pf->cy+tmpo->p.p.y-2);
|
|||
|
GrLine(dc,pf->cx+tmpo->p.p.x-2,pf->cy+tmpo->p.p.y+2,
|
|||
|
pf->cx+tmpo->p.p.x+2,pf->cy+tmpo->p.p.y-2);
|
|||
|
break;
|
|||
|
case PTY_CIRCLE:
|
|||
|
GrCircle(dc,pf->cx+tmpo->c.p->p.p.x,pf->cy+tmpo->c.p->p.p.y,
|
|||
|
tmpo->c.radius);
|
|||
|
break;
|
|||
|
case PTY_LINE:
|
|||
|
GrLine(dc,pf->cx+tmpo->l.p1->p.p.x,pf->cy+tmpo->l.p1->p.p.y,
|
|||
|
pf->cx+tmpo->l.p2->p.p.x,pf->cy+tmpo->l.p2->p.p.y);
|
|||
|
break;
|
|||
|
case PTY_SPRITE:
|
|||
|
old_r=dc->r;
|
|||
|
dc->r=tmpo->g.r;
|
|||
|
dc->x=pf->cx+tmpo->g.p->p.p.x;
|
|||
|
dc->y=pf->cy+tmpo->g.p->p.p.y;
|
|||
|
dc->z=GR_Z_ALL;
|
|||
|
dc->flags|=DCF_TRANSFORMATION;
|
|||
|
Sprite3(dc,0,0,0,tmpo->g.img);
|
|||
|
dc->flags&=~DCF_TRANSFORMATION;
|
|||
|
dc->r=old_r;
|
|||
|
|
|||
|
//Updated each refresh, not guarenteed to be uniform.
|
|||
|
//Rounding error might corrupt, as well.
|
|||
|
r=Mat4x4MulMat4x4New(tmpo->g.dr,tmpo->g.r,task);
|
|||
|
Free(tmpo->g.r);
|
|||
|
tmpo->g.r=r;
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
tmpo=tmpo->next;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
PObj *PObjNew(PickFrame *pf,I64 type,I64 color)
|
|||
|
{
|
|||
|
PObj *tmpo=CAlloc(sizeof(PObj));
|
|||
|
tmpo->type=type;
|
|||
|
tmpo->color=color;
|
|||
|
pf->o_cnts[type]++;
|
|||
|
QueIns(tmpo,pf->o_head.last);
|
|||
|
return tmpo;
|
|||
|
}
|
|||
|
|
|||
|
U0 PObjDel(PickFrame *pf,PObj *tmpo)
|
|||
|
{
|
|||
|
QueRem(tmpo);
|
|||
|
switch (tmpo->type) {
|
|||
|
case PTY_SPRITE:
|
|||
|
Free(tmpo->g.r);
|
|||
|
Free(tmpo->g.dr);
|
|||
|
break;
|
|||
|
}
|
|||
|
pf->o_cnts[tmpo->type]--;
|
|||
|
Free(tmpo);
|
|||
|
}
|
|||
|
|
|||
|
PObj *PPtNew(PickFrame *pf,I64 x,I64 y)
|
|||
|
{
|
|||
|
PObj *tmpo=PObjNew(pf,PTY_PT,BLACK);
|
|||
|
tmpo->p.p.x=x;
|
|||
|
tmpo->p.p.y=y;
|
|||
|
return tmpo;
|
|||
|
}
|
|||
|
|
|||
|
PObj *PPtNum(PickFrame *pf,I64 num)
|
|||
|
{
|
|||
|
PObj *tmpo=pf->o_head.next;
|
|||
|
while (tmpo!=&pf->o_head) {
|
|||
|
if (tmpo->type==PTY_PT && !num--)
|
|||
|
return tmpo;
|
|||
|
tmpo=tmpo->next;
|
|||
|
}
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
PObj *PPtFind(PickFrame *pf,I64 x,I64 y)
|
|||
|
{
|
|||
|
I64 dd,best_dd=I64_MAX;
|
|||
|
PObj *tmpo=pf->o_head.next,*res=NULL;
|
|||
|
while (tmpo!=&pf->o_head) {
|
|||
|
if (tmpo->type==PTY_PT) {
|
|||
|
dd=SqrI64(tmpo->p.p.x-x)+SqrI64(tmpo->p.p.y-y);
|
|||
|
if (dd<best_dd) {
|
|||
|
best_dd=dd;
|
|||
|
res=tmpo;
|
|||
|
}
|
|||
|
}
|
|||
|
tmpo=tmpo->next;
|
|||
|
}
|
|||
|
return res;
|
|||
|
}
|
|||
|
|
|||
|
PObj *PCircleNew(PickFrame *pf,I64 p_num,I64 r)
|
|||
|
{
|
|||
|
PObj *tmpo=PObjNew(pf,PTY_CIRCLE,RED);
|
|||
|
tmpo->c.p=PPtNum(pf,p_num);
|
|||
|
tmpo->c.radius=r;
|
|||
|
return tmpo;
|
|||
|
}
|
|||
|
|
|||
|
PObj *PLineNew(PickFrame *pf,I64 p1_num,I64 p2_num)
|
|||
|
{
|
|||
|
PObj *tmpo=PObjNew(pf,PTY_LINE,GREEN);
|
|||
|
tmpo->l.p1=PPtNum(pf,p1_num);
|
|||
|
tmpo->l.p2=PPtNum(pf,p2_num);
|
|||
|
return tmpo;
|
|||
|
}
|
|||
|
|
|||
|
PObj *PCSpriteNew(PickFrame *pf,U8 *img,I64 p_num,I64 *r,I64 *dr)
|
|||
|
{
|
|||
|
PObj *tmpo=PObjNew(pf,PTY_SPRITE,BLACK);
|
|||
|
tmpo->g.p=PPtNum(pf,p_num);
|
|||
|
tmpo->g.img=img;
|
|||
|
tmpo->g.r=r;
|
|||
|
tmpo->g.dr=dr;
|
|||
|
return tmpo;
|
|||
|
}
|
|||
|
|
|||
|
PickFrame *Init()
|
|||
|
{
|
|||
|
PickFrame *pf=CAlloc(sizeof(PickFrame));
|
|||
|
I64 i,*r,*dr;
|
|||
|
|
|||
|
pf->cx=Fs->pix_width>>1;
|
|||
|
pf->cy=Fs->pix_height>>1;
|
|||
|
|
|||
|
pf->o_head.next=pf->o_head.last=&pf->o_head;
|
|||
|
for (i=0;i<50;i++)
|
|||
|
PPtNew(pf,RandI32%(pf->cx-BORDER),RandI32%(pf->cy-BORDER));
|
|||
|
for (i=0;i<20;i++)
|
|||
|
PCircleNew(pf,pf->o_cnts[PTY_PT]*RandU16/U16_MAX,6);
|
|||
|
for (i=0;i<20;i++)
|
|||
|
PLineNew(pf,pf->o_cnts[PTY_PT]*RandU16/U16_MAX,
|
|||
|
pf->o_cnts[PTY_PT]*RandU16/U16_MAX);
|
|||
|
for (i=0;i<10;i++) {
|
|||
|
r=Mat4x4IdentNew;
|
|||
|
dr=Mat4x4IdentNew;
|
|||
|
Mat4x4RotZ(dr,0.05*2*(Rand-0.5));
|
|||
|
Mat4x4RotY(dr,0.05*2*(Rand-0.5));
|
|||
|
Mat4x4RotX(dr,0.05*2*(Rand-0.5));
|
|||
|
PCSpriteNew(pf,imgs[IMGS_NUM*RandU16/U16_MAX],
|
|||
|
pf->o_cnts[PTY_PT]*RandU16/U16_MAX,r,dr);
|
|||
|
}
|
|||
|
FramePtrSet("PickFrame",pf);
|
|||
|
return pf;
|
|||
|
}
|
|||
|
|
|||
|
U0 CleanUp(PickFrame *pf)
|
|||
|
{
|
|||
|
PObj *tmpo=pf->o_head.next,*tmpo1;
|
|||
|
while (tmpo!=&pf->o_head) {
|
|||
|
tmpo1=tmpo->next;
|
|||
|
PObjDel(pf,tmpo);
|
|||
|
tmpo=tmpo1;
|
|||
|
}
|
|||
|
Free(pf);
|
|||
|
}
|
|||
|
|
|||
|
U0 Pick3D()
|
|||
|
{
|
|||
|
I64 msg_code,arg1,arg2;
|
|||
|
PObj *tmpo;
|
|||
|
PickFrame *pf=NULL;
|
|||
|
|
|||
|
FramePtrAdd("PickFrame");
|
|||
|
|
|||
|
MenuPush(
|
|||
|
"File {"
|
|||
|
" Abort(,CH_SHIFT_ESC);"
|
|||
|
" Exit(,CH_ESC);"
|
|||
|
"}"
|
|||
|
"Play {"
|
|||
|
" Restart(,'\n');"
|
|||
|
"}"
|
|||
|
);
|
|||
|
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
|||
|
AutoComplete;
|
|||
|
WinBorder;
|
|||
|
WinMax;
|
|||
|
DocClear;
|
|||
|
"$$BK,1$$Move things around.$$BK,0$$\n";
|
|||
|
pf=Init;
|
|||
|
tmpo=NULL;
|
|||
|
Fs->win_inhibit=WIG_TASK_DFT-WIF_SELF_FOCUS
|
|||
|
-WIF_SELF_CTRLS-WIF_FOCUS_TASK_MENU;
|
|||
|
Fs->draw_it=&DrawIt;
|
|||
|
try {
|
|||
|
while (TRUE) {
|
|||
|
switch (msg_code=GetMsg(&arg1,&arg2,
|
|||
|
1<<MSG_KEY_DOWN|1<<MSG_MS_L_DOWN|1<<MSG_MS_L_UP|1<<MSG_MS_MOVE)) {
|
|||
|
case MSG_KEY_DOWN:
|
|||
|
switch (arg1) {
|
|||
|
case '\n':
|
|||
|
CleanUp(pf);
|
|||
|
pf=Init;
|
|||
|
tmpo=NULL;
|
|||
|
break;
|
|||
|
case CH_SHIFT_ESC:
|
|||
|
case CH_ESC:
|
|||
|
goto pd_done;
|
|||
|
}
|
|||
|
break;
|
|||
|
case MSG_MS_L_DOWN:
|
|||
|
tmpo=PPtFind(pf,arg1-pf->cx,arg2-pf->cy);
|
|||
|
break;
|
|||
|
case MSG_MS_L_UP:
|
|||
|
if (tmpo) {
|
|||
|
tmpo->p.p.x=arg1-pf->cx;
|
|||
|
tmpo->p.p.y=arg2-pf->cy;
|
|||
|
tmpo=NULL;
|
|||
|
}
|
|||
|
break;
|
|||
|
case MSG_MS_MOVE:
|
|||
|
if (tmpo) {
|
|||
|
tmpo->p.p.x=arg1-pf->cx;
|
|||
|
tmpo->p.p.y=arg2-pf->cy;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
pd_done:
|
|||
|
GetMsg(,,1<<MSG_KEY_UP);
|
|||
|
} catch
|
|||
|
PutExcept;
|
|||
|
SettingsPop;
|
|||
|
MenuPop;
|
|||
|
CleanUp(pf);
|
|||
|
FramePtrDel("PickFrame");
|
|||
|
}
|
|||
|
|
|||
|
Pick3D;
|
|||
|
|