source: abuse/trunk/src/dev.cpp @ 48

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