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

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