24 enum{EBACK,EWALL,EFRONT,ETHING,ESWITCH};
26 extern "C" dword dpmi_memavl(void);
31 extern vgaimg *walp[256];
37 char mapdir[_MAX_DIR]="",*mapmask[]={"*.WAD",NULL},mapfile[13]="";
39 int etype=ETHING,wallimg[3]={-1,-1,-1},wtype=1,pthing=TH_PLR1;
40 int thtnum,*tht_tlist;
46 char *wt_name[]={"пусто","стена","закр.дверь","откр.дверь","ступень","вода",
47 "кислота1","кислота2","блок. мон.","лифт \x18","лифт \x19",NULL};
50 static mapwin mw1(213,93);
51 static sprview *wlsv[3];
52 static textstr th_cn(115,127,0,5,"",&smallfont,12),
53 sw_cn(45,125,0,5,"",&smallfont,12);
54 static chkbox thf_r(115,135,10,9,E_THF_R,0),
55 thf_dm(115,145,10,9,E_THF_DM,0),
56 swf_pp(25,155,10,9,E_SWF_PP,0),
57 swf_mp(25,165,10,9,E_SWF_MP,0),
58 swf_pn(25,175,10,9,E_SWF_PN,0),
59 swf_mn(25,185,10,9,E_SWF_MN,0),
60 swf_kr(100,155,10,9,E_SWF_KR,0),
61 swf_kg(100,165,10,9,E_SWF_KG,0),
62 swf_kb(100,175,10,9,E_SWF_KB,0);
63 static strlist2 wl1(25,125,60,70,walls,E_WALLIMG,8),
64 wl2(25,125,60,70,walls,E_WALLIMG,8),
65 wl3(25,125,60,70,walls,E_WALLIMG,8);
67 static void about(void) {
70 sprintf(s,"Редактор уровней для DOOM'а 2D V1.30\n\n"
71 "Свободно DPMI-памяти: %uK\n\n",dpmi_memavl()>>10);
74 sprintf(s+strlen(s),"Музыка: %.8s",musname);
75 message(MB_OK,"%s",s);
78 void rebuild_wl(void) {
82 for(int i=0;walls[i];++i) free(walls[i]);
83 for(i=0;i<255 && wal[i].n[0];++i) {
84 strncpy(s,wal[i].n,8);
87 wl1.newlist(walls);wallimg[0]=-1;
88 wl2.newlist(walls);wallimg[1]=-1;
89 wl3.newlist(walls);wallimg[2]=-1;
92 static void redraw_th(void) {
93 th_cn.newtext(115,127,0,5,(curth==-1)?"":TH_getname(TH_gett(curth)),
96 thf_r.st=i&THF_DIR;thf_r.redraw();
97 thf_dm.st=i&THF_DM;thf_dm.redraw();
100 static void redraw_sw(void) {
101 sw_cn.newtext(45,125,0,5,SW_getname(),&smallfont,12);
103 swf_pp.st=f&SW_PL_PRESS;swf_pp.redraw();
104 swf_mp.st=f&SW_MN_PRESS;swf_mp.redraw();
105 swf_pn.st=f&SW_PL_NEAR;swf_pn.redraw();
106 swf_mn.st=f&SW_MN_NEAR;swf_mn.redraw();
107 swf_kr.st=f&SW_KEY_R;swf_kr.redraw();
108 swf_kg.st=f&SW_KEY_G;swf_kg.redraw();
109 swf_kb.st=f&SW_KEY_B;swf_kb.redraw();
112 static void options(void) {
113 mdialog m(110,70,100,60);
114 hslider h1(150,90,50,10,4,gamma,E_GAMMA);
115 textstr t1(115,92,0,5,"Яркость",&smallfont,15);
116 button b1(130,110,60,15,"О'кей",C_OK,0,13);
118 desktop<<=m<<=(h1+=t1+=b1);
120 for(msg=0;!msg;) GUI();
121 m.remove();desktop.redraw();
124 static void near add_wall(void) {
125 static char buf[9]="";
126 mdialog m(60,45,200,110);
127 inputbox ib(195,50,60,10,buf,9);
128 char **p=F_make_wall_list();
129 strlist2 lst(195,65,60,70,p,C_YES,8);
130 sprview sv1(64,68,128,64,NULL);
131 button b1(194,140,30,10,"О'кей",C_OK,0,13),
132 b2(226,140,30,10,"Не надо",C_CANCEL,0,27);
134 desktop<<=m<<=(b1+=b2+=ib+=lst+=sv1);
137 for(msg=0;!msg || msg==C_YES;) {
140 ib.cur=strlen(strcpy(buf,p[par]));ib.redraw();
142 if(lc!=ib.cur || msg==C_YES) {
144 sv1.img=(vgaimg*)M_lock(F_findres(buf));sv1.redraw();
147 if(msg==C_YES) msg=0;
149 m.remove();desktop.redraw();
151 if(msg==C_CANCEL || buf[0]==0) return;
152 W_addwall(buf);rebuild_wl();
155 static void set_music(void) {
156 static char buf[9]="";
157 mdialog m(125,45,70,110);
158 inputbox ib(130,50,60,10,buf,9);
159 char **p=F_make_dmm_list();
160 strlist2 lst(130,65,60,70,p,C_YES,8);
161 button b1(129,140,30,10,"О'кей",C_OK,0,13),
162 b2(161,140,30,10,"Не надо",C_CANCEL,0,27);
164 memcpy(buf,musname,8);buf[8]=0;
165 desktop<<=m<<=(b1+=b2+=ib+=lst);
167 for(msg=0;!msg || msg==C_YES;) {
168 GUI();if(msg==C_YES) {
169 msg=0;ib.cur=strlen(strcpy(buf,p[par]));ib.redraw();
172 m.remove();desktop.redraw();
174 if(msg==C_CANCEL) return;
176 strncpy(musname,buf,8);
179 static char *choose_map(char *fn,char *title) {
180 static char buf[9]="MAP01";
181 mdialog m(125,35,70,120);
182 inputbox ib(130,50,60,10,buf,9);
183 char **p=F_make_map_list(fn);
184 strlist2 lst(130,65,60,70,p,C_YES,8);
185 button b1(129,140,30,10,"О'кей",C_OK,0,13),
186 b2(161,140,30,10,"Не надо",C_CANCEL,0,27);
187 textstr t1(160,40,1,5,title,&smallfont,15);
190 desktop<<=m<<=(b1+=b2+=ib+=lst+=t1);
192 for(msg=0;!msg || msg==C_YES;) {
193 GUI();if(msg==C_YES) {
194 msg=0;ib.cur=strlen(strcpy(buf,p[par]));ib.redraw();
197 m.remove();desktop.redraw();
199 if(msg==C_CANCEL) return NULL;
203 int choose_file(char *dir,char **mask,char *file,char *title) {
204 static char str[14],cdir[_MAX_DIR];
205 mdialog m(10,10,300,180);
206 char **p=F_make_file_list(dir,mask);
207 strlist2 lst(115,50,90,120,p,C_YES,10);
208 inputbox ib(115,35,90,10,file,13);
209 button b1(115,175,40,10,"О'кей",C_OK,0,13),
210 b2(165,175,40,10,"Не надо",C_CANCEL,0,27);
211 textstr t1(160,15,1,5,title,&smallfont,15),
212 tdir(160,25,1,5,dir,&smallfont,12);
214 getcwd(cdir,_MAX_DIR);
216 desktop<<=m<<=(b1+=b2+=ib+=lst+=t1+=tdir);
218 for(msg=0;msg!=C_OK && msg!=C_CANCEL;) {
223 strcpy(str,p[par]+1);str[strlen(str)-1]=0;
224 chdir(str);getcwd(dir,_MAX_DIR);
226 lst.newlist(p=F_make_file_list(dir,mask));
227 *file=0;ib.cur=0;ib.redraw();
228 tdir.newtext(160,25,1,5,dir,&smallfont,12);
230 ib.cur=strlen(strcpy(file,p[par]));ib.redraw();
234 m.remove();desktop.redraw();
237 if(msg==C_CANCEL || file[0]==0) return 0;
238 if(f_path[strlen(strcpy(f_path,dir))-1]!='\\') strcat(f_path,"\\");
247 virtual void draw(void);
248 virtual int key(int);
249 virtual void command(int,long);
252 desk::desk():gui_obj(0,0,320,200) {}
254 void desk::draw(void) {
255 V_clr(200,120,0,200,gray[5]);
259 int desk::key(int k) {
261 send_command(this,E_QUIT,0);
264 return gui_obj::key(k);
267 void desk::command(int c,long p) {
270 static menu_t sysmnu[]={
271 "Опции",E_OPTIONS,"Справка",E_ABOUT,"Очистка",E_NEWMAP,
276 static byte swf[7]={SW_PL_PRESS,SW_MN_PRESS,SW_PL_NEAR,SW_MN_NEAR,
277 SW_KEY_R,SW_KEY_G,SW_KEY_B};
280 case E_DBACK: w_drawb=p;vw.redraw();break;
281 case E_DTYPE: w_drawt=p;vw.redraw();break;
282 case E_DFRONT: w_drawf=p;vw.redraw();break;
283 case E_DTHING: w_drawth=p;vw.redraw();break;
284 case E_DSWITCH: w_drawsw=p;vw.redraw();break;
285 case E_SYSTEM: desktop<<=*new menubox(305,2,sysmnu);desktop.redraw();break;
287 if(message(MB_YN," Уже уходите?")==C_YES) ERR_quit();
289 case E_OPTIONS: options();break;
290 case E_GAMMA: setgamma(p);break;
291 case E_ETYPE: send_command(&vw,E_DBACK+p,1);etype=p;break;
292 case E_WALLIMG: if(etype<3) {
294 wlsv[etype]->img=(p>=-1)?walp[p+1]:NULL;wlsv[etype]->redraw();
295 if(p<=-2) {wl2.lst->cline=-1;wl2.redraw();}
297 case E_WTYPE: wtype=p+1;break;
298 case E_THTYPE: pthing=tht_tlist[p];break;
299 case E_ADDWALL: add_wall();break;
300 case E_NEXTSW: SW_nexttype();redraw_sw();desktop.redraw();break;
301 case E_PREVSW: SW_prevtype();redraw_sw();desktop.redraw();break;
302 case E_DELSW: SW_delete(cursw);redraw_sw();desktop.redraw();break;
303 case E_THF_R: if(curth==-1) break;
304 TH_setf(curth,(TH_getf(curth)&(0xFFFF-THF_DIR))|(p?THF_DIR:0));
306 case E_THF_DM: if(curth==-1) break;
307 TH_setf(curth,(TH_getf(curth)&(0xFFFF-THF_DM))|(p?THF_DM:0));
309 case E_SWF_PP: case E_SWF_MP: case E_SWF_PN: case E_SWF_MN:
310 case E_SWF_KR: case E_SWF_KG: case E_SWF_KB:
313 SW_setf((SW_getf()&(0xFF-i))|(p?i:0));
319 if(message(MB_YN,"Стереть весь уровень?")!=C_YES) break;
320 if(message(MB_YN,"Вы уверены?")!=C_YES) break;
321 W_init();rebuild_wl();curth=-1;redraw_th();redraw_sw();
322 for(i=0;i<3;++i) wlsv[i]->img=NULL;
326 if(!choose_file(mapdir,mapmask,mapfile,"ЗАГРУЗКА КАРТЫ")) break;
327 if(!(s=choose_map(f_path,"ЗАГРУЗКА КАРТЫ"))) break;
328 W_init();F_loadmap(f_path,s);rebuild_wl();curth=-1;redraw_th();
329 for(i=0;i<3;++i) wlsv[i]->img=NULL;
333 if(!choose_file(mapdir,mapmask,mapfile,"ЗАПИСЬ КАРТЫ")) break;
334 // if(access(f_path,0)==0)
335 // if(message(MB_YN,"Стереть старый %s ?",f_path)!=C_YES) break;
336 if(!(s=choose_map(f_path,"ЗАПИСЬ КАРТЫ"))) break;
337 if(!F_savemap(f_path,s))
338 message(MB_OK,"ВНИМАНИЕ!!!\n\nПроизошла ошибка при записи %s в файл\n"
345 if(++skytype>2) skytype=1;
352 message(MB_OK,"Клавиши:\n\n"
354 "F2 - запись уровня\n"
355 "F3 - загрузка уровня\n"
356 "F10 - выход из редактора\n"
357 "стрелки - прокрутка вида\n"
359 case H_BACK: case H_FRONT:
360 message(MB_OK,"Выберите текстуру из списка.\n"
361 "(Добавьте, если список пустой.)\n\n"
362 "На виде уровня нажмите левую кнопку мыши и, не\n"
363 "отпуская ее, растяните прямоугольник, который\n"
364 "надо заполнить текстурой.\n\n"
365 "Аналогично, нажимая правую кнопку мыши, можно\n"
366 "стереть %s.\n",(p==H_BACK)?"фон":"передний план"
370 "Выберите тип стены.\n"
371 "Выберите текстуру, которую хотите поставить\n"
372 "вместе с типом стены.\n"
373 "Если вы хотите изменить только тип, нажмите\n"
374 "кнопку над списком текстур.\n\n"
375 "На виде уровня нажмите левую кнопку мыши и, не\n"
376 "отпуская ее, растяните прямоугольник, который\n"
377 "надо заполнить.\n\n"
378 "Аналогично, нажимая правую кнопку мыши, можно\n"
380 "Блок. мон. - блокировка монстров.\n"
384 "Чтобы поставить новый предмет, выберите его из списка\n"
385 "и на виде уровня нажмите правую кнопку мыши.\n\n"
386 "Чтобы убрать предмет, щёлкните по нему правой кнопкой.\n\n"
387 "Чтобы передвинуть предмет, нажмите на нём левую кнопку,\n"
388 "и не отпуская её, перетащите предмет.\n"
392 "Чтобы поставить новую кнопку, в нужном месте на виде\n"
393 "уровня нажмите левую кнопку мыши, и не отпуская её,\n"
394 "нажмите правую.\n\n"
395 "Чтобы поставить точку воздействия, нажмите правую\n"
399 if(!(s=SW_gethelp())) break;
400 message(MB_OK,"%s\n",s);
410 gui_obj& desktop=dsk;
414 view::view():gui_obj(0,0,250,110) {
415 *this<<=*(hs=new hscroll(0,100,200,10,FLDW*CELW-200,FLDW*CELW/2,E_VIEWX,8))
416 +=*(vs=new vscroll(200,0,10,100,FLDH*CELH-98,FLDH*CELH/2,E_VIEWY,8));
418 *this<<=*(cb[i]=new chkbox(215,i*15+10,10,9,E_DBACK+i,1));
422 view::~view() {delete hs;delete vs;}
424 void view::draw(void) {
426 {&back_icon,&wall_icon,&front_icon,&thing_icon,&switch_icon};
428 W_draw();gui_obj::draw();
430 V_spr(240,i*15+14,s[i]);
433 void view::command(int c,long p) {
435 case E_VIEWX: w_x=p+100;W_adjust();redraw();break;
436 case E_VIEWY: w_y=p+49;W_adjust();redraw();break;
437 case E_DBACK: case E_DTYPE: case E_DFRONT:
438 case E_DTHING: case E_DSWITCH:
441 default: gui_obj::command(c,p);
445 int view::mouse(int x,int y,int b) {
449 if(x>=200 || y>=99 || y==0) return gui_obj::mouse(x,y,b);
451 case EBACK: case EWALL: case EFRONT:
452 if(b!=1 && b!=2) break;
453 edt=b;edx1=edx2=(x+w_x-100)/8;edy1=edy2=(y+w_y-50)/8;
455 while(I_mget(&x,&y)&b) {
459 x=(x+w_x-100)/8;y=(y+w_y-50)/8;
460 if(x!=edx2 || y!=edy2) {edx2=x;edy2=y;redraw();}
463 if(edx2<edx1) {i=edx1;edx1=edx2;edx2=i;}
464 if(edy2<edy1) {i=edy1;edy1=edy2;edy2=i;}
466 case EWALL: if(wtype==2 || (wtype>=5 && wtype<=7)) {p=(byte*)fldf;break;}
467 case EBACK: p=(byte*)fldb;break;
468 case EFRONT: p=(byte*)fldf;break;
470 if(b==1) {i=wallimg[etype];b=wtype;}
471 else{b=0;i=(wallimg[etype]>=0)?0:-1;}
473 if(i>0) if(((unsigned)walp[i]) > 16)
474 {sx=(walp[i]->w+7)/8;sy=(walp[i]->h+7)/8;}
475 for(edx2=edx2-edx1+1,ly=0;edy1<=edy2;++edy1,++ly) {
478 for(lx=0;lx<edx2;lx+=sx)
479 p[edy1*FLDW+edx1+lx]=i;
480 }else if(i==0) memset(p+edy1*FLDW+edx1,0,edx2);
481 if(etype==EWALL) memset(&fld[edy1][edx1],b,edx2);
483 edt=0;redraw();mw1.redraw();
486 if((i=TH_isthing(w_x-100+x,w_y-50+y))!=-1) {
489 lx=TH_getx(curth);ly=TH_gety(curth);
491 while((b=I_mget(&x,&y))&1) {
493 TH_move(curth,lx+x-sx,ly+y-sy);
497 if((b&2) || x>=200 || y==0 || y>=99) TH_move(curth,lx,ly);
498 else TH_move(curth,lx+x-sx,ly+y-sy);
499 }else {TH_delete(curth);curth=-1;}
500 }else if(b&2) curth=TH_add(w_x-100+x,w_y-50+y,pthing);
503 while(I_mget(&x,&y)) GUI_wait();
506 if((i=SW_ishere((w_x-100+x)>>3,(w_y-50+y)>>3))!=-1) {
507 if((b&3)==1) {cursw=i;redraw_sw();desktop.redraw();}
509 SW_add((w_x-100+x)>>3,(w_y-50+y)>>3);
510 redraw_sw();desktop.redraw();
511 while((I_mget(&x,&y)&3)==3) GUI_wait();
514 SW_setlink((w_x-100+x)>>3,(w_y-50+y)>>3);
516 while(I_mget(&x,&y)&2) GUI_wait();
525 mapwin::mapwin(int x,int y):frame(x,y,104,104) {
526 clrh=2;clrn=0;clrl=8;
529 void mapwin::draw(void) {
531 Z_drawmap(left+2,top+2);
532 SW_draw_mini(left+2,top+2);
535 int mapwin::mouse(int x,int y,int b) {
537 if(x>=100 || y>=100 || x<0 || y<0) return 1;
538 while(I_mget(&x,&y)) {
544 vw.hs->sld->cur=x*8-100;vw.hs->sld->adjust();
545 vw.vs->sld->cur=y*8-49;vw.vs->sld->adjust();
553 sprview::sprview(int x,int y,int w,int h,vgaimg *v,char c):gui_obj(x,y,w,h) {
557 void sprview::draw(void) {
561 if(scrx>=left+width) return;
562 if(scry>=top+height) return;
563 if(scrx+w>left+width) scrw=left+width-scrx;
564 if(scry+h>top+height) scrh=top+height-scry;
565 V_clr(left,width,top,height,gray[color]);
566 if(img) if(img->w<=320 && img->h<=200) V_spr(left+img->sx,top+img->sy,img);
570 extern "C" void edit(void) {
571 static textstr t1(115,115,1,5,"ФОН",&smallfont,15),
572 t2(115,115,1,5,"СТЕНЫ, ДВЕРИ И Т.П.",&smallfont,15),
573 t3(115,115,1,5,"ПЕРЕДНИЙ ПЛАН",&smallfont,15),
574 t4(115,115,1,5,"ВЕЩИ, МОНСТРЫ И Т.П.",&smallfont,15),
575 t5(115,115,1,5,"КНОПКИ",&smallfont,15),
576 tht1(130,137,0,5,"вправо",&smallfont,15),
577 tht2(130,147,0,5,"только в DM",&smallfont,15),
578 swt1(40,157,0,5,"игрок наж.",&smallfont,15),
579 swt2(40,167,0,5,"монстр наж.",&smallfont,15),
580 swt3(40,177,0,5,"игрок близко",&smallfont,15),
581 swt4(40,187,0,5,"монстр близко",&smallfont,15),
582 swt5(115,157,0,5,"красный ключ",&smallfont,15),
583 swt6(115,167,0,5,"зеленый ключ",&smallfont,15),
584 swt7(115,177,0,5,"синий ключ",&smallfont,15);
585 static sprbutton hb1(199,113,6,7,&help_icon,E_HELP,H_BACK,0x3B00),
586 hb2(199,113,6,7,&help_icon,E_HELP,H_WALL,0x3B00),
587 hb3(199,113,6,7,&help_icon,E_HELP,H_FRONT,0x3B00),
588 hb4(199,113,6,7,&help_icon,E_HELP,H_THING,0x3B00),
589 hb5(199,113,6,7,&help_icon,E_HELP,H_SWITCH,0x3B00),
590 hb6(120,123,6,7,&help_icon,E_HELP,H_SWTYPE,0x3B00);
591 static button baw1(145,125,60,10,"Добавить",E_ADDWALL,0,-1),
592 baw2(155,125,50,10,"Добавить",E_ADDWALL,0,-1),
593 baw3(145,125,60,10,"Добавить",E_ADDWALL,0,-1),
594 bsw1(25,123,9,9,"\x1B",E_PREVSW,0,-1),
595 bsw2(34,123,9,9,"\x1A",E_NEXTSW,0,-1),
596 bsw3(25,140,40,9,"Убрать",E_DELSW,0,-1),
597 bnw1(25,114,9,9,"",E_WALLIMG,-2,-1);
598 static strlist2 thl1(25,125,85,70,thtn_list,E_THTYPE,8);
599 static cont_t cnt1[]={
607 static strlist2 wtl1(90,125,60,70,wt_name+1,E_WTYPE,4);
608 static sprbutton b1(305,2,13,10,&system_icon,E_SYSTEM,0,-1),
609 b2(270,10,16,15,&load_icon,E_LOADMAP,0,0x3D00),
610 b3(270,40,16,15,&save_icon,E_SAVEMAP,0,0x3C00),
611 b5(308,15,6,7,&help_icon,E_HELP,H_MAIN,0x3B00);
612 static vcontbox vc1(0,110,210,90,20,cnt1,ETHING,E_ETYPE);
613 static button b4(265,70,36,15,"Музыка",E_MUSIC,0,-1);
615 logo("GUI_start: настройка графического интерфейса\n");
617 for(thtnum=1,t=TH_PLR2;t!=TH_PLR1;++thtnum,t=TH_nextt(t));
618 if(!(thtn_list=(char**)malloc((thtnum+1)*4)))
619 ERR_failinit(" Не хватает памяти");
620 if(!(tht_tlist=(int*)malloc(thtnum*4)))
621 ERR_failinit(" Не хватает памяти");
622 for(t=TH_PLR1,i=0;i<thtnum;++i,t=TH_nextt(t)) {
623 thtn_list[i]=TH_getname(tht_tlist[i]=t);
625 thl1.newlist(thtn_list);thl1.lst->cline=0;
626 getcwd(mapdir,_MAX_DIR);
627 w_x=FLDW*CELW/2+100;w_y=FLDH*CELH/2+49;
629 GUI_start();setgamma(gamma);
630 desktop<<=vw+=vc1+=mw1+=b1+=b2+=b3+=b4+=b5;
632 t1+=wl1+=baw1+=*(wlsv[0]=new sprview(145,140,60,55,NULL))+=hb1;
633 t2+=wl2+=wtl1+=baw2+=bnw1+=*(wlsv[1]=new sprview(155,140,50,55,NULL))+=hb2;
634 t3+=wl3+=baw3+=*(wlsv[2]=new sprview(145,140,60,55,NULL))+=hb3;
635 t4+=thl1+=th_cn+=thf_r+=thf_dm+=tht1+=tht2+=hb4;
636 t5+=bsw1+=bsw2+=bsw3+=sw_cn+=swt1+=swt2+=swt3+=swt4+=swt5+=swt6+=swt7
637 +=swf_pp+=swf_mp+=swf_pn+=swf_mn+=swf_kr+=swf_kg+=swf_kb+=hb5+=hb6;