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

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