ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/DC/UI.pm
(Generate patch)

Comparing deliantra/Deliantra-Client/DC/UI.pm (file contents):
Revision 1.262 by elmex, Wed May 31 13:44:26 2006 UTC vs.
Revision 1.269 by root, Fri Jun 2 06:22:55 2006 UTC

40 40
41 $LAYOUT = $layout; 41 $LAYOUT = $layout;
42} 42}
43 43
44sub check_tooltip { 44sub check_tooltip {
45 return if $ENV{CFPLUS_DEBUG} & 8;
46
45 if (!$GRAB) { 47 if (!$GRAB) {
46 for (my $widget = $HOVER; $widget; $widget = $widget->{parent}) { 48 for (my $widget = $HOVER; $widget; $widget = $widget->{parent}) {
47 if (length $widget->{tooltip}) { 49 if (length $widget->{tooltip}) {
48
49 if ($TOOLTIP->{owner} != $widget) { 50 if ($TOOLTIP->{owner} != $widget) {
50 $TOOLTIP->hide; 51 $TOOLTIP->hide;
51 52
52 $TOOLTIP->{owner} = $widget; 53 $TOOLTIP->{owner} = $widget;
53 54
170sub rescale_widgets { 171sub rescale_widgets {
171 my ($sx, $sy) = @_; 172 my ($sx, $sy) = @_;
172 173
173 for my $widget (values %WIDGET) { 174 for my $widget (values %WIDGET) {
174 if ($widget->{is_toplevel}) { 175 if ($widget->{is_toplevel}) {
175 $widget->{x} += $widget->{w} * 0.5 if $widget->{x} =~ /^[0-9.]+$/; 176 $widget->{x} += int $widget->{w} * 0.5 if $widget->{x} =~ /^[0-9.]+$/;
176 $widget->{y} += $widget->{h} * 0.5 if $widget->{y} =~ /^[0-9.]+$/; 177 $widget->{y} += int $widget->{h} * 0.5 if $widget->{y} =~ /^[0-9.]+$/;
177 178
178 $widget->{x} = int 0.5 + $widget->{x} * $sx if $widget->{x} =~ /^[0-9.]+$/; 179 $widget->{x} = int 0.5 + $widget->{x} * $sx if $widget->{x} =~ /^[0-9.]+$/;
179 $widget->{w} = int 0.5 + $widget->{w} * $sx if exists $widget->{w}; 180 $widget->{w} = int 0.5 + $widget->{w} * $sx if exists $widget->{w};
180 $widget->{force_w} = int 0.5 + $widget->{force_w} * $sx if exists $widget->{force_w}; 181 $widget->{force_w} = int 0.5 + $widget->{force_w} * $sx if exists $widget->{force_w};
181 $widget->{y} = int 0.5 + $widget->{y} * $sy if $widget->{y} =~ /^[0-9.]+$/; 182 $widget->{y} = int 0.5 + $widget->{y} * $sy if $widget->{y} =~ /^[0-9.]+$/;
182 $widget->{h} = int 0.5 + $widget->{h} * $sy if exists $widget->{h}; 183 $widget->{h} = int 0.5 + $widget->{h} * $sy if exists $widget->{h};
183 $widget->{force_h} = int 0.5 + $widget->{force_h} * $sy if exists $widget->{force_h}; 184 $widget->{force_h} = int 0.5 + $widget->{force_h} * $sy if exists $widget->{force_h};
184 185
185 $widget->{x} -= $widget->{w} * 0.5 if $widget->{x} =~ /^[0-9.]+$/; 186 $widget->{x} -= int $widget->{w} * 0.5 if $widget->{x} =~ /^[0-9.]+$/;
186 $widget->{y} -= $widget->{h} * 0.5 if $widget->{y} =~ /^[0-9.]+$/; 187 $widget->{y} -= int $widget->{h} * 0.5 if $widget->{y} =~ /^[0-9.]+$/;
187 188
188 } 189 }
189 } 190 }
190 191
191 reconfigure_widgets; 192 reconfigure_widgets;
449 my ($self, $ev, $x, $y) = @_; 450 my ($self, $ev, $x, $y) = @_;
450 451
451 $self->focus_in; 452 $self->focus_in;
452} 453}
453 454
454sub w { $_[0]{w} = $_[1] if @_ > 1; $_[0]{w} }
455sub h { $_[0]{h} = $_[1] if @_ > 1; $_[0]{h} }
456sub x { $_[0]{x} = $_[1] if @_ > 1; $_[0]{x} }
457sub y { $_[0]{y} = $_[1] if @_ > 1; $_[0]{y} }
458sub z { $_[0]{z} = $_[1] if @_ > 1; $_[0]{z} }
459
460sub find_widget { 455sub find_widget {
461 my ($self, $x, $y) = @_; 456 my ($self, $x, $y) = @_;
462 457
463 return () unless $self->{can_events}; 458 return () unless $self->{can_events};
464 459
525 520
526 $self->realloc; 521 $self->realloc;
527 $self->update; 522 $self->update;
528} 523}
529 524
525# using global variables seems a bit hacky, but passing through all drawing
526# functions seems pointless.
527our ($draw_x, $draw_y, $draw_w, $draw_h); # screen rectangle being drawn
528
530sub draw { 529sub draw {
531 my ($self) = @_; 530 my ($self) = @_;
532 531
533 return unless $self->{h} && $self->{w}; 532 return unless $self->{h} && $self->{w};
533
534 # update screen rectangle
535 local $draw_x = $draw_x + $self->{x};
536 local $draw_y = $draw_y + $self->{y};
537 local $draw_w = $draw_x + $self->{w};
538 local $draw_h = $draw_y + $self->{h};
539
540 # skip widgets that are entirely outside the drawing area
541 return if ($draw_x + $self->{w} < 0) || ($draw_x >= $draw_w)
542 || ($draw_y + $self->{h} < 0) || ($draw_y >= $draw_h);
534 543
535 glPushMatrix; 544 glPushMatrix;
536 glTranslate $self->{x}, $self->{y}, 0; 545 glTranslate $self->{x}, $self->{y}, 0;
537 $self->_draw; 546 $self->_draw;
538 glPopMatrix; 547 glPopMatrix;
803 $self->SUPER::size_allocate ($w, $h); 812 $self->SUPER::size_allocate ($w, $h);
804 $self->update; 813 $self->update;
805} 814}
806 815
807sub _render { 816sub _render {
817 my ($self) = @_;
818
808 $_[0]{children}[0]->draw; 819 $self->{children}[0]->draw;
809} 820}
810 821
811sub render_child { 822sub render_child {
812 my ($self) = @_; 823 my ($self) = @_;
813 824
814 $self->{texture} = new_from_opengl CFClient::Texture $self->{w}, $self->{h}, sub { 825 $self->{texture} = new_from_opengl CFClient::Texture $self->{w}, $self->{h}, sub {
815 glClearColor 0, 0, 0, 0; 826 glClearColor 0, 0, 0, 0;
816 glClear GL_COLOR_BUFFER_BIT; 827 glClear GL_COLOR_BUFFER_BIT;
817 828
829 {
830 package CFClient::UI::Base;
831
832 ($draw_x, $draw_y, $draw_w, $draw_h) =
833 (0, 0, $self->{w}, $self->{h});
834 }
835
818 $self->_render; 836 $self->_render;
819 }; 837 };
820} 838}
821 839
822sub _draw { 840sub _draw {
823 my ($self) = @_; 841 my ($self) = @_;
824 842
825 my ($w, $h) = ($self->w, $self->h); 843 my ($w, $h) = @$self{qw(w h)};
826 844
827 my $tex = $self->{texture} 845 my $tex = $self->{texture}
828 or return; 846 or return;
829 847
830 glEnable GL_TEXTURE_2D; 848 glEnable GL_TEXTURE_2D;
912 } 930 }
913} 931}
914 932
915sub _render { 933sub _render {
916 my ($self) = @_; 934 my ($self) = @_;
935
936 local $CFClient::UI::Base::draw_x = $CFClient::UI::Base::draw_x - $self->{view_x};
937 local $CFClient::UI::Base::draw_y = $CFClient::UI::Base::draw_y - $self->{view_y};
917 938
918 CFClient::OpenGL::glTranslate -$self->{view_x}, -$self->{view_y}; 939 CFClient::OpenGL::glTranslate -$self->{view_x}, -$self->{view_y};
919 940
920 $self->SUPER::_render; 941 $self->SUPER::_render;
921} 942}
1029my @border = 1050my @border =
1030 map { new_from_file CFClient::Texture CFClient::find_rcfile $_, mipmap => 1 } 1051 map { new_from_file CFClient::Texture CFClient::find_rcfile $_, mipmap => 1 }
1031 qw(d1_border_top.png d1_border_right.png d1_border_left.png d1_border_bottom.png); 1052 qw(d1_border_top.png d1_border_right.png d1_border_left.png d1_border_bottom.png);
1032 1053
1033sub new { 1054sub new {
1034 my $class = shift; 1055 my ($class, %arg) = @_;
1056
1057 my $title = delete $arg{title};
1035 1058
1036 my $self = $class->SUPER::new ( 1059 my $self = $class->SUPER::new (
1037 bg => [1, 1, 1, 1], 1060 bg => [1, 1, 1, 1],
1038 border_bg => [1, 1, 1, 1], 1061 border_bg => [1, 1, 1, 1],
1039 border => 0.6, 1062 border => 0.6,
1040 can_events => 1, 1063 can_events => 1,
1041 min_w => 16, 1064 min_w => 16,
1042 min_h => 16, 1065 min_h => 16,
1043 @_ 1066 %arg,
1044 ); 1067 );
1045 1068
1046 $self->{title} &&= new CFClient::UI::Label 1069 $self->{title} = new CFClient::UI::Label
1047 align => 0, 1070 align => 0,
1048 valign => 1, 1071 valign => 1,
1049 text => $self->{title}, 1072 text => $title,
1050 fontsize => $self->{border}; 1073 fontsize => $self->{border}
1074 if defined $title;
1051 1075
1052 $self 1076 $self
1077}
1078
1079sub add {
1080 my ($self, @widgets) = @_;
1081
1082 $self->SUPER::add (@widgets);
1083 $self->CFClient::UI::Container::add ($self->{title}) if $self->{title};
1053} 1084}
1054 1085
1055sub border { 1086sub border {
1056 int $_[0]{border} * $::FONTSIZE 1087 int $_[0]{border} * $::FONTSIZE
1057} 1088}
1058 1089
1059sub size_request { 1090sub size_request {
1060 my ($self) = @_; 1091 my ($self) = @_;
1092
1093 $self->{title}->size_request
1094 if $self->{title};
1061 1095
1062 my ($w, $h) = $self->SUPER::size_request; 1096 my ($w, $h) = $self->SUPER::size_request;
1063 1097
1064 ( 1098 (
1065 $w + $self->border * 2, 1099 $w + $self->border * 2,
1068} 1102}
1069 1103
1070sub size_allocate { 1104sub size_allocate {
1071 my ($self, $w, $h) = @_; 1105 my ($self, $w, $h) = @_;
1072 1106
1107 if ($self->{title}) {
1108 $self->{title}{w} = $w;
1109 $self->{title}{h} = $h;
1110 $self->{title}->size_allocate ($w, $h);
1111 }
1112
1113 my $border = $self->border;
1114
1073 $h -= List::Util::max 0, $self->border * 2; 1115 $h -= List::Util::max 0, $border * 2;
1074 $w -= List::Util::max 0, $self->border * 2; 1116 $w -= List::Util::max 0, $border * 2;
1075 1117
1076 $self->{title}->configure ($self->border, int $self->border - $::FONTSIZE * 2, $w, int $::FONTSIZE * 2)
1077 if $self->{title};
1078
1079 $self->child->configure ($self->border, $self->border, $w, $h); 1118 $self->child->configure ($border, $border, $w, $h);
1080} 1119}
1081 1120
1082sub button_down { 1121sub button_down {
1083 my ($self, $ev, $x, $y) = @_; 1122 my ($self, $ev, $x, $y) = @_;
1084 1123
1136} 1175}
1137 1176
1138sub _draw { 1177sub _draw {
1139 my ($self) = @_; 1178 my ($self) = @_;
1140 1179
1180 my $child = $self->{children}[0];
1181
1141 my ($w, $h ) = ($self->{w}, $self->{h}); 1182 my ($w, $h ) = ($self->{w}, $self->{h});
1142 my ($cw, $ch) = ($self->child->{w}, $self->child->{h}); 1183 my ($cw, $ch) = ($child->{w}, $child->{h});
1143 1184
1144 glEnable GL_TEXTURE_2D; 1185 glEnable GL_TEXTURE_2D;
1145 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE; 1186 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE;
1146 1187
1147 my $border = $self->border; 1188 my $border = $self->border;
1162 $bg->draw_quad_alpha ($border, $border, $cw, $ch); 1203 $bg->draw_quad_alpha ($border, $border, $cw, $ch);
1163 } 1204 }
1164 1205
1165 glDisable GL_TEXTURE_2D; 1206 glDisable GL_TEXTURE_2D;
1166 1207
1167 $self->{title}->draw if $self->{title};
1168
1169 $self->child->draw; 1208 $child->draw;
1209
1210 if ($self->{title}) {
1211 glTranslate 0, $border - $self->{h};
1212 $self->{title}->_draw;
1213 }
1170} 1214}
1171 1215
1172############################################################################# 1216#############################################################################
1173 1217
1174package CFClient::UI::Table; 1218package CFClient::UI::Table;
1522} 1566}
1523 1567
1524sub size_allocate { 1568sub size_allocate {
1525 my ($self, $w, $h) = @_; 1569 my ($self, $w, $h) = @_;
1526 1570
1571 delete $self->{ox};
1572
1527 delete $self->{texture}; 1573 delete $self->{texture}
1574 unless $w >= $self->{req_w} && $self->{old_w} >= $self->{req_w};
1528} 1575}
1529 1576
1530sub set_fontsize { 1577sub set_fontsize {
1531 my ($self, $fontsize) = @_; 1578 my ($self, $fontsize) = @_;
1532 1579
1547 $self->{layout}->set_width ($self->{w}); 1594 $self->{layout}->set_width ($self->{w});
1548 $self->{layout}->set_ellipsise ($self->{ellipsise}); 1595 $self->{layout}->set_ellipsise ($self->{ellipsise});
1549 $self->{layout}->set_single_paragraph_mode ($self->{ellipsise}); 1596 $self->{layout}->set_single_paragraph_mode ($self->{ellipsise});
1550 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); 1597 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE);
1551 1598
1552 my $tex = new_from_layout CFClient::Texture $self->{layout}; 1599 new_from_layout CFClient::Texture $self->{layout}
1600 };
1553 1601
1602 unless (exists $self->{ox}) {
1554 $self->{ox} = int ($self->{align} < 0 ? $self->{padding_x} 1603 $self->{ox} = int ($self->{align} < 0 ? $self->{padding_x}
1555 : $self->{align} > 0 ? $self->{w} - $tex->{w} - $self->{padding_x} 1604 : $self->{align} > 0 ? $self->{w} - $tex->{w} - $self->{padding_x}
1556 : ($self->{w} - $tex->{w}) * 0.5); 1605 : ($self->{w} - $tex->{w}) * 0.5);
1557 1606
1558 $self->{oy} = int ($self->{valign} < 0 ? $self->{padding_y} 1607 $self->{oy} = int ($self->{valign} < 0 ? $self->{padding_y}
1559 : $self->{valign} > 0 ? $self->{h} - $tex->{h} - $self->{padding_y} 1608 : $self->{valign} > 0 ? $self->{h} - $tex->{h} - $self->{padding_y}
1560 : ($self->{h} - $tex->{h}) * 0.5); 1609 : ($self->{h} - $tex->{h}) * 0.5);
1561
1562 $tex
1563 }; 1610 };
1564 1611
1565 glEnable GL_TEXTURE_2D; 1612 glEnable GL_TEXTURE_2D;
1566 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; 1613 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE;
1567 1614
2776 2823
2777 $self->{timer}->cancel 2824 $self->{timer}->cancel
2778 if $self->{timer}; 2825 if $self->{timer};
2779 2826
2780 $self->SUPER::DESTROY; 2827 $self->SUPER::DESTROY;
2781}
2782
2783#############################################################################
2784
2785package CFClient::UI::Inventory;
2786
2787our @ISA = CFClient::UI::ScrolledWindow::;
2788
2789sub new {
2790 my $class = shift;
2791
2792 my $self = $class->SUPER::new (
2793 scrolled => (new CFClient::UI::Table col_expand => [0, 1, 0]),
2794 @_,
2795 );
2796
2797 $self
2798}
2799
2800sub set_items {
2801 my ($self, $items) = @_;
2802
2803 $self->{scrolled}->clear;
2804 return unless $items;
2805
2806 my @items = sort {
2807 ($a->{type} <=> $b->{type})
2808 or ($a->{name} cmp $b->{name})
2809 } @$items;
2810
2811 $self->{real_items} = \@items;
2812
2813 my $row = 0;
2814 for my $item (@items) {
2815 CFClient::Item::update_widgets $item;
2816
2817 $self->{scrolled}->add (0, $row, $item->{face_widget});
2818 $self->{scrolled}->add (1, $row, $item->{desc_widget});
2819 $self->{scrolled}->add (2, $row, $item->{weight_widget});
2820
2821 $row++;
2822 }
2823} 2828}
2824 2829
2825############################################################################# 2830#############################################################################
2826 2831
2827package CFClient::UI::Menu; 2832package CFClient::UI::Menu;
3004 $self->SUPER::reconfigure; 3009 $self->SUPER::reconfigure;
3005} 3010}
3006 3011
3007############################################################################# 3012#############################################################################
3008 3013
3009package CFClient::UI::Root; 3014package CFClient::UI::Inventory;
3010 3015
3011our @ISA = CFClient::UI::Container::; 3016our @ISA = CFClient::UI::ScrolledWindow::;
3012
3013use CFClient::OpenGL;
3014 3017
3015sub new { 3018sub new {
3016 my $class = shift; 3019 my $class = shift;
3017 3020
3018 my $self = $class->SUPER::new ( 3021 my $self = $class->SUPER::new (
3019 visible => 1, 3022 scrolled => (new CFClient::UI::Table col_expand => [0, 1, 0]),
3020 @_, 3023 @_,
3021 ); 3024 );
3022 3025
3023 Scalar::Util::weaken ($self->{root} = $self);
3024
3025 $self 3026 $self
3026} 3027}
3027 3028
3028sub size_request { 3029sub set_items {
3029 my ($self) = @_; 3030 my ($self, $items) = @_;
3030 3031
3031 ($self->{w}, $self->{h}) 3032 $self->{scrolled}->clear;
3032} 3033 return unless $items;
3033 3034
3034sub _to_pixel { 3035 my @items = sort {
3035 my ($coord, $size, $max) = @_; 3036 ($a->{type} <=> $b->{type})
3037 or ($a->{name} cmp $b->{name})
3038 } @$items;
3036 3039
3037 $coord = 3040 $self->{real_items} = \@items;
3038 $coord eq "center" ? ($max - $size) * 0.5
3039 : $coord eq "max" ? $max
3040 : $coord;
3041 3041
3042 $coord = 0 if $coord < 0; 3042 my $row = 0;
3043 $coord = $max - $size if $coord > $max - $size; 3043 for my $item (@items) {
3044 CFClient::Item::update_widgets $item;
3044 3045
3045 int $coord + 0.5 3046 $self->{scrolled}->add (0, $row, $item->{face_widget});
3046} 3047 $self->{scrolled}->add (1, $row, $item->{desc_widget});
3048 $self->{scrolled}->add (2, $row, $item->{weight_widget});
3047 3049
3048sub size_allocate { 3050 $row++;
3049 my ($self, $w, $h) = @_;
3050
3051 for my $child ($self->children) {
3052 my ($X, $Y, $W, $H) = @$child{qw(x y req_w req_h)};
3053
3054 $X = $child->{force_x} if exists $child->{force_x};
3055 $Y = $child->{force_y} if exists $child->{force_y};
3056
3057 $X = _to_pixel $X, $W, $self->{w};
3058 $Y = _to_pixel $Y, $H, $self->{h};
3059
3060 $child->configure ($X, $Y, $W, $H);
3061 } 3051 }
3062}
3063
3064sub coord2local {
3065 my ($self, $x, $y) = @_;
3066
3067 ($x, $y)
3068}
3069
3070sub coord2global {
3071 my ($self, $x, $y) = @_;
3072
3073 ($x, $y)
3074}
3075
3076sub update {
3077 my ($self) = @_;
3078
3079 $::WANT_REFRESH++;
3080}
3081
3082sub add {
3083 my ($self, @children) = @_;
3084
3085 $_->{is_toplevel} = 1
3086 for @children;
3087
3088 $self->SUPER::add (@children);
3089}
3090
3091sub remove {
3092 my ($self, @children) = @_;
3093
3094 $self->SUPER::remove (@children);
3095
3096 delete $self->{is_toplevel}
3097 for @children;
3098
3099 while (@children) {
3100 my $w = pop @children;
3101 push @children, $w->children;
3102 $w->set_invisible;
3103 }
3104}
3105
3106sub on_refresh {
3107 my ($self, $id, $cb) = @_;
3108
3109 $self->{refresh_hook}{$id} = $cb;
3110}
3111
3112sub on_post_alloc {
3113 my ($self, $id, $cb) = @_;
3114
3115 $self->{post_alloc_hook}{$id} = $cb;
3116}
3117
3118sub draw {
3119 my ($self) = @_;
3120
3121 while ($self->{refresh_hook}) {
3122 $_->()
3123 for values %{delete $self->{refresh_hook}};
3124 }
3125
3126 if ($self->{realloc}) {
3127 my @queue;
3128
3129 while () {
3130 if ($self->{realloc}) {
3131 #TODO use array-of-depth approach
3132
3133 use sort 'stable';
3134
3135 @queue = sort { $a->{visible} <=> $b->{visible} }
3136 @queue, values %{delete $self->{realloc}};
3137 }
3138
3139 my $widget = pop @queue || last;
3140
3141 $widget->{visible} or last; # do not resize invisible widgets
3142
3143 my ($w, $h) = $widget->size_request;
3144
3145 $w = List::Util::max $widget->{min_w}, $w + $widget->{padding_x} * 2;
3146 $h = List::Util::max $widget->{min_h}, $h + $widget->{padding_y} * 2;
3147
3148 $w = $widget->{force_w} if exists $widget->{force_w};
3149 $h = $widget->{force_h} if exists $widget->{force_h};
3150
3151 if ($widget->{req_w} != $w || $widget->{req_h} != $h
3152 || delete $widget->{force_realloc}) {
3153 $widget->{req_w} = $w;
3154 $widget->{req_h} = $h;
3155
3156 $self->{size_alloc}{$widget+0} = $widget;
3157
3158 if (my $parent = $widget->{parent}) {
3159 $self->{realloc}{$parent+0} = $parent;
3160 #unshift @queue, $parent;
3161 $parent->{force_size_alloc} = 1;
3162 $self->{size_alloc}{$parent+0} = $parent;
3163 }
3164 }
3165
3166 delete $self->{realloc}{$widget+0};
3167 }
3168 }
3169
3170 while (my $size_alloc = delete $self->{size_alloc}) {
3171 my @queue = sort { $b->{visible} <=> $a->{visible} }
3172 values %$size_alloc;
3173
3174 while () {
3175 my $widget = pop @queue || last;
3176
3177 my ($w, $h) = @$widget{qw(alloc_w alloc_h)};
3178
3179 $w = 0 if $w < 0;
3180 $h = 0 if $h < 0;
3181
3182 $w = int $w + 0.5;
3183 $h = int $h + 0.5;
3184
3185 if ($widget->{w} != $w || $widget->{h} != $h || delete $widget->{force_size_alloc}) {
3186 $widget->{w} = $w;
3187 $widget->{h} = $h;
3188
3189 $widget->emit (size_allocate => $w, $h);
3190 }
3191 }
3192 }
3193
3194 while ($self->{post_alloc_hook}) {
3195 $_->()
3196 for values %{delete $self->{post_alloc_hook}};
3197 }
3198
3199
3200 glViewport 0, 0, $::WIDTH, $::HEIGHT;
3201 glClearColor +($::CFG->{fow_intensity}) x 3, 1;
3202 glClear GL_COLOR_BUFFER_BIT;
3203
3204 glMatrixMode GL_PROJECTION;
3205 glLoadIdentity;
3206 glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000, 10000;
3207 glMatrixMode GL_MODELVIEW;
3208 glLoadIdentity;
3209
3210 $self->_draw;
3211} 3052}
3212 3053
3213############################################################################# 3054#############################################################################
3214 3055
3215package CFClient::UI::BindEditor; 3056package CFClient::UI::BindEditor;
3386 3227
3387 for (@$cmds) { 3228 for (@$cmds) {
3388 $self->{cmdbox}->add (my $hb = new CFClient::UI::HBox); 3229 $self->{cmdbox}->add (my $hb = new CFClient::UI::HBox);
3389 3230
3390 my $i = $idx; 3231 my $i = $idx;
3232 $hb->add (new CFClient::UI::Label text => $_);
3391 $hb->add (new CFClient::UI::Button 3233 $hb->add (new CFClient::UI::Button
3392 text => "delete", 3234 text => "delete",
3393 tooltip => "Deletes the action from the record", 3235 tooltip => "Deletes the action from the record",
3394 on_activate => sub { 3236 on_activate => sub {
3395 $self->{cmdbox}->remove ($hb); 3237 $self->{cmdbox}->remove ($hb);
3396 $cmds->[$i] = undef; 3238 $cmds->[$i] = undef;
3397 }); 3239 });
3398 3240
3399 $hb->add (new CFClient::UI::Label text => $_);
3400 3241
3401 $idx++ 3242 $idx++
3402 } 3243 }
3403} 3244}
3404
3405 3245
3406############################################################################# 3246#############################################################################
3407 3247
3408package CFClient::UI::SpellList; 3248package CFClient::UI::SpellList;
3409 3249
3435 text => $spell->{name}, 3275 text => $spell->{name},
3436 can_hover => 1, 3276 can_hover => 1,
3437 can_events => 1, 3277 can_events => 1,
3438 tooltip => $spell->{message}, 3278 tooltip => $spell->{message},
3439 expand => 1); 3279 expand => 1);
3280
3281 $self->{spellbox}->add (2, $self->{tbl_idx}, new CFClient::UI::Label
3282 text => (sprintf "lvl: %2d sp: %2d dmg: %2d",
3283 $spell->{level}, ($spell->{mana} || $spell->{grace}), $spell->{damage}),
3284 expand => 1);
3285
3440 $self->{spellbox}->add (2, $self->{tbl_idx}++, new CFClient::UI::Button 3286 $self->{spellbox}->add (3, $self->{tbl_idx}++, new CFClient::UI::Button
3441 text => "bind to key", 3287 text => "bind to key",
3442 on_activate => sub { $::BIND_EDITOR->do_quick_binding (["cast $spell->{name}"]) }); 3288 on_activate => sub { $::BIND_EDITOR->do_quick_binding (["cast $spell->{name}"]) });
3443} 3289}
3444 3290
3445sub rebuild_spell_list { 3291sub rebuild_spell_list {
3454 $self->rebuild_spell_list; 3300 $self->rebuild_spell_list;
3455} 3301}
3456 3302
3457############################################################################# 3303#############################################################################
3458 3304
3305package CFClient::UI::Root;
3306
3307our @ISA = CFClient::UI::Container::;
3308
3309use CFClient::OpenGL;
3310
3311sub new {
3312 my $class = shift;
3313
3314 my $self = $class->SUPER::new (
3315 visible => 1,
3316 @_,
3317 );
3318
3319 Scalar::Util::weaken ($self->{root} = $self);
3320
3321 $self
3322}
3323
3324sub size_request {
3325 my ($self) = @_;
3326
3327 ($self->{w}, $self->{h})
3328}
3329
3330sub _to_pixel {
3331 my ($coord, $size, $max) = @_;
3332
3333 $coord =
3334 $coord eq "center" ? ($max - $size) * 0.5
3335 : $coord eq "max" ? $max
3336 : $coord;
3337
3338 $coord = 0 if $coord < 0;
3339 $coord = $max - $size if $coord > $max - $size;
3340
3341 int $coord + 0.5
3342}
3343
3344sub size_allocate {
3345 my ($self, $w, $h) = @_;
3346
3347 for my $child ($self->children) {
3348 my ($X, $Y, $W, $H) = @$child{qw(x y req_w req_h)};
3349
3350 $X = $child->{force_x} if exists $child->{force_x};
3351 $Y = $child->{force_y} if exists $child->{force_y};
3352
3353 $X = _to_pixel $X, $W, $self->{w};
3354 $Y = _to_pixel $Y, $H, $self->{h};
3355
3356 $child->configure ($X, $Y, $W, $H);
3357 }
3358}
3359
3360sub coord2local {
3361 my ($self, $x, $y) = @_;
3362
3363 ($x, $y)
3364}
3365
3366sub coord2global {
3367 my ($self, $x, $y) = @_;
3368
3369 ($x, $y)
3370}
3371
3372sub update {
3373 my ($self) = @_;
3374
3375 $::WANT_REFRESH++;
3376}
3377
3378sub add {
3379 my ($self, @children) = @_;
3380
3381 $_->{is_toplevel} = 1
3382 for @children;
3383
3384 $self->SUPER::add (@children);
3385}
3386
3387sub remove {
3388 my ($self, @children) = @_;
3389
3390 $self->SUPER::remove (@children);
3391
3392 delete $self->{is_toplevel}
3393 for @children;
3394
3395 while (@children) {
3396 my $w = pop @children;
3397 push @children, $w->children;
3398 $w->set_invisible;
3399 }
3400}
3401
3402sub on_refresh {
3403 my ($self, $id, $cb) = @_;
3404
3405 $self->{refresh_hook}{$id} = $cb;
3406}
3407
3408sub on_post_alloc {
3409 my ($self, $id, $cb) = @_;
3410
3411 $self->{post_alloc_hook}{$id} = $cb;
3412}
3413
3414sub draw {
3415 my ($self) = @_;
3416
3417 while ($self->{refresh_hook}) {
3418 $_->()
3419 for values %{delete $self->{refresh_hook}};
3420 }
3421
3422 if ($self->{realloc}) {
3423 my %queue;
3424 my @queue;
3425 my $widget;
3426
3427 outer:
3428 while () {
3429 if (my $realloc = delete $self->{realloc}) {
3430 for $widget (values %$realloc) {
3431 $widget->{visible} or next; # do not resize invisible widgets
3432
3433 $queue{$widget+0}++ and next; # duplicates are common
3434
3435 push @{ $queue[$widget->{visible}] }, $widget;
3436 }
3437 }
3438
3439 while () {
3440 @queue or last outer;
3441
3442 $widget = pop @{ $queue[-1] || [] }
3443 and last;
3444
3445 pop @queue;
3446 }
3447
3448 delete $queue{$widget+0};
3449
3450 my ($w, $h) = $widget->size_request;
3451
3452 $w = List::Util::max $widget->{min_w}, $w + $widget->{padding_x} * 2;
3453 $h = List::Util::max $widget->{min_h}, $h + $widget->{padding_y} * 2;
3454
3455 $w = $widget->{force_w} if exists $widget->{force_w};
3456 $h = $widget->{force_h} if exists $widget->{force_h};
3457
3458 if ($widget->{req_w} != $w || $widget->{req_h} != $h
3459 || delete $widget->{force_realloc}) {
3460 $widget->{req_w} = $w;
3461 $widget->{req_h} = $h;
3462
3463 $self->{size_alloc}{$widget+0} = $widget;
3464
3465 if (my $parent = $widget->{parent}) {
3466 $self->{realloc}{$parent+0} = $parent
3467 unless $queue{$parent+0};
3468
3469 $parent->{force_size_alloc} = 1;
3470 $self->{size_alloc}{$parent+0} = $parent;
3471 }
3472 }
3473
3474 delete $self->{realloc}{$widget+0};
3475 }
3476 }
3477
3478 while (my $size_alloc = delete $self->{size_alloc}) {
3479 my @queue = sort { $b->{visible} <=> $a->{visible} }
3480 values %$size_alloc;
3481
3482 while () {
3483 my $widget = pop @queue || last;
3484
3485 my ($w, $h) = @$widget{qw(alloc_w alloc_h)};
3486
3487 $w = 0 if $w < 0;
3488 $h = 0 if $h < 0;
3489
3490 $w = int $w + 0.5;
3491 $h = int $h + 0.5;
3492
3493 if ($widget->{w} != $w || $widget->{h} != $h || delete $widget->{force_size_alloc}) {
3494 $widget->{old_w} = $widget->{w};
3495 $widget->{old_h} = $widget->{h};
3496
3497 $widget->{w} = $w;
3498 $widget->{h} = $h;
3499
3500 $widget->emit (size_allocate => $w, $h);
3501 }
3502 }
3503 }
3504
3505 while ($self->{post_alloc_hook}) {
3506 $_->()
3507 for values %{delete $self->{post_alloc_hook}};
3508 }
3509
3510
3511 glViewport 0, 0, $::WIDTH, $::HEIGHT;
3512 glClearColor +($::CFG->{fow_intensity}) x 3, 1;
3513 glClear GL_COLOR_BUFFER_BIT;
3514
3515 glMatrixMode GL_PROJECTION;
3516 glLoadIdentity;
3517 glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000, 10000;
3518 glMatrixMode GL_MODELVIEW;
3519 glLoadIdentity;
3520
3521 {
3522 package CFClient::UI::Base;
3523
3524 ($draw_x, $draw_y, $draw_w, $draw_h) =
3525 (0, 0, $self->{w}, $self->{h});
3526 }
3527
3528 $self->_draw;
3529}
3530
3531#############################################################################
3532
3459package CFClient::UI; 3533package CFClient::UI;
3460 3534
3461$ROOT = new CFClient::UI::Root; 3535$ROOT = new CFClient::UI::Root;
3462$TOOLTIP = new CFClient::UI::Tooltip z => 900; 3536$TOOLTIP = new CFClient::UI::Tooltip z => 900;
3463 3537

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines