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

Last change on this file since 650 was 650, checked in by Sam Hocevar, 12 years ago

imlib: make some Image methods use vec2i.

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