ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/DC/UI.pm
Revision: 1.17
Committed: Sat Apr 8 13:34:19 2006 UTC (18 years, 1 month ago) by elmex
Branch: MAIN
Changes since 1.16: +8 -4 lines
Log Message:
semantic fix

File Contents

# User Rev Content
1 elmex 1.6 package Crossfire::Client::Widget;
2 root 1.8
3 elmex 1.1 use strict;
4 elmex 1.11 use SDL::OpenGL;
5     use SDL::OpenGL::Constants;
6 elmex 1.1
7     our $FOCUS; # the widget with current focus
8 elmex 1.13 our @ACTIVE_WIDGETS;
9 elmex 1.1
10     # class methods for events
11     sub feed_sdl_key_down_event { $FOCUS->key_down ($_[0]) if $FOCUS }
12     sub feed_sdl_key_up_event { $FOCUS->key_up ($_[0]) if $FOCUS }
13     sub feed_sdl_button_down_event { $FOCUS->button_down ($_[0]) if $FOCUS }
14     sub feed_sdl_button_up_event { $FOCUS->button_up ($_[0]) if $FOCUS }
15    
16     sub new {
17     my $class = shift;
18 root 1.10
19     bless { @_ }, $class
20 elmex 1.1 }
21    
22 elmex 1.2 sub activate {
23 elmex 1.13 push @ACTIVE_WIDGETS, $_[0];
24 elmex 1.2 }
25 root 1.4
26 elmex 1.2 sub deactivate {
27 elmex 1.13 @ACTIVE_WIDGETS =
28     sort { $a->{z} <=> $b->{z} }
29     grep { $_ != $_[0] }
30     @ACTIVE_WIDGETS;
31 elmex 1.2 }
32    
33 root 1.14 sub size_request {
34     die "size_request is abtract";
35     }
36    
37 elmex 1.1 sub focus_in {
38     my ($widget) = @_;
39     $FOCUS = $widget;
40     }
41 root 1.4
42 elmex 1.1 sub focus_out {
43     my ($widget) = @_;
44     }
45 root 1.4
46 elmex 1.1 sub key_down {
47     my ($widget, $sdlev) = @_;
48     }
49 root 1.4
50 elmex 1.1 sub key_up {
51     my ($widget, $sdlev) = @_;
52     }
53 root 1.4
54 elmex 1.1 sub button_down {
55     my ($widget, $sdlev) = @_;
56     }
57 root 1.4
58 elmex 1.1 sub button_up {
59     my ($widget, $sdlev) = @_;
60     }
61 root 1.4
62 elmex 1.15 sub w { $_[0]->{w} }
63     sub h { $_[0]->{h} }
64 elmex 1.11 sub x { $_[0]->{x} = $_[1] if $_[1]; $_[0]->{x} }
65     sub y { $_[0]->{y} = $_[1] if $_[1]; $_[0]->{y} }
66 elmex 1.13 sub z { $_[0]->{z} = $_[1] if $_[1]; $_[0]->{z} }
67 elmex 1.11
68 elmex 1.1 sub draw {
69 elmex 1.11 my ($self) = @_;
70    
71     glPushMatrix;
72 root 1.12 glTranslate $self->{x}, $self->{y}, 0;
73 elmex 1.11 $self->_draw;
74     glPopMatrix;
75     }
76    
77     sub _draw {
78 elmex 1.1 my ($widget) = @_;
79     }
80 root 1.4
81 elmex 1.1 sub bbox {
82     my ($widget) = @_;
83     }
84 elmex 1.2
85 elmex 1.15 package Crossfire::Client::Widget::Container;
86    
87     our @ISA = Crossfire::Client::Widget::;
88    
89     use SDL::OpenGL;
90    
91     sub add { $_[0]->{child} = $_[1] }
92     sub get { $_[0]->{child} }
93    
94     sub size_request { $_[0]->{child}->size_request if $_[0]->{child} }
95    
96     sub _draw { die "Containers can't be drawn!" }
97    
98     package Crossfire::Client::Widget::Frame;
99    
100     our @ISA = Crossfire::Client::Widget::Container::;
101    
102     use SDL::OpenGL;
103    
104     sub size_request {
105     my ($self) = @_;
106     my $chld = $self->get
107     or return (0, 0);
108     map { $_ + 4 } $chld->size_request;
109     }
110    
111     sub _draw {
112     my ($self) = @_;
113    
114     my $chld = $self->get;
115    
116     my ($w, $h) = $chld->size_request;
117    
118     glColor 1, 0, 0;
119     glBegin GL_QUADS;
120     glTexCoord 0, 0; glVertex 0 , 0;
121     glTexCoord 0, 1; glVertex 0 , $h + 4;
122     glTexCoord 1, 1; glVertex $w + 4 , $h + 4;
123     glTexCoord 1, 0; glVertex $w + 4 , 0;
124     glEnd;
125    
126     glPushMatrix;
127     glTranslate (2, 2, 0);
128     $chld->_draw;
129     glPopMatrix;
130     }
131    
132     package Crossfire::Client::Widget::Table;
133    
134     our @ISA = Crossfire::Client::Widget::Container::;
135    
136     use SDL::OpenGL;
137    
138     sub add {
139     my ($self, $x, $y, $chld) = @_;
140     $self->{childs}[$y][$x] = $chld;
141     }
142    
143     sub max_row_height {
144     my ($self, $row) = @_;
145    
146     my $hs = 0;
147     for (my $xi = 0; $xi <= $#{$self->{childs}->[$row] || []}; $xi++) {
148     my $c = $self->{childs}->[$row]->[$xi];
149 elmex 1.17 if ($c) {
150     my ($w, $h) = $c->size_request;
151     if ($hs < $h) { $hs = $h }
152     }
153 elmex 1.15 }
154     return $hs;
155     }
156    
157     sub max_col_width {
158     my ($self, $col) = @_;
159    
160     my $ws = 0;
161     for (my $yi = 0; $yi <= $#{$self->{childs} || []}; $yi++) {
162     my $c = ($self->{childs}->[$yi] || [])->[$col];
163 elmex 1.17 if ($c) {
164     my ($w, $h) = $c->size_request;
165     if ($ws < $w) { $ws = $w }
166     }
167 elmex 1.15 }
168     return $ws;
169     }
170    
171     sub size_request {
172     my ($self) = @_;
173    
174     my ($hs, $ws) = (0, 0);
175    
176     for (my $yi = 0; $yi <= $#{$self->{childs}}; $yi++) {
177     $hs += $self->max_row_height ($yi);
178     }
179    
180     for (my $yi = 0; $yi <= $#{$self->{childs}}; $yi++) {
181     my $wm = 0;
182     for (my $xi = 0; $xi <= $#{$self->{childs}->[$yi]}; $xi++) {
183     $wm += $self->max_col_width ($xi)
184     }
185     if ($ws < $wm) { $ws = $wm }
186     }
187    
188     return ($ws, $hs);
189     }
190    
191     sub _draw {
192     my ($self) = @_;
193    
194     my $y = 0;
195     for (my $yi = 0; $yi <= $#{$self->{childs}}; $yi++) {
196     my $x = 0;
197    
198     for (my $xi = 0; $xi <= $#{$self->{childs}->[$yi]}; $xi++) {
199    
200     glPushMatrix;
201     glTranslate ($x, $y, 0);
202     my $c = $self->{childs}->[$yi]->[$xi];
203     $c->_draw if $c;
204     glPopMatrix;
205    
206     $x += $self->max_col_width ($xi);
207     }
208    
209     $y += $self->max_row_height ($yi);
210     }
211     }
212    
213     package Crossfire::Client::Widget::VBox;
214    
215     our @ISA = Crossfire::Client::Widget::Container::;
216    
217     use SDL::OpenGL;
218    
219     sub add {
220     my ($self, $chld) = @_;
221     push @{$self->{childs}}, $chld;
222     }
223    
224     sub size_request {
225     my ($self) = @_;
226    
227     my ($hs, $ws) = (0, 0);
228     for (@{$self->{childs} || []}) {
229     my ($w, $h) = $_->size_request;
230     $hs += $h;
231     if ($ws < $w) { $ws = $w }
232     }
233    
234     return ($ws, $hs);
235     }
236    
237     sub _draw {
238     my ($self) = @_;
239    
240     my ($x, $y);
241     for (@{$self->{childs} || []}) {
242     glPushMatrix;
243     glTranslate (0, $y, 0);
244     $_->_draw;
245     glPopMatrix;
246     my ($w, $h) = $_->size_request;
247     $y += $h;
248     }
249     }
250    
251 root 1.10 package Crossfire::Client::Widget::Label;
252    
253 root 1.12 our @ISA = Crossfire::Client::Widget::;
254    
255 root 1.10 use SDL::OpenGL;
256    
257     sub new {
258 root 1.12 my ($class, $x, $y, $z, $ttf, $text) = @_;
259 root 1.10
260 elmex 1.15 my $self = $class->SUPER::new (x => $x, y => $y, z => $z, ttf => $ttf);
261 root 1.10
262 elmex 1.15 $self->set_text ($text);
263 root 1.10
264     $self
265     }
266    
267 elmex 1.15 sub set_text {
268     my ($self, $text) = @_;
269     $self->{texture} = new_from_ttf Crossfire::Client::Texture $self->{ttf}, $self->{text} = $text;
270     }
271    
272     sub get_text {
273     my ($self, $text) = @_;
274     $self->{text}
275     }
276    
277 root 1.14 sub size_request {
278     my ($self) = @_;
279    
280     (
281     $self->{texture}{width},
282     $self->{texture}{height},
283     )
284     }
285    
286 elmex 1.11 sub _draw {
287 root 1.10 my ($self) = @_;
288    
289     my $tex = $self->{texture};
290    
291 root 1.12 $self->{x}--;
292    
293     glEnable GL_BLEND;
294 root 1.10 glEnable GL_TEXTURE_2D;
295 root 1.12 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE;
296 root 1.10 glBindTexture GL_TEXTURE_2D, $tex->{name};
297    
298 root 1.12 glColor 1, 1, 1;
299    
300 root 1.10 glBegin GL_QUADS;
301     glTexCoord 0, 0; glVertex 0 , 0;
302     glTexCoord 0, 1; glVertex 0 , $tex->{height};
303     glTexCoord 1, 1; glVertex $tex->{width}, $tex->{height};
304     glTexCoord 1, 0; glVertex $tex->{width}, 0;
305     glEnd;
306    
307 root 1.12 glDisable GL_BLEND;
308 root 1.10 glDisable GL_TEXTURE_2D;
309     }
310    
311 elmex 1.9 package Crossfire::Client::Widget::TextView;
312 root 1.4
313 elmex 1.3 use strict;
314 root 1.10
315 elmex 1.9 our @ISA = qw/Crossfire::Client::Widget/;
316 elmex 1.3
317     use SDL::OpenGL;
318     use SDL::OpenGL::Constants;
319    
320     sub add_line {
321     my ($self, $line) = @_;
322     push @{$self->{lines}}, $line;
323     }
324    
325 elmex 1.11 sub _draw {
326 elmex 1.3 my ($self) = @_;
327    
328     }
329    
330 elmex 1.9 package Crossfire::Client::Widget::MapWidget;
331 root 1.4
332 elmex 1.2 use strict;
333 elmex 1.7
334 elmex 1.9 our @ISA = qw/Crossfire::Client::Widget/;
335 elmex 1.2
336 root 1.16 use SDL;
337 elmex 1.2 use SDL::OpenGL;
338     use SDL::OpenGL::Constants;
339    
340     sub key_down {
341     print "MAPKEYDOWN\n";
342     }
343    
344     sub key_up {
345     }
346    
347 elmex 1.11 sub _draw {
348 elmex 1.2 glEnable GL_TEXTURE_2D;
349     glEnable GL_BLEND;
350 root 1.12 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE;
351 elmex 1.2
352     my $map = $::CONN->{map};
353    
354     for my $x (0 .. $::CONN->{mapw} - 1) {
355     for my $y (0 .. $::CONN->{maph} - 1) {
356    
357     my $cell = $map->[$x][$y]
358     or next;
359    
360     my $darkness = $cell->[3] * (1 / 255);
361     glColor $darkness, $darkness, $darkness;
362    
363     for my $num (grep $_, $cell->[0], $cell->[1], $cell->[2]) {
364 root 1.4 my $tex = $::CONN->{face}[$num]{texture} || next;
365 elmex 1.2
366 root 1.4 glBindTexture GL_TEXTURE_2D, $tex->{name};
367 elmex 1.2
368     glBegin GL_QUADS;
369 root 1.10 glTexCoord 0, 0; glVertex $x * 32 , $y * 32;
370     glTexCoord 0, 1; glVertex $x * 32 , $y * 32 + 32;
371     glTexCoord 1, 1; glVertex $x * 32 + 32, $y * 32 + 32;
372     glTexCoord 1, 0; glVertex $x * 32 + 32, $y * 32;
373 elmex 1.2 glEnd;
374     }
375     }
376     }
377    
378     glDisable GL_TEXTURE_2D;
379     glDisable GL_BLEND;
380     }
381    
382 root 1.16 my %DIR = (
383     SDLK_KP8, [1, "north"],
384     SDLK_KP9, [2, "northest"],
385     SDLK_KP6, [3, "east"],
386     SDLK_KP3, [4, "southeast"],
387     SDLK_KP2, [5, "south"],
388     SDLK_KP1, [6, "southwest"],
389     SDLK_KP4, [7, "west"],
390     SDLK_KP7, [8, "northwest"],
391     );
392    
393     sub key_down {
394     my ($self, $ev) = @_;
395    
396     my $mod = $ev->key_mod;
397     my $sym = $ev->key_sym;
398    
399     if ($sym == SDLK_KP5) {
400     $::CONN->send ("command stay fire");
401     } elsif (exists $DIR{$sym}) {
402     if ($mod & KMOD_SHIFT) {
403     $::CONN->send ("command fire $DIR{$sym}[0]");
404     } elsif ($mod & KMOD_CTRL) {
405     $::CONN->send ("command run $DIR{$sym}[0]");
406     } else {
407     }
408     }
409     }
410    
411     sub key_up {
412     my ($self, $ev) = @_;
413    
414     my $mod = $ev->key_mod;
415     my $sym = $ev->key_sym;
416    
417     if (exists $DIR{$sym}) {
418     if ($mod & KMOD_SHIFT) {
419     $::CONN->send ("command fire_stop");
420     } else {
421     $::CONN->send ("command run_stop");
422     }
423     }
424     }
425    
426 elmex 1.1 1;
427 root 1.5