You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
2.6 KiB
93 lines
2.6 KiB
package HexGrid::Region;
|
|
|
|
use v5.30;
|
|
|
|
use Moo;
|
|
use MooX::Aliases;
|
|
use Hash::Merge qw(merge);
|
|
use HexGrid::Tile;
|
|
use Data::Dumper;
|
|
|
|
use feature "signatures";
|
|
no warnings "experimental::signatures";
|
|
|
|
has tiles => (is => 'rw', default => sub { {} });
|
|
has name => (is => 'rw', required => 1);
|
|
has defaults => (is => 'rw', default => sub { {} });
|
|
has id_suffix => (is => 'rw', default => '_region');
|
|
|
|
has popup_class => (is => 'rw', default => 'popup region-popup');
|
|
has popup => (is => 'rw', default => undef);
|
|
|
|
# New region with same properties, but doesn't import tiles
|
|
sub clone($this)
|
|
{
|
|
return HexGrid::Region->new
|
|
(
|
|
name => $this->{name},
|
|
defaults => merge($this->{defaults},{}),
|
|
id_suffix => $this->{id_suffix}
|
|
);
|
|
}
|
|
|
|
sub add_tile($this, $tile) { return $this->{tiles}{$tile->{nw}}{$tile->{sw}} = $tile; }
|
|
sub make_tile_at($this, $nw, $sw, %tile_settings)
|
|
{
|
|
my %settings = %{merge(\%tile_settings, $this->{defaults})};
|
|
$settings{css_class} = HexGrid::to_id($this->{name});
|
|
return $this->add_tile(HexGrid::Tile::at($nw, $sw, %settings));
|
|
}
|
|
|
|
sub iter_tile($this, $code)
|
|
{
|
|
foreach my $nw (keys %{$this->{tiles}})
|
|
{
|
|
foreach my $sw (keys %{$this->{tiles}{$nw}})
|
|
{
|
|
$code->($this->{tiles}{$nw}{$sw});
|
|
}
|
|
}
|
|
}
|
|
|
|
sub render($this, $svg, $grid, $layers)
|
|
{
|
|
my $base_id = HexGrid::to_id("$this->{name}$this->{id_suffix}");
|
|
my ($min_x,$min_y,$max_x,$max_y) = qw(Inf Inf -Inf -Inf);
|
|
my $g = $svg->g(id => $base_id);
|
|
foreach my $nw (keys %{$this->{tiles}})
|
|
{
|
|
foreach my $sw (keys %{$this->{tiles}{$nw}})
|
|
{
|
|
my ($x_translate, $y_translate) = $grid->translate_coords($nw, $sw);
|
|
push @{$layers->{tiles}}, sub
|
|
{
|
|
my $tile_group = $this->{tiles}{$nw}{$sw}->render($g, $grid->tile_width, $grid->tile_height, $layers);
|
|
$tile_group->{transform} = "translate($x_translate, $y_translate)";
|
|
if ($this->popup)
|
|
{
|
|
my $popup_x = $x_translate + $grid->tile_width / 2;
|
|
my $popup_y = $y_translate - $this->{popup}{height} + $grid->tile_height / 2;
|
|
$tile_group->{onclick} = "clickRegion('$base_id', $popup_x, $popup_y, event);";
|
|
}
|
|
};
|
|
|
|
$min_x = $x_translate if $x_translate < $min_x;
|
|
$min_y = $y_translate if $y_translate < $min_y;
|
|
$max_x = $x_translate if $x_translate > $max_x;
|
|
$max_y = $y_translate if $y_translate > $max_y;
|
|
}
|
|
}
|
|
if ($this->popup)
|
|
{
|
|
push @{$layers->{popups}}, sub ($popup_container)
|
|
{
|
|
my $popup_scaler = $popup_container->
|
|
g(id => "$base_id-popup", class => $this->{popup_class}, transform => "translate(0,0)")
|
|
->svg(id => "$base_id-scaler");
|
|
$this->{popup}->render($popup_scaler);
|
|
};
|
|
}
|
|
return { min_x => $min_x,min_y => $min_y,max_x => $max_x,max_y => $max_y, group => $g };
|
|
}
|
|
|
|
1;
|
|
|