implemented normalize
[sdlgit/SDL_perl.git] / lib / SDL / Game / Rect.pm
index efab7e3..01368f0 100644 (file)
@@ -411,11 +411,6 @@ sub clip_ip {
     return;
 }
 
-=head3 union($rect)
-
-Returns a new rectangle that completely covers the area of the current Rect and the one passed as an argument. There may be area inside the new Rect that is not covered by the originals.
-
-=cut
 
 sub _test_union {
     my ($self, $rect) = (@_);
@@ -465,6 +460,119 @@ sub union_ip {
     return;
 }
 
+sub _test_unionall {
+    my ($self, $rects) = (@_);
+    
+    # initial values for union rect
+    my $left   = $self->x;
+    my $top    = $self->y;
+    my $right  = $self->x + $self->w;
+    my $bottom = $self->y + $self->h;
+    
+    foreach my $rect (@{$rects}) {
+        unless ($rect->isa('SDL::Rect')) {
+            # TODO: better error message, maybe saying which item 
+            # is the bad one (by list position)
+            croak "must receive an array reference of SDL::Rect-based objects";
+        }
+
+        $left   = $rect->x if $rect->x < $left; # MIN
+        $top    = $rect->y if $rect->y < $top; # MIN
+        $right  = ($rect->x + $rect->w) if ($rect->x + $rect->w) > $right;  # MAX
+        $bottom = ($rect->y + $rect->h) if ($rect->y + $rect->h) > $bottom; # MAX 
+    }
+    
+    return ($left, $top, $right - $left, $bottom - $top);
+}
+
+sub unionall {
+    my ($self, $rects) = (@_);
+    
+    croak "must receive an array reference of SDL::Rect-based objects"
+        unless defined $rects and ref $rects eq 'ARRAY';
+
+    my ($x, $y, $w, $h) = _test_unionall($self, $rects);
+    
+    return $self->new($x, $y, $w, $h);
+}
+
+sub unionall_ip {
+    my ($self, $rects) = (@_);
+    
+    croak "must receive an array reference of SDL::Rect-based objects"
+        unless defined $rects and ref $rects eq 'ARRAY';
+
+    my ($x, $y, $w, $h) = _test_unionall($self, $rects);
+    
+    $self->x($x);
+    $self->y($y);
+    $self->w($w);
+    $self->h($h);
+    
+    return;
+}
+
+sub _check_fit {
+    my ($self, $rect) = (@_);
+    
+    my $x_ratio = $self->w / $rect->w;
+    my $y_ratio = $self->h / $rect->h;
+    my $max_ratio = ($x_ratio > $y_ratio) ? $x_ratio : $y_ratio;
+
+    my $w = int ($self->w / $max_ratio);
+    my $h = int ($self->h / $max_ratio);
+
+    my $x = $rect->x + int (($rect->w - $w) / 2);
+    my $y = $rect->y + int (($rect->h - $h) / 2);
+    
+    return ($x, $y, $w, $h);
+}
+
+sub fit {
+    my ($self, $rect) = (@_);
+    
+    unless ($rect->isa('SDL::Rect')) {
+        croak "must receive an SDL::Rect-based object";
+    }
+
+    my ($x, $y, $w, $h) = _check_fit($self, $rect);
+    
+    return $self->new ($x, $y, $w, $h);
+}
+
+sub fit_ip {
+    my ($self, $rect) = (@_);
+    
+    unless ($rect->isa('SDL::Rect')) {
+        croak "must receive an SDL::Rect-based object";
+    }
+
+    my ($x, $y, $w, $h) = _check_fit($self, $rect);
+    
+    $self->x($x);
+    $self->y($y);
+    $self->w($w);
+    $self->h($h);
+    
+    return;
+}
+
+sub normalize {
+    my $self = shift;
+    
+    if ($self->w < 0) {
+        $self->x($self->x + $self->w);
+        $self->w(-$self->w);
+    }
+    
+    if ($self->h < 0) {
+        $self->y( $self->y + $self->h);
+        $self->h(-$self->h);
+    }
+    return;
+}
+
+
 42;
 __END__