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

Comparing deliantra/Deliantra-Client/bin/cfplus (file contents):
Revision 1.195 by root, Tue Jul 31 01:03:52 2007 UTC vs.
Revision 1.214 by elmex, Tue Aug 14 14:12:46 2007 UTC

113our $CONN; 113our $CONN;
114our $PROFILE; # current profile 114our $PROFILE; # current profile
115our $FAST; # fast, low-quality mode, possibly useful for software-rendering 115our $FAST; # fast, low-quality mode, possibly useful for software-rendering
116 116
117our $WANT_REFRESH; 117our $WANT_REFRESH;
118our $CAN_REFRESH;
119 118
120our @SDL_MODES; 119our @SDL_MODES;
121our $WIDTH; 120our $WIDTH;
122our $HEIGHT; 121our $HEIGHT;
123our $FULLSCREEN; 122our $FULLSCREEN;
144our $SETUP_KEYBOARD; 143our $SETUP_KEYBOARD;
145 144
146our $PL_NOTEBOOK; 145our $PL_NOTEBOOK;
147our $PL_WINDOW; 146our $PL_WINDOW;
148 147
148our $MUSIC_PLAYING_WIDGET;
149our $LICENSE_WIDGET;
150
149our $INVENTORY_PAGE; 151our $INVENTORY_PAGE;
150our $STATS_PAGE; 152our $STATS_PAGE;
151our $SKILL_PAGE; 153our $SKILL_PAGE;
152our $SPELL_PAGE; 154our $SPELL_PAGE;
153our $SPELL_LIST; 155our $SPELL_LIST;
159our $STATWIDS; 161our $STATWIDS;
160 162
161our $SDL_ACTIVE; 163our $SDL_ACTIVE;
162our %SDL_CB; 164our %SDL_CB;
163 165
166our $ALT_ENTER_MESSAGE;
167our $STATUSBOX;
168our $DEBUG_STATUS;
169
170our $INV;
171our $INVR;
172our $INV_RIGHT_HB;
173
174our $PICKUP_CFG;
175
176#############################################################################
177
178sub status {
179 $STATUSBOX->add (CFPlus::asxml $_[0], pri => -10, group => "status", timeout => 10, fg => [1, 1, 0, 1]);
180}
181
182sub debug {
183 $DEBUG_STATUS->set_text ($_[0]);
184}
185
186sub message {
187 my ($para) = @_;
188 $MESSAGE_WINDOW->message ($para);
189}
190
191#############################################################################
192#TODO: maybe move into own audio module...
193
164our $SDL_MIXER; 194our $SDL_MIXER;
195
165our $MUSIC_DEFAULT = "in_a_heartbeat.ogg"; 196our $MUSIC_DEFAULT = "in_a_heartbeat.ogg";
166our @MUSIC_WANT; 197our $MUSIC_WANT; # arryref of ambient music we want to play
198our @MUSIC_HAVE; # ambient music we have on disk
167our $MUSIC_START; 199our $MUSIC_START;
200our @MUSIC_JINGLE; # which jingles to play next
168our $MUSIC_PLAYING_DATA; 201our $MUSIC_PLAYING_DATA;
169our $MUSIC_PLAYING_META; 202our $MUSIC_PLAYING_META;
170our $MUSIC_PLAYER; 203our $MUSIC_PLAYER;
171our $MUSIC_RESUME = 30; # resume music when players less than these many seconds before 204our $MUSIC_RESUME = 30; # resume music when played less than these many seconds before
172our @SOUNDS; # event => file mapping 205
173our %AUDIO_CHUNK; # audio files 206our %AUDIO_CHUNK; # audio "files"
174 207our %AUDIO_PLAY; # which audio faces should be played
175our $ALT_ENTER_MESSAGE;
176our $STATUSBOX;
177our $DEBUG_STATUS;
178
179our $INV;
180our $INVR;
181our $INV_RIGHT_HB;
182
183our $PICKUP_CFG;
184
185#############################################################################
186#TODO: maybe move into own audio module...
187 208
188sub audio_channel_finished { 209sub audio_channel_finished {
189 my ($channel) = @_; 210 my ($channel) = @_;
190 211
191# warn "channel $channel finished\n";#d# 212# warn "channel $channel finished\n";#d#
192} 213}
193 214
194our %AUDIO_PLAY;
195our %AUDIO_CHUNK;
196
197sub audio_sound_push($) { 215sub audio_sound_push($) {
198 my ($face) = @_; 216 my ($face) = @_;
217
218 $CFG->{effects_enable}
219 or return;
220
221 $AUDIO_PLAY{$face}
222 or return;
199 223
200 if (my $chunk = $AUDIO_CHUNK{$face}) { 224 if (my $chunk = $AUDIO_CHUNK{$face}) {
201 for (grep $_->[0] >= Event::time, @{(delete $AUDIO_PLAY{$face}) || []}) { 225 for (grep $_->[0] >= Event::time, @{(delete $AUDIO_PLAY{$face}) || []}) {
202 my (undef, $dx, $dy, $vol) = @$_; 226 my (undef, $dx, $dy, $vol) = @$_;
203 227
204 my $channel = CFPlus::Channel::find; 228 my $channel = CFPlus::Channel::find;
205 $channel->volume (128 + $vol); 229 $channel->volume ($vol * $CFG->{effects_volume} * 128 / 255);
206 $dx = $dx / 10 * 255;
207 $channel->set_panning ((min 255, 255 - $dx), (min 255, 255 + $dx));
208
209# my $angle = $dx ? : $dx < 0 ?
210# my $distance = -$vol;
211# $channel->set_position ($angle, $distance); 230 $channel->set_position_r ($dx, $dy, 20);
212
213 $chunk->play ($channel); 231 $chunk->play ($channel);
214 } 232 }
215 } else { 233 } else {
216 # sound_meta not set means data is in flight either way 234 # sound_meta not set means data is in flight either way
217 my $meta = $CONN->{sound_meta}{$face} 235 my $meta = $CONN->{sound_meta}{$face}
218 or return; 236 or return;
219 237
238 # if its a jingle, play it as ambient music
239 if ($meta->{meta}{jingle}) {
240 if (delete $AUDIO_PLAY{$face}) { # take the jingle out of the sound queue
241 push @MUSIC_JINGLE, $meta; # push it oto the music/jingle queue
242 &audio_music_push ($face);
243 }
244 } else {
220 # fetch from database 245 # fetch from database
221 CFPlus::DB::get res_data => $meta->{name}, sub { 246 CFPlus::DB::get res_data => $meta->{name}, sub {
222 my $vol = $meta->{meta}{volume} || 1;
223 my $rwops = new CFPlus::RW $_[0]; 247 my $rwops = new CFPlus::RW $_[0];
224 my $chunk = new CFPlus::MixChunk $rwops; 248 my $chunk = new CFPlus::MixChunk $rwops
225 $chunk->volume ($vol * 128); 249 or Carp::confess "sound face " . (JSON::XS::to_json $meta) . " unloadable: " . CFPlus::Mix_GetError;
250 $chunk->volume (($meta->{meta}{volume} || 1) * 128);
226 $AUDIO_CHUNK{$face} = $chunk; 251 $AUDIO_CHUNK{$face} = $chunk;
227 252
228 audio_sound_push ($face); 253 audio_sound_push ($face);
254 };
229 }; 255 }
230 } 256 }
231} 257}
232 258
233sub audio_sound_play { 259sub audio_sound_play {
234 my ($face, $dx, $dy, $vol) = @_; 260 my ($face, $dx, $dy, $vol) = @_;
235 261
236 $SDL_MIXER 262 $SDL_MIXER
237 or return; 263 or return;
264 $CFG->{effects_enable}
265 or return;
238 266
239 my $queue = $AUDIO_PLAY{$face} ||= []; 267 my $queue = $AUDIO_PLAY{$face} ||= [];
240 push @$queue, [Event::time + 0.2, $dx, $dy, $vol]; # delay sound by max. 0.2s 268 push @$queue, [Event::time + 0.6, $dx, $dy, $vol]; # do not play sound for outdated events
241 audio_sound_push $face 269 audio_sound_push $face
242 unless @$queue > 1; 270 unless @$queue > 1;
271}
272
273sub audio_music_set_meta {
274 my ($meta) = @_;
275
276 $MUSIC_PLAYING_META = $meta;
277 $MUSIC_PLAYING_WIDGET->set_markup (
278 "<b>Name</b>: " . (CFPlus::asxml $meta->{meta}{name}) . "\n"
279 . "<b>Author</b>: " . (CFPlus::asxml $meta->{meta}{author}) . "\n"
280 . "<b>Source</b>: " . (CFPlus::asxml $meta->{meta}{source}) . "\n"
281 . "<b>License</b>: " . (CFPlus::asxml $meta->{meta}{license})
282 );
243} 283}
244 284
245sub audio_music_update_volume { 285sub audio_music_update_volume {
246 return unless $MUSIC_PLAYING_META; 286 return unless $MUSIC_PLAYING_META;
247 my $volume = $MUSIC_PLAYING_META->{meta}{volume} || 1; 287 my $volume = $MUSIC_PLAYING_META->{meta}{volume} || 1;
248 my $base = $CFG->{bgm_volume}; 288 my $base = $MUSIC_PLAYING_META->{meta}{jingle} ? 1 : $CFG->{bgm_volume};
249 CFPlus::MixMusic::volume $base * $volume * 128; 289 CFPlus::MixMusic::volume $base * $volume * 128;
250}
251
252sub audio_music_set_ambient {
253 my ($songs) = @_;
254
255 my @want =
256 grep $_,
257 map $CONN->{music_meta}{$_},
258 @$songs;
259
260 if (@want) {
261 @MUSIC_WANT = @want;
262 &audio_music_changed ();
263 }
264} 290}
265 291
266sub audio_music_start { 292sub audio_music_start {
267 my $meta = $MUSIC_PLAYING_META; 293 my $meta = $MUSIC_PLAYING_META;
268 294
280 my $rwops = $meta->{path} 306 my $rwops = $meta->{path}
281 ? new_from_file CFPlus::RW $meta->{path} 307 ? new_from_file CFPlus::RW $meta->{path}
282 : new CFPlus::RW $$MUSIC_PLAYING_DATA; 308 : new CFPlus::RW $$MUSIC_PLAYING_DATA;
283 309
284 $MUSIC_PLAYER = new CFPlus::MixMusic $rwops 310 $MUSIC_PLAYER = new CFPlus::MixMusic $rwops
285 or ((warn CFPlus::Mix_GetError), return); # pretty fatal error 311 or Carp::confess "music face $meta->{face} unloadable: " . CFPlus::Mix_GetError;
286 312
287 my $NOW = time; 313 my $NOW = time;
288 314
289 if ($MUSIC_PLAYING_META->{stop_time} > $NOW - $MUSIC_RESUME) { 315 if ($MUSIC_PLAYING_META->{stop_time} > $NOW - $MUSIC_RESUME) {
290 my $pos = $MUSIC_PLAYING_META->{stop_pos}; 316 my $pos = $MUSIC_PLAYING_META->{stop_pos};
293 } else { 319 } else {
294 $MUSIC_PLAYER->play (0); 320 $MUSIC_PLAYER->play (0);
295 $MUSIC_START = time; 321 $MUSIC_START = time;
296 } 322 }
297 323
298 delete $MUSIC_PLAYING_META->{stop_time}; 324 delete $meta->{stop_time};
299 delete $MUSIC_PLAYING_META->{stop_pos}; 325 delete $meta->{stop_pos};
300 } 326 }
301} 327}
302 328
303sub audio_music_changed { 329sub audio_music_push {
304 return unless $CFG->{bgm_enable};
305 return unless $SDL_MIXER; 330 return unless $SDL_MIXER;
306 331
332 my $fade_out;
333
334 if (@MUSIC_JINGLE) {
335 @MUSIC_HAVE = $MUSIC_JINGLE[0];
336 $fade_out = 333;
337 } else {
338 return unless $CFG->{bgm_enable};
339
340 my @have =
341 grep $_,
342 map $CONN->{music_meta}{$_},
343 @$MUSIC_WANT;
344
345 @MUSIC_HAVE = @have
346 if @have;
347
307 # default MUSIC_WANT == MUSIC_DEFAULT 348 # default MUSIC_HAVE == MUSIC_DEFAULT
308 @MUSIC_WANT = { path => CFPlus::find_rcfile "music/$MUSIC_DEFAULT" } unless @MUSIC_WANT; 349 @MUSIC_HAVE = { path => CFPlus::find_rcfile "music/$MUSIC_DEFAULT" } unless @MUSIC_HAVE;
350 $fade_out = 1000;
351 }
309 352
310 # if the currently playing song is acceptable, let it continue 353 # if the currently playing song is acceptable, let it continue
311 return if $MUSIC_PLAYING_META
312 && grep $MUSIC_PLAYING_META == $_, @MUSIC_WANT; 354 return if grep $MUSIC_PLAYING_META == $_, @MUSIC_HAVE;
313 355
314 my $NOW = time; 356 my $NOW = time;
315 357
316 if ($MUSIC_PLAYING_META) { 358 if ($MUSIC_PLAYING_META) {
317 $MUSIC_PLAYING_META->{stop_time} = $NOW; 359 $MUSIC_PLAYING_META->{stop_time} = $NOW;
318 $MUSIC_PLAYING_META->{stop_pos} = $NOW - $MUSIC_START; 360 $MUSIC_PLAYING_META->{stop_pos} = $NOW - $MUSIC_START;
319 CFPlus::MixMusic::fade_out 1000; 361 CFPlus::MixMusic::fade_out $fade_out;
320 } else { 362 } else {
321 # sort by stop time, oldest first 363 # sort by stop time, oldest first
322 @MUSIC_WANT = sort { $a->{stop_time} <=> $b->{stop_time} } @MUSIC_WANT; 364 @MUSIC_HAVE = sort { $a->{stop_time} <=> $b->{stop_time} } @MUSIC_HAVE;
323 365
324 # if the most recently-played piece played very recently, 366 # if the most recently-played piece played very recently,
325 # resume it, else choose the oldest piece for rotation. 367 # resume it, else choose the oldest piece for rotation.
326 $MUSIC_PLAYING_META = 368 audio_music_set_meta
327 $MUSIC_WANT[-1]{stop_time} > $NOW - $MUSIC_RESUME 369 $MUSIC_HAVE[-1]{stop_time} > $NOW - $MUSIC_RESUME
328 ? $MUSIC_WANT[-1] 370 ? $MUSIC_HAVE[-1]
329 : $MUSIC_WANT[0]; 371 : $MUSIC_HAVE[0];
330 372
331 audio_music_start; 373 audio_music_start;
332 } 374 }
333} 375}
334 376
377sub audio_music_set_ambient {
378 my ($songs) = @_;
379
380 $MUSIC_WANT = $songs;
381 audio_music_push;
382}
383
335sub audio_music_finished { 384sub audio_music_finished {
385 # we compress multiple jingles of the same type
386 shift @MUSIC_JINGLE
387 while @MUSIC_JINGLE && $MUSIC_PLAYING_META == $MUSIC_JINGLE[0];
388
389 $MUSIC_PLAYING_WIDGET->clear;
390
336 undef $MUSIC_PLAYER; 391 undef $MUSIC_PLAYER;
337 undef $MUSIC_PLAYING_META; 392 undef $MUSIC_PLAYING_META;
338 undef $MUSIC_PLAYING_DATA; 393 undef $MUSIC_PLAYING_DATA;
339 394
340 audio_music_changed; 395 audio_music_push;
396}
397
398sub audio_init {
399 if ($CFG->{audio_enable}) {
400 $ENV{MIX_EFFECTSMAXSPEED} = 1;
401 $SDL_MIXER = !CFPlus::Mix_OpenAudio;
402
403 unless ($SDL_MIXER) {
404 status "Unable to open sound device: there will be no sound";
405 return;
406 }
407
408 CFPlus::Mix_AllocateChannels 16;
409
410 audio_music_finished;
411 } else {
412 undef $SDL_MIXER;
413 }
414}
415
416sub audio_shutdown {
417 undef $MUSIC_PLAYER;
418 undef $MUSIC_PLAYING_META;
419 undef $MUSIC_PLAYING_DATA;
420
421 $MUSIC_WANT = [];
422 @MUSIC_JINGLE = ();
423 %AUDIO_PLAY = ();
424 %AUDIO_CHUNK = ();
425
426 CFPlus::Mix_CloseAudio if $SDL_MIXER;
427 undef $SDL_MIXER;
341} 428}
342 429
343############################################################################# 430#############################################################################
344
345sub status {
346 $STATUSBOX->add (CFPlus::asxml $_[0], pri => -10, group => "status", timeout => 10, fg => [1, 1, 0, 1]);
347}
348
349sub debug {
350 $DEBUG_STATUS->set_text ($_[0]);
351}
352
353sub message {
354 my ($para) = @_;
355 $MESSAGE_WINDOW->message ($para);
356}
357 431
358sub destroy_query_dialog { 432sub destroy_query_dialog {
359 (delete $_[0]{query_dialog})->destroy 433 (delete $_[0]{query_dialog})->destroy
360 if $_[0]{query_dialog}; 434 if $_[0]{query_dialog};
361} 435}
695 state => $CFG->{fullscreen}, 769 state => $CFG->{fullscreen},
696 tooltip => "Bring the client into fullscreen mode.", 770 tooltip => "Bring the client into fullscreen mode.",
697 on_changed => sub { my ($self, $value) = @_; $CFG->{fullscreen} = $value; 0 } 771 on_changed => sub { my ($self, $value) = @_; $CFG->{fullscreen} = $value; 0 }
698 ); 772 );
699 773
774 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Force OpenGL 1.1");
775 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
776 state => $CFG->{opengl11},
777 tooltip => "Limit CFPlus to use OpenGL 1.1 features only. This will normally result in "
778 . "higher memory usage and slower performance. It will, however, help tremendously on "
779 . "cards that claim to support a feature but fall back to software rendering. "
780 . "Nvidia Geforce FX cards are known to claim features the hardware doesn't support, "
781 . "but cards and drivers from other vendors (ATI) are often just as bad. <b>If you "
782 . "experience extremely low framerates and your card should do better, try this option.</b>",
783 on_changed => sub { my ($self, $value) = @_; $CFG->{opengl11} = $value; 0 }
784 );
785
700 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fast & Ugly"); 786 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fast & Ugly");
701 $table->add_at (1, $row++, new CFPlus::UI::CheckBox 787 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
702 state => $CFG->{fast}, 788 state => $CFG->{fast},
703 tooltip => "Lower the visual quality considerably to speed up rendering.", 789 tooltip => "Lower the visual quality considerably to speed up rendering.",
704 on_changed => sub { my ($self, $value) = @_; $CFG->{fast} = $value; 0 } 790 on_changed => sub { my ($self, $value) = @_; $CFG->{fast} = $value; 0 }
730 816
731 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Map Smoothing"); 817 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Map Smoothing");
732 $table->add_at (1, $row++, new CFPlus::UI::CheckBox 818 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
733 state => $CFG->{map_smoothing}, 819 state => $CFG->{map_smoothing},
734 tooltip => "<b>Map Smoothing</b> tries to make tile borders less square. " 820 tooltip => "<b>Map Smoothing</b> tries to make tile borders less square. "
735 . "This increases load on the graphics subsystem and works only with 2.x servers. " 821 . "This increases load on the graphics subsystem and works only with TRT servers. "
736 . "Changes take effect at next connection only.", 822 . "Changes take effect at next login only.",
737 on_changed => sub { my ($self, $value) = @_; $CFG->{map_smoothing} = $value; 0 } 823 on_changed => sub { my ($self, $value) = @_; $CFG->{map_smoothing} = $value; 0 }
738 ); 824 );
739 825
740 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fog of War"); 826 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fog of War");
741 $table->add_at (1, $row++, new CFPlus::UI::CheckBox 827 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
752 ); 838 );
753 839
754 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Message Fontsize"); 840 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Message Fontsize");
755 $table->add_at (1, $row++, new CFPlus::UI::Slider 841 $table->add_at (1, $row++, new CFPlus::UI::Slider
756 range => [$CFG->{log_fontsize}, 0.5, 2, 0, 0.1], 842 range => [$CFG->{log_fontsize}, 0.5, 2, 0, 0.1],
757 tooltip => "The font size used by the <b>message/server log</b> window only. Changes are instant.", 843 tooltip => "The font size used by the <b>message/server log</b> window only. Changes are instant, "
844 . "but you still need to press apply to correctly re-layout the widget.",
758 on_changed => sub { $MESSAGE_WINDOW->set_fontsize ($CFG->{log_fontsize} = $_[1]); 0 }, 845 on_changed => sub { $MESSAGE_WINDOW->set_fontsize ($CFG->{log_fontsize} = $_[1]); 0 },
759 ); 846 );
760 847
761 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Gauge fontsize"); 848 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Gauge fontsize");
762 $table->add_at (1, $row++, new CFPlus::UI::Slider 849 $table->add_at (1, $row++, new CFPlus::UI::Slider
784} 871}
785 872
786sub audio_setup { 873sub audio_setup {
787 my $vbox = new CFPlus::UI::VBox; 874 my $vbox = new CFPlus::UI::VBox;
788 875
789 $vbox->add (my $table = new CFPlus::UI::Table expand => 1, col_expand => [0, 1]); 876 $vbox->add (my $table = new CFPlus::UI::Table expand => 1, col_expand => [0, 0, 1]);
790 877
791 my $row = 0; 878 my $row = 0;
792 879
793 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Audio Enable"); 880 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Audio Enable");
794 $table->add_at (1, $row++, new CFPlus::UI::CheckBox 881 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
798 ); 885 );
799# $table->add_at (0, 9, new CFPlus::UI::Label valign => 0, align => 1, text => "Effects Volume"); 886# $table->add_at (0, 9, new CFPlus::UI::Label valign => 0, align => 1, text => "Effects Volume");
800# $table->add_at (1, 8, new CFPlus::UI::Slider range => [$CFG->{effects_volume}, 0, 128, 1], on_changed => sub { 887# $table->add_at (1, 8, new CFPlus::UI::Slider range => [$CFG->{effects_volume}, 0, 128, 1], on_changed => sub {
801# $CFG->{effects_volume} = $_[1]; 888# $CFG->{effects_volume} = $_[1];
802# }); 889# });
890
891 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Sound Effects");
892 $table->add_at (1, $row, new CFPlus::UI::CheckBox
893 expand => 1, state => $CFG->{effects_enable},
894 tooltip => "If enabled, sound effects are enabled. If disabled, no sound effects will be played.",
895 on_changed => sub {
896 $CFG->{effects_enable} = $_[1];
897 $CONN->update_fx_want if $CONN;
898 0
899 }
900 );
901 $table->add_at (2, $row++, new CFPlus::UI::Slider
902 expand => 1, range => [$CFG->{effects_volume}, 0, 1, 0, 1/128],
903 tooltip => "The relative volume of sound effects. Best audio quality is achieved if this "
904 . "is set highest (rightmost) and you use your operating system volume setting. Changes are instant.",
905 on_changed => sub { $CFG->{effects_volume} = $_[1]; 0 }
906 );
907
803 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Background Music"); 908 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Background Music");
804 $table->add_at (1, $row++, my $hbox = new CFPlus::UI::HBox); 909 $table->add_at (1, $row, new CFPlus::UI::CheckBox
805 $hbox->add (new CFPlus::UI::CheckBox
806 expand => 1, state => $CFG->{bgm_enable}, 910 expand => 1, state => $CFG->{bgm_enable},
807 tooltip => "If enabled, playing of background music is enabled. If disabled, no background music will be played.", 911 tooltip => "If enabled, playing of background music is enabled. If disabled, no background music will be played.",
808 on_changed => sub { $CFG->{bgm_enable} = $_[1]; 0 } 912 on_changed => sub {
913 $CFG->{bgm_enable} = $_[1];
914 $CONN->update_fx_want if $CONN;
915 0
916 }
809 ); 917 );
810 $hbox->add (new CFPlus::UI::Slider 918 $table->add_at (2, $row++, new CFPlus::UI::Slider
811 expand => 1, range => [$CFG->{bgm_volume}, 0, 1, 0, 1/128], 919 expand => 1, range => [$CFG->{bgm_volume}, 0, 1, 0, 1/128],
812 tooltip => "The volume of the background music. Changes are instant.", 920 tooltip => "The volume of the background music. Changes are instant.",
813 on_changed => sub { $CFG->{bgm_volume} = $_[1]; audio_music_update_volume; 0 } 921 on_changed => sub { $CFG->{bgm_volume} = $_[1]; audio_music_update_volume; 0 }
814 ); 922 );
815 923
816 $table->add_at (1, $row++, new CFPlus::UI::Button 924 $table->add_at (1, $row++, new CFPlus::UI::Button
817 expand => 1, align => 0, text => "Apply", 925 c_colspan => 2, expand => 1, align => 0, text => "Apply",
818 tooltip => "Apply the audio settings", 926 tooltip => "Apply the audio settings",
819 on_activate => sub { 927 on_activate => sub {
820 audio_shutdown (); 928 audio_shutdown ();
821 audio_init (); 929 audio_init ();
822 0 930 0
893 $table->add_at (0, 4, new CFPlus::UI::Button text => "die on click(tm)", on_activate => sub { &CFPlus::debug() } ); 1001 $table->add_at (0, 4, new CFPlus::UI::Button text => "die on click(tm)", on_activate => sub { &CFPlus::debug() } );
894 1002
895 $table->add_at (0, 5, new CFPlus::UI::TextEdit text => "line1\0152\0153");#d# 1003 $table->add_at (0, 5, new CFPlus::UI::TextEdit text => "line1\0152\0153");#d#
896 1004
897 $table->add_at (7,7, my $t = new CFPlus::UI::Table expand => 0); 1005 $table->add_at (7,7, my $t = new CFPlus::UI::Table expand => 0);
898 $t->add_at (0,0, new CFPlus::UI::Label text => "a a a a", rowspan => 1, colspan => 2); 1006 $t->add_at (0,0, new CFPlus::UI::Label text => "a a a a", c_rowspan => 1, c_colspan => 2);
899 $t->add_at (2,0, new CFPlus::UI::Label text => "b\nb", rowspan => 2, colspan => 1); 1007 $t->add_at (2,0, new CFPlus::UI::Label text => "b\nb", c_rowspan => 2, c_colspan => 1);
900 $t->add_at (1,2, new CFPlus::UI::Label text => "c c c c", rowspan => 1, colspan => 2); 1008 $t->add_at (1,2, new CFPlus::UI::Label text => "c c c c", c_rowspan => 1, c_colspan => 2);
901 $t->add_at (0,1, new CFPlus::UI::Label text => "d\nd", rowspan => 2, colspan => 1); 1009 $t->add_at (0,1, new CFPlus::UI::Label text => "d\nd", c_rowspan => 2, c_colspan => 1);
902 $t->add_at (1,1, new CFPlus::UI::Label text => "e"); 1010 $t->add_at (1,1, new CFPlus::UI::Label text => "e");
903 1011
904 $table->add_at (7, 6, my $c = new CFPlus::UI::Canvas); 1012 $table->add_at (7, 6, my $c = new CFPlus::UI::Canvas);
905 1013
906 $c->add_items ({ 1014 $c->add_items ({
1513 CFPlus::Protocol::set_opencont ($::CONN, 0, "Floor"); 1621 CFPlus::Protocol::set_opencont ($::CONN, 0, "Floor");
1514 1622
1515 $hb 1623 $hb
1516} 1624}
1517 1625
1626sub media_window {
1627 my $vb = new CFPlus::UI::VBox;
1628
1629 $vb->add (new CFPlus::UI::FancyFrame
1630 label => "Currently playing music",
1631 child => new CFPlus::UI::ScrolledWindow scroll_x => 1, scroll_y => 0,
1632 child => ($MUSIC_PLAYING_WIDGET = new CFPlus::UI::Label ellipsise => 0, fontsize => 0.8),
1633 );
1634
1635 $vb->add (new CFPlus::UI::FancyFrame
1636 label => "Other media used in this session",
1637 expand => 1,
1638 child => ($LICENSE_WIDGET = new CFPlus::UI::TextScroller
1639 expand => 1, fontsize => 0.8, padding_x => 4, padding_y => 4),
1640 );
1641
1642 $vb
1643}
1644
1645sub add_license {
1646 my ($meta) = @_;
1647
1648 $meta = $meta->{meta}
1649 or return;
1650
1651 $meta->{license} || $meta->{author} || $meta->{source}
1652 or return;
1653
1654 $LICENSE_WIDGET->add_paragraph ({
1655 fg => [1, 1, 1, 1],
1656 markup => "<small>"
1657 . "<b>Name:</b> " . (CFPlus::asxml $meta->{name}) . "\n"
1658 . "<b>Author:</b> " . (CFPlus::asxml $meta->{author}) . "\n"
1659 . "<b>Source:</b> " . (CFPlus::asxml $meta->{source}) . "\n"
1660 . "<b>License:</b> " . (CFPlus::asxml $meta->{license}) . "\n"
1661 . "</small>",
1662 });
1663 $LICENSE_WIDGET->scroll_to_bottom;
1664}
1665
1518sub toggle_player_page { 1666sub toggle_player_page {
1519 my ($widget) = @_; 1667 my ($widget) = @_;
1520 1668
1521 if ($PL_WINDOW->{visible} && $PL_NOTEBOOK->get_current_page == $widget) { 1669 if ($PL_WINDOW->{visible} && $PL_NOTEBOOK->get_current_page == $widget) {
1522 $PL_WINDOW->hide; 1670 $PL_WINDOW->hide;
1559 $ntb->add_tab ( 1707 $ntb->add_tab (
1560 "Inventory (F5)" => $INVENTORY_PAGE = inventory_widget, 1708 "Inventory (F5)" => $INVENTORY_PAGE = inventory_widget,
1561 "Toggles the inventory window, where you can manage your loot (or treasures :). " 1709 "Toggles the inventory window, where you can manage your loot (or treasures :). "
1562 . "You can also hit the <b>Tab</b>-key to show/hide the Inventory." 1710 . "You can also hit the <b>Tab</b>-key to show/hide the Inventory."
1563 ); 1711 );
1564 $ntb->add_tab (Pickup => autopickup_setup, 1712 $ntb->add_tab (Pickup => autopickup_setup,
1565 "Configure autopickup settings, i.e. which items you will pick up automatically when walking (or running) over them."); 1713 "Configure autopickup settings, i.e. which items you will pick up automatically when walking (or running) over them.");
1714
1715 $ntb->add_tab (Media => media_window,
1716 "License, Author and Source info for media sent by the server.");
1566 1717
1567 $ntb->set_current_page ($INVENTORY_PAGE); 1718 $ntb->set_current_page ($INVENTORY_PAGE);
1568 1719
1569 $plwin->add ($ntb); 1720 $plwin->add ($ntb);
1570 $plwin 1721 $plwin
1724 on_activate => sub { $QUIT_DIALOG->hide; 0 }, 1875 on_activate => sub { $QUIT_DIALOG->hide; 0 },
1725 ); 1876 );
1726 $hb->add (new CFPlus::UI::Button 1877 $hb->add (new CFPlus::UI::Button
1727 text => "Quit anyway", 1878 text => "Quit anyway",
1728 expand => 1, 1879 expand => 1,
1729 on_activate => sub { exit }, 1880 on_activate => sub { Event::unloop_all },
1730 ); 1881 );
1731 } 1882 }
1732 1883
1733 $QUIT_DIALOG->show; 1884 $QUIT_DIALOG->show;
1734 $QUIT_DIALOG->grab_focus; 1885 $QUIT_DIALOG->grab_focus;
1928 tooltip => "Terminates the program", 2079 tooltip => "Terminates the program",
1929 on_activate => sub { 2080 on_activate => sub {
1930 if ($CONN) { 2081 if ($CONN) {
1931 open_quit_dialog; 2082 open_quit_dialog;
1932 } else { 2083 } else {
1933 exit; 2084 Event::unloop_all;
1934 } 2085 }
1935 0 2086 0
1936 }, 2087 },
1937 ); 2088 );
1938 2089
1939 $BUTTONBAR->show; 2090 $BUTTONBAR->show;
1940 $SETUP_DIALOG->show; 2091 $SETUP_DIALOG->show;
2092 $MESSAGE_WINDOW->show;
1941 } 2093 }
1942 2094
1943 $STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]); 2095 $STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]);
1944} 2096}
1945 2097
1947 CFPlus::OpenGL::shutdown; 2099 CFPlus::OpenGL::shutdown;
1948 2100
1949 undef $SDL_ACTIVE; 2101 undef $SDL_ACTIVE;
1950} 2102}
1951 2103
1952sub audio_init {
1953 if ($CFG->{audio_enable}) {
1954 $ENV{MIX_EFFECTSMAXSPEED} = 1;
1955 $SDL_MIXER = !CFPlus::Mix_OpenAudio;
1956
1957 unless ($SDL_MIXER) {
1958 status "Unable to open sound device: there will be no sound";
1959 return;
1960 }
1961
1962 CFPlus::Mix_AllocateChannels 16;
1963
1964 audio_music_finished;
1965 } else {
1966 undef $SDL_MIXER;
1967 }
1968}
1969
1970sub audio_shutdown {
1971 CFPlus::Mix_CloseAudio if $SDL_MIXER;
1972 undef $SDL_MIXER;
1973 @SOUNDS = ();
1974 %AUDIO_CHUNK = ();
1975}
1976
1977my %animate_object; 2104my %animate_object;
1978my $animate_timer; 2105my $animate_timer;
1979 2106
1980my $fps = 9; 2107my $fps = 9;
1981 2108
1982sub force_refresh { 2109sub force_refresh {
2110 if ($ENV{CFPLUS_DEBUG} & 4) {
1983 $fps = $fps * 0.95 + 1 / (($NOW - $LAST_REFRESH) || 0.1) * 0.05; 2111 $fps = $fps * 0.98 + 1 / (($NOW - $LAST_REFRESH) || 0.1) * 0.02;
1984 debug sprintf "%3.2f", $fps if $ENV{CFPLUS_DEBUG} & 4; 2112 debug sprintf "%3.2f", $fps;
2113 }
1985 2114
1986 $CFPlus::UI::ROOT->draw; 2115 $CFPlus::UI::ROOT->draw;
1987 2116 CFPlus::SDL_GL_SwapBuffers;
1988 $WANT_REFRESH = 0;
1989 $CAN_REFRESH = 0;
1990 $LAST_REFRESH = $NOW; 2117 $LAST_REFRESH = $NOW;
1991 2118 $WANT_REFRESH->stop;
1992 CFPlus::SDL_GL_SwapBuffers;
1993} 2119}
1994 2120
2121$WANT_REFRESH = Event->idle (min => 0.001, max => 0.06, parked => 1, cb => \&force_refresh);
2122
1995my $refresh_watcher = Event->timer (after => 0, hard => 0, interval => 1 / $MAX_FPS, cb => sub { 2123my $input = Event->timer (after => 0, hard => 0, interval => 1 / 50, cb => sub {
1996 $NOW = time; 2124 $NOW = time;
1997 2125
1998 ($SDL_CB{$_->{type}} || sub { warn "unhandled event $_->{type}" })->($_) 2126 ($SDL_CB{$_->{type}} || sub { warn "unhandled event $_->{type}" })->($_)
1999 for CFPlus::poll_events; 2127 for CFPlus::poll_events;
2000 2128
2001 if (%animate_object) { 2129 if (%animate_object) {
2002 $_->animate ($LAST_REFRESH - $NOW) for values %animate_object; 2130 $_->animate ($LAST_REFRESH - $NOW) for values %animate_object;
2003 ++$WANT_REFRESH; 2131 $WANT_REFRESH->start;
2004 }
2005
2006 if ($WANT_REFRESH) {
2007 force_refresh;
2008 } else {
2009 $CAN_REFRESH = 1;
2010 } 2132 }
2011}); 2133});
2012 2134
2013sub animation_start { 2135sub animation_start {
2014 my ($widget) = @_; 2136 my ($widget) = @_;
2072 2194
2073 my %DEF_CFG = ( 2195 my %DEF_CFG = (
2074 sdl_mode => 0, 2196 sdl_mode => 0,
2075 fullscreen => 0, 2197 fullscreen => 0,
2076 fast => 0, 2198 fast => 0,
2199 opengl11 => 0,
2077 map_scale => 1, 2200 map_scale => 1,
2078 fow_enable => 1, 2201 fow_enable => 1,
2079 fow_intensity => 0, 2202 fow_intensity => 0,
2080 map_smoothing => 1, 2203 map_smoothing => 1,
2081 gui_fontsize => 1, 2204 gui_fontsize => 1,
2083 gauge_fontsize => 1, 2206 gauge_fontsize => 1,
2084 gauge_size => 0.35, 2207 gauge_size => 0.35,
2085 stat_fontsize => 0.7, 2208 stat_fontsize => 0.7,
2086 mapsize => 100, 2209 mapsize => 100,
2087 audio_enable => 1, 2210 audio_enable => 1,
2211 effects_enable => 1,
2212 effects_volume => 1,
2088 bgm_enable => 1, 2213 bgm_enable => 1,
2089 bgm_volume => 0.25, 2214 bgm_volume => 0.5,
2090 output_sync => 1, 2215 output_sync => 1,
2091 output_count => 1, 2216 output_count => 1,
2092 output_rate => "", 2217 output_rate => "",
2093 pickup => 0, 2218 pickup => 0,
2094 inv_sort => "mtime", 2219 inv_sort => "mtime",
2168} 2293}
2169 2294
2170show_tip_of_the_day if $CFG->{show_tips}; 2295show_tip_of_the_day if $CFG->{show_tips};
2171 2296
2172Event::loop; 2297Event::loop;
2298
2299#video_shutdown;
2300#audio_shutdown;
2173#CFPlus::SDL_Quit; 2301CFPlus::SDL_Quit;
2174#CFPlus::_exit 0;
2175
2176END {
2177 CFPlus::SDL_Quit;
2178 CFPlus::DB::Server::stop; 2302CFPlus::DB::Server::stop;
2179}
2180 2303
2181=head1 NAME 2304=head1 NAME
2182 2305
2183cfplus - A Crossfire+ and Crossfire game client 2306cfplus - A Crossfire TRT and Crossfire game client
2184 2307
2185=head1 SYNOPSIS 2308=head1 SYNOPSIS
2186 2309
2187Just run it - no commandline arguments are supported. 2310Just run it - no commandline arguments are supported.
2188 2311
2189=head1 USAGE 2312=head1 USAGE
2190 2313
2191cfplus utilises OpenGL for all UI elements and the game. It is supposed to be used 2314cfplus utilises OpenGL for all UI elements and the game. It is supposed to
2192fullscreen and interactively. 2315be used in fullscreen mode and interactively.
2193 2316
2194=head1 DEBUGGING 2317=head1 DEBUGGING
2195 2318
2196 2319
2197CFPLUS_DEBUG - environment variable 2320CFPLUS_DEBUG - environment variable

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines