ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/bin/pclient
(Generate patch)

Comparing deliantra/Deliantra-Client/bin/pclient (file contents):
Revision 1.17 by root, Fri Apr 7 18:20:13 2006 UTC vs.
Revision 1.45 by root, Sun Apr 9 17:34:15 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines