--- deliantra/Deliantra-Client/DC.pm 2006/05/25 21:18:09 1.65
+++ deliantra/Deliantra-Client/DC.pm 2006/05/29 19:49:33 1.74
@@ -27,40 +27,6 @@
use AnyEvent ();
use BerkeleyDB;
-use CFClient::OpenGL;
-
-our %GL_EXT;
-our $GL_VERSION;
-
-our $GL_NPOT;
-our $GL_DEBUG = 1;
-
-sub gl_init {
- $GL_VERSION = gl_version * 1;
- %GL_EXT = map +($_ => 1), split /\s+/, gl_extensions;
-
- $GL_NPOT = $GL_EXT{GL_ARB_texture_non_power_of_two} || $GL_VERSION >= 2;
- $GL_NPOT = 0 if gl_vendor =~ /ATI Technologies/; # ATI doesn't get it right...
-
- glDisable GL_COLOR_MATERIAL;
- glShadeModel GL_FLAT;
- glDisable GL_DITHER;
- glDisable GL_DEPTH_TEST;
- glDepthMask 0;
- glHint GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST;
-
- CFClient::Texture::restore_state ();
-}
-
-sub gl_check {
- return unless $GL_DEBUG;
-
- if (my $error = glGetError) {
- my ($format, @args) = @_;
- Carp::cluck sprintf "opengl error %x while $format", $error, @args;
- }
-}
-
sub find_rcfile($) {
my $path;
@@ -173,7 +139,7 @@
sub view_verbatim {
(join "",
- map +("\t" x ($indent / 2)) . "$_\n",
+ map +("\t" x ($indent / 2)) . "$_\n",
split /\n/, CFClient::UI::Label::escape ($_[1]))
. "\n"
}
@@ -183,12 +149,17 @@
}
sub view_head1 {
- "" . $_[1]->title->present ($_[0]) . "\n\n"
+ "\n\n" . $_[1]->title->present ($_[0]) . "\n\n"
. $_[1]->content->present ($_[0])
};
sub view_head2 {
- "" . $_[1]->title->present ($_[0]) . "\n\n"
+ "\n" . $_[1]->title->present ($_[0]) . "\n\n"
+ . $_[1]->content->present ($_[0])
+};
+
+sub view_head3 {
+ "\n" . $_[1]->title->present ($_[0]) . "\n\n"
. $_[1]->content->present ($_[0])
};
@@ -221,6 +192,9 @@
package CFClient::Item;
+use strict;
+use Crossfire::Protocol::Constants;
+
sub desc_string {
my ($self) = @_;
@@ -229,19 +203,19 @@
? $self->{name}
: "$self->{nrof} × $self->{name_pl}";
- $self->{flags} & Crossfire::Protocol::F_OPEN
+ $self->{flags} & F_OPEN
and $desc .= " (open)";
- $self->{flags} & Crossfire::Protocol::F_APPLIED
+ $self->{flags} & F_APPLIED
and $desc .= " (applied)";
- $self->{flags} & Crossfire::Protocol::F_UNPAID
+ $self->{flags} & F_UNPAID
and $desc .= " (unpaid)";
- $self->{flags} & Crossfire::Protocol::F_MAGIC
+ $self->{flags} & F_MAGIC
and $desc .= " (magic)";
- $self->{flags} & Crossfire::Protocol::F_CURSED
+ $self->{flags} & F_CURSED
and $desc .= " (cursed)";
- $self->{flags} & Crossfire::Protocol::F_DAMNED
+ $self->{flags} & F_DAMNED
and $desc .= " (damned)";
- $self->{flags} & Crossfire::Protocol::F_LOCKED
+ $self->{flags} & F_LOCKED
and $desc .= " *";
$desc
@@ -279,7 +253,7 @@
["mark", sub { $::CONN->send ("mark ". pack "N", $self->{tag}) }],
["apply", sub { $::CONN->send ("apply $self->{tag}") }],
(
- $self->{flags} & Crossfire::Protocol::F_LOCKED
+ $self->{flags} & F_LOCKED
? (
["unlock", sub { $::CONN->send ("lock " . pack "CN", 0, $self->{tag}) }],
)
@@ -306,7 +280,9 @@
$self->{face_widget} ||= new CFClient::UI::Face
can_events => 1,
can_hover => 1,
- connect_button_down => $button_cb,
+ anim => $self->{anim},
+ animspeed => $self->{animspeed}, # TODO# must be set at creation time
+ on_button_down => $button_cb,
;
$self->{face_widget}{face} = $self->{face};
$self->{face_widget}{anim} = $self->{anim};
@@ -322,8 +298,8 @@
can_events => 1,
can_hover => 1,
ellipsise => 2,
- xalign => 0,
- connect_button_down => $button_cb,
+ align => -1,
+ on_button_down => $button_cb,
;
my $desc = CFClient::Item::desc_string $self;
$self->{desc_widget}->set_text ($desc);
@@ -333,8 +309,8 @@
can_events => 1,
can_hover => 1,
ellipsise => 0,
- xalign => 0.5,
- connect_button_down => $button_cb,
+ align => 0,
+ on_button_down => $button_cb,
;
$self->{weight_widget}->set_text (CFClient::Item::weight_string $self);
@@ -346,195 +322,215 @@
);
}
-package CFClient::Texture;
-
-use strict;
-
-use Scalar::Util;
-
-use CFClient::OpenGL;
-
-my %TEXTURES;
-
-sub new {
- my ($class, %data) = @_;
-
- my $self = bless {
- internalformat => GL_RGBA,
- format => GL_RGBA,
- type => GL_UNSIGNED_BYTE,
- %data,
- }, $class;
-
- Scalar::Util::weaken ($TEXTURES{$self+0} = $self);
+package CFClient::Recorder;
- $self->upload;
+our $RECORD_WINDOW;
- $self
-}
+my $CMDBOX;
+my $CURRENT_CMDS;
+my $REC_BTN;
+
+my @ALLOWED_MODIFIER_KEYS = (
+ (CFClient::SDLK_LSHIFT) => "LSHIFT",
+ (CFClient::SDLK_LCTRL ) => "LCTRL",
+ (CFClient::SDLK_LALT ) => "LALT",
+ (CFClient::SDLK_LMETA ) => "LMETA",
+
+ (CFClient::SDLK_RSHIFT) => "RSHIFT",
+ (CFClient::SDLK_RCTRL ) => "RCTRL",
+ (CFClient::SDLK_RALT ) => "RALT",
+ (CFClient::SDLK_RMETA ) => "RMETA",
+);
+
+my %ALLOWED_MODIFIERS = (
+ (CFClient::KMOD_LSHIFT) => "LSHIFT",
+ (CFClient::KMOD_LCTRL ) => "LCTRL",
+ (CFClient::KMOD_LALT ) => "LALT",
+ (CFClient::KMOD_LMETA ) => "LMETA",
+
+ (CFClient::KMOD_RSHIFT) => "RSHIFT",
+ (CFClient::KMOD_RCTRL ) => "RCTRL",
+ (CFClient::KMOD_RALT ) => "RALT",
+ (CFClient::KMOD_RMETA ) => "RMETA",
+);
+
+my %DIRECT_BIND_CHARS = map { $_ => 1 } qw/0 1 2 3 4 5 6 7 8 9/;
+my @DIRECT_BIND_KEYS = (
+ CFClient::SDLK_F1,
+ CFClient::SDLK_F2,
+ CFClient::SDLK_F3,
+ CFClient::SDLK_F4,
+ CFClient::SDLK_F5,
+ CFClient::SDLK_F6,
+ CFClient::SDLK_F7,
+ CFClient::SDLK_F8,
+ CFClient::SDLK_F9,
+ CFClient::SDLK_F10,
+ CFClient::SDLK_F11,
+ CFClient::SDLK_F12,
+ CFClient::SDLK_F13,
+ CFClient::SDLK_F14,
+ CFClient::SDLK_F15,
+);
+
+# this binding dialog asks for a key-combo to be pressed
+# and if successful it binds the modifier+symbol to the
+# supplied actions in $cmd.
+# (Bindings are stored in $::CFG->{bindings}->{$mod}->{$sym})
+sub open_binding_dialog {
+ my ($cmd) = @_;
+
+ my $w = new CFClient::UI::FancyFrame
+ title => "Bind Action";
+
+ $w->add (my $vb = new CFClient::UI::VBox);
+ $vb->add (new CFClient::UI::Label
+ text => "Press a modifier (CTRL, ALT and/or SHIFT) and a key."
+ ."You can only bind 0-9 and F1-F15 without modifiers."
+ );
+ $vb->add (my $entry = new CFClient::UI::Entry
+ text => "",
+ on_key_down => sub {
+ my ($entry, $ev) = @_;
+
+ my $mod = $ev->{mod};
+ my $sym = $ev->{sym};
+
+ # XXX: This seems a little bit hackisch to me, but i have to ignore them
+ if (grep { $_ == $sym } @ALLOWED_MODIFIER_KEYS) {
+ return;
+ }
-sub new_from_image {
- my ($class, $image, %arg) = @_;
+ if ($mod == CFClient::KMOD_NONE
+ and not $DIRECT_BIND_CHARS{chr ($ev->{unicode})}
+ and not grep { $sym == $_ } @DIRECT_BIND_KEYS)
+ {
+ $::STATUSBOX->add (
+ "Can't bind key ".CFClient::SDL_GetKeyName ($sym)
+ ." directly without modifier! It would damage the completer handling."
+ );
+ return;
+ }
- $class->new (image => $image, %arg)
-}
+ $entry->focus_out;
-sub new_from_file {
- my ($class, $path, %arg) = @_;
+ $::CFG->{bindings}->{$mod}->{$sym} = $cmd;
+ $::STATUSBOX->add ("Bound actions to '".keycombo_to_name ($mod, $sym)."'. Don't forget 'Save Config'!");
- open my $fh, "<:raw", $path
- or die "$path: $!";
+ $w->destroy
+ });
- local $/;
- $class->new_from_image (<$fh>, %arg)
+ $entry->focus_in;
+ $w->center;
+ $w->show;
}
-#sub new_from_surface {
-# my ($class, $surface) = @_;
-#
-# $surface->rgba;
-#
-# $class->new (
-# data => $surface->pixels,
-# w => $surface->width,
-# h => $surface->height,
-# )
-#}
+sub keycombo_to_name {
+ my ($mod, $sym) = @_;
-sub new_from_layout {
- my ($class, $layout, %arg) = @_;
+ my $mods = join '+',
+ map { $ALLOWED_MODIFIERS{$_} }
+ grep { $_ & $mod }
+ keys %ALLOWED_MODIFIERS;
+ $mods .= "+" if $mods ne '';
- my ($w, $h, $data, $format, $internalformat) = $layout->render;
-
- $class->new (
- w => $w,
- h => $h,
- data => $data,
- format => $format,
- internalformat => $format,
- type => GL_UNSIGNED_BYTE,
- %arg,
- )
+ return $mods . CFClient::SDL_GetKeyName ($sym);
}
-sub new_from_opengl {
- my ($class, $w, $h, $cb) = @_;
-
- $class->new (w => $w || 1, h => $h || 1, render_cb => $cb)
+sub clear_command_list {
+ $CMDBOX->clear () if $CMDBOX;
}
-sub topot {
- (grep $_ >= $_[0], 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768)[0]
-}
+sub set_command_list {
+ my ($list) = @_;
-sub upload {
- my ($self) = @_;
+ return unless $CMDBOX;
- return unless $GL_VERSION;
+ $CMDBOX->clear ();
+ $CURRENT_CMDS = $list;
- my $data;
+ my $idx = 0;
- if (exists $self->{data}) {
- $data = $self->{data};
+ for (@$list) {
+ $CMDBOX->add (my $hb = new CFClient::UI::HBox);
- } elsif (exists $self->{render_cb}) {
- glViewport 0, 0, $self->{w}, $self->{h};
- glMatrixMode GL_PROJECTION;
- glLoadIdentity;
- glOrtho 0, $self->{w}, 0, $self->{h}, -10000, 10000;
- glMatrixMode GL_MODELVIEW;
- glLoadIdentity;
- $self->{render_cb}->($self, $self->{w}, $self->{h});
-
- } else {
- ($self->{w}, $self->{h}, $data, $self->{internalformat}, $self->{format}, $self->{type})
- = CFClient::load_image_inline $self->{image};
- }
+ my $i = $idx;
+ $hb->add (new CFClient::UI::Button
+ text => "delete",
+ tooltip => "Deletes the action from the record",
+ on_activate => sub {
+ $CMDBOX->remove ($hb);
+ $list->[$i] = undef;
+ });
- my ($tw, $th) = @$self{qw(w h)};
+ $hb->add (new CFClient::UI::Label text => $_);
- unless ($tw > 0 && $th > 0) {
- $tw = $th = 1;
- $data = "\x00" x 64;
+ $idx++
}
+}
- $self->{minified} = [CFClient::average $tw, $th, $data]
- if $self->{minify};
+# if $show is 1 the recorder will be shown
+sub start {
+ my ($show) = @_;
- unless ($GL_NPOT) {
- # TODO: does not work for zero-sized textures
- $tw = topot $tw;
- $th = topot $th;
-
- if (($tw != $self->{w} || $th != $self->{h}) && defined $data) {
- my $bpp = (length $data) / ($self->{w} * $self->{h});
- $data = pack "(a" . ($tw * $bpp) . ")*",
- unpack "(a" . ($self->{w} * $bpp) . ")*", $data;
- $data .= ("\x00" x ($tw * $bpp)) x ($th - $self->{h});
- }
- }
+ $RECORD_WINDOW->show if $show;
- $self->{s} = $self->{w} / $tw;
- $self->{t} = $self->{h} / $th;
+ $REC_BTN->set_text ("stop recording");
+ $REC_BTN->{recording} = 1;
+ clear_command_list;
+ $::CONN->start_record;
+}
- $self->{name} ||= glGenTexture;
+# if $autobind is 1 the recorder will be automatically
+# jump into the binding query and hide the recorder window
+sub stop {
+ my ($autobind) = @_;
- glBindTexture GL_TEXTURE_2D, $self->{name};
+ $REC_BTN->set_text ("start recording");
+ $REC_BTN->{recording} = 0;
- glTexParameter GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP;
- glTexParameter GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP;
-
- if ($::FAST) {
- glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST;
- glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST;
- } elsif ($self->{mipmap} && $GL_VERSION >= 1.4) {
- # alternatively check for 0x8191
- glTexParameter GL_TEXTURE_2D, GL_GENERATE_MIPMAP, 1;
- glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR;
- glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR;
- } else {
- glTexParameter GL_TEXTURE_2D, GL_GENERATE_MIPMAP, $self->{mipmap};
- glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR;
- glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR;
- }
-
- glGetError;
+ my $rec = $::CONN->stop_record;
+ return unless ref $rec eq 'ARRAY';
+ set_command_list ($rec);
- if (defined $data) {
- glTexImage2D GL_TEXTURE_2D, 0,
- $self->{internalformat},
- $tw, $th,
- 0,
- $self->{format},
- $self->{type},
- $data;
- CFClient::gl_check "uploading texture %dx%d if=%x f=%x t=%x",
- $tw, $th, $self->{internalformat}, $self->{format}, $self->{type};
- } else {
- glCopyTexImage2D GL_TEXTURE_2D, 0,
- $self->{internalformat},
- 0, 0,
- $tw, $th,
- 0;
- CFClient::gl_check "copying to texture %dx%d if=%x",
- $tw, $th, $self->{internalformat};
+ if ($autobind) {
+ open_binding_dialog ([ grep { defined $_ } @$CURRENT_CMDS ]);
+ $RECORD_WINDOW->hide;
}
-
- glBindTexture GL_TEXTURE_2D, 0; # just to be on the safe side
}
-sub DESTROY {
- my ($self) = @_;
-
- delete $TEXTURES{$self+0};
-
- glDeleteTexture delete $self->{name}
- if $self->{name};
-}
+sub make_window {
+ $RECORD_WINDOW = new CFClient::UI::FancyFrame
+ req_y => 1,
+ req_x => -1,
+ title => "Action Recorder";
+
+ $RECORD_WINDOW->add (my $vb = new CFClient::UI::VBox);
+ $vb->add ($REC_BTN = new CFClient::UI::Button
+ text => "start recording",
+ tooltip => "Start/Stops recording of actions."
+ ."(CTRL+Insert Starts the recorder, Insert Stops recorder and binds automatically)"
+ ."All subsequent actions after the recording started will be captured."
+ ."The actions are displayed after the record was stopped."
+ ."To bind the action you have to click on the 'Bind' button",
+ on_activate => sub {
+ my ($btn) = @_;
+
+ unless ($btn->{recording}) {
+ start;
+ } else {
+ stop;
+ }
+ });
+ $vb->add ($CMDBOX = new CFClient::UI::VBox);
+ $vb->add (new CFClient::UI::Button
+ text => "bind",
+ tooltip => "This opens a query where you have to press the key combination to bind the recorded actions",
+ on_activate => sub {
+ open_binding_dialog ([ grep { defined $_ } @$CURRENT_CMDS ]);
+ });
-sub restore_state {
- $_->upload
- for values %TEXTURES;
+ $RECORD_WINDOW
}
1;