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

Last change on this file since 512 was 512, checked in by Sam Hocevar, 7 years ago

imlib: use vec2i for image::size and unroll all necessary changes
everywhere else in the code.

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