source: abuse/tags/pd/macabuse/src/dev.c @ 608

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