/* 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 ------------------------------------------------------------------------- Editor THING definitions */ static const char rcs_id[]="$Id$"; #include "config.h" #include "globals.h" #include "specials.h" #include "flags.h" #include "util.h" #include #include "editvar.h" /* ---------------------------------------- PRIVATE UTILS */ static void ThingSelectionCentre(int *x,int *y) { int *f; EditThing *t; Iterator i; int min_x,min_y,max_x,max_y; VIDOOM_TRACE; i=ListIterator(selected); min_x=99999; min_y=99999; max_x=-99999; max_y=-99999; while(i) { f=IteratorData(i); t=GETTHING(*f); min_x=MIN(t->t.x,min_x); min_y=MIN(t->t.y,min_y); max_x=MAX(t->t.x,max_x); max_y=MAX(t->t.y,max_y); i=IteratorNext(i); } *x=min_x+(max_x-min_x)/2; *y=min_y+(max_y-min_y)/2; } /* ---------------------------------------- GENERIC THING FUNCS */ int PositionOnObject_THING(int x,int y,void *data) { EditThing *t; int r; VIDOOM_TRACE; t=data; r=ThingRadius(t->t.type,NULL); return (RADBOUND(x,y,t->t.x,t->t.y,r)); } void SelectBox_THING(int x1,int y1,int x2,int y2) { Object *o; EditThing *t; int f; VIDOOM_TRACE; for(f=0;fdata)) { if ((o->select!=SELECT_SELECTED)&& (BOXBOUND(t->t.x,t->t.y,x1,y1,x2,y2))) { SetSelect(f,SELECT_SELECTED); ListAppend(selected,&f); } } } } void SelectByType_THING(void) { Object *o; EditThing *t; int id; int f; if ((hexen_mode)&&(YesNo("Select by special action|rather than type?"))) { if ((id=SelectSpecial())!=SPECIAL_NULLID) { ClearSelection(); for(f=0;fdata)&&(t->t.special==id)) { SetSelect(f,SELECT_SELECTED); ListAppend(selected,&f); } } } else if ((id=SelectThing())!=THING_NULLID) { ClearSelection(); for(f=0;fdata)&&(t->t.type==id)) { SetSelect(f,SELECT_SELECTED); ListAppend(selected,&f); } } } void DrawObject_THING(void *data, int selmode) { EditThing *t; int a; int lx,ly; int r; int col; VIDOOM_TRACE; t=data; a=ANGLENUM(t->t.ang); r=ThingRadius(t->t.type,&col); switch(selmode) { case SELECT_OVER: col=OVERCOL; break; case SELECT_SELECTED: col=SELCOL; break; default: break; } lx=t->t.x+(t_arrow[a].x*r); ly=t->t.y+(t_arrow[a].y*r); MapCircle(t->t.x,t->t.y,r,col); DrawArrow(t->t.x,t->t.y,lx,ly,col); } void DrawObjectInfo_THING(void) { EditThing *ti; char *nm; char *a[5]; VIDOOM_TRACE; if (!draw_current_info) return; if ((current!=-1)&&((ti=GETTHING(current)))) { if (hexen_mode) { nm=SpecialName(ti->t.special,a); GuiDrawInfoBox("THING",GUI_FLUSH_LEFT,GUI_FLUSH_LOWER,FALSE, "Thing No : %d|" "Thing ID : %d|" "Z Pos : %-30d|" "Angle : %s (%d)|" "Flags : %s (0x%.2x)|" "Type : %-30.30s", current, ti->t.id, ti->t.z, ANGLESTR(ti->t.ang),ti->t.ang, FlagText(hexen_mode,THING_FLAGS, (int)ti->t.flags),ti->t.flags, ThingName(ti->t.type)); GuiDrawInfoBox("THING SPECIAL",GUI_FLUSH_RIGHT, GUI_FLUSH_LOWER,FALSE, "Special : %-20.20s|" "%-10s : %-3d|" "%-10s : %-3d|" "%-10s : %-3d|" "%-10s : %-3d|" "%-10s : %-3d", nm, (a[0] ? a[0] : "N/A"),ti->t.args[0], (a[1] ? a[1] : "N/A"),ti->t.args[1], (a[2] ? a[2] : "N/A"),ti->t.args[2], (a[3] ? a[3] : "N/A"),ti->t.args[3], (a[4] ? a[4] : "N/A"),ti->t.args[4]); } else GuiDrawInfoBox("THING",GUI_FLUSH_LEFT,GUI_FLUSH_LOWER,FALSE, "Thing No : %d|" "Angle : %s (%d)|" "Flags : %s (0x%.2x)|" "Type : %-60s", current, ANGLESTR(ti->t.ang),ti->t.ang, FlagText(hexen_mode,THING_FLAGS, (int)ti->t.flags),ti->t.flags, ThingName(ti->t.type)); } else if (hexen_mode) { GuiDrawInfoBox("THING",GUI_FLUSH_LEFT,GUI_FLUSH_LOWER,FALSE, "Thing No : -|" "Thing ID : -|" "Z Pos : -|" "Angle : -|" "Flags : - (-)|" "Type : %-30s",""); GuiDrawInfoBox("THING SPECIAL",GUI_FLUSH_RIGHT, GUI_FLUSH_LOWER,FALSE, "Special : %-20s|" "- : -|" "- : -|" "- : -|" "- : -|" "- : -|",""); } else GuiDrawInfoBox("THING",GUI_FLUSH_LEFT,GUI_FLUSH_LOWER,FALSE, "Thing No : -|" "Angle : -|" "Flags : - (-)|" "Type : %-60s",""); } void DrawObjectHeader_THING(void) { } void MoveObject_THING(void) { GFXEvent ev; int omx,omy; int dmx,dmy; int done; Iterator i; Iterator i2; EditThing *t; List orig; int *f; Point p; int cancel=FALSE; VIDOOM_TRACE; omx=SnapX(XToMap(ms.x)); omy=SnapY(YToMap(ms.y)); GFX_bounce(); done=FALSE; cancel=FALSE; orig=ListNew(sizeof(Point)); i=ListIterator(selected); while(i) { f=IteratorData(i); t=GETTHING(*f); p.x=t->t.x; p.y=t->t.y; ListAppend(orig,&p); i=IteratorNext(i); } while(!done) { GuiDrawInfoBox("Move THING",GUI_FLUSH_RIGHT,GUI_FLUSH_LOWER,FALSE, "Left mouse button to place|ESC to cancel"); GFX_redraw(); GFX_await_input_full(&ev); switch(ev.type) { case GFX_KEY_EVENT: HandleMoveKey(ev.key,FALSE); /* Cancel the move */ if (ev.key.code==GFX_ESC) { cancel=TRUE; i=ListIterator(selected); i2=ListIterator(orig); while(i2) { f=IteratorData(i); memcpy(&p,IteratorData(i2),sizeof(Point)); t=GETTHING(*f); t->t.x=p.x; t->t.y=p.y; i=IteratorNext(i); i2=IteratorNext(i2); } done=TRUE; dmx=0; dmy=0; } else { dmx=SnapX(XToMap(ms.x))-omx; dmy=SnapY(YToMap(ms.y))-omy; } break; case GFX_MOUSE_EVENT: memcpy(&ms,&ev.mouse,sizeof(ev.mouse)); if (ms.b&GFX_BUTLEFT) done=TRUE; dmx=SnapX(XToMap(ms.x))-omx; dmy=SnapY(YToMap(ms.y))-omy; break; default: dmx=0; dmy=0; break; } if ((dmx)||(dmy)) { i=ListIterator(selected); while(i) { f=IteratorData(i); t=GETTHING(*f); t->t.x+=dmx; t->t.y+=dmy; i=IteratorNext(i); } omx=SnapX(XToMap(ms.x)); omy=SnapY(YToMap(ms.y)); FullRedraw(); } } ListClear(orig); if ((clear_on_move)&&(!cancel)) ClearSelection(); FullRedraw(); } void RotateObject_THING(double angle) { int cx,cy; int x,y; int *f; Iterator i; EditThing *t; VIDOOM_TRACE; ThingSelectionCentre(&cx,&cy); i=ListIterator(selected); while(i) { f=IteratorData(i); t=GETTHING(*f); x=t->t.x; y=t->t.y; Rotate(cx,cy,&x,&y,angle); t->t.x=x; t->t.y=y; i=IteratorNext(i); } } void ScaleObject_THING(double scale) { int cx,cy; int x,y; int *f; Iterator i; EditThing *t; VIDOOM_TRACE; ThingSelectionCentre(&cx,&cy); i=ListIterator(selected); while(i) { f=IteratorData(i); t=GETTHING(*f); x=t->t.x; y=t->t.y; Scale(cx,cy,&x,&y,scale); t->t.x=x; t->t.y=y; i=IteratorNext(i); } } void SetTagObject_THING(int tag) { VIDOOM_TRACE; } void LocateObject_THING(void *obj) { EditThing *t; VIDOOM_TRACE; t=obj; ox=t->t.x-scale*SCRW/2; oy=t->t.y+scale*SCRH/2; } void ObjectInsert_THING(void) { Object o; EditThing *t; int f; VIDOOM_TRACE; t=Grab(sizeof(EditThing)); memcpy(&t->t,&ed_thing,sizeof(Thing)); t->t.x=SnapX(XToMap(ms.x)); t->t.y=SnapY(YToMap(ms.y)); f=MapSize(thing); switch(insert_select) { case HOVER_NONE: o.select=SELECT_NONE; break; case HOVER_ADD: case HOVER_SINGLE: o.select=SELECT_SELECTED; break; } o.data=t; DrawObject_THING(t,o.select); MapAdd(thing,f,&o); switch(insert_select) { case HOVER_NONE: break; case HOVER_ADD: ListAppend(selected,&f); break; case HOVER_SINGLE: ClearSelection(); ListAppend(selected,&f); FullRedraw(); break; } } void ObjectDelete_THING(void) { Iterator i; Object *o; int *f; VIDOOM_TRACE; i=ListIterator(selected); while(i) { f=IteratorData(i); o=MapElem(thing,*f); Release(o->data); o->data=NULL; o->select=SELECT_NONE; i=IteratorNext(i); } ClearSelection(); FullRedraw(); } void ObjectMenu_THING(void) { EditThing *t; int f,*s; Iterator i; int cancel; int redraw=FALSE; VIDOOM_TRACE; cancel=FALSE; GFX_redraw(); switch(GUI_menu("Thing",ms.x,ms.y, (hexen_mode ? thing_popup_hexen:thing_popup),GUI_CANCEL)) { case TM_TYPE: { Short id; id=(Short)SelectThing(); if (id!=THING_NULLID) { ed_thing.type=id; i=ListIterator(selected); while(i) { s=IteratorData(i); t=GETTHING(*s); t->t.type=id; i=IteratorNext(i); } redraw=TRUE; } } break; case TM_SPECIAL: { Short id; id=(Short)SelectSpecial(); if (id!=SPECIAL_NULLID) { ed_thing.special=id; i=ListIterator(selected); while(i) { s=IteratorData(i); t=GETTHING(*s); t->t.special=id; i=IteratorNext(i); } redraw=TRUE; } break; } case TM_THING_ID: { static int id; if (GetNumber("Enter THING ID",&id)) { i=ListIterator(selected); while(i) { s=IteratorData(i); t=GETTHING(*s); t->t.id=id; i=IteratorNext(i); } redraw=TRUE; } break; } case TM_VAL: { static int id; if (GetNumber("Enter THING type",&id)) { i=ListIterator(selected); while(i) { s=IteratorData(i); t=GETTHING(*s); t->t.type=id; i=IteratorNext(i); } redraw=TRUE; } } break; case TM_SPECIAL_VAL: { static int id; if (GetNumber("Enter THING special action",&id)) { i=ListIterator(selected); while(i) { s=IteratorData(i); t=GETTHING(*s); t->t.special=id; i=IteratorNext(i); } redraw=TRUE; } } break; case TM_ANGLE: { int a; t=SelHead(); a=t->t.ang; if ((a=GUI_radio_box ("Angle",thing_angle,a,GUI_CANCEL))!=GUI_CANCEL) { ed_thing.ang=a; i=ListIterator(selected); while(i) { s=IteratorData(i); t=GETTHING(*s); t->t.ang=a; i=IteratorNext(i); } } redraw=TRUE; } break; case TM_ANGLE_VAL: { int a; t=SelHead(); a=t->t.ang; if (GetNumber("Enter angle value",&a)) { i=ListIterator(selected); while(i) { s=IteratorData(i); t=GETTHING(*s); t->t.ang=a; i=IteratorNext(i); } } redraw=TRUE; } break; case TM_FLAGS: i=ListIterator(selected); s=IteratorData(i); t=GETTHING(*s); f=t->t.flags; if (SelectFlags(hexen_mode,THING_FLAGS,&f)) { ed_thing.flags=f; while(i) { s=IteratorData(i); t=GETTHING(*s); t->t.flags=ed_thing.flags; i=IteratorNext(i); } redraw=TRUE; } break; case TM_SNAP: { int orig_lock; orig_lock=grid_lock; grid_lock=TRUE; i=ListIterator(selected); while(i) { s=IteratorData(i); t=GETTHING(*s); t->t.x=SnapX(t->t.x); t->t.y=SnapX(t->t.y); i=IteratorNext(i); } grid_lock=orig_lock; redraw=TRUE; break; } case TM_DELETE: ObjectDelete_THING(); break; case TM_MOVE: MoveObject_THING(); break; case TM_Z_POS: t=SelHead(); zcoord_dialog[D_ZCOORD].data.i=t->t.z; if (GUI_dialog("Change Z co-ord",D_ZCOORD_NO,zcoord_dialog)) { ed_thing.z=zcoord_dialog[D_ZCOORD].data.i; i=ListIterator(selected); while(i) { s=IteratorData(i); t=GETTHING(*s); t->t.z=ed_thing.z; i=IteratorNext(i); } } else cancel=TRUE; redraw=TRUE; break; case TM_ARGS: { int a[5]; int id; int diff; t=SelHead(); id=t->t.special; i=ListIterator(selected); i=IteratorNext(i); diff=FALSE; while((i)&&(!diff)) { s=IteratorData(i); t=GETTHING(*s); if (t->t.special!=id) diff=TRUE; i=IteratorNext(i); } if ((diff)&&(YesNo("Selected things have|different types| |" "Set individually?"))) { cancel=TRUE; i=ListIterator(selected); while(i) { s=IteratorData(i); t=GETTHING(*s); id=t->t.special; for(f=0;f<5;f++) a[f]=t->t.args[f]; if (SpecialArgDialog(NULL,id,a)) { for(f=0;f<5;f++) t->t.args[f]=ed_thing.args[f]=a[f]; cancel=FALSE; } i=IteratorNext(i); } } else { t=SelHead(); for(f=0;f<5;f++) a[f]=t->t.args[f]; if (SpecialArgDialog(NULL,id,a)) { for(f=0;f<5;f++) ed_thing.args[f]=a[f]; i=ListIterator(selected); while(i) { s=IteratorData(i); t=GETTHING(*s); for(f=0;f<5;f++) t->t.args[f]=ed_thing.args[f]; i=IteratorNext(i); } } else cancel=TRUE; } redraw=TRUE; break; } case TM_ZERO: i=ListIterator(selected); while(i) { s=IteratorData(i); t=GETTHING(*s); for(f=0;f<5;f++) t->t.args[f]=0; i=IteratorNext(i); } FullRedraw(); break; case TM_ARGS_RANGE: { int a[5]; int d[5]; int id; int diff; t=SelHead(); id=t->t.special; i=ListIterator(selected); i=IteratorNext(i); diff=FALSE; while(i) { s=IteratorData(i); t=GETTHING(*s); if (t->t.special!=id) { diff=TRUE; i=IteratorClear(i); } else i=IteratorNext(i); } t=SelHead(); for(f=0;f<5;f++) { a[f]=t->t.args[f]; d[f]=0; } if ((!diff)||(YesNo("Selected things have|different types| |" "Continue?"))) if ((SpecialArgDialog("Start values",id,a))&& (SpecialArgDialog("Increments",id,d))) { i=ListIterator(selected); while(i) { s=IteratorData(i); t=GETTHING(*s); for(f=0;f<5;f++) { t->t.args[f]=(Byte)a[f]; a[f]+=d[f]; } i=IteratorNext(i); } FullRedraw(); } break; } default: cancel=TRUE; break; } if ((!cancel)&&(clear_on_menu)) { ClearSelection(); FullRedraw(); } else if (redraw) FullRedraw(); } void ObjectKey_THING(GFXKey k) { Iterator i; EditThing *t; int tmpsel; int redraw; int *f; int a; tmpsel=TmpAddCurrent(); redraw=FALSE; if (ListSize(selected)==0) return; if (k.code!=GFX_ASCII) switch(k.code) { default: break; } else { i=ListIterator(selected); while(i) { f=IteratorData(i); t=GETTHING(*f); switch(toupper(k.ascii)) { case ',': a=ANGLENUM(t->t.ang); if (++a==8) a=0; t->t.ang=a*45; redraw=TRUE; break; case '.': a=ANGLENUM(t->t.ang); if (--a<0) a=7; t->t.ang=a*45; redraw=TRUE; break; case '<': if (hexen_mode) { t->t.z--; redraw=TRUE; } break; case '>': if (hexen_mode) { t->t.z++; redraw=TRUE; } break; default: break; } i=IteratorNext(i); } } if (redraw) FullRedraw(); if (tmpsel) ListEmpty(selected); } int ObjectHasTag_THING(void *obj, int tag) { return(FALSE); } ObjDesc *ObjectOverlaid_THING(int x, int y, int *no) { int n; EditThing *t; ObjDesc *od; int f; VIDOOM_TRACE; od=NULL; n=0; for(f=0;ft.type),29), TrimStr(FlagText(hexen_mode,THING_FLAGS, t->t.flags),19)); } } *no=n; return(od); } /* END OF FILE */