ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/bin/pclient
Revision: 1.60
Committed: Mon Apr 10 11:56:28 2006 UTC (18 years, 1 month ago) by root
Branch: MAIN
Changes since 1.59: +1 -1 lines
Log Message:
trying grey, for fog effect

File Contents

# User Rev Content
1 root 1.1 #!/opt/bin/perl
2 root 1.25
3 root 1.2 use strict;
4 root 1.25 use utf8;
5 root 1.2
6 root 1.13 use Glib;
7     use Gtk2 -init;
8    
9     use SDL;
10     use SDL::App;
11     use SDL::Event;
12     use SDL::Surface;
13     use SDL::OpenGL;
14     use SDL::OpenGL::Constants;
15    
16 elmex 1.11 use Crossfire;
17 root 1.2 use Crossfire::Protocol;
18    
19 root 1.58 use Crossfire::Client;
20 elmex 1.20 use Crossfire::Client::Widget;
21 elmex 1.10
22 root 1.19 our $FACECACHE;
23    
24 root 1.13 our $VERSION = '0.1';
25 root 1.2
26 root 1.30 our %GL_EXT;
27    
28 elmex 1.10 our $CFG;
29 root 1.13 our $CONN;
30 root 1.2
31 root 1.30 our $WIDTH;
32     our $HEIGHT;
33     our $FULLSCREEN;
34    
35 root 1.39 our $FONTSIZE;
36 root 1.57
37 root 1.13 our $SDL_TIMER;
38     our $SDL_APP;
39 root 1.58 our $SDL_EV;
40 root 1.13 our %SDL_CB;
41 root 1.18
42     our @GL_INIT; # hooks called on every gl init
43 root 1.2
44 root 1.30 our $ALT_ENTER_MESSAGE;
45 root 1.51 our $STATUS_LINE;
46 root 1.30
47 root 1.45 my $last_refresh;
48 root 1.50 my %ANIMATE;
49     my $refresh_handler;
50 root 1.45
51 root 1.58 our ($tw, $te); # Test widget #d#
52    
53 root 1.13 sub init_screen {
54     $SDL_APP = new SDL::App
55 root 1.5 -flags => SDL_ANYFORMAT | SDL_HWSURFACE,
56     -title => "Crossfire+ Client",
57 root 1.30 -width => $WIDTH,
58     -height => $HEIGHT,
59 root 1.5 -opengl => 1,
60 root 1.51 -red_size => 5,
61     -green_size => 5,
62     -blue_size => 5,
63     -alpha_size => 0,
64 root 1.2 -double_buffer => 1,
65 root 1.30 -fullscreen => $FULLSCREEN,
66 root 1.5 -resizeable => 0;
67 root 1.2
68 root 1.58 $SDL_EV = new SDL::Event;
69     $SDL_EV->set_unicode (1);
70    
71 root 1.45 $last_refresh = SDL::GetTicks;
72    
73 root 1.30 %GL_EXT = map +($_ => 1), split /\s+/, Crossfire::Client::gl_extensions;
74    
75     $GL_EXT{GL_ARB_texture_non_power_of_two}
76     or warn "WARNING: non-power-of-two opengl extension required";
77    
78 root 1.40 $FONTSIZE = int $HEIGHT / 50;
79 root 1.39
80 root 1.52 #############################################################################
81    
82 root 1.60 glClearColor 0.5, 0.5, 0.5, 1;
83 root 1.52
84     glEnable GL_TEXTURE_2D;
85     glEnable GL_COLOR_MATERIAL;
86     glShadeModel GL_FLAT;
87     glDisable GL_DEPTH_TEST;
88     glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA;
89    
90     $_->() for @GL_INIT;
91    
92     #############################################################################
93    
94 root 1.51 $STATUS_LINE = new Crossfire::Client::Widget::Label
95     0, $HEIGHT * 59 / 60 - $FONTSIZE, 1, $FONTSIZE,
96     "";
97 root 1.58 $Crossfire::Client::Widget::TOPLEVEL->add ($STATUS_LINE);
98 root 1.51
99 root 1.40 $ALT_ENTER_MESSAGE = new Crossfire::Client::Widget::Label
100 root 1.51 0, $HEIGHT * 59 / 60, 1, $HEIGHT / 60,
101 root 1.40 "Use <b>Alt-Enter</b> to toggle fullscreen mode";
102 root 1.58 $Crossfire::Client::Widget::TOPLEVEL->add ($ALT_ENTER_MESSAGE);
103 root 1.30
104 elmex 1.34 # Test code #d#
105 elmex 1.43 unless ($tw) { # haha...
106 root 1.58 $te = new Crossfire::Client::Widget::FancyFrame;
107     $te->add (new Crossfire::Client::Widget::Entry);
108     $te->move (300, 0, 2);
109     $Crossfire::Client::Widget::TOPLEVEL->add ($te);
110    
111 root 1.45 $tw = new Crossfire::Client::Widget::Animator;
112 elmex 1.46 my $lbl1 = new Crossfire::Client::Widget::Label
113     0, 0, 10, $FONTSIZE, "<i>This</i> is a\n<u>TEST</u>!\nOf a themed\nFrame!";
114     my $lbl2 = new Crossfire::Client::Widget::Label
115     0, 0, 10, $FONTSIZE, "LBL2";
116    
117     my $vb = new Crossfire::Client::Widget::VBox;
118     my $f = new Crossfire::Client::Widget::FancyFrame;
119     my $f2 = new Crossfire::Client::Widget::FancyFrame;
120     $f->add ($lbl1);
121     $f2->add ($lbl2);
122     $vb->add ($f);
123     $vb->add ($f2, 1);
124    
125     $tw->add ($vb);
126     $tw->w (400);
127     $tw->h (300);
128 elmex 1.44 $tw->move ($WIDTH - 200, 0);
129 root 1.45 $tw->moveto (0, 0);
130 root 1.58 $Crossfire::Client::Widget::TOPLEVEL->add ($tw);
131 elmex 1.46
132     # $f->move ($WIDTH - 200, 0);
133 root 1.58 # $Crossfire::Client::Widget::TOPLEVEL->add ($f);
134 root 1.39 }
135 root 1.2 }
136    
137 root 1.13 sub start_game {
138 root 1.50 $SDL_TIMER = add Glib::Timeout 1000/50, sub {
139 root 1.30 ($SDL_CB{$SDL_EV->type} || sub { warn "unhandled event ", $SDL_EV->type })->()
140     while $SDL_EV->poll;
141 root 1.13
142     1
143     };
144    
145 root 1.30 $WIDTH = $CFG->{width};
146     $HEIGHT = $CFG->{height};
147     $FULLSCREEN = 0;
148    
149 root 1.13 init_screen;
150    
151 root 1.59 my $mapsize = List::Util::min 64, List::Util::max 11, int $WIDTH * $CFG->{mapsize} * 0.01 / 32;
152 root 1.50
153 root 1.13 $CONN = new conn
154     host => $CFG->{host},
155 root 1.28 port => $CFG->{port},
156     user => $CFG->{user},
157 root 1.37 pass => $CFG->{password},
158 root 1.50 mapw => $mapsize,
159     maph => $mapsize,
160 root 1.37 ;
161 root 1.45
162     Crossfire::Client::lowdelay fileno $CONN->{fh};
163 root 1.13 }
164    
165     sub stop_game {
166     remove Glib::Source $SDL_TIMER;
167 root 1.51 remove Glib::Source $refresh_handler if $refresh_handler;
168 root 1.50 undef $refresh_handler;
169 root 1.13
170     undef $SDL_APP;
171 root 1.50 undef $CONN;
172 root 1.13 SDL::Quit;
173     }
174    
175 root 1.30 sub force_refresh {
176     glViewport 0, 0, $WIDTH, $HEIGHT;
177 root 1.35
178     glMatrixMode GL_PROJECTION;
179     glLoadIdentity;
180 root 1.59 glOrtho 0, $WIDTH, $HEIGHT, 0, -10000 , 10000;
181 root 1.35 glMatrixMode GL_MODELVIEW;
182    
183 root 1.5 glClear GL_COLOR_BUFFER_BIT;
184 root 1.2
185 root 1.58 $Crossfire::Client::Widget::TOPLEVEL->draw;
186 root 1.1
187 root 1.2 SDL::GLSwapBuffers;
188 root 1.1 }
189    
190 root 1.30 sub refresh {
191     $refresh_handler ||= add Glib::Idle sub {
192 root 1.58 if ($SDL_APP) {
193     my $next_refresh = SDL::GetTicks;
194     my $interval = ($next_refresh - $last_refresh) * 0.001;
195     $last_refresh = $next_refresh;
196    
197     force_refresh;
198     $_->animate ($interval) for grep $_, values %ANIMATE;
199    
200     if (%ANIMATE) {
201     1
202     } else {
203     undef $refresh_handler;
204     0
205     }
206 root 1.45 } else {
207     undef $refresh_handler;
208     0
209     }
210 root 1.30 };
211     }
212    
213 root 1.45 sub animation_start {
214     my ($widget) = @_;
215     $ANIMATE{$widget} = $widget;
216     Scalar::Util::weaken $ANIMATE{$widget};
217    
218     refresh;
219     }
220    
221     sub animation_stop {
222     my ($widget) = @_;
223     delete $ANIMATE{$widget};
224     }
225    
226 root 1.13 %SDL_CB = (
227     SDL_QUIT() => sub {
228 root 1.19 main_quit Gtk2;
229 root 1.13 },
230     SDL_VIDEORESIZE() => sub {
231     },
232     SDL_VIDEOEXPOSE() => sub {
233     refresh;
234     },
235     SDL_KEYDOWN() => sub {
236 root 1.18 if ($SDL_EV->key_mod & KMOD_ALT && $SDL_EV->key_sym == SDLK_RETURN) {
237     # alt-enter
238 root 1.30 $FULLSCREEN = !$FULLSCREEN;
239 root 1.18 init_screen;
240     } else {
241 root 1.22 Crossfire::Client::Widget::feed_sdl_key_down_event ($SDL_EV);
242 root 1.18 }
243 root 1.13 },
244     SDL_KEYUP() => sub {
245 root 1.22 Crossfire::Client::Widget::feed_sdl_key_up_event ($SDL_EV);
246 root 1.13 },
247     SDL_MOUSEMOTION() => sub {
248 root 1.58 Crossfire::Client::Widget::feed_sdl_motion_event ($SDL_EV);
249 root 1.13 },
250     SDL_MOUSEBUTTONDOWN() => sub {
251 root 1.22 Crossfire::Client::Widget::feed_sdl_button_down_event ($SDL_EV);
252 root 1.13 },
253     SDL_MOUSEBUTTONUP() => sub {
254 root 1.22 Crossfire::Client::Widget::feed_sdl_button_up_event ($SDL_EV);
255 root 1.13 },
256     SDL_ACTIVEEVENT() => sub {
257 root 1.58 printf "active %x %x\n", $SDL_EV->active_gain, $SDL_EV->active_state;#d#
258 root 1.13 },
259     );
260 root 1.1
261 root 1.2 @conn::ISA = Crossfire::Protocol::;
262 root 1.1
263 root 1.2 sub conn::map_update {
264 root 1.1 my ($self, $dirty) = @_;
265    
266 root 1.2 refresh;
267 root 1.1 }
268    
269 root 1.2 sub conn::map_scroll {
270 root 1.1 my ($self, $dx, $dy) = @_;
271    
272 root 1.45 # refresh;
273 root 1.1 }
274    
275 root 1.2 sub conn::map_clear {
276 root 1.1 my ($self) = @_;
277    
278 root 1.45 # refresh;
279 root 1.1 }
280    
281 root 1.19 sub conn::face_find {
282     my ($self, $face) = @_;
283    
284     $FACECACHE->{"$face->{chksum},$face->{name}"}
285     }
286    
287 root 1.2 sub conn::face_update {
288 root 1.19 my ($self, $face) = @_;
289    
290     $FACECACHE->{"$face->{chksum},$face->{name}"} = $face->{image};
291 root 1.1
292 root 1.18 $face->{texture} = new_from_image Crossfire::Client::Texture delete $face->{image};
293 root 1.1 }
294    
295 root 1.33 sub conn::query {
296     my ($self, $flags, $prompt) = @_;
297    
298     warn "<<<<QUERY:$flags:$prompt>>>\n";#d#
299     }
300    
301 elmex 1.23 sub gtk_add_cfg_field {
302     my ($tbl, $cfg, $klbl, $key, $value) = @_;
303     my $i = $cfg->{_i}++;
304     $tbl->attach_defaults (my $lbl = Gtk2::Label->new ($klbl), 0, 1, $i, $i + 1);
305     $tbl->attach_defaults (my $ent = Gtk2::Entry->new, 1, 2, $i, $i + 1);
306     if ($key eq 'password') {
307     $ent->set_invisible_char ("*");
308     $ent->set (visibility => 0)
309     }
310     $ent->set_text ($value);
311     $ent->signal_connect (changed => sub {
312     my ($ent) = @_;
313     $cfg->{$key} = $ent->get_text;
314 elmex 1.49 # TODO: Mapsize should be a slider in the game gui
315 elmex 1.47 if ($key eq 'mapsize' and $cfg->{$key} > 100) {
316     $cfg->{$key} = 100;
317 elmex 1.48 } elsif ($key eq 'mapsize' and $cfg->{$key} < 50) {
318     $cfg->{$key} = 50;
319 elmex 1.47 }
320 elmex 1.23 });
321     }
322    
323     sub run_config_dialog {
324     my (%events) = @_;
325    
326     my $w = Gtk2::Window->new;
327    
328     my @cfg = (
329     [qw/Host host/],
330     [qw/Port port/],
331 elmex 1.47 [qw/Mapsize% mapsize/],
332 elmex 1.23 [qw/Username user/],
333     [qw/Password password/],
334     );
335    
336     my $cfg = {};
337    
338     my $a = SDL::ListModes (0, SDL_FULLSCREEN|SDL_HWSURFACE);
339     my @modes = map { [SDL::RectW ($_), SDL::RectH ($_)] } @$a;
340    
341     $w->add (my $vb = Gtk2::VBox->new);
342     $vb->pack_start (my $t = Gtk2::Table->new (2, scalar @cfg), 0, 0, 0);
343     my $selmode = $::CFG->{width} . 'x' . $::CFG->{height};
344     $t->attach_defaults (Gtk2::Label->new ("Modes"), 0, 1, 0, 1);
345     $t->attach_defaults (my $cb = Gtk2::ComboBox->new_text, 1, 2, 0, 1);
346     my $i = 0;
347     my $act = 0;
348     for (map { "$_->[0]x$_->[1]" } reverse @modes) {
349     if ($_ eq $selmode) { $act = $i }
350     $cb->append_text ($_);
351     $i++;
352     }
353     $cb->set_active ($act);
354     $cb->signal_connect (changed => sub {
355     my ($cb) = @_;
356     my $txt = $cb->get_active_text;
357     if ($txt =~ m/(\d+)x(\d+)/) {
358     $::CFG->{width} = $1;
359     $::CFG->{height} = $2;
360     }
361     });
362    
363     $cfg->{_i} = 1;
364     for (@cfg) {
365     gtk_add_cfg_field ($t, $cfg, $_->[0], $_->[1], $::CFG->{$_->[1]});
366     }
367    
368     $vb->pack_start (my $hb = Gtk2::HBox->new, 0, 0, 0);
369     $hb->pack_start (my $cb = Gtk2::Button->new ("save"), 1, 1, 5);
370     $cb->signal_connect (clicked => sub {
371     for (keys %$cfg) {
372     $::CFG->{$_} = $cfg->{$_}
373     if $_ ne '_i';
374     }
375     Crossfire::Client::write_cfg "$Crossfire::VARDIR/pclientrc";
376     });
377     $hb->pack_start (my $cb = Gtk2::Button->new ("login"), 1, 1, 5);
378     $cb->signal_connect (clicked => sub {
379     for (keys %$cfg) {
380     $::CFG->{$_} = $cfg->{$_}
381     if $_ ne '_i';
382     }
383     my $cb = $events{login} || sub {};
384     $cb->($::CFG->{user}, $::CFG->{password});
385     });
386     $hb->pack_start (my $cb = Gtk2::Button->new ("logout"), 1, 1, 5);
387     $cb->signal_connect (clicked => sub {
388 root 1.50 my $cb = $events{logout} || sub {};
389 elmex 1.23 $cb->();
390     });
391     $hb->pack_start (my $cb = Gtk2::Button->new ("quit"), 1, 1, 5);
392     $cb->signal_connect (clicked => sub { $w->destroy });
393    
394     $w->show_all;
395    
396     $w->signal_connect (destroy => sub { Gtk2->main_quit });
397     }
398    
399    
400 root 1.1 #############################################################################
401    
402 root 1.24 SDL::Init SDL_INIT_EVERYTHING;
403 elmex 1.20
404     my $mapwidget = Crossfire::Client::Widget::MapWidget->new;
405    
406 root 1.58 $Crossfire::Client::Widget::TOPLEVEL->add ($mapwidget);
407 elmex 1.16 $mapwidget->focus_in;
408    
409 root 1.22 Crossfire::Client::read_cfg "$Crossfire::VARDIR/pclientrc";
410 elmex 1.10
411 root 1.13 $CFG ||= {
412     width => 640,
413     height => 480,
414 elmex 1.47 mapsize => 100,
415 root 1.13 fullscreen => 0,
416     host => "crossfire.schmorp.de",
417     port => 13327,
418     };
419 elmex 1.12
420 root 1.42 Crossfire::Client::set_font Crossfire::Client::find_rcfile "uifont.ttf";
421 root 1.40
422 root 1.24 $FACECACHE = eval { Crossfire::load_ref "$Crossfire::VARDIR/pclient.faces" } || {};
423    
424 elmex 1.23 run_config_dialog
425 elmex 1.16 login => sub { start_game },
426     logout => sub { stop_game };
427 root 1.1
428 root 1.13 main Gtk2;
429 root 1.19
430     Crossfire::save_ref $FACECACHE, "$Crossfire::VARDIR/pclient.faces";