#!/usr/bin/perl -w

#############################################################################
# Light - a thing that acts as a HSV/RGB spot/omni light
#
# Copyright (C) 1999-2000 by Tels. All rights reserved.
#############################################################################

package CoW::Light;
use vars qw($VERSION);
$VERSION = 1.00;    # Current version of this package
require  5.005;     # requires this Perl version or later

use base CoW::Thing;
use strict;
use vars qw($AUTOLOAD);

use CoW::Misc qw/range/;

#############################################################################
# private, initialize self 

sub _init
  {
  my $self = shift;
  my $args = shift;

  $self->SUPER::_init($args); 	# use things _init to make copy and checks
  # now imply some more checks
  $self->SUPER::_default( {
    h => 0, s => 0, v => 128, kind => 0, range => 128,
   } );
  if (defined $self->{r} || defined $self->{g} || defined $self->{b})
    {
    ($self->{h},$self->{s},$self->{v}) = 
    rgb2hsv($self->{r}||0,$self->{g}||0,$self->{b}||0);
    }
  else
    {
    ($self->{r},$self->{g},$self->{b}) = 
    hsv2rgb($self->{h},$self->{s},$self->{v});
    }  
  delete $self->{w};
  delete $self->{l};
  range(0,1,\$self->{kind});
  return $self;
  }

sub DESTROY
  {
  my $self = shift;

  $self->SUPER::DESTROY( qw/x y z range rx ry rz/ ); 
  }

#############################################################################
# public

sub hue
  {
  my $self = shift;
  my $h = shift;
  if (defined $h)
    {
    $self->{h} = range(0,1,$h); 
    ($self->{r}, $self->{g}, $self->{b}) = 
      hsv2rgb($self->{h},$self->{s},$self->{v});
    }
  return $self->{h};
  }

sub saturation
  {
  my $self = shift;
  my $s = shift;
  if (defined $s)
    { 
    $self->{s} = range(0,1,$s); 
    ($self->{r}, $self->{g}, $self->{b}) = 
      hsv2rgb($self->{h},$self->{s},$self->{v});
    }
  return $self->{s};
  }

sub value
  {
  my $self = shift;
  my $v = shift;
  if (defined $v)
    {
    $self->{v} = range(0,255,$v); 
    ($self->{r}, $self->{g}, $self->{b}) = 
      hsv2rgb($self->{h},$self->{s},$self->{v});
    }
  return $self->{v};
  }

sub bright
  {
  my $self = shift;
  return $self->value(@_);
  }

sub hsv2rgb
  {
  # return rgb from hsv values
  my ($h,$s,$v) = @_;
  range(0,1,\$h,\$s); range(0,255,\$v);
  my ($r,$g,$b);
  $r = 0; $g = 0; $b = 0;
  return ($r,$g,$b);
  }

sub rgb2hsv
  {
  # return hsv fromvalues
  my ($r,$g,$b) = @_;
  range(0,255,\$r,\$g,\$b);
  my ($h,$s,$v);
  $h = 0; $s = 0; $v = 0;
  return ($h,$s,$v);
  }

sub red
  {
  my $self = shift;
  my $red = shift;
  if (defined $red)
    {
    $self->{r} = range(0,255,$red);
    ($self->{h}, $self->{s}, $self->{v}) = 
      rgb2hsv($self->{r},$self->{g},$self->{b});
    } 
  return $self->{r};
  }

sub green
  {
  my $self = shift;
  my $green = shift;
  if (defined $green)
    {
    $self->{g} = range(0,255,$green);
    ($self->{h}, $self->{s}, $self->{v}) = 
      rgb2hsv($self->{r},$self->{g},$self->{b});
    } 
  return $self->{g};
  }

sub blue
  {
  my $self = shift;
  my $blue = shift;
  if (defined $blue)
    {
    $self->{b} = range(0,255,$blue);
    ($self->{h}, $self->{s}, $self->{v}) = 
      rgb2hsv($self->{r},$self->{g},$self->{b});
    } 
  return $self->{b};
  }

sub kind
  {
  my $self = shift;
  my $kind = shift;
  $self->{kind} = rande(0,1,$kind) if (defined $kind);
  return $self->{kind};
  }

sub scale
  {
  # scale a things size by some factors
  # scale effects only the range
  my $self = shift;
  my $scale = shift || 1;

  $self->{range} *= $scale;
  }

sub absolute
  {
  # make all coords/angles/sizes absolute instead of relative
  my $self = shift;
  return $self->SUPER::absolute( qw/x y z range rx ry rz/ );
  }

1; 

__END__

#############################################################################

=pod

=head1 NAME

Light -- a thing that acts as a HSV or RGB spot/omni light

=head1 SYNOPSIS

	use CoW::Light;

	$light = new CoW::Light ( r => 128, g => 0, b => 128 );
	print $light->red(),"\n";
	print $light->hue(),"\n";
	
        $light = new CoW::Light ( h => 0.5, s => 0.4, v => 128 );
	print $light->red(),"\n";
	print $light->hue(),"\n";

=head1 REQUIRES

perl5.005, L<Bunch|Bunch>, L<Item|Item>

=head1 EXPORTS

Exports nothing.

=head1 DESCRIPTION

This represents a light, which is stored as HSV (hue/saturation/value)
and RGB (red/green/blue) light. You can
construct such a light from RGB or HSV. If new() sees either a C<r>, C<g> or
C<b> parameter, it will use RGB to construct the light and ignore HSV,
otherwise RGB will be ignored and the HSV used instead.

=head1 FIELDS

=over 2

=item kind

The kind of the light, either SPOT or OMNI.

=item h

The hue component of the light, 0..1.

=item s

The saturation component of the light, 0..1.

=item v

The brightness/value component of the light, 0...255.

=item r

The red component of the light, 0..255.

=item g

The green component of the light, 0..255.

=item b

The blue component of the light, 0...255.

=item rx,ry,rz

The rotation of the light. In case of spot lights, this means that the
spot will be targetet at this angle. Default (rx = 0, ry = 0, rz = 0) ist
straight down.

=item x,y,z

The center of the light.

=item range

The maximum range of the light. A light has no C<w>, C<l> and C<h> fields!

=back

=head1 METHODS

=head2 red

Set/sets the red component of the light. 

=head2 green

Set/sets the green component of the light.

=head2 blue

Set/sets the blue component of the light.

=head2 kind

Set/sets the kind of the light.

=head2 hue

Set/sets the hue component of the light. 

=head2 saturation

Set/sets the saturation component of the light.

=head2 bright/value

Both Set/sets the value/bright component of the light. Value is actually only
an alias for bright().

=head2 kind

Set/sets the kind of the light.

=head2 scale

Scale the light. Affects only the range, so only one parameter is needed.

=head2 absolute

Make lights range, center etc absolute instead of relative.

=head1 BUGS

Lights are a bit expensive, since conversions to/from HSV/RGB will happen.

=head1 AUTHOR

Tels http://bloodgate.com 1999-2000.

=cut

