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

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

imlib: refactor dirty_rect clipping coordiantes so that the upper
bound is no longer inclusive. It will make things easier in the future.

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