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

Last change on this file since 655 was 655, checked in by Sam Hocevar, 11 years ago

imlib: refactor a few image methods so that they use vec2i.

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