Games-Axmud
view release on metacpan or search on metacpan
lib/Games/Axmud/Obj/Zone.pm view on Meta::CPAN
} elsif ($self->startCorner eq 'bottom_left') {
# Gridblock at which the top-left corner of a window will be, when it is in the
# bottom-left corner of the search area
$startX = 0;
$startY = $self->heightBlocks - $heightBlocks;
if ($self->orientation eq 'horizontal') {
$step = 1;
} else {
$step = -1;
}
} elsif ($self->startCorner eq 'bottom_right') {
# Gridblock at which the top-left corner of the first window is, when it is in the
# bottom-right corner of the search area
$startX = $self->widthBlocks - $widthBlocks;
$startY = $self->heightBlocks - $heightBlocks;
$step = -1;
}
# Set more search parameters - the number of possible positions of a window, of size
# $widthBlocks and $heightBlocks, in this zone's internal grid
$numX = ($self->widthBlocks - $widthBlocks + 1);
$numY = ($self->heightBlocks - $heightBlocks + 1);
# Conduct the search
for (my $posX = $startX; $posX < ($startX + $numX); $posX += $step) {
for (my $posY = $startY; $posY < ($startY + $numY); $posY += $step) {
# Check that every gridblock in the area starting at grid coordinates $posX/$posY
# region is free
if (
$self->checkPosnInLayer(
$layer,
$posX,
$posY,
$widthBlocks,
$heightBlocks,
$winObj,
)
) {
# The entire area is free, so a window can be placed at this position, at the
# specified layer, without overlapping other windows
return (1, $posX, $posY);
}
}
}
# There isn't space for this window anywhere in this zone at the specified layer
return @emptyList;
}
sub adjustSingleWin {
# Called by GA::Obj::Workspace->chooseWinPosn
# If the window's proposed position on a zone's internal grid puts it rather close to the
# edge (or edges) of the zone, and if the gaps between the proposed window and the zone's
# edge(s) are unoccupied, adjust the size of the window to fill the gap (this prevents
# small regions of the zone from always being empty and makes the desktop look nice)
#
# Expected arguments
# $layer - Which layer within the zone to check first (matches a number between 0 and
# (GA::Obj::WorkspaceGrid->maxLayers - 1) )
# $winXPosBlocks, $winYPosBlocks
# - The window's proposed x/y coordinates on the zone's internal grid (in
# gridblocks)
# $winWidthBlocks, $winHeightBlocks
# - The window's proposed width and height (in gridblocks)
#
# Return values
# An empty list on improper arguments
# Otherwise returns the list
# ($winXPosBlocks, $winYPosBlocks, $winWidthBlocks, $winHeightBlocks)
# ...some of which may have been adjusted by this function
my (
$self, $layer, $winXPosBlocks, $winYPosBlocks, $winWidthBlocks, $winHeightBlocks,
$check,
) = @_;
# Local variables
my (
$gapSize, $maxGapSize, $regionXPosBlocks, $regionYPosBlocks, $regionWidthBlocks,
$regionHeightBlocks,
@emptyList,
);
# Check for improper arguments
if (
! defined $layer || ! defined $winXPosBlocks || ! defined $winYPosBlocks
|| ! defined $winWidthBlocks || ! defined $winHeightBlocks || defined $check
) {
$axmud::CLIENT->writeImproper($self->_objClass . '->adjustSingleWin', @_);
return @emptyList;
}
# If this zone has a maximum number of visible windows, the biggest gap this function will
# close is that number minus 1 (bigger gaps shouldn't occur in zones with a maximum number
# of visible windows)
# Otherwise, the biggest gap is the one defined by the global variable
if ($self->visibleAreaMax) {
$maxGapSize = ($self->visibleAreaMax - 1);
# If this value is 0 (because only one window is allowed), don't need to check for gaps.
# Return the unadjusted size of the window
if (! $maxGapSize) {
return (
$winXPosBlocks, $winYPosBlocks, $winWidthBlocks, $winHeightBlocks,
);
}
} else {
# Use the default value
$maxGapSize = $axmud::CLIENT->gridGapMaxSize;
}
# Search the region to the left of the window
lib/Games/Axmud/Obj/Zone.pm view on Meta::CPAN
# GA::Client->createGridWin)
# Otherwise returns the GA::Obj::Area object created
my (
$self, $layer, $xPosBlocks, $yPosBlocks, $widthBlocks, $heightBlocks, $xPosPixels,
$yPosPixels, $widthPixels, $heightPixels, $session, $changeWinObj, $check,
) = @_;
# Local variables
my $areaObj;
# Check for improper arguments
if (
! defined $layer || ! defined $xPosBlocks || ! defined $yPosBlocks
|| ! defined $widthBlocks || ! defined $heightBlocks || ! defined $xPosPixels
|| ! defined $yPosPixels || ! defined $widthPixels || ! defined $heightPixels
|| defined $check
) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->addArea', @_);
}
# Check that the area is unoccupied by other windows (it shouldn't be)
if (
! $self->checkPosnInLayer(
$layer,
$xPosBlocks,
$yPosBlocks,
$widthBlocks,
$heightBlocks,
$changeWinObj,
)
) {
return $axmud::CLIENT->writeError(
'Window cannot be placed at the specified position, because the area is already'
. ' occupied',
$self->_objClass . '->addArea',
);
}
# Create a new area object to store details about the window's size and position
$areaObj = Games::Axmud::Obj::Area->new($self->areaCount, $self);
$self->ivAdd('areaHash', $areaObj->number, $areaObj);
$self->ivIncrement('areaCount');
# If $self->ownerString is defined, this zone is reserved for a single session. The IV's
# value can be any non-empty string. All zones with the same ->ownerString are reserved
# for a particular session
# The first session to place one of its windows into any 'owned' zone claims all of
# those zones for itself. If $self->ownerString IV is 'undef', the zone is available for
# any session to use (subject to restriction described in the comments in $self->new)
# ->ownerString is ignored in GA::Client->shareMainWinFlag = TRUE
if (
! $axmud::CLIENT->shareMainWinFlag
&& defined $session
&& defined $self->ownerString
&& $self->ownerString ne ''
&& ! defined $self->owner
) {
# Claim this zone, and all other zones (across all workspaces) with the same
# ->ownerString for this session
$axmud::CLIENT->desktopObj->claimZones($session, $self->ownerString);
}
# Set its IVs (->set_win is called by GA::Obj::Workspace->createGridWin, once the window
# object has been created)
$areaObj->set_zone($layer, $xPosBlocks, $yPosBlocks, $widthBlocks, $heightBlocks);
$areaObj->set_posn($xPosPixels, $yPosPixels, $widthPixels, $heightPixels);
return $areaObj;
}
sub removeArea {
# Called by GA::Obj::Workspace->createGridWin, GA::Obj::WorkspaceGrid->changeWinzone and
# ->del_gridWin
# Removes the GA::Obj::Area object (which is occupied by a single window) from this zone's
# internal grid
# Optionally reshuffles remaining windows
#
# Expected arguments
# $areaObj - The GA::Obj::Area which should be removed
#
# Optional arguments
# $noShuffleFlag - Set to TRUE when called GA::Obj::WorkspaceGrid->changeWinzone, in
# which case this function doesn't call $self->replaceAreaSpace to
# reshuffle the positions of windows in this zone
#
# Return values
# 'undef' on improper arguments, or if the area doesn't seem to exist in this zone, or
# if an operation to re-shuffle window positions fails
# 1 otherwise
my ($self, $areaObj, $noShuffleFlag, $check) = @_;
# Check for improper arguments
if (! defined $areaObj || defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->removeArea', @_);
}
# Update IVs
$self->ivDelete('areaHash', $areaObj->number);
# If there are no areas left in this zone, and the zone's ->owner is set, tell the
# GA::Obj::Desktop to check all zones across all workspaces. If the session has no windows
# in any of the zones it controls, free up those zones so they're available to another
# session
if ($self->owner && ! $self->areaHash) {
$axmud::CLIENT->desktopObj->relinquishZones($self->ownerString);
}
# If the global flag is set, reshuffle the position of all windows in this zone, removing
# any gaps that might have appeared in the middle of the zone, if the removed window
# occupied that space
if (! $noShuffleFlag && $axmud::CLIENT->gridReshuffleFlag) {
return $self->replaceAreaSpace($areaObj->layer);
} else {
return 1;
}
}
sub replaceAreaSpace {
# Called by $self->removeArea
# After a window has been removed, it's often desirable to move all the windows in the zone
# (on the same layer) to fill the gap - so, instead of having a gap in the middle, we have
# a gap at the end (the opposite end to the starting corner).
# This function performs that operation
#
# Expected arguments
# $layer - Which layer to reshuffle
#
# Return values
# 'undef' on improper arguments, or if (for some very unlikely reason) one of the windows
# won't fit in the zone
# 1 otherwise
my ($self, $layer, $check) = @_;
# Local variables
my (
$blockSize,
@areaList,
);
# Check for improper arguments
if (! defined $layer || defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->replaceAreaSpace', @_);
}
# Compile a list of GA::Obj::Area objects (one area for each window), sorted in order of
# their proximity to the starting corner
@areaList = $self->getSortedAreaList($layer);
# Move the windows into position. Start with the closest windows, so that all windows are in
# turn moved closer to the starting corner
$blockSize = $axmud::CLIENT->gridBlockSize;
foreach my $areaObj (@areaList) {
my (
$widthBlocks, $heightBlocks, $widthPixels, $heightPixels, $xPosBlocks, $yPosBlocks,
$xPosPixels, $yPosPixels, $successFlag,
);
# Get the area's size on the zone's internal grid. Remove the influence of any past
( run in 2.948 seconds using v1.01-cache-2.11-cpan-bbc515a03b3 )