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

Last change on this file since 106 was 106, checked in by Sam Hocevar, 15 years ago
  • Rename the "eh" variable to "wm" because it's a window manager, not an event handler.
  • No longer pass the window manager to functions, there's only one.

Inspired by Win32 Abuse changelog for January 28, 2001:

  • Starting work on singleton code; will get rid of all

references to an arbitrary window_manager* because
there's only going to be one, and it's not ever
going to change.

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