/* viDOOM - level editor for DOOM Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------------- Handles definition and storage of the supported generalised LINEDEFs */ static const char rcs_id[]="$Id$"; #include "config.h" #include "globals.h" #include "platgui.h" #include "gfx.h" #include "platgui.h" #include "genlines.h" #include "mem.h" #include "map.h" #include "linedefs.h" /* ---------------------------------------- TYPES AND VARS */ typedef struct { char *name; char *abbrev; int val; } gl_BitField; typedef struct { int i; char *name; int no; gl_BitField *bf; } gl_BitMask; typedef struct { int mask; int shift; gl_BitMask *bm; } gl_ClassBitMask; typedef struct { int i; char *name; int hi; int lo; int no; int mask; gl_ClassBitMask *bm; PLAT_DIALOG *dial; } gl_Class; static Map mask_map=NULL; static Map class_map[2]={NULL,NULL}; /* ---------------------------------------- PRIVATE FUNCTIONS */ static int Index(int for_hexen) { if (for_hexen) return(1); else return(0); } static gl_BitMask *GetMask(char *class) { gl_BitMask *m; int f; for(f=0;fname))) return(m); } return(NULL); } static gl_Class *GetClass(int i,char *class) { gl_Class *c; int f; for(f=0;fname))) return(c); } return(NULL); } static gl_Class *ClassMenu(int i) { static PLAT_MENU *menu[2]={NULL,NULL}; gl_Class *cl; int f,x,y; if (!menu[i]) { menu[i]=Grab(sizeof(PLAT_MENU)*(MapSize(class_map[i])+1)); for(f=0;fname; menu[i][f].client_index=f; menu[i][f].child=NULL; } menu[i][f].text=NULL; } GFX_mouse(&x,&y); f=GUI_menu("Generalised LINEDEF type",x,y,menu[i],GENLINE_NULLID); if (f==GENLINE_NULLID) return(NULL); else return(MapElem(class_map[i],f)); } static void InitDialog(gl_Class *cl, int type) { int f,r; int mask; /* Create the dialog if not already done so */ if (!cl->dial) { if (cl->i!=cl->no) GFX_exit(EXIT_FAILURE, "Not all bitfields defined for class:\n %s\n",cl->name); cl->dial=Grab(sizeof(PLAT_DIALOG)*cl->no); for(f=0;fno;f++) { cl->dial[f].text=cl->bm[f].bm->name; cl->dial[f].type=PLAT_DIAL_PICKLIST; cl->dial[f].data.pl.no=cl->bm[f].bm->no; cl->dial[f].data.pl.current=0; cl->dial[f].data.pl.text=Grab(cl->bm[f].bm->no*sizeof(char *)); for(r=0;rbm[f].bm->no;r++) cl->dial[f].data.pl.text[r]=Strdup(cl->bm[f].bm->bf[r].name); } } /* Set the flags from the current value */ for(f=0;fno;f++) { cl->dial[f].data.pl.current=0; mask=(type>>cl->bm[f].shift)&cl->bm[f].mask; for(r=0;rbm[f].bm->no;r++) if (cl->bm[f].bm->bf[r].val==mask) cl->dial[f].data.pl.current=r; } } /* ---------------------------------------- EXPORTED FUNCTIONS */ void GenLineNewBitClass(char *class, int no_fields) { gl_BitMask *bm; bm=Grab(sizeof(gl_BitMask)); if (!mask_map) mask_map=MapNew(sizeof(gl_BitMask)); bm->name=Strdup(class); bm->no=no_fields; bm->i=0; bm->bf=Grab(sizeof(gl_BitField)*bm->no); MapAdd(mask_map,-1,bm); } void GenLineAddBitmask(char *class, char *name, char *abbrev, int mask) { gl_BitField *bf; gl_BitMask *bm; if (!(bm=GetMask(class))) GFX_exit(EXIT_FAILURE,"Adding bit field:\n%s\n\nfailed as " "there is no bitmask:\n%s\n",name,class); if (bm->i==bm->no) GFX_exit(EXIT_FAILURE,"Adding bit field:\n%s\n\n " "overflows bitmask:\n%s\n",name,class); bf=&(bm->bf[bm->i++]); bf->name=Strdup(name); bf->abbrev=Strdup(abbrev); bf->val=mask; } void GenLineNewClass(int for_hexen, char *class, int lo, int hi, int mask, int no_bitmasks) { gl_Class *cl; int i; i=Index(for_hexen); cl=Grab(sizeof(gl_Class)); if (!class_map[i]) class_map[i]=MapNew(sizeof(gl_Class)); cl->name=Strdup(class); cl->hi=hi; cl->lo=lo; cl->mask=mask; cl->no=no_bitmasks; cl->i=0; cl->bm=Grab(sizeof(gl_ClassBitMask)*cl->no); cl->dial=NULL; MapAdd(class_map[i],-1,cl); } void GenLineAdd(int for_hexen, char *class, char *bitmask, int shift) { gl_Class *cl; gl_BitMask *bm; int f; int i; i=Index(for_hexen); if (!(bm=GetMask(bitmask))) GFX_exit(EXIT_FAILURE,"Adding bitmask:\n%s\n\nto class:\n%s\n\n" "failed as there is no such bitmask class\n\n", bitmask,class); if (bm->i!=bm->no) GFX_exit(EXIT_FAILURE,"Adding bitmask:\n%s\n\nto class:\n%s\n\n" "failed as not all fields have been defined " "in the bitmask\n\n", bitmask,class); if (!(cl=GetClass(i,class))) GFX_exit(EXIT_FAILURE,"Adding bitmask:\n%s\n\nto class:\n%s\n\n" "failed as there is no such class\n\n", bitmask,class); if (cl->i==cl->no) GFX_exit(EXIT_FAILURE,"Adding bitmask:\n%s\n\nto class:\n%s\n\n" "overflows class\n\n", bitmask,class); cl->bm[cl->i].bm=bm; cl->bm[cl->i].shift=shift; cl->bm[cl->i].mask=0; for(f=0;fbm[cl->i].bm->no;f++) cl->bm[cl->i].mask|=cl->bm[cl->i].bm->bf[f].val; cl->i++; } int SelectGenLine(int for_hexen, int current_type) { gl_Class *cl; int n; int f; int i; i=Index(for_hexen); if (MapSize(class_map[i])==0) return(GENLINE_NULLID); if (MapSize(class_map[i])==1) cl=MapElem(class_map[i],0); else if (!(cl=ClassMenu(i))) return(GENLINE_NULLID); InitDialog(cl,current_type); if (GUI_dialog(cl->name,cl->no,cl->dial)) { if (cl->mask!=-1) n=cl->mask; else { n=current_type; for(f=0;fno;f++) n&=~(cl->bm[f].mask<bm[f].shift); } for(f=0;fno;f++) n|=(cl->bm[f].bm->bf[cl->dial[f].data.pl.current].val) <bm[f].shift; } else n=GENLINE_NULLID; return(n); } char *GenLineName(int for_hexen, int id,char *(*GetName)(int id)) { static char s[512]; gl_Class *cl; int f,r,i; int got; int mask; int index; index=Index(for_hexen); for(f=0;f=cl->lo)&&(id<=cl->hi)) { s[0]=0; for(r=0;rno;r++) { if (r) strcat(s,"/"); mask=(id>>cl->bm[r].shift)&cl->bm[r].mask; got=FALSE; for(i=0;(ibm[r].bm->no)&&(!got);i++) if (mask==cl->bm[r].bm->bf[i].val) { strcat(s,cl->bm[r].bm->bf[i].abbrev); got=TRUE; } if (!got) strcat(s,"???"); } if (cl->mask==-1) { for(f=0;fno;f++) id&=~(cl->bm[f].mask<bm[f].shift); if (GetName(id)) { strcat(s," & "); strcat(s,GetName(id)); } } return(s); } } return(NULL); } char *GenLineClass(int for_hexen, int id,char *(*GetClass)(int id)) { static char s[512]; gl_Class *cl; int f; int i; i=Index(for_hexen); for(f=0;f=cl->lo)&&(id<=cl->hi)) { strcpy(s,cl->name); if (cl->mask==-1) { for(f=0;fno;f++) id&=~(cl->bm[f].mask<bm[f].shift); if (GetClass(id)) { strcat(s," & "); strcat(s,GetClass(id)); } } return(s); } } return(NULL); } int GenLineNoClasses(int for_hexen) { return(MapSize(class_map[Index(for_hexen)])); } /* END OF FILE */