329 lines
6.4 KiB
HolyC
Executable File
329 lines
6.4 KiB
HolyC
Executable File
//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;
|
||
|