summaryrefslogtreecommitdiff
path: root/gensect.c
diff options
context:
space:
mode:
Diffstat (limited to 'gensect.c')
-rw-r--r--gensect.c423
1 files changed, 423 insertions, 0 deletions
diff --git a/gensect.c b/gensect.c
new file mode 100644
index 0000000..74cbafa
--- /dev/null
+++ b/gensect.c
@@ -0,0 +1,423 @@
+/*
+
+ 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 SECTOR types.
+ Basically a copy of genlines.c.
+
+*/
+static const char rcs_id[]="$Id$";
+
+#include "config.h"
+#include "globals.h"
+
+#include "platgui.h"
+#include "gfx.h"
+#include "platgui.h"
+#include "gensect.h"
+#include "mem.h"
+#include "map.h"
+
+
+/* ---------------------------------------- TYPES AND VARS
+*/
+typedef struct
+ {
+ char *name;
+ char *abbrev;
+ int val;
+ } gs_BitField;
+
+typedef struct
+ {
+ int i;
+
+ char *name;
+ int no;
+ gs_BitField *bf;
+ } gs_BitMask;
+
+typedef struct
+ {
+ int mask;
+ int shift;
+ gs_BitMask *bm;
+ } gs_ClassBitMask;
+
+typedef struct
+ {
+ int i;
+
+ char *name;
+ int hi;
+ int lo;
+ int mask;
+ int no;
+ gs_ClassBitMask *bm;
+
+ PLAT_DIALOG *dial;
+ } gs_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 gs_BitMask *GetMask(char *class)
+{
+ gs_BitMask *m;
+ int f;
+
+ for(f=0;f<MapSize(mask_map);f++)
+ {
+ m=MapElem(mask_map,f);
+
+ if ((m)&&(STREQ(class,m->name)))
+ return(m);
+ }
+
+ return(NULL);
+}
+
+
+static gs_Class *GetClass(int index, char *class)
+{
+ gs_Class *c;
+ int f;
+
+ for(f=0;f<MapSize(class_map[index]);f++)
+ {
+ c=MapElem(class_map[index],f);
+
+ if ((c)&&(STREQ(class,c->name)))
+ return(c);
+ }
+
+ return(NULL);
+}
+
+
+static gs_Class *ClassMenu(int index)
+{
+ static PLAT_MENU *menu[2]={NULL,NULL};
+ gs_Class *cl;
+ int f,x,y;
+
+ if (!menu[index])
+ {
+ menu[index]=Grab(sizeof(PLAT_MENU)*(MapSize(class_map[index])+1));
+
+ for(f=0;f<MapSize(class_map[index]);f++)
+ {
+ cl=MapElem(class_map[index],f);
+
+ menu[index][f].text=cl->name;
+ menu[index][f].client_index=f;
+ menu[index][f].child=NULL;
+ }
+
+ menu[index][f].text=NULL;
+ }
+
+ GFX_mouse(&x,&y);
+ f=GUI_menu("Generalised SECTOR type",x,y,menu[index],GENSECT_NULLID);
+
+ if (f==GENSECT_NULLID)
+ return(NULL);
+ else
+ return(MapElem(class_map[index],f));
+}
+
+
+static void InitDialog(gs_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;f<cl->no;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;r<cl->bm[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;f<cl->no;f++)
+ {
+ cl->dial[f].data.pl.current=0;
+
+ mask=(type>>cl->bm[f].shift)&cl->bm[f].mask;
+
+ for(r=0;r<cl->bm[f].bm->no;r++)
+ if (cl->bm[f].bm->bf[r].val==mask)
+ cl->dial[f].data.pl.current=r;
+ }
+}
+
+
+/* ---------------------------------------- EXPORTED FUNCTIONS
+*/
+
+void GenSectNewBitClass(char *class, int no_fields)
+{
+ gs_BitMask *bm;
+
+ bm=Grab(sizeof(gs_BitMask));
+
+ if (!mask_map)
+ mask_map=MapNew(sizeof(gs_BitMask));
+
+ bm->name=Strdup(class);
+ bm->no=no_fields;
+ bm->i=0;
+ bm->bf=Grab(sizeof(gs_BitField)*bm->no);
+
+ MapAdd(mask_map,-1,bm);
+}
+
+
+void GenSectAddBitmask(char *class, char *name, char *abbrev, int mask)
+{
+ gs_BitField *bf;
+ gs_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 GenSectNewClass(int for_hexen, char *class,
+ int lo, int hi, int mask, int no_bitmasks)
+{
+ gs_Class *cl;
+ int i;
+
+ i=Index(for_hexen);
+
+ cl=Grab(sizeof(gs_Class));
+
+ if (!class_map[i])
+ class_map[i]=MapNew(sizeof(gs_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(gs_ClassBitMask)*cl->no);
+ cl->dial=NULL;
+
+ MapAdd(class_map[i],-1,cl);
+}
+
+
+void GenSectAdd(int for_hexen, char *class, char *bitmask, int shift)
+{
+ gs_Class *cl;
+ gs_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;f<cl->bm[cl->i].bm->no;f++)
+ cl->bm[cl->i].mask|=cl->bm[cl->i].bm->bf[f].val;
+
+ cl->i++;
+}
+
+
+int SelectGenSect(int for_hexen, int current_type)
+{
+ gs_Class *cl;
+ int n;
+ int f;
+ int i;
+
+ i=Index(for_hexen);
+
+ if (MapSize(class_map[i])==0)
+ return(GENSECT_NULLID);
+
+ if (MapSize(class_map[i])==1)
+ cl=MapElem(class_map[i],0);
+ else
+ if (!(cl=ClassMenu(i)))
+ return(GENSECT_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;f<cl->no;f++)
+ n&=~(cl->bm[f].mask<<cl->bm[f].shift);
+ }
+
+ for(f=0;f<cl->no;f++)
+ n|=(cl->bm[f].bm->bf[cl->dial[f].data.pl.current].val)
+ <<cl->bm[f].shift;
+ }
+ else
+ n=GENSECT_NULLID;
+
+ return(n);
+}
+
+
+char *GenSectName(int for_hexen, int id,char *(*GetName)(int hexen, int id))
+{
+ static char s[512];
+ gs_Class *cl;
+ int f,r,i;
+ int got;
+ int mask;
+ int index;
+
+ index=Index(for_hexen);
+
+ for(f=0;f<MapSize(class_map[index]);f++)
+ {
+ cl=MapElem(class_map[index],f);
+
+ if ((id>=cl->lo)&&(id<=cl->hi))
+ {
+ s[0]=0;
+
+ for(r=0;r<cl->no;r++)
+ {
+ if (r)
+ strcat(s,"/");
+
+ mask=(id>>cl->bm[r].shift)&cl->bm[r].mask;
+
+ got=FALSE;
+
+ for(i=0;(i<cl->bm[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;f<cl->no;f++)
+ id&=~(cl->bm[f].mask<<cl->bm[f].shift);
+
+ if (GetName(for_hexen,id))
+ {
+ strcat(s," & ");
+ strcat(s,GetName(for_hexen,id));
+ }
+ }
+
+
+ return(s);
+ }
+ }
+
+ return(NULL);
+}
+
+
+int GenSectNoClasses(int for_hexen)
+{
+ return(MapSize(class_map[Index(for_hexen)]));
+}
+
+
+/* END OF FILE */