--- deliantra/Deliantra-Client/DC/UI.pm 2006/05/19 16:43:57 1.216 +++ deliantra/Deliantra-Client/DC/UI.pm 2006/05/23 20:00:55 1.224 @@ -138,6 +138,14 @@ } } +sub full_refresh { + # make a copy, otherwise for complains about freed values. + my @widgets = values %WIDGET; + + $_->update + for @widgets; +} + # call when resolution changes etc. sub rescale_widgets { my ($sx, $sy) = @_; @@ -200,12 +208,24 @@ sub show { my ($self) = @_; - return if $self->{parent}; $CFClient::UI::ROOT->add ($self); } +sub show_centered { + my ($self) = @_; + return if $self->{parent}; + + $self->show; + + $CFClient::UI::ROOT->on_post_alloc ( + "centered $self" => sub { + $self->move (($::WIDTH - $self->{w}) * 0.5, ($::HEIGHT - $self->{h}) * 0.5); + }, + ); +} + sub hide { my ($self) = @_; @@ -421,6 +441,8 @@ # TODO: req_w _does_change after ->reconfigure $self->check_size unless exists $self->{req_w}; + + $self->show; } sub check_size { @@ -799,7 +821,7 @@ ; $self = $class->SUPER::new ( - vp => (new CFClient::UI::ViewPort), + vp => (new CFClient::UI::ViewPort expand => 1), slider => $slider, @_, ); @@ -2052,7 +2074,7 @@ req_h => $::WIDTH / 80, vertical => 0, can_hover => 1, - inner_pad => .05, + inner_pad => 0.02, @_ ); @@ -2209,13 +2231,25 @@ $self->reflow; } +sub size_allocate { + my ($self, $w, $h) = @_; + + $self->SUPER::size_allocate ($w, $h); + + $self->{layout}->set_font ($self->{font}) if $self->{font}; + $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); + $self->{layout}->set_width ($self->{children}[0]{w}); + + $self->reflow; +} + sub text_height { - my ($self, $text) = @_; + my ($self, $text, $indent) = @_; my $layout = $self->{layout}; $layout->set_height ($self->{fontsize} * $::FONTSIZE); - $layout->set_width ($self->{children}[0]{w}); + $layout->set_width ($self->{children}[0]{w} - $indent); $layout->set_markup ($text); ($layout->size)[1] @@ -2228,28 +2262,16 @@ $self->update; } -sub size_allocate { - my ($self, $w, $h) = @_; - - $self->SUPER::size_allocate ($w, $h); - - $self->{layout}->set_font ($self->{font}) if $self->{font}; - $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); - $self->{layout}->set_width ($self->{children}[0]{w}); - - $self->reflow; -} - sub add_paragraph { - my ($self, $color, $text) = @_; + my ($self, $color, $text, $indent) = @_; #TODO: intelligently "reformat" paragraph - my $height = $self->text_height ($text); - - $self->{height} += $height; - - push @{$self->{par}}, [$height, $color, $text]; + for my $line (split /\n/, $text) { + my $height = $self->text_height ($line); + $self->{height} += $height; + push @{$self->{par}}, [$height, $color, $indent, $line]; + } $self->{children}[1]{range} = [$self->{height} - $self->{h}, 0, $self->{height}, $self->{h}]; $self->{children}[1]->update; @@ -2268,12 +2290,13 @@ if (delete $self->{need_reflow}) { my $height = 0; - $height += $_->[0] = $self->text_height ($_->[2]) + $height += $_->[0] = $self->text_height ($_->[3], $_->[2]) for @{$self->{par}}; $self->{height} = $height; $self->{children}[1]{range} = [$height - $self->{h}, 0, $height, $self->{h}]; + $self->{children}[1]->update; delete $self->{texture}; } @@ -2282,9 +2305,6 @@ glClearColor 0.5, 0.5, 0.5, 0; glClear GL_COLOR_BUFFER_BIT; - glEnable GL_TEXTURE_2D; - glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; - my $top = int $self->{children}[1]{range}[0]; my $y0 = $top; @@ -2296,21 +2316,27 @@ $layout->set_font ($self->{font}) if $self->{font}; + glEnable GL_BLEND; + glBlendFunc GL_ONE, GL_ONE_MINUS_SRC_ALPHA; + for my $par (@{$self->{par}}) { my $h = $par->[0]; if ($y0 < $y + $h && $y < $y1) { $layout->set_foreground (@{ $par->[1] }); - $layout->set_markup ($par->[2]); + $layout->set_width ($self->{w} - $par->[2]); + $layout->set_markup ($par->[3]); + + my ($w, $h, $data, $format, $internalformat) = $layout->render; - my ($W, $H) = $layout->size; - CFClient::Texture->new_from_layout ($layout)->draw_quad_alpha_premultiplied (0, $y - $y0); + glRasterPos $par->[2], $y - $y0; + glDrawPixels $w, $h, $format, GL_UNSIGNED_BYTE, $data; } $y += $h; } - glDisable GL_TEXTURE_2D; + glDisable GL_BLEND; }; }); } @@ -2491,23 +2517,56 @@ sub new { my $class = shift; - $class->SUPER::new ( + my $self = $class->SUPER::new ( aspect => 1, @_, - ) + ); + + if ($self->{anim} && $self->{animspeed}) { + Scalar::Util::weaken (my $widget = $self); + + $self->{timer} = Event->timer ( + at => $self->{animspeed} * int $::NOW / $self->{animspeed}, + hard => 1, + interval => $self->{animspeed}, + cb => sub { + ++$widget->{frame}; + $widget->update; + }, + ); + } + + $self } sub size_request { (32, 8) } +sub update { + my ($self) = @_; + + return unless $self->{visible}; + + $self->SUPER::update; +} + sub _draw { my ($self) = @_; return unless $::CONN;#d# manage and cache textures differently - my $tex = $::CONN->{texture}[$::CONN->{faceid}[$self->{face}]]; - # TODO animation + my $face; + + if ($self->{frame}) { + my $anim = $::CONN->{anim}[$self->{anim}]; + + $face = $anim->[ $self->{frame} % @$anim ] + if $anim && @$anim; + } + + my $tex = $::CONN->{texture}[$::CONN->{faceid}[$face || $self->{face}]]; + if ($tex) { glEnable GL_TEXTURE_2D; glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; @@ -2517,6 +2576,15 @@ } } +sub DESTROY { + my ($self) = @_; + + $self->{timer}->cancel + if $self->{timer}; + + $self->SUPER::DESTROY; +} + ############################################################################# package CFClient::UI::InventoryItem; @@ -2529,7 +2597,7 @@ my $desc = $item->{nrof} < 2 ? $item->{name} - : "$item->{nrof} $item->{name_pl}"; + : "$item->{nrof} × $item->{name_pl}"; $item->{flags} & Crossfire::Protocol::F_OPEN and $desc .= " (open)"; @@ -2559,15 +2627,15 @@ my $desc = _item_to_desc ($item); my $self = $class->SUPER::new ( - can_hover => 1, + can_hover => 1, can_events => 1, - tooltip => ((CFClient::UI::Label::escape $desc) - . "\nleftclick - pick up\nmiddle click - apply\nrightclick - menu"), + tooltip => ((CFClient::UI::Label::escape $desc) + . "\nleftclick - examine\nshift+leftclick - move/pickup/drop\nmiddle click - apply\nrightclick - menu"), connect_button_down => sub { my ($self, $ev, $x, $y) = @_; # todo: maybe put examine on 1? but should just be a tooltip :( - if ($ev->{button} == 1) { + if (($ev->{mod} & CFClient::KMOD_SHIFT) && $ev->{button} == 1) { my $targ = $::CONN->{player}{tag}; if ($item->{container} == $::CONN->{player}{tag}) { @@ -2575,18 +2643,25 @@ } $::CONN->send ("move $targ $item->{tag} 0"); + } elsif ($ev->{button} == 1) { + $::CONN->send ("examine $item->{tag}"); } elsif ($ev->{button} == 2) { $::CONN->send ("apply $item->{tag}"); } elsif ($ev->{button} == 3) { my @menu_items = ( ["examine", sub { $::CONN->send ("examine $item->{tag}") }], - ["mark", sub { $::CONN->send ("mark $item->{tag}") }], + ["mark", sub { $::CONN->send ("mark ". pack "N", $item->{tag}) }], ["apply", sub { $::CONN->send ("apply $item->{tag}") }], - ["drop", sub { $::CONN->send ("move $main::OPENCONT $item->{tag} 0") }], - [ - $item->{flags} & Crossfire::Protocol::F_LOCKED ? "lock" : "unlock", - sub { $::CONN->send ("lock $item->{tag}") }, - ], + ( + $item->{flags} & Crossfire::Protocol::F_LOCKED + ? ( + ["unlock", sub { $::CONN->send ("lock " . pack "CN", 0, $item->{tag}) }], + ) + : ( + ["lock", sub { $::CONN->send ("lock " . pack "CN", 1, $item->{tag}) }], + ["drop", sub { $::CONN->send ("move $main::OPENCONT $item->{tag} 0") }], + ) + ), ); CFClient::UI::Menu->new (items => \@menu_items)->popup ($ev); @@ -2632,7 +2707,7 @@ my $class = shift; my $self = $class->SUPER::new ( - scrolled => (new CFClient::UI::VBox), + scrolled => (new CFClient::UI::Table), @_, ); @@ -2653,11 +2728,17 @@ $self->{real_items} = \@items; for my $item (@items) { + $item->{item} = $item; $item = $item->{widget} ||= new CFClient::UI::InventoryItem item => $item; $item->update_item (); } - $self->{scrolled}->add (@items); + my $i = 0; + for (@items) { + $self->{scrolled}->add (0, $i, $_); + my $nrof = $_->{item}->{nrof} || 1; + $self->{scrolled}->add (1, $i++, new CFClient::UI::Label text => ($_->{item}->{weight} * $nrof) / 1000); + } # $range->{range} = [$self->{pos}, 0, $self->{max_pos}, $page]; } @@ -2939,6 +3020,24 @@ } $self->SUPER::add (@children); + + while (@children) { + my $w = pop @children; + push @children, $w->children; + $w->{visible} = 1; + } +} + +sub remove { + my ($self, @children) = @_; + + $self->SUPER::remove (@children); + + while (@children) { + my $w = pop @children; + push @children, $w->children; + delete $w->{visible}; + } } sub on_refresh { @@ -3017,7 +3116,7 @@ glMatrixMode GL_PROJECTION; glLoadIdentity; - glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000 , 10000; + glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000, 10000; glMatrixMode GL_MODELVIEW; glLoadIdentity;