/* 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 "util.h" #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; 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; 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; 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 ((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; TRACE; t=data; a=((t->t.ang+22)/45%8); 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; TRACE; if (!draw_current_info) return; if ((current!=-1)&&((ti=GETTHING(current)))) GuiDrawInfoBox("THING",GUI_FLUSH_LEFT,GUI_FLUSH_LOWER,FALSE, "Thing No : %d|" "Thing Id : %d|" "Angle : %s (%d)|" "Flags : %s (0x%.2x)|" "Name : %-60s", current, ti->t.type, ANGLESTR(ti->t.ang),ti->t.ang, ThingFlagText((int)ti->t.opt),ti->t.opt, ThingName(ti->t.type)); else GuiDrawInfoBox("THING",GUI_FLUSH_LEFT,GUI_FLUSH_LOWER,FALSE, "Thing No : -|" "Thing Id : -|" "Angle : -|" "Flags : - (-)|" "Name : %-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; 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; 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; 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) { TRACE; } void LocateObject_THING(void *obj) { EditThing *t; 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; 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; 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; TRACE; cancel=FALSE; GFX_redraw(); switch(GUI_menu("Thing",ms.x,ms.y,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_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_FLAGS: i=ListIterator(selected); s=IteratorData(i); t=GETTHING(*s); f=t->t.opt; if (GUI_multi_box("Flags",ThingFlagArray(),&f)) { ed_thing.opt=f; while(i) { s=IteratorData(i); t=GETTHING(*s); t->t.opt=ed_thing.opt; 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; default: cancel=TRUE; break; } if ((!cancel)&&(clear_on_menu)) { ClearSelection(); FullRedraw(); } else if (redraw) FullRedraw(); } void ObjectKey_THING(GFXKey k) { } 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; TRACE; od=NULL; n=0; for(f=0;ft.type),29), TrimStr(ThingFlagText(t->t.opt),19)); } } *no=n; return(od); } /* END OF FILE */