source: abuse/trunk/src/imlib/input.cpp @ 655

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

imlib: refactor a few image methods so that they use vec2i.

File size: 12.1 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com, by
8 *  Jonathan Clark, or by Sam Hocevar.
9 */
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <string.h>
16
17#include "common.h"
18
19#include "input.h"
20
21void button::remap(Filter *f)
22{
23  if (visual)
24  {
25    f->Apply(visual);
26    if (pressed)
27      f->Apply(pressed);
28  }
29}
30
31void button_box::press_button(int id)      // if button box doesn't contain id, nothing happens
32{
33}
34
35void button_box::remap(Filter *f)
36{
37  for (button *b=buttons; b; b=(button *)b->next)
38    b->remap(f);
39}
40
41ifield *button_box::find(int search_id)
42{
43  if (search_id==id) return this;
44  for (ifield *i=(ifield *)buttons; i; i=i->next)
45    if (search_id==i->id) return i;
46  return NULL;
47}
48
49button_box::button_box(int X, int Y, int ID, int MaxDown, button *Buttons, ifield *Next)
50{
51  x=X; y=Y; id=ID; next=Next;
52  buttons=Buttons;
53  maxdown=MaxDown;
54  if (buttons && maxdown) buttons->push();  // the first button is automatically selected!
55}
56
57button_box::~button_box()
58{
59  while (buttons)
60  {
61    button *b=buttons;
62    buttons=(button *)buttons->next;
63    delete b;
64  }
65}
66
67void button_box::area(int &x1, int &y1, int &x2, int &y2)
68{
69  button *b=buttons;
70  if (!b) return ;
71  else
72  {
73    b->area(x1,y1,x2,y2);
74    int xp1,yp1,xp2,yp2;
75    for (b=(button *)b->next; b; b=(button *)b->next)
76    {
77      b->area(xp1,yp1,xp2,yp2);
78      if (xp1<x1) x1=xp1;
79      if (xp2>x2) x2=xp2;
80      if (yp1<y1) y1=yp1;
81      if (yp2>y2) y2=yp2;
82    }
83  }
84}
85
86void button_box::draw_first(image *screen)
87{
88  for (button *b=buttons; b; b=(button *)b->next)
89    b->draw_first(screen);
90}
91
92void button_box::draw(int active, image *screen)
93{
94  return ;
95}
96
97void button_box::move(int newx, int newy)
98{
99    for(button * b = buttons; b; b = (button *)b->next)
100        b->move(newx + b->x, newy + b->y);
101    x = newx;
102    y = newy;
103}
104
105char *button_box::read()
106{
107  for (button *b=buttons; b; b=(button *)b->next)
108  {
109    if (*((int *)b->read())==0)
110      return (char *)b;
111  }
112  return NULL;
113}
114
115void button_box::handle_event(Event &ev, image *screen, InputManager *im)
116{
117  switch (ev.type)
118  {
119    case EV_MOUSE_BUTTON :
120    {
121      int x1,y1,x2,y2;
122      int found=0;
123      for (button *b=buttons; !found && b; b=(button *)b->next)  // see if the user clicked on a button
124      {
125    b->area(x1,y1,x2,y2);
126    if (ev.mouse_move.x>=x1 && ev.mouse_move.x<=x2 &&
127        ev.mouse_move.y>=y1 && ev.mouse_move.y<=y2)
128    {
129      b->handle_event(ev,screen,im);
130
131      int total=0;
132      button *b2=buttons;
133      for (; b2; b2=(button *)b2->next)
134        if (*((int *)b2->read())==0)
135          total++;
136
137      if (*((int *)b->read())==0)  // did the user press or release the button
138      {
139        if (total>maxdown)
140        {
141          for (b2=buttons; total>maxdown && b2; b2=(button *)b2->next)
142            if ((b!=b2 || maxdown==0) && *((int *)b2->read())==0)
143        {
144          total--;
145          b2->push();
146          b2->draw_first(screen);
147        }
148        }
149        b->draw_first(screen);
150      } else if (total==0 && maxdown)
151        b->push();    // don't let the user de-press a button if non others are selected.
152
153      found=1; // don't look at anymore buttons
154
155    }
156      }
157    } break;
158  }
159}
160
161
162void button_box::add_button(button *b)
163{
164  b->next=buttons;
165  buttons=b;
166}
167
168
169void button_box::arrange_left_right()
170{
171  button *b=buttons;
172  int x_on=x,x1,y1,x2,y2;
173  for (; b; b=(button *)b->next)
174  {
175    b->area(x1,y1,x2,y2);
176    b->x=x_on;
177    b->y=y;
178    x_on+=(x2-x1+1)+1;
179  }
180}
181
182void button_box::arrange_up_down()
183{
184  button *b=buttons;
185  int y_on=y,x1,y1,x2,y2;
186  for (; b; b=(button *)b->next)
187  {
188    b->area(x1,y1,x2,y2);
189    b->y=y_on;
190    b->x=x;
191    y_on+=(y2-y1+1)+1;
192  }
193}
194
195void button::change_visual(image *new_visual)
196{
197  CHECK(visual);
198  visual=new_visual;
199}
200
201void button::area(int &x1, int &y1, int &x2, int &y2)
202{
203  x1=x; y1=y;
204  if (pressed)
205  {
206    x2=x+pressed->Size().x-1;
207    y2=y+pressed->Size().y-1;
208  }
209  else
210  {
211    if (text)
212    {
213      x2=x+wm->font()->width()*strlen(text)+6;
214      y2=y+wm->font()->height()+6;
215    } else
216    {
217      x2=x+6+visual->Size().x;
218      y2=y+6+visual->Size().y;
219    }
220  }
221}
222
223
224button::button(int X, int Y, int ID, char const *Text, ifield *Next)
225{
226  x=X; y=Y; id=ID;
227  act_id=-1;
228  text = strdup(Text);
229  up=1; next=Next; act=0;
230  visual=NULL;
231  pressed=NULL;
232}
233
234
235button::button(int X, int Y, int ID, image *vis, ifield *Next)
236{ x=X; y=Y; id=ID; text=NULL;
237  act_id=-1;
238  visual=vis; up=1; next=Next; act=0;
239  pressed=NULL;
240}
241
242button::button(int X, int Y, int ID, image *Depressed, image *Pressed, image *active, ifield *Next)
243{ x=X; y=Y; id=ID; text=NULL;
244  act_id=-1;
245  visual=Depressed; up=1; next=Next; act=0;
246  pressed=Pressed;
247  act_pict=active;
248}
249
250
251void text_field::change_data(char const *new_data, int new_cursor, // cursor==-1, does not change it.
252                 int active, image *screen)
253{
254  if (strlen(format)<strlen(new_data))
255    data=(char *)realloc(data,strlen(new_data));
256
257  strcpy(data,new_data);
258  if (new_cursor!=-1)
259    cur=new_cursor;
260  draw_first(screen);
261  draw(active,screen);
262}
263
264char *text_field::read()
265{
266  while (*data && data[strlen(data)-1]==' ') data[strlen(data)-1]=0;
267  return data;
268}
269
270void text_field::handle_event(Event &ev, image *screen, InputManager *im)
271{
272  int xx;
273  if (ev.type==EV_KEY)
274  {
275    switch (ev.key)
276    {
277      case JK_LEFT : if (cur) { draw_cur(wm->dark_color(),screen); cur--;
278                           draw_cur(wm->bright_color(),screen); } break;
279      case JK_RIGHT : if (cur<(int)strlen(format)-1) { draw_cur(wm->dark_color(),screen); cur++;
280                           draw_cur(wm->bright_color(),screen); } break;
281      case JK_END : if (cur!=last_spot())
282                          { draw_cur(wm->dark_color(),screen); cur=last_spot();
283                            if (cur==(int)strlen(format)-1) cur--;
284                           draw_cur(wm->bright_color(),screen); } break;
285      case JK_HOME : if (cur)
286                          { draw_cur(wm->dark_color(),screen); cur=0;
287                           draw_cur(wm->bright_color(),screen); } break;
288      case JK_BACKSPACE : if (cur)
289         { draw_cur(wm->dark_color(),screen); cur--;
290           for (xx=cur; xx<(int)strlen(format)-1; xx++)
291             data[xx]=data[xx+1];
292           data[strlen(format)-1]=' ';
293           draw_text(screen);
294           draw_cur(wm->bright_color(),screen);
295           wm->Push(new Event(id,(char *)this));
296         } break;
297      default : if (ev.key>=' ' && ev.key<='~')
298         {
299           draw_cur(wm->dark_color(),screen);
300           for (xx=strlen(format)-1; xx>cur && xx>0; xx--)
301             data[xx]=data[xx-1];
302           data[cur]=ev.key;
303           if (cur<(int)strlen(format)-1)
304             cur++;
305       data[strlen(format)]=0;
306           draw_text(screen);
307           draw_cur(wm->bright_color(),screen);
308           wm->Push(new Event(id,(char *)this));
309         } break;
310    }
311  }
312}
313
314void text_field::draw(int active, image *screen)
315{
316  if (active)
317  {
318    screen->Rectangle(vec2i(xstart(), y), vec2i(xend(), yend()),
319                      wm->bright_color());
320    draw_cur(wm->bright_color(),screen);
321  }
322  else
323  {
324    screen->Rectangle(vec2i(xstart(), y), vec2i(xend(), yend()),
325                      wm->dark_color());
326    draw_cur(wm->dark_color(),screen);
327  }
328}
329
330void text_field::area(int &x1, int &y1, int &x2, int &y2)
331{
332  x1=x; y1=y;
333  x2=xend();
334  y2=yend();
335}
336
337text_field::text_field(int X, int Y, int ID, char const *Prompt,
338                       char const *Format, char const *Data, ifield *Next)
339{
340  int slen=(strlen(Format)>strlen(Data) ? strlen(Format) : strlen(Data));
341
342  x=X; y=Y; id=ID;
343  prompt = strdup(Prompt);
344  format=strcpy((char *)malloc(slen+1),Format);
345  data=strcpy((char *)malloc(slen+1),Data);
346  cur=strlen(data);
347  while (cur && data[cur-1]==' ') cur--;
348  next=Next;
349}
350
351text_field::text_field(int X, int Y, int ID, char const *Prompt,
352                       char const *Format, double Data, ifield *Next)
353{
354  char num[20];
355  sprintf(num,"%g",Data);
356  int slen=(strlen(Format)>strlen(num) ? strlen(Format) : strlen(num));
357  x=X; y=Y; id=ID;
358  prompt = strdup(Prompt);
359  format=strcpy((char *)malloc(slen+1),Format);
360  data=strcpy((char *)malloc(slen+1),num);
361  cur=strlen(num);
362  while (cur && data[cur-1]==' ') cur--;
363  next=Next;
364}
365
366
367void button::push()
368{ up=!up; }
369
370void button::handle_event(Event &ev, image *screen, InputManager *im)
371{
372  if ((ev.type==EV_KEY && ev.key==13) || (ev.type==EV_MOUSE_BUTTON &&
373                                         ev.mouse_button))
374  {
375    int  x1,y1,x2,y2;
376    area(x1,y1,x2,y2);
377    up=!up;
378    draw_first(screen);
379    draw(act,screen);
380    wm->Push(new Event(id,(char *)this));
381  }
382}
383
384void button::draw(int active, image *screen)
385{
386  int x1,y1,x2,y2,color=(active ? wm->bright_color() : wm->medium_color());
387  area(x1,y1,x2,y2);
388  if (active!=act  && act_id!=-1 && active)
389    wm->Push(new Event(act_id,NULL));
390
391  if (pressed)
392  {
393    if (up)
394    {
395      if (!active)
396        screen->PutImage(visual, vec2i(x, y));
397      else
398        screen->PutImage(pressed, vec2i(x, y));
399    } else screen->PutImage(act_pict, vec2i(x, y));
400  }
401  else
402  {
403    screen->Rectangle(vec2i(x1 + 2, y1 + 2), vec2i(x2 - 2, y2 - 2), color);
404    act = active;
405  }
406}
407
408void button::draw_first(image *screen)
409{
410  if (pressed)
411    draw(0,screen);
412  else
413  {
414
415    int x1,y1,x2,y2;
416    area(x1,y1,x2,y2);
417
418
419    if (up)
420    {
421      screen->Rectangle(vec2i(x1, y1), vec2i(x2, y2), wm->black());
422//      screen->widget_bar(,wm->bright_color(),wm->medium_color(),wm->dark_color());
423      screen->WidgetBar(vec2i(x1 + 1, y1 + 1), vec2i(x2 - 1, y2 - 1),
424                        wm->bright_color(),wm->medium_color(),wm->dark_color());
425      if (text)
426      {
427        wm->font()->put_string(screen,x+4,y+5,text,wm->black());
428        wm->font()->put_string(screen,x+3,y+4,text);
429      }
430      else screen->PutImage(visual, vec2i(x + 3, y + 3), 1);
431    } else
432    {
433      screen->Line(vec2i(x1, y1), vec2i(x2, y1), wm->dark_color());
434      screen->Line(vec2i(x1, y1), vec2i(x1, y2), wm->dark_color());
435      screen->Line(vec2i(x2, y1 + 1), vec2i(x2, y2), wm->bright_color());
436      screen->Line(vec2i(x1 + 1, y2), vec2i(x2, y2), wm->bright_color());
437      screen->Bar(vec2i(x1 + 1, y1 + 1), vec2i(x2 - 1, y2 - 1),
438                  wm->medium_color());
439      if (visual)
440        screen->PutImage(visual, vec2i(x1 + 3, y1 + 3), 1);
441      else
442      {
443        wm->font()->put_string(screen,x+4,y+5,text,wm->black());
444        wm->font()->put_string(screen,x+3,y+4,text);
445      }
446    }
447  }
448}
449
450void text_field::draw_first(image *screen)
451{
452  wm->font()->put_string(screen,x,y+3,prompt);
453  screen->Bar(vec2i(xstart(), y), vec2i(xend(), yend()), wm->dark_color());
454  wm->font()->put_string(screen,xstart()+1,y+3,data);
455}
456
457
458void text_field::draw_cur(int color, image *screen)
459{
460  screen->Bar(vec2i(xstart() + cur * wm->font()->width() + 1, yend() - 2),
461              vec2i(xstart() + (cur + 1) * wm->font()->width(), yend() - 1),
462              color);
463}
464
465
466
467info_field::info_field(int X, int Y, int ID, char const *info, ifield *Next)
468{
469  x = X; y = Y; id = ID; next = Next;
470  text = strdup(info);
471  w = -1;
472}
473
474
475void info_field::area(int &x1, int &y1, int &x2, int &y2)
476{
477  if (w==-1)     // if we haven't calculated this yet
478  {
479    int fw=wm->font()->width(),fh=wm->font()->height(),maxw=0;
480    char *info=text;
481    for (w=fw,h=fh+1; *info; info++)
482    {
483      if (w>maxw) maxw=w;
484      if (*info=='\n')
485      {
486    h+=fh+1;
487    w=1;
488      }
489      else w+=fw;
490    }
491    w=maxw;
492  }
493  x1=x;
494  y1=y;
495  x2=x+w;
496  y2=y+h;
497}
498
499void info_field::put_para(image *screen, char const *st, int dx, int dy,
500              int xspace, int yspace, JCFont *font, int color)
501{
502  int ox=dx;
503  while (*st)
504  {
505    if (*st=='\n')
506    {
507      dx=ox;
508      dy+=yspace;
509    }
510    else
511    {
512      font->put_char(screen,dx,dy,*st,color);
513      dx+=xspace;
514    }
515    st++;
516  }
517}
518
519void info_field::draw_first(image *screen)
520{
521  put_para(screen,text,x+1,y+1,wm->font()->width(),wm->font()->height(),wm->font(),wm->black());
522  put_para(screen,text,x,y,wm->font()->width(),wm->font()->height(),wm->font(),wm->bright_color());
523}
524
525
526
527
Note: See TracBrowser for help on using the repository browser.