/* 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 MULTIMODE definitions */ static const char rcs_id[]="$Id$"; #include "config.h" #include "globals.h" #include "util.h" #include "editvar.h" #define VERTEX 1 #define THING 2 /* ---------------------------------------- PRIVATE UTILS */ static int GetIterType(Iterator *i,MultiObj **mr,EditVert **v,EditThing **t) { int *f; MultiObj *m; TRACE; f=IteratorData(*i); m=GETMULTI(*f); switch(m->type) { case VERTEX: *v=GETVERT(m->i); break; case THING: *t=GETTHING(m->i); break; } *i=IteratorNext(*i); if (mr) *mr=m; return(m->type); } static int GetType(MultiObj *m,EditVert **v,EditThing **t) { TRACE; switch(m->type) { case VERTEX: *v=GETVERT(m->i); break; case THING: *t=GETTHING(m->i); break; } return(m->type); } static void SelectionCentre(int *x,int *y) { int *f; MultiObj *m; 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); m=GETMULTI(*f); min_x=MIN(m->x,min_x); min_y=MIN(m->y,min_y); max_x=MAX(m->x,max_x); max_y=MAX(m->y,max_y); i=IteratorNext(i); } *x=min_x+(max_x-min_x)/2; *y=min_y+(max_y-min_y)/2; } static void ApplySelectionCoords(void) { MultiObj *m; Iterator i; EditVert *v; EditThing *t; TRACE; i=ListIterator(selected); while(i) switch(GetIterType(&i,&m,&v,&t)) { case THING: t->t.x=m->x; t->t.y=m->y; break; case VERTEX: v->v.x=m->x; v->v.y=m->y; break; } } /* ---------------------------------------- EXPORTED UTILS */ void GenerateMultiMap(void) { MultiObj *m; EditVert *v; EditThing *t; Object o; int f; TRACE; if (!multimap) multimap=MapNew(sizeof(MultiObj)); else { for(f=0;ftype=VERTEX; m->i=f; m->x=v->v.x; m->y=v->v.y; o.data=m; o.select=SELECT_NONE; MapAdd(multimap,-1,&o); } for(f=0;ftype=THING; m->i=f; m->x=t->t.x; m->y=t->t.y; o.data=m; o.select=SELECT_NONE; MapAdd(multimap,-1,&o); } } /* ---------------------------------------- GENERIC THING FUNCS */ int PositionOnObject_MULTI(int x,int y,void *data) { EditVert *v; EditThing *t; TRACE; switch(GetType(data,&v,&t)) { case VERTEX: return (PositionOnObject_VERTEX(x,y,v)); break; case THING: return (PositionOnObject_THING(x,y,t)); break; } return (FALSE); } void SelectBox_MULTI(int x1,int y1,int x2,int y2) { Object *o; MultiObj *m; int f; TRACE; for(f=0;fdata)) { if ((o->select!=SELECT_SELECTED)&& (BOXBOUND(m->x,m->y,x1,y1,x2,y2))) { SetSelect(f,SELECT_SELECTED); ListAppend(selected,&f); } } } } void SelectByType_MULTI(void) { TRACE; return; } void DrawObject_MULTI(void *data, int selmode) { MultiObj *m; TRACE; m=data; switch(m->type) { case VERTEX: DrawObject_VERTEX(GETVERT(m->i),selmode); break; case THING: DrawObject_THING(GETTHING(m->i),selmode); break; default: break; } } void DrawObjectInfo_MULTI(void) { MultiObj *m; TRACE; if (!draw_current_info) return; if ((current!=-1)&&((m=GETMULTI(current)))) GuiDrawInfoBox("MULTI MODE",GUI_FLUSH_LEFT,GUI_FLUSH_LOWER,FALSE, "Object type : %s|" "Number : %d", (m->type == VERTEX ? "VERTEX" : "THING "), m->i); else GuiDrawInfoBox("MULTI MODE",GUI_FLUSH_LEFT,GUI_FLUSH_LOWER,FALSE, "Object type : |" "Number : -"); } void DrawObjectHeader_MULTI(void) { TRACE; } void MoveObject_MULTI(void) { GFXEvent ev; int omx,omy; int dmx,dmy; int done; Iterator i; Iterator i2; MultiObj *m; 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); m=GETMULTI(*f); p.x=m->x; p.y=m->y; ListAppend(orig,&p); i=IteratorNext(i); } while(!done) { GuiDrawInfoBox("Move Multiple Objects", 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)); m=GETMULTI(*f); m->x=p.x; m->y=p.y; i=IteratorNext(i); i2=IteratorNext(i2); } ApplySelectionCoords(); 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); m=GETMULTI(*f); m->x+=dmx; m->y+=dmy; i=IteratorNext(i); } ApplySelectionCoords(); omx=SnapX(XToMap(ms.x)); omy=SnapY(YToMap(ms.y)); FullRedraw(); } } ListClear(orig); if ((clear_on_move)&&(!cancel)) ClearSelection(); FullRedraw(); } void RotateObject_MULTI(double angle) { int cx,cy; int x,y; int *f; Iterator i; MultiObj *m; TRACE; SelectionCentre(&cx,&cy); i=ListIterator(selected); while(i) { f=IteratorData(i); m=GETMULTI(*f); x=m->x; y=m->y; Rotate(cx,cy,&x,&y,angle); m->x=x; m->y=y; i=IteratorNext(i); } ApplySelectionCoords(); } void ScaleObject_MULTI(double scale) { int cx,cy; int x,y; int *f; Iterator i; MultiObj *m; TRACE; SelectionCentre(&cx,&cy); i=ListIterator(selected); while(i) { f=IteratorData(i); m=GETMULTI(*f); x=m->x; y=m->y; Scale(cx,cy,&x,&y,scale); m->x=x; m->y=y; i=IteratorNext(i); } ApplySelectionCoords(); } void SetTagObject_MULTI(int tag) { TRACE; } void LocateObject_MULTI(void *obj) { MultiObj *m; TRACE; m=obj; ox=m->x-scale*SCRW/2; oy=m->y+scale*SCRH/2; } void ObjectInsert_MULTI(void) { TRACE; } void ObjectDelete_MULTI(void) { TRACE; } void ObjectMenu_MULTI(void) { static double last_rot=0.0; static double last_scale=0.0; int cancel; TRACE; cancel=FALSE; switch(GUI_menu("Mutlimode",ms.x,ms.y,multi_popup,GUI_CANCEL)) { case TM_MOVE: MoveObject_MULTI(); break; case TM_ROTATE: rotate_dialog[D_ROTATE].data.d=last_rot; if (GUI_dialog("Rotate",D_ROTATE_NO,rotate_dialog)) { last_rot=rotate_dialog[D_ROTATE].data.d; RotateObject_MULTI(-last_rot); FullRedraw(); } else cancel=TRUE; break; case TM_SCALE: scale_dialog[D_SCALE].data.d=last_scale; if (GUI_dialog("Scale",D_SCALE_NO,scale_dialog)) { ScaleObject_MULTI(last_scale=scale_dialog[D_SCALE].data.d); FullRedraw(); } else cancel=TRUE; break; default: cancel=TRUE; break; } if ((!cancel)&&(clear_on_menu)) { ClearSelection(); FullRedraw(); } } void ObjectKey_MULTI(GFXKey k) { TRACE; } int ObjectHasTag_MULTI(void *obj, int tag) { TRACE; return(FALSE); } void SetSelect_MULTI(int i, int mode) { Object *o; MultiObj *m; Map om; TRACE; o=MapElem(multimap,i); if ((m=o->data)) { o->select=mode; if (m->type==VERTEX) om=vertex; else om=thing; o=MapElem(om,m->i); o->select=mode; } } ObjDesc *ObjectOverlaid_MULTI(int x, int y, int *no) { int n; MultiObj *m; EditThing *t; EditVert *v; ObjDesc *od; int f; TRACE; od=NULL; n=0; for(f=0;fv.x,v->v.y); break; case THING: sprintf(od[n-1].detail,"Thing %-5d - %s",f, TrimStr(ThingName(t->t.type),29)); break; } } } *no=n; return(od); } /* END OF FILE */