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

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

imlib: image::Pixel and image::PutPixel? now use vec2i arguments.

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