source: abuse/tags/pd/abuse/src/dev.c @ 49

Last change on this file since 49 was 49, checked in by Sam Hocevar, 11 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 94.3 KB
Line 
1#include "dev.hpp"
2#include "input.hpp"
3#include "objects.hpp"
4#include "id.hpp"
5#include "lisp.hpp"
6#include "light.hpp"
7#include "devsel.hpp"
8#include "dprint.hpp"
9#include "property.hpp"
10#include "pmenu.hpp"
11#include "filesel.hpp"
12#include "tools.hpp"
13#include "game.hpp"
14#include "pcxread.hpp"
15#include "lisp_gc.hpp"
16#include "demo.hpp"
17#include "profile.hpp"
18#include "sbar.hpp"
19#include "compiled.hpp"
20#include "chat.hpp"
21#include <ctype.h>
22
23#define make_above_tile(x) ((x)|0x4000)
24extern int registered;
25char backw_on=0,forew_on=0,show_menu_on=0,ledit_on=0,pmenu_on=0,omenu_on=0,commandw_on=0,tbw_on=0,
26     searchw_on=0,small_render_on=0,interpolate_draw=0,disable_autolight=0,fps_on=0,profile_on=0,
27     show_names=0,fg_reversed=0,
28     raise_all;
29
30char *symbol_str(char *name)
31{
32  void *sym=make_find_symbol(name);
33  if (symbol_value(sym) && item_type(symbol_value(sym))==L_STRING)
34    return lstring_value(symbol_value(sym));
35
36
37  // maybe english.lsp was not loaded yet, let's try to do that
38  int sp=current_space;
39  current_space=PERM_SPACE;
40
41 
42  char prog[50];
43  char *cs=prog;
44  strcpy(prog,"(setq section 'game_section)\n");
45  eval(compile(cs));
46  strcpy(prog,"(load \"lisp/english.lsp\")\n");
47  cs=prog;
48  if (!eval(compile(cs)))
49  {
50    printf("unable to open file '%s'\n",lsf);
51    exit(0);
52  }
53  current_space=sp;
54
55
56  // check again to see if the symbol is there
57  sym=make_find_symbol(name);
58  if (symbol_value(sym) && item_type(symbol_value(sym))==L_STRING)
59    return lstring_value(symbol_value(sym));
60
61
62  // check to see if there is a missing symbol definition
63  sym=make_find_symbol("missing_sym");
64  if (symbol_value(sym) && item_type(symbol_value(sym))==L_STRING)
65    return lstring_value(symbol_value(sym));
66
67  // last resort, return english string
68  return "Missing language symbol!";
69}
70
71
72static game_object *copy_object=NULL;
73
74pmenu *dev_menu=NULL;
75jwindow *mess_win=NULL,*warn_win=NULL;
76
77game_object *edit_object;
78dev_controll *dev_cont=NULL;
79image *small_render=NULL;
80
81int scale_mult,scale_div,dlastx,dlasty;
82int last_created_type=-1;
83char level_file[100]="levels/level00.spe";
84
85
86class cached_image : public visual_object
87{
88  int id;
89  public :
90  cached_image(int Id) { id=Id; }
91  virtual void draw(image *screen, int x, int y,
92                    window_manager *wm, filter *f)
93  {
94    if (f)
95      f->put_image(screen,cash.img(id),x,y,1);
96    else
97      cash.img(id)->put_image(screen,x,y);
98  }
99  virtual int width(window_manager *wm) { return cash.img(id)->width(); }
100  virtual int height(window_manager *wm) { return cash.img(id)->height(); }
101} ;
102
103
104#define DEV_MODES 3
105cached_image *dev_mode_pict[DEV_MODES];
106
107int dev_del,dev_move, dev_char_left,dev_char_right,dev_back,dev_front,dev_ok,dev_copy,dev_brain,
108    dev_lights,dev_objects,dev_ai,dev_mode_icon[DEV_MODES],
109    dev_forward,dev_backward;
110
111char *dev_mode_icon_names[DEV_MODES]={"pixel_mode","pick_mode", /* "fill_mode",
112                                      "line_mode","rect_mode","bar_mode", */ "area_select"};
113
114int dev_mode_ids[DEV_MODES]={ID_DMODE_DRAW,ID_DMODE_PICK, ID_DMODE_AREA};
115
116int edit_mode=ID_DMODE_DRAW;
117
118
119dev_term *dev_console=NULL;
120int ldef_width=0,ldef_height=0,ldef_r1=1,ldef_r2=100;
121
122void make_screen_size(int w, int h);
123
124class amb_cont : public scroller
125{
126  public :
127  amb_cont(int X, int Y, ifield *Next) : scroller(X,Y,ID_NULL,100,eh->font()->height()+2,0,64,Next)
128  { if (player_list) sx=player_list->ambient; }
129  virtual void scroll_event(int newx, image *screen, window_manager *wm)
130  {
131    screen->bar(x,y,x+l-1,y+h-1,wm->dark_color());
132    char st[100];
133    sprintf(st,"%d",newx);
134    wm->font()->put_string(screen,x+30,y+1,st,eh->bright_color());
135    if (player_list)
136      player_list->ambient=newx;
137    the_game->need_refresh();
138  }
139} ;
140
141
142int confirm_quit()
143{
144  image *ok_image=cash.img(cash.reg("art/frame.spe","dev_ok",SPEC_IMAGE,1))->copy(),
145        *cancel_image=cash.img(cash.reg("art/frame.spe","cancel",SPEC_IMAGE,1))->copy();
146
147
148  jwindow *quitw=eh->new_window(xres/2+40,yres/2,80,-1,
149                          new button(WINDOW_FRAME_LEFT+10,WINDOW_FRAME_TOP+20,ID_QUIT_OK,ok_image,
150                          new button(WINDOW_FRAME_LEFT+38,WINDOW_FRAME_TOP+20,ID_CANCEL,cancel_image,
151                          new info_field(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP,ID_NULL,symbol_str("sure?"),NULL))),
152                                    symbol_str("quit_title"));
153  eh->grab_focus(quitw);
154  int fin=0,quit=0;
155  do
156  {
157    eh->flush_screen();
158
159    event ev;
160    eh->get_event(ev);
161    if (ev.type==EV_MESSAGE && ev.message.id==ID_QUIT_OK)
162      fin=quit=1;
163    else if (ev.type==EV_MESSAGE && ev.message.id==ID_CANCEL)
164      fin=1;
165    else if (ev.type==EV_KEY && toupper(ev.key)==toupper(*symbol_str("YES")))
166      fin=quit=1;
167    else if (ev.type==EV_KEY && toupper(ev.key)==toupper(*symbol_str("NO")))
168      fin=1;
169    if ((ev.type==EV_KEY && ev.key==JK_ESC) || ev.type==EV_CLOSE_WINDOW) fin=1;
170 
171  } while (!fin);
172  delete ok_image;
173  delete cancel_image;
174
175  the_game->reset_keymap();
176
177  eh->close_window(quitw);
178  eh->flush_screen();
179  return quit;
180}
181
182void show_object_number (game_object *who)
183{
184  int total=0,number=0;
185  game_object *c; 
186  for (c=current_level->first_object();c;c=c->next)
187  {
188    if (c->otype==who->otype)
189      total++;
190    if (c==who) number=total;
191  }
192  char msg[100];
193  sprintf(msg,"%s : %d of %d",object_names[who->otype],number,total);
194}
195
196void dev_controll::search_backward()
197{ ;
198}
199
200
201void single_render()
202{
203  // enlarge clip area
204  the_game->first_view->cx2=the_game->first_view->cx1+
205                            (the_game->first_view->cx2-the_game->first_view->cx1+1)*2;
206  the_game->first_view->cy2=the_game->first_view->cy1+
207                            (the_game->first_view->cy2-the_game->first_view->cy1+1)*2;             
208  delete small_render;
209  small_render=NULL;
210  small_render_on=0;
211}
212
213void double_render()
214{
215  small_render_on=1;
216  // reduce clip area
217  the_game->first_view->cx2=the_game->first_view->cx1+
218                            (the_game->first_view->cx2-the_game->first_view->cx1+1)/2;
219  the_game->first_view->cy2=the_game->first_view->cy1+
220                            (the_game->first_view->cy2-the_game->first_view->cy1+1)/2;
221
222  small_render=new image((the_game->first_view->cx2-the_game->first_view->cx1+1),
223                         (the_game->first_view->cy2-the_game->first_view->cy1+1),NULL,2);
224}
225
226
227void dev_controll::search_forward()
228{
229  if (search_window) // if no window then we can't get the object name
230  {
231    char *name=search_window->read(ID_SEARCH_TEXT);
232    int type=-1;    // see if this type exsists
233    int i;
234    for (i=0;i<total_objects;i++)
235      if (!strcmp(object_names[i],name))
236        type=i;
237    if (type==-1)
238    {
239      char msg[60];
240      sprintf(msg,"Object type '%s' does not exsists!\n",name);
241      the_game->show_help(msg);
242      the_game->need_refresh();
243    } else
244    {
245      game_object *first,*find=NULL;     
246      if (!search_object || search_object->otype!=type)
247        first=current_level->first_object();
248      else
249        first=search_object->next;
250      for (;!find && first;first=first->next)
251        if (first->otype==type)
252          find=first;
253      int loop=0;
254      if (!find)
255      {
256        for (first=current_level->first_object();first && !find;first=first->next)
257        {
258          if (first->otype==type)
259            find=first;
260        }
261        loop=1;
262      }
263      if (find)
264      {
265        search_object=find;
266        show_object_number(search_object);
267      }
268      else
269      {
270        the_game->show_help("No object matching name exsist in level\n");
271       
272      }
273    }
274  }
275}
276
277
278long dev_controll::snap_x(long x)
279{
280  if (eh->key_pressed(JK_CTRL_L) || eh->key_pressed(JK_CTRL_R))
281    return x-(x%the_game->ftile_width());
282  else if (eh->key_pressed(JK_ALT_L) || eh->key_pressed(JK_ALT_R))
283    return x-(x%the_game->ftile_width())+the_game->ftile_width()/2;
284  else return x; 
285}
286
287long dev_controll::snap_y(long y)
288{
289  if (eh->key_pressed(JK_CTRL_L) || eh->key_pressed(JK_CTRL_R))
290    return y-(y%the_game->ftile_height())-1;
291  else if (eh->key_pressed(JK_ALT_L) || eh->key_pressed(JK_ALT_R))
292    return y-(y%the_game->ftile_height())+the_game->ftile_height()/2-1;
293  else return y;
294}
295
296void dev_controll::make_ambient()
297{
298  if (!ambw)
299  ambw=eh->new_window(prop->getd("ambient x",-1),
300                      prop->getd("ambient y",-1),-1,-1,
301                      new amb_cont(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP,NULL),"ambient");
302}
303
304void dev_term::execute(char *st)
305{
306  if (!strcmp(st,"?"))
307  {
308    put_string("unchop x y, size x y,\n"
309               "load, esave, name\n");
310  } else
311  {
312    event ev;
313    dv->do_command(st,ev);
314  }
315}
316
317void load_dev_icons()
318{
319  char *artf="art/dev.spe";
320  dev_del=cash.reg(artf,"dev_del",SPEC_IMAGE,0);
321  dev_move=cash.reg(artf,"dev_move",SPEC_IMAGE,0);
322  dev_char_left=cash.reg(artf,"dev_char_left",SPEC_IMAGE,0);
323  dev_char_right=cash.reg(artf,"dev_char_right",SPEC_IMAGE,0);
324  dev_back=cash.reg(artf,"dev_back",SPEC_IMAGE,0);
325  dev_front=cash.reg(artf,"dev_front",SPEC_IMAGE,0);
326  dev_ok=cash.reg(artf,"dev_ok",SPEC_IMAGE,0);
327  dev_copy=cash.reg(artf,"dev_copy",SPEC_IMAGE,0);
328  dev_brain=cash.reg(artf,"brain",SPEC_IMAGE,0);
329  dev_lights=cash.reg(artf,"lights",SPEC_IMAGE,0);
330  dev_objects=cash.reg(artf,"objects",SPEC_IMAGE,0);
331  dev_ai=cash.reg(artf,"ai",SPEC_IMAGE,0);
332  dev_forward=cash.reg(artf,"forward",SPEC_IMAGE,0);
333  dev_backward=cash.reg(artf,"backward",SPEC_IMAGE,0);
334
335  for (int i=0;i<DEV_MODES;i++)
336    dev_mode_icon[i]=cash.reg(artf,dev_mode_icon_names[i],SPEC_IMAGE,0);
337 
338}
339
340void scale_put(image *im, image *screen, int x, int y, short new_width, short new_height)
341{
342  unsigned char *sl1,*sl2;
343  long xstep=(im->width()<<16)/new_width,
344       ystep=(im->height()<<16)/new_height,iy,ix,sx,ix_start,iy_start;
345  screen->add_dirty(x,y,x+new_width-1,y+new_height-1);
346
347
348  short cx1,cy1,cx2,cy2;
349  screen->get_clip(cx1,cy1,cx2,cy2);
350  if (cx1>cx2 || cy1>cy2 || x>cx2 || y>cy2 || x+new_width<=cx1 || y+new_height<=cy1) return ;
351  if (x<cx1)
352  {
353    ix_start=(cx1-x)*xstep;
354    new_width-=(cx1-x);
355    x=cx1;
356  } else ix_start=0;
357  if (x+new_width>=cx2)
358    new_width-=x+new_width-1-cx2;
359  if (y<cy1)
360  {
361    iy_start=(cy1-y)*ystep;
362    new_height-=(cy1-y);
363    y=cy1;
364  } else iy_start=0;
365  if (y+new_height>cy2)
366    new_height-=y+new_height-cy2;
367 
368
369  for (iy=iy_start;new_height>0;new_height--,y++,iy+=ystep)
370  {
371    sl1=im->scan_line(iy>>16);
372    sl2=screen->scan_line(y)+x;
373    for (ix=ix_start,sx=0;sx<new_width;sx++,ix+=xstep,sl2++)
374      *sl2=sl1[ix>>16];   
375  }
376}
377
378
379void scale_put_trans(image *im, image *screen, int x, int y, short new_width, short new_height)
380{
381  unsigned char *sl1,*sl2;
382  long xstep=(im->width()<<16)/new_width,
383       ystep=(im->height()<<16)/new_height,iy,ix,sx,ix_start,iy_start;
384  screen->add_dirty(x,y,x+new_width-1,y+new_height-1);
385
386
387  short cx1,cy1,cx2,cy2;
388  screen->get_clip(cx1,cy1,cx2,cy2);
389  if (cx1>cx2 || cy1>cy2 || x>cx2 || y>cy2 || x+new_width<=cx1 || y+new_height<=cy1) return ;
390  if (x<cx1)
391  {
392    ix_start=(cx1-x)*xstep;
393    new_width-=(cx1-x);
394    x=cx1;
395  } else ix_start=0;
396  if (x+new_width>=cx2)
397    new_width-=x+new_width-1-cx2;
398  if (y<cy1)
399  {
400    iy_start=(cy1-y)*ystep;
401    new_height-=(cy1-y);
402    y=cy1;
403  } else iy_start=0;
404  if (y+new_height>cy2)
405    new_height-=y+new_height-cy2;
406 
407  uchar d;
408  for (iy=iy_start;new_height>0;new_height--,y++,iy+=ystep)
409  {
410    sl1=im->scan_line(iy>>16);
411    sl2=screen->scan_line(y)+x;
412    for (ix=ix_start,sx=0;sx<new_width;sx++,ix+=xstep,sl2++)
413    {
414      d=sl1[ix>>16];
415      if (d)
416        *sl2=d;
417    }
418  }
419}
420
421int dev_controll::need_plus_minus()
422{
423  if (state==DEV_MOVE_LIGHT) return 1; else return 0;
424}
425
426int dev_controll::need_arrows()
427{
428  if (state==DEV_MOVE_LIGHT) return 1; else return 0;
429}
430
431int dev_controll::repeat_key_mode()
432{
433  if (state==DEV_MOVE_LIGHT) return 1; else return 0;
434}
435
436int last_link_x=0,last_link_y=0;
437
438void dev_controll::dev_draw(view *v)
439{
440  long x1,y1,x2,y2;
441  if (dev&EDIT_MODE)
442  {
443    long vx=v->xoff(),vy=v->yoff();
444 
445    if (dev&DRAW_LINKS)
446    {
447      for (light_source *f=first_light_source;f;f=f->next)
448      {
449        if (f->x-vx>=0 && f->x-vx<=(v->cx2-v->cx1+1) && f->y-vy>=0 && f->y-vy<=(v->cy2-v->cy1+1))
450        {
451          image *im=cash.img(light_buttons[f->type]);
452          im->put_image(screen,f->x-vx+v->cx1-im->width()/2,f->y-vy+v->cy1-im->height()/2,1);
453          screen->rectangle(f->x1-vx+v->cx1,f->y1-vy+v->cy1,f->x2-vx+v->cx1,f->y2-vy+v->cy1,
454                            eh->medium_color());
455        }
456      }
457    }
458
459    if (link_object)
460    {
461      long rx1,ry1;
462      the_game->game_to_mouse(link_object->x,link_object->y,v,rx1,ry1);     
463      screen->line(rx1,ry1,dlastx,dlasty,yellow);           
464    }
465
466    if (selected_light)
467    {
468      image *i=cash.img(light_buttons[0]);
469      int l=i->width()/2,h=i->height()/2;
470      long rx1,ry1;
471      the_game->game_to_mouse(selected_light->x,selected_light->y,v,rx1,ry1);     
472      screen->rectangle(rx1-l,ry1-h,rx1+l,ry1+h,eh->bright_color());
473    }
474
475    game_object *o;
476    if (show_names)
477      for (o=current_level->first_object();o;o=o->next)
478      {
479        the_game->game_to_mouse(o->x,o->y,current_view,x1,y1);
480        char *nm=object_names[o->otype];
481        console_font->put_string(screen,x1-strlen(nm)*console_font->width()/2,y1+2,nm);
482      }
483   
484    if (dev&DRAW_LINKS)
485    {
486      // draw connections between objects
487      for (o=current_level->first_object();o;o=o->next)
488      {
489        the_game->game_to_mouse(o->x,o->y,current_view,x1,y1);
490
491        int i=0;
492        for (;i<o->total_objects();i++)
493        {
494          game_object *other=o->get_object(i);
495          the_game->game_to_mouse(other->x,other->y,current_view,x2,y2);       
496          screen->line(x1,y1,x2,y2,eh->bright_color());
497        }
498
499        for (i=0;i<o->total_lights();i++)
500        {
501          light_source *l=o->get_light(i);
502          the_game->game_to_mouse(l->x,l->y,current_view,x2,y2);
503          screen->line(x1,y1,x2,y2,light_connection_color);
504        }
505
506      }
507    }
508
509    if (selected_object)
510    {   
511      selected_object->picture_space(x1,y1,x2,y2);   
512      long rx1,ry1,rx2,ry2;
513      the_game->game_to_mouse(x1,y1,v,rx1,ry1);
514      the_game->game_to_mouse(x2,y2,v,rx2,ry2);
515      screen->rectangle(rx1,ry1,rx2,ry2,eh->bright_color());
516
517      the_game->game_to_mouse(selected_object->x,selected_object->y,current_view,x1,y1);
518      for (int i=0;i<selected_object->total_objects();i++)
519      {
520        game_object *other=selected_object->get_object(i);
521        the_game->game_to_mouse(other->x,other->y,current_view,x2,y2);
522        screen->line(x1,y1,x2,y2,light_connection_color);
523      }
524    } 
525
526
527  }
528
529  update_memprof();
530}
531
532light_source *find_light(long x, long y)
533{
534  image *i=cash.img(light_buttons[0]);
535  int l=i->width()/2,h=i->height()/2;
536  for (light_source *f=first_light_source;f;f=f->next)
537  {
538    if (x>=f->x-l && x<=f->x+l && y>=f->y-h && y<=f->y+h)
539      return f;
540  }
541  return NULL;
542}
543
544
545extern void small_static_allocation_summary(int &total, int *&static_list, int *&cache_list);
546
547void dev_controll::update_memprof()
548{
549  if (memprof)
550  {
551    int i,largest=0;
552    int total,*st,*ch;
553    small_static_allocation_summary(total,st,ch);
554
555    int x=WINDOW_FRAME_LEFT;
556    int y=WINDOW_FRAME_TOP;
557    memprof->clear();
558
559    for (i=0;i<total;i++)
560    {
561      int h=st[i]*100/3000;  x++;
562      memprof->screen->bar(x,y,x,y+h,eh->bright_color());
563      h=ch[i]*100/3000;
564      memprof->screen->bar(x,y,x,y+h,eh->medium_color());
565      x++;
566    }
567    jfree(st);
568    jfree(ch);
569    char buf[100];
570    sprintf(buf,"%8d %8d",j_allocated(),j_available());
571    eh->font()->put_string(memprof->screen,memprof->x1(),memprof->y2()-eh->font()->height(),buf);
572
573  }
574 
575}
576
577void dev_controll::toggle_memprof()
578{
579  if (memprof)
580  {
581    prop->setd("memprof x",memprof->x);
582    prop->setd("memprof y",memprof->y);
583    eh->close_window(memprof);
584    memprof=NULL;
585  } else
586  {
587    int total,*st,*ch;
588    small_static_allocation_summary(total,st,ch);
589    jfree(st);
590    jfree(ch);
591    memprof=eh->new_window(0,0,total*2+20,100,NULL);
592    update_memprof();   
593  }
594}
595
596void dev_controll::toggle_toolbar()
597{
598  if (tbw)
599  {
600    tbw_on=0;
601    prop->setd("toolbar x",tbw->x);
602    prop->setd("toolbar y",tbw->y);
603    eh->close_window(tbw);
604    tbw=NULL;
605  } else
606  {
607    tbw_on=1;
608    int setx=0;
609    for (int i=0;i<DEV_MODES;i++)
610    {
611      if (edit_mode==dev_mode_ids[i])
612        setx=i;
613      dev_mode_pict[i]=new cached_image(dev_mode_icon[i]);
614    }
615
616    tool_picker *tp=new tool_picker(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP,
617                                             ID_NULL,
618                                             5,(visual_object **)dev_mode_pict,dev_mode_ids,DEV_MODES,
619                                                pal,pal,eh,NULL);
620    int sx=WINDOW_FRAME_LEFT,sy=WINDOW_FRAME_TOP;
621    tbw=eh->new_window(prop->getd("toolbar x",-1),
622                       prop->getd("toolbar y",-1),-1,-1,tp);
623    tp->set_x(setx,tbw->screen,eh);
624  }
625}
626
627void dev_controll::toggle_show_menu()
628{
629  if (show_menu)
630  {
631    show_menu_on=0;
632    prop->setd("layer x",show_menu->x);
633    prop->setd("layer y",show_menu->y);
634    eh->close_window(show_menu);
635    show_menu=NULL;
636  } else
637  {
638    show_menu_on=1;
639    int sx=WINDOW_FRAME_LEFT,sy=WINDOW_FRAME_TOP;
640
641    button *lnb=new button(sx,sy+100,SHOW_LINKS,            symbol_str("l_links"),NULL);           if (dev&DRAW_LINKS)          lnb->push();
642    button *lb=new button(sx,sy+80,  SHOW_LIGHT,            symbol_str("l_light"),lnb);          if (dev&DRAW_LIGHTS)         lb->push();
643    button *cb=new button(sx,sy+60,  SHOW_CHARACTERS,       symbol_str("l_char"),lb);       if (dev&DRAW_PEOPLE_LAYER)   cb->push();
644    button *bb=new button(sx,sy+40,  SHOW_BACKGROUND,       symbol_str("l_back"),cb);       if (dev&DRAW_BG_LAYER)       bb->push();
645    button *bdb=new button(sx,sy+20, SHOW_FOREGROUND_BOUND, symbol_str("l_bound"),bb); if (dev&DRAW_FG_BOUND_LAYER) bdb->push();
646    button *fb=new button(sx,sy+ 0,  SHOW_FOREGROUND,       symbol_str("l_fore"),bdb);      if (dev&DRAW_FG_LAYER)       fb->push();
647
648    show_menu=eh->new_window(prop->getd("layer x",-1),
649                             prop->getd("layer y",-1),
650                             -1,-1,fb,symbol_str(symbol_str("SHOW?")));
651  }
652}
653
654
655char **listable_objs=NULL;
656int total_listable;
657
658void dev_controll::toggle_omenu()
659{
660  if (omenu)
661  {
662    omenu_on=0;
663    prop->setd("objects x",omenu->x);
664    prop->setd("objects y",omenu->y);
665    eh->close_window(omenu);
666    omenu=NULL;
667    jfree(listable_objs);
668    listable_objs=NULL;
669  }
670  else
671  {
672    omenu_on=1;
673    total_listable=0;
674    int i=0;
675    for (;i<total_objects;i++)
676      if (!figures[i]->get_cflag(CFLAG_UNLISTABLE))
677        total_listable++;
678    listable_objs=(char **)jmalloc(sizeof(char *)*total_listable,"omenu list");
679    int c=0;   
680    for (i=0;i<total_objects;i++)
681      if (!figures[i]->get_cflag(CFLAG_UNLISTABLE))
682      {
683        listable_objs[c]=object_names[i];
684        c++;
685      }
686             
687    omenu=eh->new_window(prop->getd("objects x",0),
688                         prop->getd("objects y",0),-1,-1,
689                         new pick_list(WINDOW_FRAME_LEFT,
690                                       WINDOW_FRAME_TOP,DEV_CREATE,yres/eh->font()->height()/2,
691                                       listable_objs,total_listable,0,NULL,cash.img(window_texture)));
692  } 
693}
694
695int get_omenu_item(int x)
696{
697  for (int i=0;i<total_objects;i++)
698    if (listable_objs[x]==object_names[i])
699      return i;
700  return 0;
701}
702
703void dev_controll::toggle_pmenu()
704{
705  if (pmenu)
706  {
707    pmenu_on=0;
708    prop->setd("pal x",pmenu->x);
709    prop->setd("pal y",pmenu->y);
710    eh->close_window(pmenu);
711    pmenu=NULL;
712    jfree(pwin_list);
713  }
714  else if (total_pals)
715  {
716    pmenu_on=1;
717    pwin_list=(char **)jmalloc(total_pals*sizeof(char *),"pal pick list");
718    int i;
719    for (i=0;i<total_pals;i++)
720      pwin_list[i]=pal_wins[i]->name;
721
722    pmenu=eh->new_window(prop->getd("pal x",0),
723                         prop->getd("pal y",-1),
724                         -1,-1,
725                         new pick_list(WINDOW_FRAME_LEFT,
726                                       WINDOW_FRAME_TOP,DEV_PALETTE,yres/eh->font()->height()/2,
727                                       pwin_list,total_pals,0,NULL,cash.img(window_texture)));
728  } else the_game->show_help(symbol_str("no_pals"));
729}
730
731
732void dev_controll::toggle_fgw()
733{
734  if (!forew)
735  {
736    forew_on=0;
737    int maxh=(yres-25)/(the_game->ftile_height()/fg_scale);
738    int tw=the_game->ftile_width()*fg_w/fg_scale,
739        th=the_game->ftile_height()/fg_scale;
740
741    tile_picker *f_tp=new tile_picker(WINDOW_FRAME_LEFT+1,WINDOW_FRAME_TOP+1,
742                                         DEV_FG_PICKER,SPEC_FORETILE,eh,fg_scale,maxh,fg_w,NULL);
743    f_tp->reverse();
744
745    forew=eh->new_window(prop->getd("fore x",-30),
746                         prop->getd("fore y",0),
747                         -1,-1,
748                         f_tp,symbol_str("l_fg"));
749  } else
750  {
751    forew_on=1;
752    prop->setd("fore x",forew->x);
753    prop->setd("fore y",forew->y);
754    eh->close_window(forew);
755    forew=NULL;
756  }
757}
758
759void dev_controll::toggle_music_window()
760{
761/*  if (!music_window)
762  {
763    music_window=eh->new_window(-1,30,0,0,
764                         new pick_list(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP,
765                                       DEV_MUSIC_PICKLIST,10,song_list,total_songs,0,NULL));
766    eh->fnt->put_string(music_window->screen,WINDOW_FRAME_LEFT,1,"songs");
767  } else
768  {
769    eh->close_window(music_window);
770    music_window=NULL;
771  }*/
772}
773
774void dev_controll::toggle_bgw()
775{
776  if (!backw)
777  {
778    backw_on=0;
779    int maxh=(yres-25)/(the_game->btile_height()/bg_scale);
780    int tw=the_game->btile_width()*bg_w/bg_scale,
781        th=the_game->btile_height()/bg_scale;
782
783    backw=eh->new_window(prop->getd("back x",-30),
784                         prop->getd("back y",0),
785                         -1,-1,
786                         new tile_picker(WINDOW_FRAME_LEFT+1,WINDOW_FRAME_TOP+1,
787                                         DEV_BG_PICKER,SPEC_BACKTILE,eh,bg_scale,maxh,bg_w,NULL),symbol_str("l_bg"));
788  } else
789  {
790    backw_on=1;
791    prop->setd("back x",backw->x);
792    prop->setd("back y",backw->y);
793    eh->close_window(backw);
794    backw=NULL;
795  }
796}
797
798void dev_controll::toggle_search_window()
799{
800  if (!search_window)
801  {
802    int wl=WINDOW_FRAME_LEFT+1,
803        wh=WINDOW_FRAME_TOP+1;
804    int bh=cash.img(dev_forward)->height(),
805        bw=cash.img(dev_forward)->width();
806    search_window=eh->new_window(prop->getd("searchw x",-30),
807                                 prop->getd("searchw y",0),
808                                 -1,-1,
809                                 new text_field(wl,wh,ID_SEARCH_TEXT,"object name>",
810                                                "***************************",
811                                                prop->get("search name",""),
812                                  new button(wl+bw*1,wh+eh->font()->height()+5,ID_SEARCH_BACKWARD,
813                                            cash.img(dev_backward),
814                                  new button(wl+bw*3,wh+eh->font()->height()+5,ID_SEARCH_FOREWARD,
815                                            cash.img(dev_forward),NULL))),"SEARCH");
816    searchw_on=0;
817  } else
818  {
819    searchw_on=1;
820    prop->setd("searchw x",search_window->x);
821    prop->setd("searchw y",search_window->y);
822    prop->set("search name",search_window->read(ID_SEARCH_TEXT));
823    eh->close_window(search_window);
824    search_window=NULL;
825    search_object=NULL;
826  }
827}
828
829int open_owin=0,open_fwin=0,open_bwin=0,start_edit=0,start_nodelay=0,start_doubled=0,start_mem=0;
830
831
832int get_option(char *name);
833
834
835void dev_init(int argc, char **argv)
836{
837  scale_mult=1;
838  scale_div=1;
839  dev=0;
840  int i;
841  prop=new property_manager;
842  prop->load("defaults.prp");
843
844  for (i=1;i<argc;i++)
845  {   
846    if (!strcmp(argv[i],"-edit"))
847    {
848      if (!registered)
849        printf("%s\n",symbol_str("no_edit"));
850      else
851      {
852                                dev|=EDIT_MODE;   
853                                start_edit=1;
854                                start_running=1;
855                                disable_autolight=1;
856                                if (get_option("-2"))
857                                {
858                                  printf("%s\n",symbol_str("no2"));
859                                  exit(0);
860                                }
861      }
862    }
863    else if (!strcmp(argv[i],"-fwin"))
864      open_fwin=1;   
865    else if (!strcmp(argv[i],"-show_mem"))
866      start_mem=1;   
867    else if (!strcmp(argv[i],"-bwin"))
868      open_bwin=1;         
869    else if (!strcmp(argv[i],"-owin"))
870      open_owin=1;       
871    else if (!strcmp(argv[i],"-nodelay"))
872      start_nodelay=1;       
873    else if (!strcmp(argv[i],"-scale"))
874    {
875      i++;     
876      scale_mult=atoi(argv[i++]);
877      scale_div=atoi(argv[i]);
878    } else if (!strcmp(argv[i],"-f"))
879    {
880      i++;
881      strcpy(level_file,argv[i]);
882    } else if (!strcmp(argv[i],"-2"))
883      start_doubled=1;
884    else if (!strcmp(argv[i],"-demo"))
885      demo_start=1;
886
887  } 
888
889  if (get_option("-no_autolight"))
890    disable_autolight=0;
891
892  if ((get_option("-size") || get_option("-vmode")) && !start_edit)
893  {
894    printf("%s\n",symbol_str("no_hirez"));
895    exit(0);
896  }
897
898  fg_reversed=prop->getd("fg_reversed",0);
899  mouse_scrolling=prop->getd("mouse_scrolling",0);
900  palettes_locked=prop->getd("palettes_locked",0);
901  view_shift_disabled=prop->getd("view_shift_disabled",0);
902  fps_on=prop->getd("fps_on",0);
903  show_names=prop->getd("show_names",0);
904  raise_all=prop->getd("raise_all",0);
905}
906
907static pmenu *make_menu(int x, int y);
908
909
910dev_controll::dev_controll()
911{
912  area_win=NULL;
913  current_area=NULL;
914  fg_w=bg_w=1;
915  commandw=NULL;
916  bg_scale=fg_scale=1;
917  pal_wins=NULL;
918  total_pals=0;
919  state=DEV_SELECT;
920  aiw=NULL;
921  edit_light=NULL;
922  selected_light=NULL;
923
924  tbw=NULL;
925  modew=NULL;
926  link_object=NULL;
927  selected_object=NULL;
928  edit_object=NULL;
929  ai_object=NULL;
930  memprof=NULL;
931  oedit=NULL; 
932  forew=NULL;
933  backw=NULL; 
934  omenu=NULL; 
935  ledit=NULL;
936  pmenu=NULL;
937  lightw=NULL;
938  search_window=NULL;
939  show_menu=NULL;
940  music_window=NULL;
941  ambw=NULL;
942  load_dev_icons();
943
944  if (open_owin) toggle_omenu();
945  if (open_fwin) toggle_fgw();
946  if (open_bwin) toggle_bgw();
947  if (start_nodelay) the_game->toggle_delay();
948  yellow=pal->find_closest(255,255,0);
949  if (start_edit)
950  {
951    the_game->load_level(level_file);
952    the_game->draw();
953  }
954 
955  dev_console=new dev_term(50,18,this);
956  if (start_edit)
957    dev_menu=make_menu(0,yres-eh->font()->height()-5);   
958
959  if (get_option("-nolight"))
960    dev=dev^DRAW_LIGHTS;
961  if (start_mem)
962    toggle_memprof();
963}
964
965
966void dev_controll::set_state(int new_state)
967{
968  if (start_doubled && new_state==RUN_STATE && !small_render)
969    double_render();
970}
971
972void dev_controll::load_stuff()
973
974  if (dev & EDIT_MODE)
975  {
976    char prog[100],*cs;
977    strcpy(prog,"(compile-file \"edit.lsp\")");
978    cs=prog;
979    void *p=compile(cs);
980    l_user_stack.push(p);
981    eval(p);
982    l_user_stack.pop(1);
983    for (int i=0;i<total_pals;i++)
984      pal_wins[i]->close_window();
985  }
986
987}
988
989void dev_controll::do_command(char *command, event &ev)
990{
991  char fword[50],*st;
992  int l,h,x,y,i;
993  if (command[0]=='(')            // is this a lisp command?
994  {
995    eval(compile(command)); 
996    return ;
997  }
998
999  sscanf(command,"%s",fword);
1000  for (st=command;*st && *st!=' ';st++);
1001  if (*st) st++;
1002  if (!strcmp(fword,"active"))
1003  {
1004    if (current_level && current_level->first_active_object())
1005    {
1006      game_object *o=current_level->first_active_object();
1007      while (o)
1008      {
1009        dprintf("%s %d %d %d %d\n",object_names[o->otype],o->x,o->y,
1010                figures[o->otype]->rangex,
1011                figures[o->otype]->rangey
1012                );
1013        o=o->next_active;
1014      }
1015    }
1016  }
1017
1018  if (!strcmp(fword,"clear_weapons"))
1019  {
1020    view *f=NULL;
1021    for (f=player_list;f;f=f->next)
1022    {
1023      int i;
1024      for (i=0;i<total_weapons;i++)
1025        f->weapons[i]=-1;
1026
1027      if (total_weapons)
1028        f->weapons[0]=0;
1029    }
1030  }
1031
1032  if (!strcmp(fword,"reload"))
1033  {
1034    if (current_level && player_list && player_list->focus)
1035    {
1036      edit_object=selected_object=NULL;
1037      long cx=player_list->focus->x,cy=player_list->focus->y;
1038
1039      // save the old weapon array
1040      long *w=(long *)jmalloc(total_weapons*sizeof(long),"tmp weapon array");
1041      memcpy(w,player_list->weapons,total_weapons*sizeof(long));
1042     
1043      char tmp[100];
1044      strcpy(tmp,current_level->name());
1045      the_game->load_level(tmp);
1046      current_level->unactivate_all();
1047
1048      if (screen)  // don't draw if graphics haven't been setup yet.
1049        the_game->draw();
1050      player_list->reset_player();
1051      player_list->focus->x=cx;
1052      player_list->focus->y=cy;
1053
1054      memcpy(player_list->weapons,w,total_weapons*sizeof(long));     
1055      jfree(w);
1056
1057      the_game->need_refresh();
1058    }   
1059  }
1060
1061  if (!strcmp(fword,"unchop"))
1062  {
1063    long rx,ry;
1064    the_game->btile_on(dlastx,dlasty,rx,ry);
1065    if (rx>=0 && ry>=0)
1066    {
1067      if (sscanf(command,"%s%d%d",fword,&l,&h)==3)
1068      {
1069        dprintf("unchopped %dx%d to ",l,h);
1070        l=(l+the_game->btile_width()-1)/the_game->btile_width();
1071        h=(h+the_game->btile_height()-1)/the_game->btile_height();
1072        for (y=0,i=cur_bg;y<h;y++)
1073          for (x=0;x<l;x++)
1074            the_game->put_bg(rx+x,ry+y,i++);
1075        dprintf("%dx%d\n",l,h);
1076      } else dprintf(symbol_str("unchop1"));
1077
1078    }     
1079  }
1080  if (!strcmp(fword,"center"))
1081  {
1082    view *v=the_game->first_view;
1083    for (;v;v=v->next)
1084    {
1085      v->pan_x=0;
1086      v->pan_y=0;
1087    }
1088    the_game->need_refresh();
1089  }
1090
1091  if (!strcmp(fword,"size"))
1092  {
1093    int l,w;   
1094    if (sscanf(command,"%s%d%d",fword,&l,&w)==3)
1095    {
1096      current_level->set_size(l,w);   
1097      dprintf("level is now %dx%d\n",l,w);
1098    } else dprintf(symbol_str("size1"));
1099
1100
1101  }
1102  if (!strcmp(fword,"name"))
1103  {
1104    while (*command && *command!=' ') command++;
1105    if (*command)
1106      current_level->set_name(command+1);   
1107    dprintf(symbol_str("name_now"),current_level->name());
1108  }
1109  if (!strcmp(fword,"set_first_level"))
1110  {
1111    strcpy(level_file,st);
1112    dprintf("first level will be '%s'\n",level_file);     
1113  }
1114
1115  if (!strcmp(fword,"load"))
1116  {
1117    if (!strcmp(st,"STARTING_LEVEL"))
1118      st=level_file;
1119
1120    dprintf("loading '%s'\n",st);
1121    the_game->load_level(st);   
1122    current_level->unactivate_all();
1123
1124    the_game->need_refresh();
1125  }
1126
1127  if (!strcmp(fword,"mem"))
1128  {
1129    if (st[0])   
1130      show_char_mem(st);
1131    else show_mem();
1132  }
1133
1134  if (!strcmp(fword,"esave"))
1135  {
1136    dprintf(symbol_str("esave"));
1137    save();
1138  }
1139
1140  if (!strcmp(fword,"delete"))
1141  {     
1142    if (selected_object)
1143    {
1144      if (!(dev&EDIT_MODE) && current_level->is_attacker(selected_object))
1145        the_game->show_help(symbol_str("nd_player"));
1146      else
1147      {     
1148        if (selected_object->controller())
1149          the_game->show_help(symbol_str("nd_player"));
1150        else
1151        {
1152          current_level->delete_object(selected_object);
1153          if (S_DELETE_SND>0) cash.sfx(S_DELETE_SND)->play(sfx_volume/2);
1154          selected_object=NULL;
1155        }
1156      }
1157    } else if (selected_light)
1158    {
1159      if (!edit_light)
1160      {
1161        if (current_level)
1162        {
1163          current_level->remove_light(selected_light);
1164          if (S_DELETE_SND>0) cash.sfx(S_DELETE_SND)->play(sfx_volume/2);
1165        }
1166        else
1167          delete_light(selected_light);
1168        selected_light=NULL;
1169      }     
1170    } else the_game->show_help(symbol_str("d_nosel"));
1171    the_game->need_refresh();
1172  }
1173
1174  if (!strcmp(fword,"create"))
1175  {
1176    char oname[100];
1177    sscanf(command,"%s%s",fword,oname);       // read the type of object to create
1178    int x,t=-1;
1179    for (x=0;x<total_objects;x++)             // find the object type by name
1180       if (!strcmp(object_names[x],oname))
1181         t=x;
1182
1183    if (t>=0)                                 // did we find it?
1184    {
1185      long rx,ry;
1186      the_game->mouse_to_game(dlastx,dlasty,rx,ry);
1187      edit_object=create(t,rx,ry);
1188      current_level->add_object(edit_object);
1189      the_game->need_refresh();
1190      last_created_type=t;
1191    } else
1192    {
1193      sprintf(fword,"No such object type : %s\n",oname);
1194      the_game->show_help(fword);
1195    }
1196  }
1197
1198  if (!strcmp(fword,"move"))
1199  {
1200    if (selected_object)   
1201      edit_object=selected_object;       
1202
1203    if (edit_object)
1204      state=DEV_MOVE_OBJECT;
1205    else the_game->show_help("No object selected");
1206     
1207  }
1208  if (!strcmp(fword,"move_light"))
1209  {
1210    if (selected_light)   
1211      edit_light=selected_light;         
1212
1213    if (edit_light)
1214      state=DEV_MOVE_LIGHT;
1215    else the_game->show_help("No light selected");
1216     
1217  }
1218
1219 
1220  if (!strcmp(fword,"clear_auto"))
1221  {
1222    long i,j;
1223    for (i=0;i<current_level->foreground_width();i++)
1224      for (j=0;j<current_level->foreground_height();j++)
1225        current_level->clear_fg(i,j);
1226  }
1227
1228  if (!strcmp(fword,"fg_select"))
1229  {
1230    long x,y;
1231    the_game->ftile_on(dlastx,dlasty,x,y);
1232    if (x>=0 && y>=0 && x<current_level->foreground_width() &&
1233        y<current_level->foreground_height())
1234    {
1235      cur_fg=current_level->get_fg(x,y);
1236      if (forew)     
1237        ((tile_picker *)forew->read(DEV_FG_PICKER))->recenter(forew->screen,eh);     
1238      the_game->need_refresh();
1239    }
1240  }
1241
1242  if (!strcmp(fword,"toggle_fg_raise"))
1243  {
1244    long x,y;
1245    the_game->ftile_on(dlastx,dlasty,x,y);
1246    if (x>=0 && y>=0 && x<current_level->foreground_width() &&
1247        y<current_level->foreground_height())   
1248      current_level->fg_set_raised(x,y,!current_level->fg_raised(x,y));   
1249  }
1250 
1251  if (!strcmp(fword,"fg_add"))
1252  {
1253    int x;
1254    if (sscanf(st,"%d",&x))
1255    {
1256      cur_fg++;
1257      if (cur_fg<0) cur_fg=0;
1258      if (cur_fg>=nforetiles) cur_fg=nforetiles-1;
1259
1260      if (forew)     
1261        ((tile_picker *)forew->read(DEV_FG_PICKER))->recenter(forew->screen,eh);     
1262    }   
1263  }
1264
1265  if (!strcmp(fword,"mem_report"))
1266    mem_report("memory.report");
1267
1268  if (!strcmp(fword,"restart"))
1269  {
1270    current_level->restart();
1271  }
1272  if (!strcmp(fword,"quit"))
1273  {
1274    the_game->end_session();
1275  }
1276
1277  if (!strcmp(fword,"to_front"))
1278  {
1279    game_object *which=selected_object;
1280    if (!selected_object) which=edit_object;
1281    if (which)   
1282      current_level->to_front(which);
1283    else the_game->show_help(symbol_str("forward?"));
1284  }
1285
1286  if (!strcmp(fword,"to_back"))
1287  {
1288    game_object *which=selected_object;
1289    if (!selected_object) which=edit_object;
1290    if (which)   
1291      current_level->to_back(which);
1292    else the_game->show_help(symbol_str("back?"));
1293  }
1294
1295  if (!strcmp(fword,"set_aitype"))
1296  {
1297    game_object *which=selected_object;
1298    if (!selected_object) which=edit_object;
1299    if (which)   
1300    {
1301      int x;
1302      if (*st && sscanf(st,"%d",&x)!=EOF)
1303        which->change_aitype(x);
1304      else
1305      {
1306        switch (ev.key)
1307        {
1308          case '0' : which->change_aitype(0); break;
1309          case '1' : which->change_aitype(1); break;
1310          case '2' : which->change_aitype(2); break;
1311          case '3' : which->change_aitype(3); break;
1312          case '4' : which->change_aitype(4); break;
1313          case '5' : which->change_aitype(5); break;
1314          case '6' : which->change_aitype(6); break;
1315          case '7' : which->change_aitype(7); break;
1316          case '8' : which->change_aitype(8); break;
1317          case '9' : which->change_aitype(9); break;
1318          case ')' : which->change_aitype(10); break;
1319          case '!' : which->change_aitype(11); break;
1320          case '@' : which->change_aitype(12); break;
1321          case '#' : which->change_aitype(13); break;
1322          case '$' : which->change_aitype(14); break;
1323          case '%' : which->change_aitype(15); break;
1324          case '^' : which->change_aitype(16); break;
1325          case '&' : which->change_aitype(17); break;
1326          case '*' : which->change_aitype(18); break;
1327          case '(' : which->change_aitype(19); break;
1328        }
1329      } 
1330      the_game->need_refresh();
1331    }
1332    else the_game->show_help(symbol_str("aitype"));
1333  }
1334
1335
1336}
1337
1338
1339void dev_controll::toggle_light_window()
1340{
1341  if (!lightw)
1342  {
1343    int wl=WINDOW_FRAME_LEFT,wh=WINDOW_FRAME_TOP,bh=16+6,bw=20+6,th=eh->font()->height()+4;   
1344    lightw=eh->new_window(prop->getd("light create x",0),
1345                          prop->getd("light create y",0),
1346                          -1,-1,new button_box(wl,wh,DEV_LIGHT_BUTTON_BOX,1,
1347                                    new button(wl+bw*0,wh+bh*0,DEV_LIGHT0,cash.img(light_buttons[0]),
1348                                    new button(wl+bw*1,wh+bh*0,DEV_LIGHT1,cash.img(light_buttons[1]),
1349                                    new button(wl+bw*2,wh+bh*0,DEV_LIGHT2,cash.img(light_buttons[2]),
1350
1351                                    new button(wl+bw*0,wh+bh*1,DEV_LIGHT3,cash.img(light_buttons[3]),
1352                                    new button(wl+bw*1,wh+bh*1,DEV_LIGHT4,cash.img(light_buttons[4]),
1353                                    new button(wl+bw*2,wh+bh*1,DEV_LIGHT5,cash.img(light_buttons[5]),
1354
1355                                    new button(wl+bw*0,wh+bh*2,DEV_LIGHT6,cash.img(light_buttons[6]),
1356                                    new button(wl+bw*1,wh+bh*2,DEV_LIGHT7,cash.img(light_buttons[7]),
1357                                    new button(wl+bw*2,wh+bh*2,DEV_LIGHT8,cash.img(light_buttons[8]),
1358
1359                                    new button(wl+bw*0,wh+bh*3,DEV_LIGHT9,cash.img(light_buttons[9]),
1360                                 new button(wl+bw*1,wh+bh*3,DEV_AMBIENT,cash.img(light_buttons[11]),
1361                                               NULL))))))))))),
1362
1363                                    new text_field(wl,wh+bh*4,DEV_LIGHTW,      "W ","******",
1364                                                   prop->getd("light create w",0),
1365                                    new text_field(wl,wh+bh*4+th*1,DEV_LIGHTH, "H ","******",
1366                                                   prop->getd("light create h",0),
1367                                    new text_field(wl,wh+bh*4+th*2,DEV_LIGHTR1,"R1","******",
1368                                                   prop->getd("light create r1",1),
1369                                    new text_field(wl,wh+bh*4+th*3,DEV_LIGHTR2,"R2","******",
1370                                                   prop->getd("light create r2",100),
1371                                                   NULL))))),
1372                                                   symbol_str("l_light"));
1373                                                   
1374  } else
1375  {
1376    prop->setd("light create x",lightw->x);
1377    prop->setd("light create y",lightw->y);
1378    prop->setd("light create w",atoi(lightw->read(DEV_LIGHTW)));
1379    prop->setd("light create h",atoi(lightw->read(DEV_LIGHTH)));
1380    prop->setd("light create r1",atoi(lightw->read(DEV_LIGHTR1)));
1381    prop->setd("light create r2",atoi(lightw->read(DEV_LIGHTR2)));
1382    eh->close_window(lightw);
1383    lightw=NULL;
1384  }
1385}
1386
1387void dev_controll::make_ai_window(game_object *o)
1388{
1389  ai_object=o;
1390  int th=eh->font()->height()+4,wl=WINDOW_FRAME_LEFT,wh=WINDOW_FRAME_TOP+20;
1391  if (figures[o->otype]->total_fields)
1392  {
1393    ifield *next=NULL;
1394    int maxl=0;
1395    int i=0;
1396    for (;i<figures[o->otype]->total_fields;i++)
1397      if (strlen(figures[o->otype]->fields[i]->descript_name)>maxl)
1398        maxl=strlen(figures[o->otype]->fields[i]->descript_name);
1399 
1400    int owh=wh;
1401    ifield *first,*last=NULL;
1402    for (i=0;i<figures[o->otype]->total_fields;i++)
1403    {
1404      char tmp[200];
1405      strcpy(tmp,figures[o->otype]->fields[i]->descript_name);
1406      for (int j=maxl-strlen(figures[o->otype]->fields[i]->descript_name);j;j--)
1407        strcat(tmp," ");     
1408      int er;
1409      ifield *p=new text_field(wl,wh,ID_NULL,tmp,"######",
1410                               (double)o->get_var_by_name(figures[o->otype]->fields[i]->real_name,er),
1411                               NULL);
1412      if (last)
1413        last->next=p;
1414      else
1415        first=p;
1416      last=p;
1417      wh+=th;
1418    }         
1419    aiw=eh->new_window(prop->getd("ai x",0),
1420                       prop->getd("ai y",0),
1421                       -1,-1,               
1422       new button(wl,owh-20,DEV_AI_OK,cash.img(dev_ok),first),"ai");
1423
1424  }
1425  else
1426  {
1427    aiw=eh->new_window(prop->getd("ai x",0),
1428                       prop->getd("ai y",0),
1429                       -1,-1,
1430       new button(wl,wh-20,DEV_AI_OK,cash.img(dev_ok),
1431       new text_field(wl,wh+th*0, DEV_AI_XVEL,    symbol_str("ai_xvel"),"#####",(double)o->xvel(),
1432       new text_field(wl,wh+th*1, DEV_AI_YVEL,    symbol_str("ai_yvel"),"#####",(double)o->yvel(),
1433       new text_field(wl,wh+th*2, DEV_AI_XACEL,   symbol_str("ai_xacel"),"#####",(double)o->xacel(),
1434       new text_field(wl,wh+th*3, DEV_AI_YACEL,   symbol_str("ai_yacel"),"#####",(double)o->yacel(),
1435       new text_field(wl,wh+th*4, DEV_AI_STTIME,  symbol_str("ai_stime"),"####",(double)o->aistate_time(),
1436       new text_field(wl,wh+th*5, DEV_AI_GRAVITY, symbol_str("ai_gravity"),"####",(double)o->gravity(),
1437       new text_field(wl,wh+th*6, DEV_AI_HEALTH,  symbol_str("ai_health"),"####",(double)o->hp(),
1438       new text_field(wl,wh+th*7, DEV_AI_MORPHPR, symbol_str("ai_morph"),"####",(double)o->mp(),
1439       new text_field(wl,wh+th*8, DEV_AI_TYPE,    symbol_str("ai_type"),"####",(double)o->aitype(),
1440       new text_field(wl,wh+th*9,DEV_AI_STATE,    symbol_str("ai_state"),"####",(double)o->aistate(),
1441       new text_field(wl,wh+th*10,DEV_AI_FADE,    symbol_str("ai_fade"),"####",(double)o->fade_count(),
1442                      NULL)))))))))))),"ai");
1443  }
1444
1445  eh->grab_focus(aiw);
1446}
1447
1448void dev_controll::notify_deleted_light(light_source *l)
1449{
1450  if (l==edit_light)
1451  {
1452    if (ledit)
1453    {
1454      prop->setd("ledit x",ledit->x);
1455      prop->setd("ledit y",ledit->y);
1456      eh->close_window(ledit); ledit=NULL;
1457    }
1458    edit_light=NULL;
1459  }
1460  if (l==selected_light) 
1461    selected_light=NULL;
1462}
1463
1464void dev_controll::notify_deleted_object(game_object *o)
1465{
1466  if (o==edit_object)
1467  {
1468    state=DEV_SELECT;
1469    close_oedit_window();
1470  }
1471
1472  if (o==ai_object)
1473    close_ai_window();
1474  if (o==search_object)
1475  { if (search_window)
1476      toggle_search_window();
1477    search_object=NULL;
1478  }
1479  if (o==link_object)
1480    link_object=NULL;
1481  if (o==selected_object)
1482  {
1483    selected_object=NULL;
1484    state=DEV_SELECT;
1485  }
1486
1487}
1488
1489void dev_controll::close_ai_window()
1490{
1491  if (aiw)
1492  {   
1493    game_object *o=ai_object;
1494    long x;
1495    if (o)
1496    {
1497      if (figures[o->otype]->total_fields)
1498      {
1499        ifield *f=aiw->inm->get(DEV_AI_OK)->next;
1500        for (int i=0;i<figures[o->otype]->total_fields;i++)
1501        {
1502          x=atoi(f->read());
1503          char *v=figures[o->otype]->fields[i]->real_name;
1504          int er;
1505          if (o->get_var_by_name(v,er)!=x)
1506          o->set_var_by_name(v,x);
1507          f=f->next;
1508        }
1509      }
1510      else
1511      {
1512        x=atoi(aiw->read(DEV_AI_XVEL)); if (x!=o->xvel()) o->set_xvel(x);
1513        x=atoi(aiw->read(DEV_AI_YVEL)); if (x!=o->yvel()) o->set_yvel(x);
1514
1515        x=atoi(aiw->read(DEV_AI_XACEL)); if (x!=o->xacel()) o->set_xacel(x);
1516        x=atoi(aiw->read(DEV_AI_YACEL)); if (x!=o->yacel()) o->set_yacel(x);
1517
1518        x=atoi(aiw->read(DEV_AI_STTIME)); if (x!=o->aistate_time()) o->set_aistate_time(x);
1519        x=atoi(aiw->read(DEV_AI_GRAVITY)); if (x!=o->gravity()) o->set_gravity(x);
1520
1521        x=atoi(aiw->read(DEV_AI_HEALTH)); if (x!=o->hp()) o->set_hp(x);
1522        x=atoi(aiw->read(DEV_AI_MORPHPR)); if (x!=o->mp()) o->set_mp(x);
1523
1524        x=atoi(aiw->read(DEV_AI_TYPE)); if (x!=o->aitype()) o->set_aitype(x);
1525        x=atoi(aiw->read(DEV_AI_STATE)); if (x!=o->aistate()) o->set_aistate(x);
1526        x=atoi(aiw->read(DEV_AI_FADE)); if (x!=o->fade_count()) o->set_fade_count(x);
1527      }
1528    }
1529    prop->setd("ai x",aiw->x);
1530    prop->setd("ai y",aiw->y);
1531    eh->close_window(aiw);
1532    aiw=NULL;
1533    ai_object=NULL;
1534    the_game->need_refresh();
1535  }
1536}
1537
1538
1539void dev_controll::area_handle_input(event &ev)
1540{
1541
1542  if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button)
1543  {
1544    long gx,gy;
1545    the_game->mouse_to_game(last_demo_mx,last_demo_my,gx,gy);
1546    if (!current_level) return ;
1547    current_area=current_level->area_list=new area_controller(gx,gy,
1548                                                              the_game->ftile_width(),
1549                                                              the_game->ftile_height(),
1550                                                              current_level->area_list);
1551    the_game->need_refresh();
1552    state=DEV_DRAG_AREA_BOTTOM;
1553  }
1554}
1555
1556void dev_controll::close_area_win(int read_values)
1557{
1558  if (area_win)
1559  {
1560    prop->setd("area_box x",area_win->x);
1561    prop->setd("area_box y",area_win->y);
1562
1563    if (current_area && read_values)
1564    {     
1565      current_area->ambient=atoi(area_win->read(DEV_AREA_AMBIENT));
1566      current_area->ambient_speed=atoi(area_win->read(DEV_AREA_AMBIENT_SPEED));
1567      current_area->view_xoff=atoi(area_win->read(DEV_AREA_VIEW_XOFF));
1568      current_area->view_yoff=atoi(area_win->read(DEV_AREA_VIEW_YOFF));
1569      current_area->view_xoff_speed=atoi(area_win->read(DEV_AREA_VIEW_XOFF_SPEED));
1570      current_area->view_yoff_speed=atoi(area_win->read(DEV_AREA_VIEW_YOFF_SPEED));
1571    }   
1572    eh->close_window(area_win);
1573    area_win=NULL;
1574  }
1575}
1576
1577void dev_controll::pick_handle_input(event &ev)
1578{
1579  area_controller *find=NULL;
1580  int find_top=0;
1581  if (!current_level) return;
1582  if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button)
1583  {
1584    long mx=last_demo_mx,my=last_demo_my;
1585    view *v=the_game->view_in(mx,my);
1586    for (area_controller *a=current_level->area_list;a;a=a->next)
1587    {
1588      long x1,y1,x2,y2;
1589      the_game->game_to_mouse(a->x,a->y,v,x1,y1);
1590      the_game->game_to_mouse(a->x+a->w,a->y+a->h,v,x2,y2);
1591      if (abs(x1-mx)<2 && abs(y1-my)<2)
1592      { find=a; find_top=1; }
1593      else if (abs(x2-mx)<2 && abs(y2-my)<2)
1594      { find=a; find_top=0; }
1595    } 
1596
1597    time_marker now;
1598    int dc=now.diff_time(&last_area_click)<0.5;
1599    last_area_click.get_time();
1600    if (find && current_area && dc)
1601    {         
1602      if (area_win) close_area_win(0);
1603      int wl=WINDOW_FRAME_LEFT;
1604      int wh=WINDOW_FRAME_TOP,th=eh->font()->height()+12,bw=cash.img(dev_ok)->width()+10;
1605      area_win=eh->new_window(prop->getd("area_box x",0),
1606                              prop->getd("area_box y",0),
1607                              -1,-1,
1608
1609                              new button(wl+bw*0,wh-8,DEV_AREA_OK,cash.img(dev_ok),
1610                              new button(wl+bw*1,wh-8,DEV_AREA_DELETE,cash.img(dev_del),
1611
1612                              new text_field(wl,wh+th*1,DEV_AREA_AMBIENT,         symbol_str("a_ambient"),"******",current_area->ambient,
1613                              new text_field(wl,wh+th*2,DEV_AREA_AMBIENT_SPEED,   symbol_str("a_aspeed"),"******",current_area->ambient_speed,
1614                              new text_field(wl,wh+th*3,DEV_AREA_VIEW_XOFF,       symbol_str("a_view_xoff"),"******",current_area->view_xoff,
1615                              new text_field(wl,wh+th*4,DEV_AREA_VIEW_YOFF,       symbol_str("a_view_yoff"),"******",current_area->view_yoff,
1616                              new text_field(wl,wh+th*5,DEV_AREA_VIEW_XOFF_SPEED, symbol_str("a_view_xspd"),"******",current_area->view_xoff_speed,
1617                              new text_field(wl,wh+th*6,DEV_AREA_VIEW_YOFF_SPEED, symbol_str("a_view_yspd"),"******",current_area->view_yoff_speed,
1618                                             NULL)))))))));
1619    } else if (find)
1620    {
1621      current_area=find;
1622      current_area->active=1;
1623      if (find_top)
1624      state=DEV_DRAG_AREA_TOP;
1625      else state=DEV_DRAG_AREA_BOTTOM;
1626      the_game->need_refresh();
1627    } else if (current_area)
1628    {
1629      current_area->active=0;
1630      current_area=NULL;
1631      the_game->need_refresh();
1632    }
1633  }
1634}
1635
1636void dev_controll::close_oedit_window()
1637{
1638  if (oedit)
1639  {
1640    prop->setd("oedit x",oedit->x);
1641    prop->setd("oedit y",oedit->y);
1642    eh->close_window(oedit);
1643    oedit=NULL;     
1644    edit_object=NULL;
1645  }
1646}
1647
1648int screen_shot_on=1;
1649int sshot_fcount=-1;
1650
1651void dev_controll::handle_event(event &ev)
1652{
1653  long x,y;
1654  if (link_object && (dlastx!=last_link_x || dlasty!=last_link_y))
1655  {
1656    last_link_x=dlastx;
1657    last_link_y=dlasty;
1658    the_game->need_refresh();
1659  }
1660
1661  if (dev_menu && dev_menu->handle_event(ev,screen,eh)) return ;
1662
1663  if (!current_level) return ;
1664
1665  for (x=0;x<total_pals;x++)
1666    pal_wins[x]->handle_event(ev);
1667  if (ev.type==EV_MOUSE_MOVE)
1668  {
1669    dlastx=last_demo_mx;
1670    dlasty=last_demo_my;   
1671  }
1672  if (dev_console && dev_console->handle_event(ev,eh))
1673    return;
1674
1675  if (ev.type==EV_KEY && ev.key==JK_F2)
1676    write_PCX(screen,pal,"scrnshot.pcx");
1677  else if (ev.type==EV_KEY && ev.key==JK_F3)
1678  {
1679    char name[100];
1680    sprintf(name,"shot%04d.pcx",screen_shot_on++);
1681    write_PCX(screen,pal,name);
1682  } else if (ev.type==EV_KEY && ev.key==JK_F5)
1683  {
1684    if (sshot_fcount!=-1)
1685    {
1686      sshot_fcount=-1;
1687      the_game->show_help(symbol_str("seqs_off"));
1688    }
1689    else
1690    {
1691      sshot_fcount=0;
1692      the_game->show_help(symbol_str("seqs_on"));
1693    }   
1694  }
1695
1696  switch (state)
1697  {
1698    case DEV_MOUSE_RELEASE :
1699    {
1700      if (!ev.mouse_button)
1701        state=DEV_SELECT;   
1702    } break;
1703
1704    case DEV_CREATE_OBJECT :
1705    {
1706      if (!ev.mouse_button)   
1707        state=DEV_MOVE_OBJECT;
1708    } break;
1709
1710
1711    case DEV_MOVE_OBJECT :
1712    {
1713      if (!edit_object)
1714      { state=DEV_SELECT; }
1715      else
1716      {
1717        if (ev.type==EV_MOUSE_MOVE)
1718        {
1719          the_game->mouse_to_game(last_demo_mx,last_demo_my,edit_object->x,edit_object->y);     
1720          edit_object->x=snap_x(edit_object->x);
1721          edit_object->y=snap_y(edit_object->y);
1722          the_game->need_refresh();
1723        }
1724        else if (ev.mouse_button==1 && ev.window==NULL)
1725        {
1726          state=DEV_MOUSE_RELEASE;
1727          selected_object=edit_object=NULL;     
1728        }
1729        if (ev.window==NULL && ev.type==EV_KEY && ev.key=='d')
1730        {
1731          long xv=0,yv=100;
1732          edit_object->try_move(edit_object->x,edit_object->y,xv,yv,1);
1733          edit_object->y+=yv;
1734          state=DEV_SELECT;
1735          selected_object=edit_object=NULL;     
1736        }
1737      }
1738    } break;
1739   
1740
1741    case DEV_MOVE_LIGHT :   
1742    {
1743      if (edit_light)
1744      {
1745        if (ev.type==EV_MOUSE_MOVE)
1746        {
1747          the_game->mouse_to_game(last_demo_mx,last_demo_my,edit_light->x,edit_light->y);
1748          edit_light->x=snap_x(edit_light->x);
1749          edit_light->y=snap_y(edit_light->y);
1750
1751          edit_light->calc_range();
1752          the_game->need_refresh();
1753        } else if (ev.type==EV_KEY)
1754        {
1755          int rd=0;
1756          switch (ev.key)
1757          {
1758            case '+' :
1759            {
1760              if (edit_light->type==9)
1761              {
1762                if (edit_light->inner_radius<64)
1763                { edit_light->inner_radius++; rd=1; }
1764              } else { edit_light->outer_radius++; rd=1; }
1765            } break;
1766            case '-' :
1767            {
1768              if (edit_light->type==9)
1769              {
1770                if (edit_light->inner_radius>0)
1771                { edit_light->inner_radius--; rd=1; }
1772              } else if (edit_light->outer_radius>edit_light->inner_radius+1)
1773              { edit_light->outer_radius--; rd=1; }
1774            } break;
1775            case JK_RIGHT :
1776            {
1777              if (edit_light->type==9)
1778              { edit_light->xshift++; rd=1; }
1779              else if (edit_light->xshift>0)
1780              { edit_light->xshift--; rd=1; }
1781            } break;
1782            case JK_LEFT :
1783            {
1784              if (edit_light->type==9)
1785              {
1786                if (edit_light->xshift>1)
1787                { edit_light->xshift--; rd=1; }
1788              }
1789              else
1790              { edit_light->xshift++; rd=1; }
1791            } break;
1792            case JK_UP :
1793            {
1794              if (edit_light->type==9)
1795              { edit_light->yshift++; rd=1; }
1796              else if (edit_light->yshift>0)
1797              { edit_light->yshift--; rd=1; }
1798            } break;
1799            case JK_DOWN :
1800            {
1801              if (edit_light->type==9)
1802              {
1803                if (edit_light->yshift>1)
1804                { edit_light->yshift--; rd=1; }
1805              }
1806              else
1807              { edit_light->yshift++; rd=1; }
1808            } break;
1809           
1810          }       
1811          if (rd)
1812          {
1813            edit_light->calc_range();
1814            the_game->need_refresh();
1815          }
1816
1817        }
1818      }
1819
1820      if ((ev.mouse_button==1 && ev.window==NULL) || !edit_light)
1821        state=DEV_MOUSE_RELEASE;
1822    } break;
1823
1824
1825    case DEV_DRAG_AREA_BOTTOM :
1826    {
1827      if (current_area)
1828      {
1829        long gx,gy;
1830        the_game->mouse_to_game(last_demo_mx,last_demo_my,gx,gy);
1831        if (gx>current_area->x && gy>current_area->y)
1832        {       
1833          if (gx-current_area->x!=current_area->w || gy-current_area->y!=current_area->h)
1834          {
1835            the_game->need_refresh();
1836            current_area->w=gx-current_area->x;
1837            current_area->h=gy-current_area->y;   
1838          }
1839        }
1840        if (ev.type==EV_MOUSE_BUTTON && !ev.mouse_button)
1841        {
1842          current_area->active=0;
1843          state=DEV_SELECT;
1844        }
1845      }
1846    } break;
1847
1848    case DEV_DRAG_AREA_TOP :
1849    {
1850      if (current_area)
1851      {
1852        long gx,gy;
1853        the_game->mouse_to_game(last_demo_mx,last_demo_my,gx,gy);
1854        if (gx<current_area->x+current_area->w && gy<current_area->y+current_area->h)
1855        {       
1856          if (gx!=current_area->x || gy!=current_area->y)
1857          {
1858            the_game->need_refresh();
1859            current_area->x=gx;
1860            current_area->y=gy;
1861          }
1862        }
1863        if (ev.type==EV_MOUSE_BUTTON && !ev.mouse_button)
1864        {
1865          current_area->active=0;
1866          state=DEV_SELECT;
1867        }
1868      }
1869    } break;
1870
1871    case DEV_SELECT :
1872    {
1873      if (dev&EDIT_MODE)
1874      {
1875        game_object *old=selected_object;     
1876        selected_object=NULL;
1877        if (ev.window==NULL)
1878        {       
1879          long rx,ry;
1880          the_game->mouse_to_game(last_demo_mx,last_demo_my,rx,ry);
1881
1882          if (!(dev & MAP_MODE))
1883          {
1884            if (dev&DRAW_PEOPLE_LAYER)
1885              selected_object=current_level->find_object(rx,ry);
1886            light_source *old_light=selected_light;
1887            if (selected_object)
1888              selected_light=NULL;
1889            else
1890              selected_light=find_light(rx,ry);
1891            if (selected_light!=old_light)
1892              the_game->need_refresh();           
1893          } else { selected_light=NULL; }
1894
1895          if (edit_mode==ID_DMODE_DRAW)
1896          {
1897            if (ev.mouse_button==1 && !selected_object && !selected_light)
1898            {
1899              long xs,ys;
1900              the_game->ftile_on(last_demo_mx,last_demo_my,xs,ys);
1901              if (xs>=0 && ys>=0 && xs<current_level->foreground_width() &&
1902                  ys<current_level->foreground_height())             
1903              current_level->put_fg(xs,ys,raise_all ? make_above_tile(cur_fg) : cur_fg);
1904              the_game->need_refresh();
1905            } else if (ev.mouse_button==1 && !selected_object && !selected_light)
1906            {
1907              long xs,ys;
1908              the_game->btile_on(last_demo_mx,last_demo_my,xs,ys);
1909              if (xs>=0 && ys>=0 && xs<current_level->background_width() &&
1910                  ys<current_level->background_height())
1911              current_level->put_bg(xs,ys,cur_fg);
1912              the_game->need_refresh();
1913            }
1914          } else if (edit_mode==ID_DMODE_AREA)
1915            area_handle_input(ev);
1916          else if (edit_mode==ID_DMODE_PICK)
1917            pick_handle_input(ev);                       
1918        }
1919       
1920        if (old!=selected_object)
1921        the_game->need_refresh();           
1922
1923
1924        if (ev.mouse_button)
1925        {
1926          if (selected_object)
1927          {
1928            if (edit_object && edit_object!=selected_object)     
1929              edit_object->add_object(selected_object);
1930
1931            if (oedit)
1932              close_oedit_window();
1933             
1934            int bw=20+6,bh=16+6,wl=WINDOW_FRAME_LEFT,wh=WINDOW_FRAME_TOP,th=eh->font()->height()+4;
1935
1936            oedit=eh->new_window(prop->getd("oedit x",0),
1937                                 prop->getd("oedit y",0),
1938                                 -1,-1,new button_box(wl,wh,ID_NULL,1,
1939                new button(wl+bw*0,wh,DEV_OEDIT_OK,cash.img(dev_ok),
1940                new button(wl+bw*1,wh,DEV_OEDIT_MOVE,cash.img(dev_move),
1941                new button(wl+bw*2,wh,DEV_OEDIT_FRONT,cash.img(dev_front),
1942                new button(wl+bw*3,wh,DEV_OEDIT_BACK,cash.img(dev_back),
1943                new button(wl+bw*4,wh,DEV_OEDIT_COPY,cash.img(dev_copy),
1944                new button(wl+bw*0,wh+bh*1,DEV_OEDIT_DELETE,cash.img(dev_del),
1945                           NULL)))))),
1946               new button(wl+bw*5,wh+bh*0,DEV_OEDIT_AI,cash.img(dev_ai),
1947
1948               new button_box(wl+bw*1,wh+bh*1,DEV_OEDIT_CHAR_BOX,0,
1949               new button(wl+bw*1,wh+bh*1,DEV_OEDIT_LEFT,cash.img(dev_char_left),
1950               new button(wl+bw*2,wh+bh*1,DEV_OEDIT_RIGHT,cash.img(dev_char_right),NULL)),
1951
1952               new button(wl+bw*3,wh+bh*1,DEV_OBJECTS_DELETE,cash.img(dev_objects),
1953               new button(wl+bw*4,wh+bh*1,DEV_LIGHTS_DELETE,cash.img(dev_lights),NULL))))),
1954                                 symbol_str("l_EDIT"));
1955
1956           
1957            edit_object=selected_object;       
1958          } else if (selected_light)
1959          {
1960            if (ledit)
1961            {
1962              prop->setd("ledit x",ledit->x);
1963              prop->setd("ledit x",ledit->y);
1964              eh->close_window(ledit);
1965            }
1966            int bw=20+6,bh=16+6,wl=WINDOW_FRAME_LEFT,wh=WINDOW_FRAME_TOP,th=eh->font()->height()+4;
1967            edit_light=selected_light;
1968            if (edit_object)
1969            {
1970              edit_object->add_light(edit_light);
1971              edit_light->known=1;
1972            }
1973            ledit=eh->new_window(prop->getd("ledit x",0),
1974                                 prop->getd("ledit y",0),
1975                                 -1,-1,
1976                         new button_box(wl,wh,ID_NULL,1,
1977                        new button(wl+bw*0,wh,DEV_LEDIT_OK,cash.img(dev_ok),
1978                       new button(wl+bw*1,wh,DEV_LEDIT_MOVE,cash.img(dev_move),
1979                     new button(wl+bw*2,wh,DEV_LEDIT_COPY,cash.img(dev_copy),
1980                    new button(wl+bw*3,wh,DEV_LEDIT_DEL,cash.img(dev_del),NULL)))),
1981                    new text_field(wl,wh+bh,DEV_LEDIT_W,      "W ","******",edit_light->xshift,
1982                    new text_field(wl,wh+bh+th*1,DEV_LEDIT_H, "H ","******",edit_light->yshift,
1983              new text_field(wl,wh+bh+th*2,DEV_LEDIT_R1,"R1","******",(int)(edit_light->inner_radius),
1984             new text_field(wl,wh+bh+th*3,DEV_LEDIT_R2,"R2","******",(int)(edit_light->outer_radius),
1985                               NULL))))));
1986          }
1987          else if (ev.window==NULL)
1988          {
1989            if (dlastx>=0 && dlasty>=0 && edit_mode==ID_DMODE_DRAW)
1990            {
1991              if ((dev & DRAW_FG_LAYER) && ev.mouse_button==1)
1992              {
1993                the_game->ftile_on(last_demo_mx,last_demo_my,x,y);
1994                if (x>=0 && y>=0 && x<current_level->foreground_width() &&
1995                    y<current_level->foreground_height())
1996                the_game->put_fg(x,y,raise_all ? make_above_tile(cur_fg) : cur_fg);
1997              }       
1998              if ((dev & DRAW_BG_LAYER) && ev.mouse_button==2)
1999              {   
2000                the_game->btile_on(last_demo_mx,last_demo_my,x,y);
2001                if (x>=0 && y>=0 && x<current_level->background_width() &&
2002                    y<current_level->background_height())
2003                the_game->put_bg(x,y,cur_bg);
2004              }
2005            }
2006          }
2007        }
2008      }
2009    }
2010  }
2011
2012  switch (ev.type)
2013  {
2014    case EV_MESSAGE :
2015    {
2016      switch (ev.message.id)
2017      {
2018        case ID_DMODE_DRAW :
2019        case ID_DMODE_PICK :
2020        case ID_DMODE_FILL :
2021        case ID_DMODE_LINE :
2022        case ID_DMODE_RECT :
2023        case ID_DMODE_BAR  :
2024        case ID_DMODE_AREA :
2025        {
2026          edit_mode=ev.message.id;
2027        } break;
2028/*      case ID_ENLARGE_RENDER :
2029        {
2030          if (!small_render)
2031            double_render();
2032          else   
2033            single_render();
2034         
2035          view_shift_disabled=!view_shift_disabled;
2036        } break; */
2037
2038        case ID_SEARCH :
2039        {
2040          toggle_search_window();
2041        } break;
2042        case ID_SEARCH_FOREWARD :
2043        { search_forward();
2044        } break;
2045        case ID_SEARCH_BACKWARD :
2046        { search_forward();
2047        } break;
2048        case ID_CANCEL :
2049        {
2050          if (mess_win)
2051          {
2052            eh->close_window(mess_win);
2053            mess_win=NULL;
2054          } break;
2055        } break;
2056        case ID_LEVEL_LOAD :
2057        {       
2058          if (!mess_win)
2059          {
2060            mess_win=file_dialog(eh,symbol_str("level_name"),current_level ? current_level->name() : "",
2061                                 ID_LEVEL_LOAD_OK,symbol_str("ok_button"),ID_CANCEL,symbol_str("cancel_button"),
2062                                 symbol_str("FILENAME"),ID_MESS_STR1);
2063            eh->grab_focus(mess_win);
2064          }
2065        } break;
2066        case ID_LEVEL_LOAD_OK :
2067        {
2068          char cmd[100];
2069          sprintf(cmd,"load %s",mess_win->read(ID_MESS_STR1));
2070          dev_cont->do_command(cmd,ev);
2071          eh->push_event(new event(ID_CANCEL,NULL));        // close window
2072        } break;       
2073        case ID_GAME_SAVE :
2074        {
2075          current_level->save("savegame.spe",1);
2076          the_game->show_help(symbol_str("saved_game"));
2077          the_game->need_refresh();       
2078        } break;
2079        case ID_LEVEL_SAVE :
2080        { if (current_level)
2081          {
2082            if (current_level->save(current_level->name(),0))
2083            {
2084              char msg[100];
2085              sprintf(msg,symbol_str("saved_level"),current_level->name());
2086              the_game->show_help(msg);
2087              the_game->need_refresh();
2088            }
2089          }
2090          else the_game->show_help("no current level, cannot save");
2091        } break;
2092        case ID_LEVEL_SAVEAS :
2093        {
2094          if (!mess_win)
2095          {
2096            mess_win=file_dialog(eh,symbol_str("saveas_name"),current_level ? current_level->name() : "untitled.spe",
2097                               ID_LEVEL_SAVEAS_OK,symbol_str("ok_button"),
2098                                 ID_CANCEL,symbol_str("cancel_button"),
2099                                 symbol_str("FILENAME"),ID_MESS_STR1);
2100            eh->grab_focus(mess_win);
2101          }
2102        } break;
2103        case ID_LEVEL_SAVEAS_OK :
2104        {
2105          if (current_level)
2106          {
2107            current_level->set_name(mess_win->read(ID_MESS_STR1));
2108            eh->push_event(new event(ID_CANCEL,NULL));        // close window after save
2109            eh->push_event(new event(ID_LEVEL_SAVE,NULL));         
2110          }
2111        } break;
2112        case ID_EDIT_SAVE :
2113        {
2114          do_command("esave",ev);
2115          the_game->show_help(symbol_str("edit_saved"));
2116        } break;
2117        case ID_CACHE_PROFILE :
2118        {
2119          if (current_level && !cash.prof_is_on())
2120          {
2121            cash.prof_init();
2122            the_game->show_help("Cache profiling is now on.");
2123          }
2124          else the_game->show_help("Cache profiling is already on!");
2125        } break;
2126
2127        case ID_CACHE_PROFILE_END :  // ask the user for a file name to save as
2128        {
2129          if (cash.prof_is_on())
2130          {
2131            cash.prof_uninit();
2132            the_game->show_help(symbol_str("prof_off"));
2133          } else the_game->show_help(symbol_str("prof"));
2134        } break;
2135
2136        case ID_LEVEL_NEW :
2137        {
2138          if (!mess_win)
2139          {
2140            mess_win=eh->new_window(xres/2,yres/2,-1,-1,
2141                       new button(WINDOW_FRAME_LEFT+10,WINDOW_FRAME_TOP+20,ID_LEVEL_NEW_OK,symbol_str("YES"),
2142                       new button(WINDOW_FRAME_LEFT+40,WINDOW_FRAME_TOP+20,ID_CANCEL,symbol_str("NO"),
2143              new info_field(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP,ID_NULL,symbol_str("sure?"),NULL))),symbol_str("New?"));
2144            eh->grab_focus(mess_win);
2145          }
2146        } break;
2147        case ID_LEVEL_NEW_OK :
2148        {
2149          eh->push_event(new event(ID_CANCEL,NULL));  // close_window
2150          if (current_level)     
2151            delete current_level;       
2152          current_level=new level(100,100,"untitled.spe");
2153        } break;
2154        case ID_LEVEL_RESIZE :
2155        {
2156          if (!mess_win)
2157          {
2158            int wl=WINDOW_FRAME_LEFT,wt=WINDOW_FRAME_TOP,h=eh->font()->height()+8;
2159            mess_win=eh->new_window(xres/2,yres/2,-1,-1,
2160                    new text_field(wl,wt+h*0,ID_MESS_STR1,symbol_str("width_"),"****",
2161                               current_level ? current_level->foreground_width() : 100,
2162                    new text_field(wl,wt+h*1,ID_MESS_STR2,symbol_str("height_"),"****",
2163                               current_level ? current_level->foreground_height() : 100,
2164                                   new button(wl+10,wt+h*4,ID_LEVEL_RESIZE_OK,symbol_str("ok_button"),
2165                                   new button(wt+40,wt+h*4,ID_CANCEL,symbol_str("cancel_button"),NULL)))),symbol_str("_scroll"));
2166          }
2167        } break;
2168        case ID_LEVEL_RESIZE_OK :
2169        {
2170          if (current_level)
2171          {
2172            current_level->set_size(atoi(mess_win->read(ID_MESS_STR1)),
2173                                    atoi(mess_win->read(ID_MESS_STR2)));
2174          } else the_game->show_help("Create a level first!");
2175          eh->push_event(new event(ID_CANCEL,NULL));  // close_window
2176        } break;
2177
2178        case ID_SUSPEND :
2179        {
2180          dev^=SUSPEND_MODE;
2181          if (dev&SUSPEND_MODE)
2182            the_game->show_help(symbol_str("suspend_on"));
2183          else
2184             the_game->show_help(symbol_str("suspend_off"));
2185        } break;
2186        case ID_PLAY_MODE :
2187        {
2188          dev^=EDIT_MODE;
2189        } break;
2190        case ID_QUIT :
2191        {
2192          if (confirm_quit())
2193            do_command("quit",ev);
2194        } ;
2195        case ID_TOGGLE_MAP :
2196        {
2197          if (dev&MAP_MODE) dev-=MAP_MODE;
2198          else dev|=MAP_MODE;
2199          the_game->need_refresh();     
2200        } break;
2201        case ID_TOGGLE_LIGHT :
2202        {
2203          dev^=DRAW_LIGHTS;
2204          the_game->need_refresh();
2205        } break;
2206        case ID_RECORD_DEMO :
2207        {
2208          if (!mess_win)
2209          {
2210            int wl=WINDOW_FRAME_LEFT,wt=WINDOW_FRAME_TOP,h=eh->font()->height()+8;
2211            mess_win=eh->new_window(xres/2,yres/2,-1,-1,
2212                    new text_field(wl,wt+h*0,ID_RECORD_DEMO_FILENAME,
2213                                   "demo filename","*******************",
2214                                   "demo.dat",
2215                                   new button(wl+10,wt+h*2,ID_RECORD_DEMO_OK,symbol_str("ok_button"),
2216                                   new button(wt+40,wt+h*2,ID_CANCEL,symbol_str("cancel_button"),NULL))));
2217          }
2218        } break;
2219
2220        case ID_RECORD_DEMO_OK :
2221        {
2222          demo_man.set_state(demo_manager::RECORDING,mess_win->read(ID_RECORD_DEMO_FILENAME));
2223          eh->push_event(new event(ID_CANCEL,NULL));        // close window       
2224        } break;
2225
2226        case ID_PLAY_DEMO :
2227        {
2228          if (!mess_win)
2229          {
2230            int wl=WINDOW_FRAME_LEFT,wt=WINDOW_FRAME_TOP,h=eh->font()->height()+8;
2231            mess_win=eh->new_window(xres/2,yres/2,-1,-1,
2232                    new text_field(wl,wt+h*0,ID_PLAY_DEMO_FILENAME,
2233                                   "demo filename","*******************",
2234                                   "demo.dat",
2235                                   new button(wl+10,wt+h*2,ID_PLAY_DEMO_OK,symbol_str("ok_button"),
2236                                   new button(wt+40,wt+h*2,ID_CANCEL,symbol_str("cancel_button"),NULL))));
2237          }
2238        } break;
2239
2240        case ID_PLAY_DEMO_OK :
2241        {
2242          demo_man.set_state(demo_manager::PLAYING,mess_win->read(ID_PLAY_DEMO_FILENAME));
2243          eh->close_window(mess_win);
2244          mess_win=NULL;
2245        } break;
2246
2247        case ID_SET_SCROLL :
2248        {
2249          if (!mess_win)
2250          {
2251            int wl=WINDOW_FRAME_LEFT,wt=WINDOW_FRAME_TOP,h=eh->font()->height()+8;
2252            mess_win=eh->new_window(xres/2,yres/2,-1,-1,
2253                    new text_field(wl,wt+h*0,ID_MESS_STR1,symbol_str("x_mul"),"****",bg_xmul,
2254                    new text_field(wl,wt+h*1,ID_MESS_STR2,symbol_str("x_div"),"****",bg_xdiv,
2255                    new text_field(wl,wt+h*2,ID_MESS_STR3,symbol_str("y_mul"),"****",bg_ymul,
2256                    new text_field(wl,wt+h*3,ID_MESS_STR4,symbol_str("y_div"),"****",bg_ydiv,
2257                                   new button(wl+10,wt+h*4,ID_SET_SCROLL_CHECK,symbol_str("ok_button"),
2258                                   new button(wt+40,wt+h*4,ID_CANCEL,symbol_str("cancel_button"),NULL)))))),symbol_str("_scroll"));
2259          }
2260        } break;
2261        case ID_SET_SCROLL_CHECK :
2262        {
2263          int tbg_xmul=atoi(mess_win->read(ID_MESS_STR1));
2264          int tbg_xdiv=atoi(mess_win->read(ID_MESS_STR2));
2265          int tbg_ymul=atoi(mess_win->read(ID_MESS_STR3));
2266          int tbg_ydiv=atoi(mess_win->read(ID_MESS_STR4));
2267
2268          if ( (((float)tbg_xmul/(float)tbg_xdiv) < ((float)bg_xmul/(float)bg_xdiv)) ||
2269              (((float)tbg_ymul/(float)tbg_ydiv) < ((float)bg_ymul/(float)bg_ydiv)))
2270          {
2271            int wl=WINDOW_FRAME_LEFT,wt=WINDOW_FRAME_TOP,h=eh->font()->height()+8;
2272
2273            warn_win=eh->new_window(xres/2-40,yres/2-40,-1,-1,
2274                              new info_field(wl,wt,ID_NULL,
2275                                          symbol_str("back_loss"),
2276                                          new button(wl+10,wt+h*4,ID_SET_SCROLL_OK,symbol_str("ok_button"),
2277                                          new button(wt+40,wt+h*4,ID_WARN_CANCEL,symbol_str("cancel_button"),NULL))),
2278                                    symbol_str("WARNING"));
2279            eh->grab_focus(warn_win);
2280          } else eh->push_event(new event(ID_SET_SCROLL_OK,NULL));
2281        } break;
2282        case ID_WARN_CANCEL :
2283        {
2284          eh->close_window(warn_win); warn_win=NULL;
2285          eh->push_event(new event(ID_CANCEL,NULL));
2286        } break;
2287        case ID_SET_SCROLL_OK :
2288        {
2289          if (warn_win) { eh->close_window(warn_win); warn_win=NULL; }
2290          bg_xmul=atoi(mess_win->read(ID_MESS_STR1));
2291          bg_xdiv=atoi(mess_win->read(ID_MESS_STR2));
2292          bg_ymul=atoi(mess_win->read(ID_MESS_STR3));
2293          bg_ydiv=atoi(mess_win->read(ID_MESS_STR4));
2294          eh->push_event(new event(ID_CANCEL,NULL));        // close window
2295        } break;
2296
2297        case ID_CENTER_PLAYER :
2298        {
2299           do_command("center",ev); break;
2300        } break;
2301
2302        case ID_INTERPOLATE_DRAW : 
2303        {
2304          interpolate_draw=!interpolate_draw;
2305        } break;
2306
2307        case ID_DISABLE_AUTOLIGHT :
2308        {
2309          disable_autolight=!disable_autolight;
2310        } break;
2311
2312        case ID_ADD_PALETTE :
2313        {
2314          if (!mess_win)
2315          {
2316            int wl=WINDOW_FRAME_LEFT,wt=WINDOW_FRAME_TOP,h=eh->font()->height()+8;
2317            mess_win=eh->new_window(xres/2,yres/2,-1,-1,
2318                    new text_field(wl,wt+h*0,ID_MESS_STR1,symbol_str("ap_width"),"****",2,
2319                    new text_field(wl,wt+h*1,ID_MESS_STR2,symbol_str("ap_height"),"****",2,
2320                    new text_field(wl,wt+h*2,ID_MESS_STR3,symbol_str("ap_name"),"***********","pal",
2321                                   new button(wl+10,wt+h*3,ID_ADD_PALETTE_OK,symbol_str("ok_button"),
2322                                   new button(wt+40,wt+h*3,ID_CANCEL,symbol_str("cancel_button"),NULL))))),symbol_str("ap_pal"));
2323          }
2324        } break;
2325        case ID_ADD_PALETTE_OK :
2326        {
2327          char name[70];
2328          sprintf(name,"(add_palette \"%s\" %d %d)",mess_win->read(ID_MESS_STR3),
2329                  atoi(mess_win->read(ID_MESS_STR1)),
2330                  atoi(mess_win->read(ID_MESS_STR2)));
2331          char *s=name;
2332          eval(compile(s));
2333          eh->push_event(new event(ID_CANCEL,NULL));        // close window
2334        } break;
2335        case ID_TOGGLE_DELAY :
2336        {
2337          the_game->toggle_delay(); break;
2338        } break;
2339
2340        case ID_SMALL_MODE :
2341        {
2342          make_screen_size(311,160); break;
2343        } break;
2344        case ID_CLEAR_WEAPONS :
2345        {
2346          event ev;
2347          do_command("clear_weapons",ev);
2348        } break;
2349        case ID_GOD_MODE :
2350        {
2351          for (view *v=player_list;v;v=v->next)
2352            v->god=!v->god;
2353        } break;
2354        case ID_MOUSE_SCROLL :
2355        {
2356          mouse_scrolling=!mouse_scrolling;
2357          prop->setd("mouse_scrolling",mouse_scrolling);
2358          if (mouse_scrolling)
2359            the_game->show_help(symbol_str("ms_on"));
2360          else
2361            the_game->show_help(symbol_str("ms_off"));
2362        } break;
2363
2364        case ID_LOCK_PALETTES :
2365        {
2366          palettes_locked=!palettes_locked;
2367          prop->setd("palettes_locked",palettes_locked);
2368          if (palettes_locked)
2369            the_game->show_help(symbol_str("pal_lock"));
2370          else the_game->show_help(symbol_str("pal_unlock"));     
2371        } break;
2372
2373        case ID_DISABLE_VIEW_SHIFT :
2374        {
2375          view_shift_disabled=!view_shift_disabled;
2376          prop->setd("view_shift_disabled",view_shift_disabled);
2377          if (view_shift_disabled)
2378            the_game->show_help(symbol_str("vs_dis"));
2379          else the_game->show_help(symbol_str("vs_en"));         
2380        } break;
2381
2382        case ID_WIN_FORE :
2383        {
2384          toggle_fgw();
2385        } break;
2386        case ID_WIN_BACK :
2387        {
2388          toggle_bgw();
2389        } break;
2390        case ID_WIN_OBJECTS :
2391        {
2392          toggle_omenu();
2393        } break;
2394        case ID_WIN_PALETTES :
2395        {
2396          toggle_pmenu();
2397        } break;
2398        case ID_WIN_LIGHTING :
2399        {
2400          toggle_light_window();
2401        } break;
2402        case ID_WIN_LAYERS :
2403        {
2404          toggle_show_menu();
2405        } break;
2406        case ID_WIN_CONSOLE :
2407        {
2408          if (dev_console) dev_console->toggle();
2409        } break;
2410        case ID_WIN_TOOLBAR :
2411        {
2412          toggle_toolbar();
2413        } break;
2414
2415        case DEV_AMBIENT :
2416        { if (!ambw) make_ambient(); } break;
2417        case DEV_AREA_OK :
2418        { close_area_win(1); } break;
2419        case DEV_AREA_DELETE :
2420        { close_area_win(0);
2421          if (current_area && current_level)
2422          {
2423            if (current_level->area_list==current_area)
2424              current_level->area_list=current_level->area_list->next;
2425            else
2426            {
2427              area_controller *a=current_level->area_list,*l=NULL;
2428              for (;a!=current_area && a;a=a->next) { l=a; }
2429              l->next=a->next;
2430              delete a;
2431            }
2432            current_area=NULL;
2433            the_game->need_refresh();
2434          }
2435        } break;
2436        case DEV_AI_OK :
2437          close_ai_window(); break;
2438        case DEV_OEDIT_AI :
2439          make_ai_window(edit_object); break;
2440        case DEV_OBJECTS_DELETE :
2441        {
2442          if (edit_object)
2443          {
2444            for (int i=0;i<edit_object->total_objects();i++)
2445              edit_object->remove_object(edit_object->get_object(0));
2446            the_game->need_refresh();       
2447          }
2448        } break;
2449
2450        case DEV_LIGHTS_DELETE :
2451        {
2452          if (edit_object)
2453          {
2454            for (int i=0;i<edit_object->total_lights();i++)
2455              edit_object->remove_light(edit_object->get_light(0));
2456            the_game->need_refresh();       
2457          }
2458        } break;
2459
2460        case DEV_LEDIT_DEL :
2461        {
2462          prop->setd("ledit x",ledit->x);
2463          prop->setd("ledit y",ledit->y);
2464          eh->close_window(ledit); ledit=NULL;
2465          if (current_level)
2466            current_level->remove_light(edit_light);
2467          else
2468            delete_light(edit_light);
2469          edit_light=NULL;
2470          the_game->need_refresh();
2471        } break;
2472        case DEV_LEDIT_OK :
2473        {
2474          edit_light->xshift=atoi(ledit->read(DEV_LEDIT_W));
2475          edit_light->yshift=atoi(ledit->read(DEV_LEDIT_H));
2476          edit_light->inner_radius=atoi(ledit->read(DEV_LEDIT_R1));
2477          edit_light->outer_radius=atoi(ledit->read(DEV_LEDIT_R2));
2478          if (edit_light->outer_radius<=edit_light->inner_radius)
2479          {
2480            edit_light->inner_radius=edit_light->outer_radius-1;
2481            if (edit_light->inner_radius<1)
2482            {
2483              edit_light->inner_radius=1;
2484              edit_light->outer_radius=2;
2485            }
2486          }
2487
2488          edit_light->calc_range();
2489          edit_light=NULL;
2490          prop->setd("ledit x",ledit->x);
2491          prop->setd("ledit y",ledit->y);
2492          eh->close_window(ledit); ledit=NULL;
2493          the_game->need_refresh();       
2494        } break;
2495        case DEV_LEDIT_MOVE :
2496        {
2497          prop->setd("ledit x",ledit->x);
2498          prop->setd("ledit y",ledit->y);
2499          eh->close_window(ledit); ledit=NULL;
2500          state=DEV_MOVE_LIGHT;
2501        } break;
2502        case DEV_LEDIT_COPY :
2503        {
2504          edit_light=edit_light->copy();
2505          prop->setd("ledit x",ledit->x);
2506          prop->setd("ledit y",ledit->y);
2507          eh->close_window(ledit); ledit=NULL;   
2508          state=DEV_MOVE_LIGHT;
2509        } break;
2510
2511
2512        case DEV_LIGHT0 :
2513        case DEV_LIGHT1 :
2514        case DEV_LIGHT2 :
2515        case DEV_LIGHT3 :
2516        case DEV_LIGHT4 :
2517        case DEV_LIGHT5 :
2518        case DEV_LIGHT6 :
2519        case DEV_LIGHT7 :
2520        case DEV_LIGHT8 :
2521        case DEV_LIGHT9 :
2522        {
2523          long lx,ly;
2524          the_game->mouse_to_game(last_demo_mx,last_demo_my,lx,ly);
2525          lx=snap_x(lx);
2526          ly=snap_y(ly);
2527          edit_light=add_light_source(ev.message.id-DEV_LIGHT0,lx,ly,
2528                                       atoi(lightw->read(DEV_LIGHTR1)),
2529                                       atoi(lightw->read(DEV_LIGHTR2)),
2530                                       atoi(lightw->read(DEV_LIGHTW)),
2531                                       atoi(lightw->read(DEV_LIGHTH)));
2532          state=DEV_MOVE_LIGHT;                               
2533        } break;
2534        case ID_RAISE_ALL :
2535        {
2536          raise_all=!raise_all;
2537          prop->setd("raise_all",raise_all);
2538          if (raise_all)
2539            the_game->show_help(symbol_str("fg_r"));
2540          else
2541            the_game->show_help(symbol_str("fg_l"));
2542        } break;
2543        case DEV_OEDIT_COPY :
2544        {
2545          game_object *use=copy_object;
2546          if (!use) use=edit_object;
2547          if (use)
2548          {         
2549            game_object *old=use;
2550            close_oedit_window();
2551            if (use->controller())
2552              the_game->show_help(symbol_str("no_clone"));
2553            else
2554            {
2555              edit_object=old->copy();
2556
2557              current_level->add_object(edit_object);
2558              the_game->need_refresh();
2559              state=DEV_MOVE_OBJECT;
2560
2561              close_oedit_window();
2562              copy_object=NULL;
2563            }
2564          }
2565        } break;
2566        case DEV_OEDIT_LEFT :
2567        {
2568          if (edit_object)
2569          {
2570            the_game->need_refresh();
2571            edit_object->direction=-1;
2572          }
2573        } break;
2574        case DEV_OEDIT_RIGHT :
2575        {
2576          if (edit_object)
2577          {
2578            the_game->need_refresh();
2579            edit_object->direction=1;
2580          }
2581        } break;
2582
2583
2584        case DEV_COMMAND_OK :
2585        {
2586          char cmd[100];
2587          strcpy(cmd,commandw->inm->get(DEV_COMMAND)->read());     
2588          prop->setd("commandw x",commandw->x);
2589          prop->setd("commandw y",commandw->y);
2590          eh->close_window(commandw);
2591          commandw=NULL;
2592          do_command(cmd,ev);
2593        } break;
2594
2595        case ID_SHOW_FPS :
2596        { fps_on=!fps_on; } break;
2597        case ID_PROFILE :
2598        { profile_toggle();
2599          profile_on=!profile_on;
2600        } break;
2601         
2602        case ID_TOGGLE_NAMES : { show_names=!show_names; } break;
2603        case DEV_QUIT : the_game->end_session(); break;
2604        case DEV_EDIT_FG : dev=1; break; //the_game->draw(); break;
2605        case DEV_EDIT_BG : dev=2; break; //the_game->draw(); break;
2606        case DEV_EDIT_FGBG : dev=3; break; //the_game->draw(); break;
2607        case DEV_PLAY : dev=0; break; //the_game->draw(); break;
2608        case SHOW_FOREGROUND :
2609        { dev=dev^DRAW_FG_LAYER; the_game->need_refresh(); } break;
2610        case SHOW_FOREGROUND_BOUND :
2611        { dev=dev^DRAW_FG_BOUND_LAYER; the_game->need_refresh(); } break;
2612        case SHOW_BACKGROUND :
2613        { dev=dev^DRAW_BG_LAYER; the_game->need_refresh(); } break;
2614        case SHOW_CHARACTERS :
2615        { dev=dev^DRAW_PEOPLE_LAYER; the_game->need_refresh(); } break;
2616        case SHOW_LIGHT :
2617        { dev=dev^DRAW_LIGHTS; the_game->need_refresh(); } break;               
2618        case SHOW_LINKS :
2619        { dev=dev^DRAW_LINKS;  the_game->need_refresh(); } break;
2620         
2621
2622        case DEV_CREATE :
2623        {         
2624          int val=get_omenu_item(((pick_list *)ev.message.data)->get_selection());
2625          char cmd[100];
2626          sprintf(cmd,"create %s",object_names[val]);
2627          do_command(cmd,ev);
2628          state=DEV_CREATE_OBJECT;
2629          dev|=(EDIT_MODE | DRAW_PEOPLE_LAYER);     
2630        }             
2631        break; 
2632
2633        case DEV_PALETTE :
2634        {
2635          int val=((pick_list *)ev.message.data)->get_selection();         
2636          pal_wins[val]->open_window();
2637        } break;
2638
2639        case DEV_MUSIC_PICKLIST :
2640        {         
2641/*          int *val=((int *)((pick_list *)ev.message.data)->read());
2642            if (current_song) delete current_song;
2643            current_song=new song(song_list[*val]);
2644            current_song->play();           */
2645        }             
2646        break;           
2647
2648        case DEV_OEDIT_OK :
2649        { close_oedit_window(); } break;
2650         
2651        case DEV_OEDIT_DELETE :
2652        {
2653          selected_object=edit_object;
2654          do_command("delete",ev);
2655          close_oedit_window();
2656        }
2657        break;
2658         
2659        case DEV_OEDIT_FRONT :
2660        {
2661          do_command("to_front",ev);
2662          close_oedit_window();                     
2663        }
2664        break;
2665
2666        case DEV_OEDIT_BACK :
2667        {
2668          do_command("to_back",ev);
2669          close_oedit_window();                     
2670        }
2671        break;
2672
2673        case DEV_OEDIT_MOVE :       
2674        {
2675          game_object *o=edit_object;
2676          close_oedit_window();
2677          edit_object=o;
2678          do_command("move",ev);
2679        }
2680        break;   
2681      }
2682    } break;
2683
2684
2685    case EV_CLOSE_WINDOW :
2686    {
2687      if (ev.window)
2688      {   
2689        if (ev.window==commandw)
2690        {
2691          prop->setd("commandw x",commandw->x);
2692          prop->setd("commandw y",commandw->y);   
2693          eh->close_window(commandw);
2694          commandw=NULL;       
2695        } else if (ev.window==oedit)
2696          close_oedit_window();
2697        else if (ev.window==ambw)
2698        { eh->close_window(ambw); ambw=NULL; }
2699        else if (ev.window==backw) toggle_bgw();
2700        else if (ev.window==forew) toggle_fgw();
2701        else if (ev.window==lightw) toggle_light_window();
2702        else if (ev.window==show_menu) toggle_show_menu();
2703        else if (ev.window==pmenu) toggle_pmenu();
2704        else if (ev.window==tbw) toggle_toolbar();
2705        else if (ev.window==omenu) toggle_omenu();
2706        else if (ev.window==memprof) toggle_memprof();
2707        else if (ev.window==search_window) toggle_search_window();
2708        else if (profile_handle_event(ev))  profile_on=!profile_on;
2709        else if (chat->chat_event(ev)) chat->toggle();
2710   
2711      }
2712    }
2713    break;
2714    case EV_KEYRELEASE :
2715    {
2716      if (ev.key==JK_CTRL_L)
2717      {
2718        if (!edit_object && link_object && selected_object && link_object!=selected_object)
2719        {
2720          link_object->add_object(selected_object);
2721          if (S_LINK_SND>0) cash.sfx(S_LINK_SND)->play(sfx_volume/2);
2722          the_game->need_refresh();
2723        }
2724
2725        link_object=NULL;
2726      }
2727    } break;
2728    case EV_KEY :
2729    {   
2730      if (backw && ev.window==backw)
2731      { if (ev.key=='-' && bg_scale<the_game->btile_height()/2)
2732        { toggle_bgw();
2733          bg_scale++;
2734          toggle_bgw();
2735        } else if (ev.key=='+' && bg_scale>1)
2736        { toggle_bgw();
2737          bg_scale--;
2738          toggle_bgw();
2739        } else if (ev.key=='b') toggle_bgw();
2740        else if (ev.key=='B') { toggle_bgw(); bg_w++; if (bg_w>6) bg_w=1; toggle_bgw(); }
2741      }
2742      if (forew && ev.window==forew)
2743      { if (ev.key=='-' && fg_scale<the_game->ftile_height()/2)
2744        { toggle_fgw();
2745          fg_scale++;
2746          toggle_fgw();
2747        } else if (ev.key=='+' && fg_scale>1)
2748        { toggle_fgw();
2749          fg_scale--;
2750          toggle_fgw();
2751        } else if (ev.key=='i')
2752        {
2753          toggle_fgw();
2754          fg_reversed=!fg_reversed;
2755          prop->setd("fg_reversed",fg_reversed);
2756          toggle_fgw();
2757        } else if (ev.key=='f') toggle_fgw();
2758
2759        else if (ev.key=='F') { toggle_fgw(); fg_w++; if (fg_w>6) fg_w=1; toggle_fgw(); }
2760      }
2761      if (ev.window==NULL || ev.window==pmenu ||
2762          ev.window==forew || is_pal_win(ev.window))  // main window actions
2763      {         
2764        switch (ev.key)
2765        {
2766          case JK_CTRL_L : if (!edit_object && !link_object) { link_object=selected_object; }
2767          case 'n' : current_level->next_focus(); break;                           
2768//        case '/' : if (dev_console) dev_console->toggle(); break;       
2769          case 't' :
2770          {
2771            if (ev.window==NULL || ev.window==forew)
2772            {
2773              the_game->ftile_on(last_demo_mx,last_demo_my,x,y);
2774              fg_fill(cur_fg,x,y,NULL);
2775            }
2776          } break;
2777          case 'f' : toggle_fgw(); break;
2778          case 'M' : toggle_music_window(); break;                         
2779
2780          case 'b' : toggle_bgw(); break;
2781          case 'a' : toggle_toolbar(); break;
2782          case 'A' : { if (selected_object)
2783                       {
2784                         if (oedit) eh->push_event(new event(DEV_OEDIT_OK,NULL));                     
2785                         make_ai_window(selected_object);
2786                       }
2787                     } break;
2788                     
2789          case 'o' : toggle_omenu(); break;                   
2790
2791          case '<' : do_command("to_back",ev); break;
2792
2793          case '>' : do_command("to_front",ev); break;
2794          case 'p' : toggle_pmenu(); break;                   
2795          case 'P' : profile_toggle(); break;
2796          case '|' : toggle_memprof(); break;
2797          case '.' :
2798          {
2799            if (last_created_type>=0)
2800            {
2801              int val=last_created_type;
2802              char cmd[100];
2803              sprintf(cmd,"create %s",object_names[val]);
2804              do_command(cmd,ev);
2805              state=DEV_CREATE_OBJECT;
2806              dev|=(EDIT_MODE | DRAW_PEOPLE_LAYER);         
2807            }
2808          }             
2809          break;       
2810
2811
2812          case 'd' : { do_command("delete",ev);  the_game->need_refresh(); } break;
2813          case 'i' :
2814          {       
2815            fg_reversed=!fg_reversed;
2816            prop->setd("fg_reversed",fg_reversed);
2817            if (forew)
2818            {
2819              toggle_fgw();
2820              toggle_fgw();
2821            }
2822          } break;
2823          case 'l' : toggle_light_window(); break;
2824          case '!' :
2825          case '@' :
2826          case '#' :
2827          case '$' :
2828          case '%' :
2829          case '^' :
2830          case '&' :
2831          case '*' :
2832          case '(' :
2833          case ')' :
2834
2835          case '0' :
2836          case '1' :
2837          case '2' :
2838          case '3' :
2839          case '4' :
2840          case '5' :
2841          case '6' :
2842          case '7' :
2843          case '8' :
2844          case '9' : do_command("set_aitype",ev); break;
2845          case 'c' : do_command("center",ev); break;
2846          case 'C' : 
2847          if (selected_object && selected_object->controller()==NULL)
2848          { copy_object=selected_object;
2849                        eh->push_event(new event(DEV_OEDIT_COPY,NULL)); } break;
2850         
2851          case 'D' : the_game->toggle_delay(); break;
2852          case 'L' : toggle_show_menu(); break;
2853          case '`' : do_command("fg_select",ev); break;
2854          case 'r' : { do_command("toggle_fg_raise",ev); the_game->need_refresh(); }  break;
2855          case '[' : do_command("fg_add -1",ev); break;
2856          case ']' : do_command("fg_add 1",ev); break;
2857          case 'R' : do_command("reload",ev); break;
2858          case 'w' :
2859          {       
2860            long rx,ry;
2861            the_game->mouse_to_game(dlastx,dlasty,rx,ry);
2862            char msg[100]; sprintf(msg,symbol_str("mouse_at"),rx,ry);
2863            the_game->show_help(msg);
2864            the_game->need_refresh();
2865          } break;
2866          case 'k' :
2867          {
2868            if (selected_object && selected_object->total_objects())
2869              selected_object->remove_object(selected_object->get_object(0));
2870            the_game->need_refresh();
2871          } break;
2872          case 'K' :
2873          {
2874            if (selected_object && selected_object->total_objects())
2875              selected_object->remove_object(selected_object->get_object(selected_object->total_objects()-1));
2876            the_game->need_refresh();
2877          } break;
2878          case 'j' :
2879          {
2880            if (current_level && player_list && player_list->focus)
2881            {
2882              long rx,ry;
2883              the_game->mouse_to_game(dlastx,dlasty,rx,ry);
2884              player_list->focus->x=rx;
2885              player_list->focus->y=ry;
2886              do_command("center",ev);
2887              the_game->need_refresh();
2888            }
2889          } break;
2890          case 'z' : do_command("clear_weapons",ev); break;       
2891          case 'Z' : if (dev&EDIT_MODE)
2892          { view *v=the_game->view_in(last_demo_mx,last_demo_my);
2893            if (v)
2894            {
2895              v->god=!v->god;
2896              sbar.redraw(screen);
2897            }
2898          } break;
2899          case ' ' :
2900          {
2901            if (dev & EDIT_MODE)
2902            {
2903              if (selected_object)
2904              {
2905                if (oedit)
2906                  close_oedit_window();
2907                edit_object=selected_object;
2908                do_command("move",ev);
2909              } else if (selected_light)
2910              {
2911                if (ledit)
2912                {
2913                  eh->close_window(ledit);
2914                  ledit=NULL;
2915                }
2916                edit_light=selected_light;
2917                do_command("move_light",ev);
2918              }
2919             
2920            } break;       
2921          }       
2922          case 'x' :
2923          {
2924            if (selected_object)
2925            { if (selected_object->direction>0)
2926              selected_object->direction=-1;
2927            else selected_object->direction=1;
2928            }
2929          } break;
2930         
2931        }         
2932      }
2933    }
2934  }
2935 
2936
2937}
2938
2939
2940void dev_controll::add_palette(void *args)
2941{
2942  total_pals++;
2943  pal_wins=(pal_win **)jrealloc(pal_wins,sizeof(pal_win *)*total_pals,"edit pal array");
2944  pal_wins[total_pals-1]=new pal_win(args);
2945}
2946
2947
2948pal_win::pal_win(void *args)
2949{
2950  int i=0;
2951  Cell *ao=(Cell *)args;
2952 
2953  name=strcpy((char *)jmalloc(strlen(lstring_value(CAR(args)))+1,
2954                              "pal name"),lstring_value(CAR(args)));
2955  ao=CDR(ao);
2956  scale=w=h=1;
2957  x=y=0;
2958 
2959  if (!NILP(ao))
2960  {
2961    w=lnumber_value(CAR(ao)); ao=CDR(ao);
2962    if (!NILP(ao))
2963    {
2964      h=lnumber_value(CAR(ao)); ao=CDR(ao);
2965      if (!NILP(ao))
2966      {
2967        x=lnumber_value(CAR(ao)); ao=CDR(ao);
2968        if (!NILP(ao))
2969        {
2970          y=lnumber_value(CAR(ao)); ao=CDR(ao);
2971          if (!NILP(ao))
2972            scale=lnumber_value(CAR(ao)); ao=CDR(ao);
2973        }
2974      }
2975    }
2976  }
2977
2978  if (w<=0) w=0;
2979  if (h<=0) h=0;
2980
2981  pat=(unsigned short *)jmalloc(w*h*sizeof(unsigned short),"palwin::pat");
2982  memset(pat,0,sizeof(unsigned short)*w*h);   // set the palette to black if no parameters are given
2983  while (!NILP(ao))   // loop until we run out of parameters
2984  {
2985    if (i>w*h)
2986    {
2987      lbreak("to many parameters to add_palette ");
2988      exit(0);
2989    }
2990    pat[i]=lnumber_value(CAR(ao));
2991    // make sure the tile that they suggested exists
2992    if (pat[i]<=0 || pat[i]>nforetiles || foretiles[pat[i]]<0)
2993      pat[i]=0;   
2994    ao=CDR(ao);
2995    i++;
2996  }
2997  last_selected=-1;
2998  me=NULL;
2999  open_window();
3000}
3001
3002void pal_win::open_window()
3003{
3004  if (me) close_window();
3005  me=eh->new_window(x,y,w*f_wid/scale,h*f_hi/scale,NULL,name);
3006  draw();
3007}
3008
3009void pal_win::close_window()
3010{
3011  if (me)       // dont' close the window if the window is already closed
3012  {
3013    x=me->x;    //  save the old poisition of the window so that when we  open it
3014                //  it will be in the same spot
3015    y=me->y;
3016    eh->close_window(me);
3017    me=NULL;
3018   
3019  }
3020}
3021
3022#ifdef __POWERPC__
3023#pragma global_optimizer on
3024#endif
3025
3026void pal_win::draw()
3027{
3028  int i,find=-1,d=cur_fg;
3029  if (me)
3030  {
3031    me->clear();
3032    image *im=new image(the_game->ftile_width(),the_game->ftile_height());
3033    int th=the_game->ftile_height()/scale,tw=the_game->ftile_width()/scale;
3034
3035    for (i=0;i<w*h;i++)
3036    {
3037      im->clear();     
3038      the_game->get_fg(pat[i])->im->put_image(im,0,0);
3039      scale_put(im,me->screen,me->x1()+(i%w)*tw,
3040                me->y1()+(i/w)*th,tw,th);
3041      if (d==pat[i])
3042      {
3043        find=i;
3044        me->screen->rectangle(me->x1()+(i%w)*tw,
3045                          me->y1()+(i/w)*th,
3046                          me->x1()+(i%w)*tw+tw-1,
3047                          me->y1()+(i/w)*th+th-1,eh->bright_color());
3048      }
3049    }
3050    delete im;
3051    last_selected=d;
3052  }
3053}
3054
3055#ifdef __POWERPC__
3056#pragma global_optimizer reset
3057#endif
3058
3059void pal_win::handle_event(event &ev)
3060{
3061  int d=cur_fg;
3062
3063  if (d!=last_selected)  // if so see if we need to hilight any of our tiles.
3064  {
3065    int i,dr=0;
3066    for (i=0;i<w*h;i++)
3067    {
3068      if (pat[i]==d || pat[i]==last_selected)
3069        dr=1;
3070    }
3071    if (dr) draw();
3072    last_selected=d;
3073  }
3074
3075  if (ev.window && ev.window==me)
3076  {
3077    switch (ev.type)
3078    {
3079      case EV_MOUSE_BUTTON :
3080      {
3081        if (ev.mouse_button==1)
3082        {         
3083          int selx=(last_demo_mx-me->x-me->x1())/(the_game->ftile_width()/scale),
3084              sely=(last_demo_my-me->y-me->y1())/(the_game->ftile_height()/scale);
3085          if (selx>=0 && sely>=0 && selx<w && sely<h)
3086          {
3087            cur_fg=pat[selx+sely*w];
3088            if (dev_cont->forew)     
3089              ((tile_picker *)dev_cont->forew->
3090               read(DEV_FG_PICKER))->recenter(dev_cont->forew->screen,eh);     
3091          }
3092        } else if (ev.mouse_button==2)
3093        {
3094          if (palettes_locked)
3095            the_game->show_help(symbol_str("pal_lock"));
3096          else
3097          {
3098            int selx=(last_demo_mx-me->x-me->x1())/(the_game->ftile_width()/scale),
3099                sely=(last_demo_my-me->y-me->y1())/(the_game->ftile_height()/scale);
3100            if (selx>=0 && sely>=0 && selx<w && sely<h)
3101            {
3102              pat[selx+sely*w]=cur_fg;
3103              draw();
3104            }
3105          }
3106        }
3107      } break;
3108
3109      case EV_KEY :
3110      {
3111        switch (ev.key)
3112        {
3113          case '+' :
3114          { if (scale>1) 
3115            {
3116              close_window();
3117              scale--;
3118              open_window();
3119            }
3120          } break;
3121          case '-' :
3122          { if (scale<the_game->ftile_height()/2)
3123            {
3124              close_window();
3125              scale++;
3126              open_window();
3127            }
3128          } break;       
3129          case JK_LEFT :
3130          {
3131            if (palettes_locked) the_game->show_help(symbol_str("pal_lock"));
3132            else if (w>1) resize(-1,0);
3133          } break;
3134          case JK_RIGHT :
3135          {
3136            if (palettes_locked) the_game->show_help(symbol_str("pal_lock"));
3137            else
3138              resize(1,0);
3139          } break;
3140          case JK_UP :
3141          {
3142            if (palettes_locked) the_game->show_help(symbol_str("pal_lock"));
3143            else if (h>1) resize(0,-1);
3144          } break;
3145          case JK_DOWN :
3146          {
3147            if (palettes_locked)           
3148              the_game->show_help(symbol_str("pal_lock"));
3149            else
3150              resize(0,1);
3151          } break;       
3152          case JK_ESC : close_window();  break;
3153          case ' ' :
3154          {
3155            long xs,ys,xx,yy;
3156            the_game->ftile_on(me->x,me->y,xs,ys);
3157
3158            for (xx=xs;xx<xs+w;xx++)
3159            {
3160              for (yy=ys;yy<ys+h;yy++)
3161              {       
3162                if (xx>=0 && yy>=0 && xx<current_level->foreground_width() &&
3163                    yy<current_level->foreground_height())
3164                  the_game->put_fg(xx,yy,raise_all ? make_above_tile(pat[xx-xs+(yy-ys)*w]) : pat[xx-xs+(yy-ys)*w] );
3165              }
3166            }
3167          } break;
3168          case 't' :
3169          {
3170            long xs,ys,xx,yy;
3171            the_game->ftile_on(me->x,me->y,xs,ys);
3172            dev_cont->fg_fill(-1,xs,ys,this);
3173          } break;
3174
3175        }
3176      } break;
3177
3178      case EV_CLOSE_WINDOW : close_window(); break;
3179    }
3180  }
3181
3182
3183}
3184
3185
3186void pal_win::resize(int xa, int ya)
3187{
3188  int i,j;
3189  unsigned short *npat;
3190  if (w+xa<1 || y+ya<1) return ;
3191
3192  npat=(unsigned short *)jmalloc(sizeof(unsigned short)*(w+xa)*(h+ya),"resized pal_win");
3193  memset(npat,0,sizeof(unsigned short)*(w+xa)*(h+ya));
3194  for (i=0;i<(w+xa);i++)
3195    for (j=0;j<(h+ya);j++)
3196      if (i+j*w<w*h)
3197        npat[i+j*(w+xa)]=pat[i+j*w];
3198  jfree(pat);
3199  w+=xa;
3200  h+=ya;
3201  pat=npat;
3202  last_selected=-1;
3203  close_window();
3204  open_window();
3205}
3206
3207
3208void pal_win::save(FILE *fp)
3209{
3210  if (me)
3211  {
3212    x=me->x;
3213    y=me->y;
3214  }
3215
3216  fprintf(fp,"(add_palette \"%s\" %d %d %d %d %d ",name,w,h,x,y,scale);
3217  int i;
3218  for (i=0;i<w*h;i++)
3219    fprintf(fp,"%d ",pat[i]&0x7fff);
3220  fprintf(fp,")\n");
3221
3222}
3223
3224FILE *open_FILE(char *filename, char *mode);
3225
3226void dev_controll::save()
3227{
3228  FILE *fp=open_FILE("edit.lsp","w");
3229  if (!fp)
3230    the_game->show_help(symbol_str("no_edit.lsp"));
3231  else
3232  {
3233    fprintf(fp,"(set_zoom %d)\n",the_game->zoom);
3234   
3235    int i;
3236    for (i=0;i<total_pals;i++)
3237    {
3238      pal_wins[i]->save(fp);
3239    }
3240    fprintf(fp,"\n");
3241    fclose(fp);
3242  }
3243
3244}
3245
3246int dev_controll::is_pal_win(jwindow *win)
3247{
3248  int i;
3249  for (i=0;i<total_pals;i++)
3250    if (win==pal_wins[i]->me) return 1;
3251  return 0;
3252}
3253
3254
3255class fill_rec
3256{
3257public :
3258  short x,y;
3259  fill_rec *last;
3260  fill_rec(short X, short Y, fill_rec *Last)
3261  { x=X; y=Y; last=Last; }
3262} ;
3263
3264static int get_color(int color, int x, int y, pal_win *p)
3265{
3266  if (p) 
3267  {
3268    while (x<0) x+=p->width();
3269    while (y<0) y+=p->height();
3270    return p->get_pat(x%p->width(),y%p->height());
3271  }
3272  else return color;
3273}
3274
3275void dev_controll::fg_fill(int color, int x, int y, pal_win *p)
3276{
3277  unsigned short *sl,*above,*below;
3278  fill_rec *recs=NULL,*r;
3279  unsigned short fcolor;
3280  sl=current_level->get_fgline(y);
3281  fcolor=fgvalue(sl[x]);
3282  int startx=x,starty=y;
3283  if (fcolor==color) return ;
3284  do
3285  {
3286    if (recs)
3287    { r=recs;
3288      recs=recs->last;
3289      x=r->x; y=r->y;
3290      delete r;
3291    }
3292    sl=current_level->get_fgline(y);
3293    if (fgvalue(sl[x])==fcolor)
3294    {
3295      while (x>0 && fgvalue(sl[x])==fcolor) x--;
3296      if (fgvalue(sl[x])!=fgvalue(fcolor) && x<current_level->foreground_width()-1) x++;
3297      if (y>0)
3298      {
3299        above=current_level->get_fgline(y-1);
3300        if (fgvalue(above[x])==fcolor)
3301        { r=new fill_rec(x,y-1,recs);
3302          recs=r; 
3303        }
3304      }
3305      if (y<current_level->foreground_height()-1)
3306      {
3307        above=current_level->get_fgline(y+1);
3308        if (above[x]==fcolor)
3309        { r=new fill_rec(x,y+1,recs);
3310          recs=r;
3311        }
3312      }
3313
3314
3315
3316      do
3317      {
3318        sl[x]=get_color(color,x-startx,y-starty,p);
3319        if (y>0)
3320        { above=current_level->get_fgline(y-1);
3321          if (x>0 && fgvalue(above[x-1])!=fgvalue(fcolor) && fgvalue(above[x])==fgvalue(fcolor))
3322          { r=new fill_rec(x,y-1,recs);
3323            recs=r; 
3324          }
3325        }
3326        if (y<current_level->foreground_height()-1)
3327        { below=current_level->get_fgline(y+1);
3328          if (x>0 && fgvalue(below[x-1])!=fgvalue(fcolor) && fgvalue(below[x])==fgvalue(fcolor))
3329          { r=new fill_rec(x,y+1,recs);
3330            recs=r; 
3331          }
3332        }
3333        x++;
3334      } while (fgvalue(sl[x])==fgvalue(fcolor) && x<current_level->foreground_width());
3335      x--;
3336      if (y>0)
3337      {
3338        above=current_level->get_fgline(y-1);
3339        if (fgvalue(above[x])==fgvalue(fcolor))
3340        { r=new fill_rec(x,y-1,recs);
3341          recs=r;
3342        }
3343      }
3344      if (y<current_level->foreground_height()-1)
3345      {
3346        above=current_level->get_fgline(y+1);
3347        if (fgvalue(above[x])==fgvalue(fcolor))
3348        { r=new fill_rec(x,y+1,recs);
3349          recs=r;
3350        }
3351      }
3352    }
3353  } while (recs);
3354  the_game->need_refresh();
3355}
3356
3357int get_char_mem(int type, int print)
3358{
3359  int t=0;
3360  for (int j=0;j<MAX_STATE;j++)
3361  {
3362    if (figures[type]->has_sequence((character_state)j))
3363    {
3364      int s=figures[type]->get_sequence((character_state)j)->size();
3365      if (print)
3366        dprintf("(%s=%d)",state_names[j],s);
3367      t+=s;
3368    }
3369  }
3370  if (print)
3371    dprintf("\ntotal=%d\n",t);     
3372  return t;
3373}
3374
3375void dev_controll::show_char_mem(char *name)
3376{
3377  int find=-1;
3378  for (int i=0;i<total_objects;i++)
3379  {
3380    if (!strcmp(name,object_names[i]))
3381      find=i;
3382  }
3383  if (find<0)
3384    dprintf("No character '%s' defined\n",name);
3385  else 
3386    get_char_mem(find,1);
3387 
3388}
3389
3390void dev_controll::show_mem()
3391{
3392  int t=0,s=0;
3393  int i=0;
3394  for (;i<nforetiles;i++)
3395  {
3396    if (foretiles[i]>=0)
3397    {
3398      if (cash.loaded(foretiles[i]))
3399      {
3400        t++;     
3401        s+=cash.foret(foretiles[i])->size();
3402      }
3403    }
3404  }
3405  dprintf("%d loaded foretiles=%d bytes\n",t,s);
3406
3407  t=0; s=0;
3408  for (i=0;i<nbacktiles;i++)
3409  {
3410    if (backtiles[i]>=0)
3411    {
3412      if (cash.loaded(foretiles[i]))
3413      {
3414        t++;
3415        s+=cash.backt(backtiles[i])->size();
3416      }
3417    }
3418  }
3419  dprintf("%d loaded backtiles=%d bytes\n",t,s);
3420 
3421  t=0; s=0;
3422  for (i=0;i<total_objects;i++)
3423  {
3424    t++;
3425    s+=get_char_mem(i,0);
3426  }
3427  dprintf("%d character=%d bytes\n",t,s);
3428
3429}
3430
3431
3432
3433void dev_cleanup()
3434{
3435  if (start_edit) 
3436    prop->save("defaults.prp");
3437  delete prop;
3438  if (listable_objs)
3439  {
3440    jfree(listable_objs);
3441    listable_objs=NULL;
3442  }
3443  crc_man.clean_up();
3444
3445}
3446
3447
3448
3449struct pmi
3450{
3451  char *name;
3452  int id;
3453  char *on_off;
3454  int key;
3455} ;
3456
3457
3458static pmi fm[]={
3459          {"menu1_load",         ID_LEVEL_LOAD,NULL,-1},
3460          {NULL,0,NULL,-1},
3461          {"menu1_save",     ID_LEVEL_SAVE,NULL,-1},
3462          {"menu1_saveas",      ID_LEVEL_SAVEAS,NULL,-1},
3463          {"menu1_savegame",          ID_GAME_SAVE,NULL,-1},
3464          {"menu1_new",          ID_LEVEL_NEW,NULL,-1},
3465          {"menu1_resize",         ID_LEVEL_RESIZE,NULL,-1},
3466          {NULL,0,NULL,-1},
3467          {"menu1_suspend",ID_SUSPEND,NULL,-1},
3468          {"menu1_toggle",ID_PLAY_MODE,NULL,-1},
3469          {NULL,0,NULL,-1},
3470          {"menu1_savepal",ID_EDIT_SAVE,NULL,-1},
3471//        {"menu1_startc",ID_CACHE_PROFILE,NULL,-1},
3472//        {"menu1_endc",ID_CACHE_PROFILE_END,NULL,-1},
3473          {NULL,0,NULL,-1},     
3474          {"menu1_quit",      ID_QUIT,NULL,-1},
3475          {NULL,-1,NULL,-1}
3476        };
3477
3478
3479static pmi em[]={
3480  {"menu2_light",               ID_TOGGLE_LIGHT,NULL,-1},
3481  {"menu2_scroll",            ID_SET_SCROLL,NULL,-1},
3482  {"menu2_center",       ID_CENTER_PLAYER,NULL,-1},
3483  {"menu2_addpal",                ID_ADD_PALETTE,NULL,-1},
3484  {"menu2_delay",          ID_TOGGLE_DELAY,NULL,-1},
3485
3486  {"menu2_god",                   ID_GOD_MODE,NULL,-1},
3487  {"menu2_clear",          ID_CLEAR_WEAPONS,NULL,-1},
3488  {"menu2_mscroll",               ID_MOUSE_SCROLL,&mouse_scrolling,-1},
3489  {"menu2_lock",       ID_LOCK_PALETTES,&palettes_locked,-1},
3490  {"menu2_raise",       ID_RAISE_ALL,&raise_all,-1},
3491  {"menu2_names",        ID_TOGGLE_NAMES,&show_names,-1},
3492
3493  {NULL,0,NULL,-1},
3494  {"menu2_map",      ID_TOGGLE_MAP,NULL,-1},
3495//  {"Shrink to 320x200 (F10)",    ID_SMALL_MODE,NULL,-1},
3496  {"menu2_view",        ID_DISABLE_VIEW_SHIFT,&view_shift_disabled,-1},
3497//  {"Ultra Smooth draw (U)",      ID_INTERPOLATE_DRAW,  &interpolate_draw,'U'},
3498  {"menu2_alight",      ID_DISABLE_AUTOLIGHT, &disable_autolight,'A'},
3499  {"menu2_fps",         ID_SHOW_FPS,          &fps_on,-1},
3500//  {NULL,0,NULL,-1},
3501//  {"Record demo",                ID_RECORD_DEMO,NULL,-1},
3502//  {"Play demo",                  ID_PLAY_DEMO,NULL,-1},
3503  {NULL,-1,NULL,-1}
3504};
3505
3506
3507
3508// Window Menus
3509static pmi wm[]={
3510          {"menu3_fore",    ID_WIN_FORE,    &forew_on,-1},
3511          {"menu3_back",    ID_WIN_BACK,    &backw_on,-1},
3512          {"menu3_layers",    ID_WIN_LAYERS,  &show_menu_on,-1},
3513          {"menu3_light",    ID_WIN_LIGHTING,&ledit_on,-1},
3514          {"menu3_pal",    ID_WIN_PALETTES,&pmenu_on,-1},
3515          {"menu3_objs",    ID_WIN_OBJECTS, &omenu_on,-1},
3516//        {"menu3_console",    ID_WIN_CONSOLE, &commandw_on,-1},
3517          {"menu3_toolbar",    ID_WIN_TOOLBAR, &tbw_on,-1},
3518//        {"Search      (s)",    ID_SEARCH,      &searchw_on,-1},
3519          {"menu3_prof",    ID_PROFILE,     &profile_on,-1},
3520          {"menu3_save",     ID_SAVE_WINDOWS,NULL,-1},
3521          {NULL,-1,NULL,-1}
3522        };
3523
3524
3525
3526/*
3527static pmi fm[]={
3528          {"Load Level",         ID_LEVEL_LOAD,NULL,-1},
3529          {NULL,0,NULL,-1},
3530          {"Save Level (S)",     ID_LEVEL_SAVE,NULL,-1},
3531          {"Save level as",      ID_LEVEL_SAVEAS,NULL,-1},
3532          {"Save game",          ID_GAME_SAVE,NULL,-1},
3533          {"New level",          ID_LEVEL_NEW,NULL,-1},
3534          {"Resize map",         ID_LEVEL_RESIZE,NULL,-1},
3535          {NULL,0,NULL,-1},
3536          {"Suspend non-players",ID_SUSPEND,NULL,-1},
3537          {"Play mode toggle (TAB)",ID_PLAY_MODE,NULL,-1},
3538          {NULL,0,NULL,-1},
3539          {"Save Palettes         ",ID_EDIT_SAVE,NULL,-1},
3540          {"Start cache profile   ",ID_CACHE_PROFILE,NULL,-1},
3541          {"End cache profile     ",ID_CACHE_PROFILE_END,NULL,-1},
3542          {NULL,0,NULL,-1},     
3543          {"Quit      (Q)",      ID_QUIT,NULL,-1},
3544          {NULL,-1,NULL,-1}
3545        };
3546
3547
3548static pmi em[]={
3549  {"Toggle light",               ID_TOGGLE_LIGHT,NULL,-1},
3550  {"Set scroll rate",            ID_SET_SCROLL,NULL,-1},
3551  {"Center on player   (c)",       ID_CENTER_PLAYER,NULL,-1},
3552  {"Add palette",                ID_ADD_PALETTE,NULL,-1},
3553  {"Toggle Delays      (D)",          ID_TOGGLE_DELAY,NULL,-1},
3554
3555  {"God mode",                   ID_GOD_MODE,NULL,-1},
3556  {"Clear weapons (z)",          ID_CLEAR_WEAPONS,NULL,-1},
3557  {"Mouse scroll",               ID_MOUSE_SCROLL,&mouse_scrolling,-1},
3558  {"Lock palette windows",       ID_LOCK_PALETTES,&palettes_locked,-1},
3559  {"Raise all foreground",       ID_RAISE_ALL,&raise_all,-1},
3560  {"Toggle object names",        ID_TOGGLE_NAMES,&show_names,-1},
3561
3562  {NULL,0,NULL,-1},
3563  {"Toggle map        (m)",      ID_TOGGLE_MAP,NULL,-1},
3564//  {"Shrink to 320x200 (F10)",    ID_SMALL_MODE,NULL,-1},
3565  {"Disable view shifts",        ID_DISABLE_VIEW_SHIFT,&view_shift_disabled,-1},
3566//  {"Ultra Smooth draw (U)",      ID_INTERPOLATE_DRAW,  &interpolate_draw,'U'},
3567  {"Disable Autolight (A)",      ID_DISABLE_AUTOLIGHT, &disable_autolight,'A'},
3568  {"Show FPS/Obj count",         ID_SHOW_FPS,          &fps_on,-1},
3569//  {NULL,0,NULL,-1},
3570//  {"Record demo",                ID_RECORD_DEMO,NULL,-1},
3571//  {"Play demo",                  ID_PLAY_DEMO,NULL,-1},
3572  {NULL,-1,NULL,-1}
3573};
3574
3575
3576
3577// Window Menus
3578static pmi wm[]={
3579          {"Foreground  (f)",    ID_WIN_FORE,    &forew_on,-1},
3580          {"Background  (b)",    ID_WIN_BACK,    &backw_on,-1},
3581          {"Draw layers (L)",    ID_WIN_LAYERS,  &show_menu_on,-1},
3582          {"Lighting    (l)",    ID_WIN_LIGHTING,&ledit_on,-1},
3583          {"Palettes    (p)",    ID_WIN_PALETTES,&pmenu_on,-1},
3584          {"Objects     (o)",    ID_WIN_OBJECTS, &omenu_on,-1},
3585          {"Console     (/)",    ID_WIN_CONSOLE, &commandw_on,-1},
3586          {"Tool Bar    (a)",    ID_WIN_TOOLBAR, &tbw_on,-1},
3587//        {"Search      (s)",    ID_SEARCH,      &searchw_on,-1},
3588          {"Profile     (P)",    ID_PROFILE,     &profile_on,-1},
3589          {"Save positions",     ID_SAVE_WINDOWS,NULL,-1},
3590          {NULL,-1,NULL,-1}
3591        };
3592
3593*/
3594       
3595static pmenu_item *i_recurse(pmi *first)
3596{
3597  if (first->id==-1)
3598    return NULL;
3599  else 
3600    return new pmenu_item(first->id,first->name ? symbol_str(first->name) : 0,first->on_off,first->key,i_recurse(first+1));
3601}
3602   
3603static pmenu *make_menu(int x, int y)
3604{
3605  return new pmenu(x,y,
3606         new pmenu_item(symbol_str("file_top"),new psub_menu(i_recurse(fm),NULL),
3607         new pmenu_item(symbol_str("edit_top"),new psub_menu(i_recurse(em),NULL),
3608         new pmenu_item(symbol_str("window_top"),new psub_menu(i_recurse(wm),NULL),NULL))),screen,eh);
3609}
3610
3611
3612
3613void toggle_edit_mode()
3614{
3615  dev=dev^EDIT_MODE;
3616  if (dev&EDIT_MODE)
3617  {
3618    eh->set_mouse_shape(cash.img(c_normal)->copy(),1,1);
3619    pal->load();
3620  }
3621  else
3622  {
3623    if (dev&MAP_MODE) dev-=MAP_MODE;                        // no map mode while playing!
3624    eh->set_mouse_shape(cash.img(c_target)->copy(),8,8);
3625  }
3626  if ((dev&EDIT_MODE) && !dev_menu)
3627  {
3628    dev_menu=make_menu(0,yres-eh->font()->height()-5);   
3629  }
3630  else if (!(dev&EDIT_MODE) && dev_menu)
3631  {
3632    delete dev_menu;
3633    dev_menu=NULL;
3634  }
3635}
3636
3637
3638int dev_controll::ok_to_scroll()
3639{
3640  if (state==DEV_MOVE_LIGHT || state==DEV_MOVE_OBJECT || mouse_scrolling) return 1;
3641  else return 0;
3642}
3643
3644dev_controll::~dev_controll()
3645{
3646  for (int i=0;i<total_pals;i++)
3647    delete pal_wins[i];
3648  if (total_pals)
3649    jfree(pal_wins);
3650}
3651
3652
3653
3654pal_win::~pal_win()
3655{
3656  jfree(pat);
3657  jfree(name);
3658}
Note: See TracBrowser for help on using the repository browser.