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

Last change on this file since 682 was 682, checked in by Sam Hocevar, 8 years ago

core: rename vec2i to ivec2 and update matrix.h from Lol Engine.

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