/* 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 ------------------------------------------------------------------------- Merging of WAD maps */ static const char rcs_id[]="$Id$"; #include "config.h" #include "globals.h" #include "editvar.h" #include "gui.h" #include "wad.h" /* ---------------------------------------- LOCAL DATA */ static WadMap *wad; static int min_x; static int min_y; static int max_x; static int max_y; static int cx; static int cy; static int ang; /* ---------------------------------------- CO-ORD FUNCS */ static void MergeCoord(int *x, int *y) { if (ang) { Rotate(min_x,min_y,x,y,(double)ang); *x=cx-min_x+(*x); *y=cy-min_y+(*y); } else { *x=cx-min_x+(*x); *y=cy-min_y+(*y); } } /* ---------------------------------------- PickPoint() CALLBACKS */ static void PickDraw(int *x,int *y) { Map lm,vm; Linedef *l; Vertex *v1,*v2; int x1,y1,x2,y2; int f; cx=*x=SnapX(*x); cy=*y=SnapY(*y); lm=wad->linedef; vm=wad->vertex; for(f=0;ffrom); v2=MapElem(vm,l->to); x1=v1->x; y1=v1->y; MergeCoord(&x1,&y1); x1=MapToX(x1); y1=MapToY(y1); x2=v2->x; y2=v2->y; MergeCoord(&x2,&y2); x2=MapToX(x2); y2=MapToY(y2); GFX_line(x1,y1,x2,y2,WHITE); } } static void PickKey(GFXKey k) { TRACE; if (k.code==GFX_ASCII) switch(k.ascii) { case '.': if (--ang<0) ang=359; break; case ',': ang=(ang+1)%360; break; case '>': if ((ang-=10)<0) ang+=360; break; case '<': ang=(ang+10)%360; break; default: break; } } static void PickInfo(char *p) { TRACE; GuiDrawInfoBox(p,GUI_FLUSH_RIGHT,GUI_FLUSH_LOWER,FALSE,"Angle : %3d|",ang); GuiDrawInfoBox(p,GUI_FLUSH_LEFT,GUI_FLUSH_LOWER,FALSE, ", - rotate left 1 deg |" ". - rotate right 1 deg |" "< - rotate left 10 deg |" "> - rotate right 10 deg|" " |" "Press left button to complete. ESC to cancel"); } /* ---------------------------------------- WAD MERGEING */ void MergeWad(void) { Object o; Linedef *l; Sector *s=NULL; Thing *t; Vertex *v; Sidedef *si; EditVert *ev; EditLine *el; EditSect *es; EditThing *et; char *name; int f; int unbound; int n_thing; int n_line; int n_side; int n_vert; int n_sect; int n_tag; int tmp_wad; char *tmp_n; char *wadf; int *secmap; int x,y; if (level_style==DOOM_2_LEVELS) tmp_n="MAP01"; else tmp_n="E1M1"; if ((tmp_wad=YesNo("Load a new PWAD and read %s from it?",tmp_n))) { if (!(wadf=GUI_fsel("Pick PWAD to merge map from",PWAD_dir,".WAD"))) return; if (AddPWAD(wadf)!=WAD_OK) { GuiInfoBox("ERROR","AddPWAD(%s): %s",wadf,WadErrorString()); FullRedraw(); Release(wadf); return; } name=tmp_n; } else { wadf=NULL; if (!(name=GuiPickLevel("Pick map to merge"))) return; } GuiDrawInfoBox("Loading...",GUI_CENTRE,GUI_CENTRE,TRUE, "Loading level %s",name); if (!(wad=LoadMap(name))) { GuiInfoBox("ERROR","LoadMap(%s): %s",name,WadErrorString()); FullRedraw(); if (tmp_wad) { if (CloseWad(wadf)!=WAD_OK) GuiInfoBox("ERROR","CloseWad(%s)|%s",wadf,WadErrorString()); Release(wadf); } return; } if (MapSize(wad->linedef)==0) { GuiInfoBox("ERROR","No LINEDEFS in %s",name); ClearMap(wad); FullRedraw(); if (tmp_wad) { if (CloseWad(wadf)!=WAD_OK) GuiInfoBox("ERROR","CloseWad(%s)|%s",wadf,WadErrorString()); Release(wadf); } return; } FullRedraw(); /* Get top left hand corner of map and see if there are unbound left sidedefs */ ang=0; min_x=99999; min_y=99999; max_x=-99999; max_y=-99999; for(f=0;fvertex);f++) { v=MapElem(wad->vertex,f); min_x=MIN(min_x,v->x); min_y=MIN(min_y,v->y); max_x=MAX(max_x,v->x); max_y=MAX(max_y,v->y); } min_x=min_x+(max_x-min_x)/2; min_y=min_y+(max_y-min_y)/2; unbound=FALSE; for(f=0;(flinedef))&&(!unbound);f++) { l=MapElem(wad->linedef,f); if (l->left!=-1) { si=MapElem(wad->sidedef,l->left); if (si->sector==-1) unbound=TRUE; } } /* Position */ if (!PickPoint("Position MAP",&cx,&cy,PickDraw,PickKey,PickInfo)) { ClearMap(wad); if (tmp_wad) { if (CloseWad(wadf)!=WAD_OK) GuiInfoBox("ERROR","CloseWad(%s)|%s",wadf,WadErrorString()); Release(wadf); } return; } /* Adjust co-ords */ for(f=0;fvertex);f++) { v=MapElem(wad->vertex,f); x=v->x; y=v->y; MergeCoord(&x,&y); v->x=x; v->y=y; } for(f=0;fthing);f++) { t=MapElem(wad->thing,f); x=t->x; y=t->y; MergeCoord(&x,&y); t->x=x; t->y=y; } /* If the map is a structure with some unbound left sidedefs, calculate which sectors the new linedefs appear in (taken from the line's midpoint) */ if (unbound) { Vertex *v1,*v2; int lcx,lcy; secmap=Grab(sizeof(int)*MapSize(wad->linedef)); for(f=0;flinedef);f++) { l=MapElem(wad->linedef,f); v1=MapElem(wad->vertex,l->from); v2=MapElem(wad->vertex,l->to); lcx=v1->x+((v2->x-v1->x)/2); lcy=v1->y+((v2->y-v1->y)/2); secmap[f]=SectorHoldingPoint(lcx,lcy); } /* See if floor and ceilings shold be adjusted */ if (YesNo("Adjust structure floor heights?")) { int t,min,diff; if ((t=SectorHoldingPoint(cx,cy))!=-1) es=GETSECT(t); else es=NULL; if (es) { min=99999; for(f=0;fsector);f++) { s=MapElem(wad->sector,f); if (min>s->floor) min=s->floor; } diff=min-es->s.floor; for(f=0;fsector);f++) { s=MapElem(wad->sector,f); s->floor-=diff; s->ceiling-=diff; } } } if (YesNo("Adjust structure ceiling heights?")) { int t; if ((t=SectorHoldingPoint(cx,cy))!=-1) es=GETSECT(t); else es=NULL; if (es) for(f=0;fsector);f++) { s=MapElem(wad->sector,f); if ((s->ceiling!=es->s.ceiling)&&(s->floors.ceiling)) s->ceiling=es->s.ceiling; } } } else secmap=NULL; /* Renumber tags? */ n_tag=0; if (YesNo("Renumber tags?")) { for(f=0;fl.tag); for(f=0;fs.tag); } n_thing=MapSize(thing); n_line=MapSize(linedef); n_side=MapSize(sidedef); n_sect=MapSize(sector); n_vert=MapSize(vertex); /* Insert vertexes */ for(f=0;fvertex);f++) { v=MapElem(wad->vertex,f); ev=Grab(sizeof(EditVert)); memcpy(&ev->v,v,sizeof(Vertex)); ev->l=ListNew(sizeof(int)); o.select=SELECT_NONE; o.data=ev; MapAdd(vertex,f+n_vert,&o); } /* Insert sidedefs */ for(f=0;fsidedef);f++) { o.select=SELECT_NONE; si=o.data=Copy(MapElem(wad->sidedef,f),sizeof(Sidedef)); if (si->sector!=-1) si->sector+=n_sect; MapAdd(sidedef,f+n_side,&o); } /* Insert linedefs and get associated sidedefs, vertex pointers and calc bounding box */ for(f=0;flinedef);f++) { l=MapElem(wad->linedef,f); el=Grab(sizeof(EditLine)); memcpy(&el->l,l,sizeof(Linedef)); if (el->l.tag) el->l.tag+=n_tag; el->l.from+=n_vert; el->l.to+=n_vert; el->l.right+=n_side; if (el->l.left!=-1) el->l.left+=n_side; el->no=f+n_line; el->sr=GETSIDE(el->l.right); if (l->left!=-1) { el->sl=GETSIDE(el->l.left); if ((unbound)&&(el->sl->sector==-1)) el->sl->sector=secmap[f]; } else el->sl=NULL; el->v[0]=GETVERT(el->l.from); el->v[1]=GETVERT(el->l.to); IntListUniqAdd(el->v[0]->l,f+n_line); IntListUniqAdd(el->v[1]->l,f+n_line); LineCalcBounding(el); o.select=SELECT_NONE; o.data=el; MapAdd(linedef,f+n_line,&o); } /* Insert sectors */ for(f=0;fsector);f++) { s=MapElem(wad->sector,f); es=Grab(sizeof(EditSect)); memcpy(&es->s,s,sizeof(Sector)); es->no=f+n_sect; if (es->s.tag) es->s.tag+=n_tag; es->v=ListNew(sizeof(Short)); es->sr=ListNew(sizeof(EditLine *)); es->sl=ListNew(sizeof(EditLine *)); es->all=ListNew(sizeof(EditLine *)); o.select=SELECT_NONE; o.data=es; MapAdd(sector,f+n_sect,&o); } /* Insert things */ for(f=0;fthing);f++) { t=MapElem(wad->thing,f); et=Grab(sizeof(EditThing)); memcpy(&et->t,t,sizeof(Thing)); o.select=SELECT_NONE; o.data=et; MapAdd(thing,f+n_thing,&o); } SectorCalcContainingAll(); GuiInfoBox("NOTICE","Vertexes adjusted by %d|" "Linedefs adjusted by %d|" "Sidedefs adjusted by %d|" "Sectors adjusted by %d|" "Things adjusted by %d|" "Tags adjusted by %d", n_vert,n_line,n_side,n_sect,n_thing,n_tag); FullRedraw(); /* Tidy up */ ClearMap(wad); if (unbound) Release(secmap); if (tmp_wad) { if (CloseWad(wadf)!=WAD_OK) GuiInfoBox("ERROR","CloseWad(%s)|%s",wadf,WadErrorString()); Release(wadf); } } /* END OF FILE */