1 | package CFClient::Widget; |
1 | package CFClient::UI; |
2 | |
2 | |
3 | use strict; |
3 | use strict; |
4 | |
4 | |
5 | use Scalar::Util; |
5 | use Scalar::Util (); |
6 | |
6 | use List::Util (); |
7 | use SDL::OpenGL; |
|
|
8 | use SDL::OpenGL::Constants; |
|
|
9 | |
7 | |
10 | use CFClient; |
8 | use CFClient; |
11 | |
9 | |
12 | our ($FOCUS, $HOVER, $GRAB); # various widgets |
10 | our ($FOCUS, $HOVER, $GRAB); # various widgets |
13 | |
11 | |
… | |
… | |
69 | $HOVER->update if $HOVER; |
67 | $HOVER->update if $HOVER; |
70 | } |
68 | } |
71 | |
69 | |
72 | $HOVER->mouse_motion ($ev, $HOVER->translate ($x, $y)) if $HOVER; |
70 | $HOVER->mouse_motion ($ev, $HOVER->translate ($x, $y)) if $HOVER; |
73 | } |
71 | } |
|
|
72 | |
|
|
73 | ############################################################################# |
|
|
74 | |
|
|
75 | package CFClient::UI::Base; |
|
|
76 | |
|
|
77 | use strict; |
|
|
78 | |
|
|
79 | use SDL::OpenGL; |
74 | |
80 | |
75 | sub new { |
81 | sub new { |
76 | my $class = shift; |
82 | my $class = shift; |
77 | |
83 | |
78 | bless { |
84 | bless { |
… | |
… | |
158 | glTranslate $self->{x}, $self->{y}, 0; |
164 | glTranslate $self->{x}, $self->{y}, 0; |
159 | $self->_draw; |
165 | $self->_draw; |
160 | glPopMatrix; |
166 | glPopMatrix; |
161 | |
167 | |
162 | if ($self == $HOVER) { |
168 | if ($self == $HOVER) { |
163 | my ($x, $y) = @$self->{qw(x y)}; |
169 | my ($x, $y) = @$self{qw(x y)}; |
164 | |
170 | |
165 | glColor 1, 1, 1, 0.1; |
171 | glColor 1, 1, 1, 0.1; |
166 | glEnable GL_BLEND; |
172 | glEnable GL_BLEND; |
|
|
173 | glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA; |
167 | glBegin GL_QUADS; |
174 | glBegin GL_QUADS; |
168 | glVertex $x , $y; |
175 | glVertex $x , $y; |
169 | glVertex $x + $self->{w}, $y; |
176 | glVertex $x + $self->{w}, $y; |
170 | glVertex $x + $self->{w}, $y + $self->{h}; |
177 | glVertex $x + $self->{w}, $y + $self->{h}; |
171 | glVertex $x , $y + $self->{h}; |
178 | glVertex $x , $y + $self->{h}; |
… | |
… | |
240 | #$self->deactivate; |
247 | #$self->deactivate; |
241 | } |
248 | } |
242 | |
249 | |
243 | ############################################################################# |
250 | ############################################################################# |
244 | |
251 | |
245 | package CFClient::Widget::DrawBG; |
252 | package CFClient::UI::DrawBG; |
246 | |
253 | |
247 | our @ISA = CFClient::Widget::; |
254 | our @ISA = CFClient::UI::Base::; |
248 | |
255 | |
249 | use strict; |
256 | use strict; |
250 | use SDL::OpenGL; |
257 | use SDL::OpenGL; |
251 | |
258 | |
252 | sub new { |
259 | sub new { |
… | |
… | |
275 | glEnd; |
282 | glEnd; |
276 | } |
283 | } |
277 | |
284 | |
278 | ############################################################################# |
285 | ############################################################################# |
279 | |
286 | |
280 | package CFClient::Widget::Empty; |
287 | package CFClient::UI::Empty; |
281 | |
288 | |
282 | our @ISA = CFClient::Widget::; |
289 | our @ISA = CFClient::UI::Base::; |
283 | |
290 | |
284 | sub size_request { |
291 | sub size_request { |
285 | (0, 0) |
292 | (0, 0) |
286 | } |
293 | } |
287 | |
294 | |
288 | sub draw { } |
295 | sub draw { } |
289 | |
296 | |
290 | ############################################################################# |
297 | ############################################################################# |
291 | |
298 | |
292 | package CFClient::Widget::Container; |
299 | package CFClient::UI::Container; |
293 | |
300 | |
294 | our @ISA = CFClient::Widget::; |
301 | our @ISA = CFClient::UI::Base::; |
295 | |
302 | |
296 | sub new { |
303 | sub new { |
297 | my ($class, %arg) = @_; |
304 | my ($class, %arg) = @_; |
298 | |
305 | |
299 | my $children = delete $arg{children} || []; |
306 | my $children = delete $arg{children} || []; |
… | |
… | |
349 | $_->draw for @{$self->{children}}; |
356 | $_->draw for @{$self->{children}}; |
350 | } |
357 | } |
351 | |
358 | |
352 | ############################################################################# |
359 | ############################################################################# |
353 | |
360 | |
354 | package CFClient::Widget::Bin; |
361 | package CFClient::UI::Bin; |
355 | |
362 | |
356 | our @ISA = CFClient::Widget::Container::; |
363 | our @ISA = CFClient::UI::Container::; |
357 | |
364 | |
358 | sub new { |
365 | sub new { |
359 | my ($class, %arg) = @_; |
366 | my ($class, %arg) = @_; |
360 | |
367 | |
361 | my $child = (delete $arg{child}) || new CFClient::Widget::Empty::; |
368 | my $child = (delete $arg{child}) || new CFClient::UI::Empty::; |
362 | |
369 | |
363 | $class->SUPER::new (children => [$child], %arg) |
370 | $class->SUPER::new (children => [$child], %arg) |
364 | } |
371 | } |
365 | |
372 | |
366 | sub add { |
373 | sub add { |
… | |
… | |
374 | sub remove { |
381 | sub remove { |
375 | my ($self, $widget) = @_; |
382 | my ($self, $widget) = @_; |
376 | |
383 | |
377 | $self->SUPER::remove ($widget); |
384 | $self->SUPER::remove ($widget); |
378 | |
385 | |
379 | $self->{children} = [new CFClient::Widget::Empty] |
386 | $self->{children} = [new CFClient::UI::Empty] |
380 | unless @{$self->{children}}; |
387 | unless @{$self->{children}}; |
381 | } |
388 | } |
382 | |
389 | |
383 | sub child { $_[0]->{children}[0] } |
390 | sub child { $_[0]->{children}[0] } |
384 | |
391 | |
… | |
… | |
395 | $self->{children}[0]->size_allocate ($w, $h); |
402 | $self->{children}[0]->size_allocate ($w, $h); |
396 | } |
403 | } |
397 | |
404 | |
398 | ############################################################################# |
405 | ############################################################################# |
399 | |
406 | |
400 | package CFClient::Widget::Window; |
407 | package CFClient::UI::Window; |
401 | |
408 | |
402 | our @ISA = CFClient::Widget::Bin::; |
409 | our @ISA = CFClient::UI::Bin::; |
403 | |
410 | |
404 | use SDL::OpenGL; |
411 | use SDL::OpenGL; |
405 | |
412 | |
406 | sub new { |
413 | sub new { |
407 | my ($class, %arg) = @_; |
414 | my ($class, %arg) = @_; |
… | |
… | |
446 | |
453 | |
447 | my $tex = $self->{texture} |
454 | my $tex = $self->{texture} |
448 | or return; |
455 | or return; |
449 | |
456 | |
450 | glEnable GL_BLEND; |
457 | glEnable GL_BLEND; |
|
|
458 | glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA; |
451 | glEnable GL_TEXTURE_2D; |
459 | glEnable GL_TEXTURE_2D; |
452 | glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; |
460 | glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; |
453 | |
461 | |
454 | $tex->draw_quad (0, 0, $w, $h); |
462 | $tex->draw_quad (0, 0, $w, $h); |
455 | |
463 | |
… | |
… | |
457 | glDisable GL_TEXTURE_2D; |
465 | glDisable GL_TEXTURE_2D; |
458 | } |
466 | } |
459 | |
467 | |
460 | ############################################################################# |
468 | ############################################################################# |
461 | |
469 | |
462 | package CFClient::Widget::Frame; |
470 | package CFClient::UI::Frame; |
463 | |
471 | |
464 | our @ISA = CFClient::Widget::Bin::; |
472 | our @ISA = CFClient::UI::Bin::; |
465 | |
473 | |
466 | use SDL::OpenGL; |
474 | use SDL::OpenGL; |
467 | |
475 | |
468 | sub size_request { |
476 | sub size_request { |
469 | my ($self) = @_; |
477 | my ($self) = @_; |
… | |
… | |
505 | $chld->draw; |
513 | $chld->draw; |
506 | } |
514 | } |
507 | |
515 | |
508 | ############################################################################# |
516 | ############################################################################# |
509 | |
517 | |
510 | package CFClient::Widget::FancyFrame; |
518 | package CFClient::UI::FancyFrame; |
511 | |
519 | |
512 | our @ISA = CFClient::Widget::Bin::; |
520 | our @ISA = CFClient::UI::Bin::; |
513 | |
521 | |
514 | use SDL::OpenGL; |
522 | use SDL::OpenGL; |
515 | |
523 | |
516 | my @tex = |
524 | my @tex = |
517 | map { new_from_file CFClient::Texture CFClient::find_rcfile $_ } |
525 | map { new_from_file CFClient::Texture CFClient::find_rcfile $_ } |
… | |
… | |
556 | |
564 | |
557 | my ($w, $h) = ($self->{w}, $self->{h}); |
565 | my ($w, $h) = ($self->{w}, $self->{h}); |
558 | my ($cw, $ch) = ($self->child->{w}, $self->child->{h}); |
566 | my ($cw, $ch) = ($self->child->{w}, $self->child->{h}); |
559 | |
567 | |
560 | glEnable GL_BLEND; |
568 | glEnable GL_BLEND; |
|
|
569 | glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA; |
561 | glEnable GL_TEXTURE_2D; |
570 | glEnable GL_TEXTURE_2D; |
562 | glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA; |
|
|
563 | glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; |
571 | glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; |
564 | |
572 | |
565 | my $top = $tex[1]; |
573 | my $top = $tex[1]; |
566 | $top->draw_quad (0, 0, $w, $top->{h}); |
574 | $top->draw_quad (0, 0, $w, $top->{h}); |
567 | |
575 | |
… | |
… | |
592 | |
600 | |
593 | } |
601 | } |
594 | |
602 | |
595 | ############################################################################# |
603 | ############################################################################# |
596 | |
604 | |
597 | package CFClient::Widget::Table; |
605 | package CFClient::UI::Table; |
598 | |
606 | |
599 | our @ISA = CFClient::Widget::; |
607 | our @ISA = CFClient::UI::Base::; |
600 | |
608 | |
601 | use SDL::OpenGL; |
609 | use SDL::OpenGL; |
602 | |
610 | |
603 | sub add { |
611 | sub add { |
604 | my ($self, $x, $y, $chld) = @_; |
612 | my ($self, $x, $y, $chld) = @_; |
… | |
… | |
679 | } |
687 | } |
680 | } |
688 | } |
681 | |
689 | |
682 | ############################################################################# |
690 | ############################################################################# |
683 | |
691 | |
684 | package CFClient::Widget::VBox; |
692 | package CFClient::UI::VBox; |
685 | |
693 | |
686 | our @ISA = CFClient::Widget::Container::; |
694 | our @ISA = CFClient::UI::Container::; |
687 | |
695 | |
688 | use SDL::OpenGL; |
696 | use SDL::OpenGL; |
689 | |
697 | |
690 | sub size_request { |
698 | sub size_request { |
691 | my ($self) = @_; |
699 | my ($self) = @_; |
… | |
… | |
743 | } |
751 | } |
744 | } |
752 | } |
745 | |
753 | |
746 | ############################################################################# |
754 | ############################################################################# |
747 | |
755 | |
748 | package CFClient::Widget::Label; |
756 | package CFClient::UI::Label; |
749 | |
757 | |
750 | our @ISA = CFClient::Widget::; |
758 | our @ISA = CFClient::UI::Base::; |
751 | |
759 | |
752 | use SDL::OpenGL; |
760 | use SDL::OpenGL; |
753 | |
761 | |
754 | sub new { |
762 | sub new { |
755 | my ($class, %arg) = @_; |
763 | my ($class, %arg) = @_; |
… | |
… | |
831 | sub _draw { |
839 | sub _draw { |
832 | my ($self) = @_; |
840 | my ($self) = @_; |
833 | |
841 | |
834 | my $tex = $self->{texture} ||= do { |
842 | my $tex = $self->{texture} ||= do { |
835 | $self->{layout}->set_width ($self->{w}); |
843 | $self->{layout}->set_width ($self->{w}); |
836 | new_from_layout CFClient::Texture $self->{layout}; |
844 | new_from_layout CFClient::Texture $self->{layout} |
837 | }; |
845 | }; |
838 | |
846 | |
839 | glEnable GL_BLEND; |
847 | glEnable GL_BLEND; |
|
|
848 | glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA; |
840 | glEnable GL_TEXTURE_2D; |
849 | glEnable GL_TEXTURE_2D; |
841 | glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA; |
|
|
842 | glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE; |
850 | glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE; |
843 | |
851 | |
844 | glColor @{$self->{fg}}; |
852 | glColor @{$self->{fg}}; |
845 | |
853 | |
846 | my $x = |
854 | my $x = |
847 | $self->{align} < 0 ? 0 |
855 | $self->{align} < 0 ? 0 |
848 | : $self->{align} > 0 ? $self->{w} - $self->{texture}{w} |
856 | : $self->{align} > 0 ? $self->{w} - $tex->{w} |
849 | : ($self->{w} + $self->{texture}{w}) * 0.5; |
857 | : ($self->{w} - $tex->{w}) * 0.5; |
850 | |
858 | |
851 | $tex->draw_quad ($x, 0); |
859 | $tex->draw_quad ($x, 0); |
852 | |
860 | |
|
|
861 | glDisable GL_TEXTURE_2D; |
853 | glDisable GL_BLEND; |
862 | glDisable GL_BLEND; |
854 | glDisable GL_TEXTURE_2D; |
863 | glGetError and die; |
855 | } |
864 | } |
856 | |
865 | |
857 | ############################################################################# |
866 | ############################################################################# |
858 | |
867 | |
859 | package CFClient::Widget::Entry; |
868 | package CFClient::UI::Entry; |
860 | |
869 | |
861 | our @ISA = CFClient::Widget::Label::; |
870 | our @ISA = CFClient::UI::Label::; |
862 | |
871 | |
863 | use SDL; |
872 | use SDL; |
864 | use SDL::OpenGL; |
873 | use SDL::OpenGL; |
865 | |
874 | |
866 | sub new { |
875 | sub new { |
… | |
… | |
1006 | } |
1015 | } |
1007 | } |
1016 | } |
1008 | |
1017 | |
1009 | ############################################################################# |
1018 | ############################################################################# |
1010 | |
1019 | |
1011 | package CFClient::Widget::Slider; |
1020 | package CFClient::UI::Slider; |
1012 | |
1021 | |
1013 | use strict; |
1022 | use strict; |
1014 | |
1023 | |
1015 | use SDL::OpenGL; |
1024 | use SDL::OpenGL; |
1016 | use SDL::OpenGL::Constants; |
|
|
1017 | |
1025 | |
1018 | our @ISA = CFClient::Widget::DrawBG::; |
1026 | our @ISA = CFClient::UI::DrawBG::; |
1019 | |
1027 | |
1020 | sub size_request { |
1028 | sub size_request { |
1021 | my ($self) = @_; |
1029 | my ($self) = @_; |
1022 | |
1030 | |
1023 | my $w = 50; |
1031 | my $w = 50; |
… | |
… | |
1120 | glEnd; |
1128 | glEnd; |
1121 | } |
1129 | } |
1122 | |
1130 | |
1123 | ############################################################################# |
1131 | ############################################################################# |
1124 | |
1132 | |
1125 | package CFClient::Widget::MapWidget; |
1133 | package CFClient::UI::MapWidget; |
1126 | |
1134 | |
1127 | use strict; |
1135 | use strict; |
1128 | |
1136 | |
1129 | use List::Util qw(min max); |
1137 | use List::Util qw(min max); |
1130 | |
1138 | |
1131 | use SDL; |
1139 | use SDL; |
1132 | use SDL::OpenGL; |
1140 | use SDL::OpenGL; |
1133 | use SDL::OpenGL::Constants; |
|
|
1134 | |
1141 | |
1135 | our @ISA = CFClient::Widget::; |
1142 | our @ISA = CFClient::UI::Base::; |
1136 | |
1143 | |
1137 | sub new { |
1144 | sub new { |
1138 | my $class = shift; |
1145 | my $class = shift; |
1139 | |
1146 | |
1140 | $class->SUPER::new ( |
1147 | $class->SUPER::new ( |
… | |
… | |
1160 | |
1167 | |
1161 | sub update { |
1168 | sub update { |
1162 | my ($self) = @_; |
1169 | my ($self) = @_; |
1163 | |
1170 | |
1164 | $self->{need_update} = 1; |
1171 | $self->{need_update} = 1; |
|
|
1172 | $self->SUPER::update; |
1165 | } |
1173 | } |
1166 | |
1174 | |
1167 | sub _draw { |
1175 | sub _draw { |
1168 | my ($self) = @_; |
1176 | my ($self) = @_; |
1169 | |
1177 | |
… | |
… | |
1192 | $yofs = $self->{yofs} = min $my, max $my + $::CONN->{maph} - $sh + 1, $self->{yofs}; |
1200 | $yofs = $self->{yofs} = min $my, max $my + $::CONN->{maph} - $sh + 1, $self->{yofs}; |
1193 | } |
1201 | } |
1194 | |
1202 | |
1195 | glEnable GL_TEXTURE_2D; |
1203 | glEnable GL_TEXTURE_2D; |
1196 | glEnable GL_BLEND; |
1204 | glEnable GL_BLEND; |
|
|
1205 | glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA; |
1197 | glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; |
1206 | glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; |
1198 | |
1207 | |
1199 | my $sw4 = ($sw + 3) & ~3; |
1208 | my $sw4 = ($sw + 3) & ~3; |
1200 | my $darkness = "\x00" x ($sw4 * $sh); |
1209 | my $darkness = "\x00" x ($sw4 * $sh); |
1201 | |
1210 | |
… | |
… | |
1231 | # |
1240 | # |
1232 | # $lighting = $pb->get_pixels; |
1241 | # $lighting = $pb->get_pixels; |
1233 | # $lighting =~ s/(.)../$1/gs; |
1242 | # $lighting =~ s/(.)../$1/gs; |
1234 | # } |
1243 | # } |
1235 | |
1244 | |
1236 | glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA; |
|
|
1237 | glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE; |
1245 | glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE; |
1238 | |
1246 | |
1239 | $darkness = new CFClient::Texture |
1247 | $darkness = new CFClient::Texture |
1240 | width => $sw4, |
1248 | w => $sw4, |
1241 | height => $sh, |
1249 | h => $sh, |
1242 | data => $darkness, |
1250 | data => $darkness, |
1243 | internalformat => GL_ALPHA, |
1251 | internalformat => GL_ALPHA, |
1244 | format => GL_ALPHA; |
1252 | format => GL_ALPHA; |
1245 | |
1253 | |
1246 | glColor 0.45, 0.45, 0.45, 1; |
1254 | glColor 0.45, 0.45, 0.45, 1; |
… | |
… | |
1306 | } |
1314 | } |
1307 | } |
1315 | } |
1308 | |
1316 | |
1309 | ############################################################################# |
1317 | ############################################################################# |
1310 | |
1318 | |
1311 | package CFClient::Widget::Animator; |
1319 | package CFClient::UI::Animator; |
1312 | |
1320 | |
1313 | use SDL::OpenGL; |
1321 | use SDL::OpenGL; |
1314 | |
1322 | |
1315 | our @ISA = CFClient::Widget::Bin::; |
1323 | our @ISA = CFClient::UI::Bin::; |
1316 | |
1324 | |
1317 | sub moveto { |
1325 | sub moveto { |
1318 | my ($self, $x, $y) = @_; |
1326 | my ($self, $x, $y) = @_; |
1319 | |
1327 | |
1320 | $self->{moveto} = [$self->{x}, $self->{y}, $x, $y]; |
1328 | $self->{moveto} = [$self->{x}, $self->{y}, $x, $y]; |
… | |
… | |
1348 | glPopMatrix; |
1356 | glPopMatrix; |
1349 | } |
1357 | } |
1350 | |
1358 | |
1351 | ############################################################################# |
1359 | ############################################################################# |
1352 | |
1360 | |
1353 | package CFClient::Widget::Toplevel; |
1361 | package CFClient::UI::Toplevel; |
1354 | |
1362 | |
1355 | our @ISA = CFClient::Widget::Container::; |
1363 | our @ISA = CFClient::UI::Container::; |
1356 | |
1364 | |
1357 | sub size_request { |
1365 | sub size_request { |
1358 | ($::WIDTH, $::HEIGHT) |
1366 | ($::WIDTH, $::HEIGHT) |
1359 | } |
1367 | } |
1360 | |
1368 | |
… | |
… | |
1394 | $self->_draw; |
1402 | $self->_draw; |
1395 | } |
1403 | } |
1396 | |
1404 | |
1397 | ############################################################################# |
1405 | ############################################################################# |
1398 | |
1406 | |
1399 | package CFClient::Widget; |
1407 | package CFClient::UI; |
1400 | |
1408 | |
1401 | $TOPLEVEL = new CFClient::Widget::Toplevel; |
1409 | $TOPLEVEL = new CFClient::UI::Toplevel; |
1402 | |
1410 | |
1403 | 1 |
1411 | 1 |
1404 | |
1412 | |