public void InvalidateRowsMeasureState(bool forceInvalidateRows) { InvalidateMeasure(); if (forceInvalidateRows) { CellCache.ClearAll(); foreach (UIElement elem in Children) { elem.InvalidateMeasure(); } } }
internal void InvalidateRowsMeasureState(bool forceInvalidateRows) { _rowsLayer.InvalidateMeasure(); if (forceInvalidateRows) { CellCache.ClearAll(); CellOverflowLayoutBuildEngine.Clear(); foreach (UIElement elem in _rowsLayer.Children) { elem.InvalidateMeasure(); } } }
void UpdateCellBlocking(CPos cell) { using (new PerfSample("locomotor_cache")) { var cache = cell.Layer == 0 ? blockingCache : customLayerBlockingCache[cell.Layer]; var actors = actorMap.GetActorsAt(cell); var cellFlag = CellFlag.HasFreeSpace; if (!actors.Any()) { cache[cell] = new CellCache(default(LongBitSet <PlayerBitMask>), cellFlag); return; } if (sharesCell && actorMap.HasFreeSubCell(cell)) { cache[cell] = new CellCache(default(LongBitSet <PlayerBitMask>), cellFlag); return; } var cellImmovablePlayers = default(LongBitSet <PlayerBitMask>); var cellCrushablePlayers = world.AllPlayersMask; foreach (var actor in actors) { var actorImmovablePlayers = world.AllPlayersMask; var actorCrushablePlayers = world.NoPlayersMask; var crushables = actor.TraitsImplementing <ICrushable>(); var mobile = actor.OccupiesSpace as Mobile; var isMovable = mobile != null && !mobile.IsTraitDisabled && !mobile.IsTraitPaused && !mobile.IsImmovable; var isMoving = isMovable && mobile.CurrentMovementTypes.HasMovementType(MovementType.Horizontal); var building = actor.OccupiesSpace as Building; var isTransitOnly = building != null && building.TransitOnlyCells().Contains(cell); if (isTransitOnly) { cellFlag |= CellFlag.HasTransitOnlyActor; continue; } if (crushables.Any()) { cellFlag |= CellFlag.HasCrushableActor; foreach (var crushable in crushables) { actorCrushablePlayers = actorCrushablePlayers.Union(crushable.CrushableBy(actor, Info.Crushes)); } } if (isMoving) { cellFlag |= CellFlag.HasMovingActor; } else { cellFlag |= CellFlag.HasStationaryActor; } if (isMovable) { cellFlag |= CellFlag.HasMovableActor; actorImmovablePlayers = actorImmovablePlayers.Except(actor.Owner.AlliedPlayersMask); } // PERF: Only perform ITemporaryBlocker trait look-up if mod/map rules contain any actors that are temporary blockers if (world.RulesContainTemporaryBlocker) { // If there is a temporary blocker in this cell. if (actor.TraitOrDefault <ITemporaryBlocker>() != null) { cellFlag |= CellFlag.HasTemporaryBlocker; } } cellCrushablePlayers = cellCrushablePlayers.Intersect(actorCrushablePlayers); cellImmovablePlayers = cellImmovablePlayers.Union(actorImmovablePlayers); } cache[cell] = new CellCache(cellImmovablePlayers, cellFlag, cellCrushablePlayers); } }
/// <summary> /// Arranges specified cell. /// </summary> /// <param name="cell">Target cell to arrange.</param> /// <param name="finalSize">Size of area for the cell.</param> private void ArrangeCell(CellCache cell, SizeF finalSize) { var rows = this.RowDefinitionsInternal.ListRange(cell.RowStart, cell.RowSpan); var columns = this.ColumnDefinitionsInternal.ListRange(cell.ColumnStart, cell.ColumnSpan); if (rows.Count == 0 || columns.Count == 0) { return; } var left = (nfloat)columns[0].Offset; var top = (nfloat)rows[0].Offset; var width = (nfloat)columns.Sum(x => x.ActualWidth); var height = (nfloat)rows.Sum(x => x.ActualHeight); if (left + width > finalSize.Width) { width = finalSize.Width - left; } if (width < 0) { width = 0; } if (top + height > finalSize.Height) { height = finalSize.Height - top; } if (height < 0) { height = 0; } var contentRectangle = new RectangleF(left, top, width, height); if (cell.Element.ContainsValue(VerticalAlignmentProperty)) { switch (cell.Element.VerticalAlignment) { case VerticalAlignment.Bottom: contentRectangle.Y = top + height - cell.MeasuredSize.Height; contentRectangle.Height = cell.MeasuredSize.Height; break; case VerticalAlignment.Center: contentRectangle.Y = top + (height - cell.MeasuredSize.Height) / 2; contentRectangle.Height = cell.MeasuredSize.Height; break; case VerticalAlignment.Top: contentRectangle.Height = cell.MeasuredSize.Height; break; } } else if (cell.Element.ContainsValue(HeightProperty)) { var elementHeight = (nfloat)cell.Element.Height; contentRectangle.Y = top + (height - elementHeight) / 2; contentRectangle.Height = elementHeight; } if (cell.Element.ContainsValue(HorizontalAlignmentProperty)) { switch (cell.Element.HorizontalAlignment) { case HorizontalAlignment.Center: contentRectangle.X = left + (width - cell.MeasuredSize.Width) / 2; contentRectangle.Width = cell.MeasuredSize.Width; break; case HorizontalAlignment.Left: contentRectangle.Width = cell.MeasuredSize.Width; break; case HorizontalAlignment.Right: contentRectangle.X = left + width - cell.MeasuredSize.Width; contentRectangle.Width = cell.MeasuredSize.Width; break; } } else if (cell.Element.ContainsValue(WidthProperty)) { var elementWidth = (nfloat)cell.Element.Width; contentRectangle.X = left + (width - elementWidth) / 2; contentRectangle.Width = elementWidth; } cell.Element.Arrange(contentRectangle); }
/// <summary> /// ValidateCellsCore /// </summary> private void ValidateCellsCore() { UIElementCollection children = InternalChildren; ExtendedData extData = ExtData; extData.CellCachesCollection = new CellCache[children.Count]; extData.CellGroup1 = int.MaxValue; extData.CellGroup2 = int.MaxValue; extData.CellGroup3 = int.MaxValue; extData.CellGroup4 = int.MaxValue; bool hasStarCellsU = false; bool hasStarCellsV = false; bool hasGroup3CellsInAutoRows = false; for (int i = PrivateCells.Length - 1; i >= 0; --i) { UIElement child = children[i]; if (child == null) { continue; } CellCache cell = new CellCache(); // // read and cache child positioning properties // // read indices from the corresponding properties // clamp to value < number_of_columns // column >= 0 is guaranteed by property value validation callback cell.ColumnIndex = Math.Min(GetColumn(child), DefinitionsU.Length - 1); // clamp to value < number_of_rows // row >= 0 is guaranteed by property value validation callback cell.RowIndex = Math.Min(GetRow(child), DefinitionsV.Length - 1); // read span properties // clamp to not exceed beyond right side of the grid // column_span > 0 is guaranteed by property value validation callback cell.ColumnSpan = Math.Min(GetColumnSpan(child), DefinitionsU.Length - cell.ColumnIndex); // clamp to not exceed beyond bottom side of the grid // row_span > 0 is guaranteed by property value validation callback cell.RowSpan = Math.Min(GetRowSpan(child), DefinitionsV.Length - cell.RowIndex); Debug.Assert(0 <= cell.ColumnIndex && cell.ColumnIndex < DefinitionsU.Length); Debug.Assert(0 <= cell.RowIndex && cell.RowIndex < DefinitionsV.Length); // // calculate and cache length types for the child // cell.SizeTypeU = GetLengthTypeForRange(DefinitionsU, cell.ColumnIndex, cell.ColumnSpan); cell.SizeTypeV = GetLengthTypeForRange(DefinitionsV, cell.RowIndex, cell.RowSpan); hasStarCellsU |= cell.IsStarU; hasStarCellsV |= cell.IsStarV; // // distribute cells into four groups. // if (!cell.IsStarV) { if (!cell.IsStarU) { cell.Next = extData.CellGroup1; extData.CellGroup1 = i; } else { cell.Next = extData.CellGroup3; extData.CellGroup3 = i; // remember if this cell belongs to auto row hasGroup3CellsInAutoRows |= cell.IsAutoV; } } else { if ( cell.IsAutoU // note below: if spans through Star column it is NOT Auto && !cell.IsStarU ) { cell.Next = extData.CellGroup2; extData.CellGroup2 = i; } else { cell.Next = extData.CellGroup4; extData.CellGroup4 = i; } } PrivateCells[i] = cell; } HasStarCellsU = hasStarCellsU; HasStarCellsV = hasStarCellsV; HasGroup3CellsInAutoRows = hasGroup3CellsInAutoRows; }
protected override void OnPaint(PaintEventArgs e) { e.Graphics.Clear(Color.FromArgb(63, 25, 0)); if (game == null) { return; } int cellX1 = Math.Max(0, (int)(game.Camera.ViewPort.X / game.Camera.SCALE)); int cellY1 = Math.Max(0, (int)(game.Camera.ViewPort.Y / game.Camera.SCALE)); int cellCountX = (int)(ClientSize.Width / game.Camera.SCALE) + 2; int cellCountY = (int)(ClientSize.Height / game.Camera.SCALE) + 2; int cellX2 = Math.Min(cellX1 + cellCountX, (int)(game.PlaygroundSize.X)); int cellY2 = Math.Min(cellY1 + cellCountY, (int)(game.PlaygroundSize.Y)); for (int x = cellX1; x < cellX2; x++) { for (int y = cellY1; y < cellY2; y++) { CellCache cell = game.Map.CellCache[x, y]; switch (cell.CellType) { case CellType.Grass: e.Graphics.DrawImage(grass, new Rectangle( (int)(x * game.Camera.SCALE - game.Camera.ViewPort.X), (int)(y * game.Camera.SCALE - game.Camera.ViewPort.Y), (int)game.Camera.SCALE, (int)game.Camera.SCALE) ); break; case CellType.Sand: sandRenderer.Draw(e.Graphics, game, x, y); break; case CellType.Water: waterRenderer.Draw(e.Graphics, game, x, y); break; } } } foreach (var item in game.Map.Items.OrderBy(t => t.Position.Y)) { if (item is TreeItem) { e.Graphics.DrawImage(tree, new Rectangle( (int)(item.Position.X * game.Camera.SCALE - game.Camera.ViewPort.X - 30), (int)(item.Position.Y * game.Camera.SCALE - game.Camera.ViewPort.Y - 118), (int)game.Camera.SCALE, (int)game.Camera.SCALE * 2) ); } if (item is BoxItem) { e.Graphics.DrawImage(box, new Rectangle( (int)(item.Position.X * game.Camera.SCALE - game.Camera.ViewPort.X - 32), (int)(item.Position.Y * game.Camera.SCALE - game.Camera.ViewPort.Y - 35), (int)game.Camera.SCALE, (int)game.Camera.SCALE) ); } if (item is Player) { int frame = (int)((watch.ElapsedMilliseconds / 250) % 4); int offsetx = 0; if (game.Player.State == PlayerState.Walk) { switch (frame) { case 0: offsetx = 0; break; case 1: offsetx = SPRITE_WIDTH; break; case 2: offsetx = 2 * SPRITE_WIDTH; break; case 3: offsetx = SPRITE_WIDTH; break; } } else { offsetx = SPRITE_WIDTH; } float direction = (game.Player.Angle * 360f) / (float)(2 * Math.PI) + 225f; float sector = (int)(direction / 90); int offsety = 0; switch (sector) { case 1: offsety = 3 * SPRITE_HEIGHT; break; case 2: offsety = 2 * SPRITE_HEIGHT; break; case 3: offsety = 0 * SPRITE_HEIGHT; break; case 4: offsety = 1 * SPRITE_HEIGHT; break; } Point spriteCenter = new Point(27, 48); e.Graphics.DrawImage(sprite, new RectangleF( (game.Player.Position.X * game.Camera.SCALE) - game.Camera.ViewPort.X - spriteCenter.X, (game.Player.Position.Y * game.Camera.SCALE) - game.Camera.ViewPort.Y - spriteCenter.Y, SPRITE_WIDTH, SPRITE_HEIGHT), new RectangleF(offsetx, offsety, SPRITE_WIDTH, SPRITE_HEIGHT), GraphicsUnit.Pixel); } } }
/// <summary> /// Arranges specified cell. /// </summary> /// <param name="cell">Target cell to arrange.</param> /// <param name="finalSize">Size of area for the cell.</param> private void ArrangeCell(CellCache cell, SizeF finalSize) { var rows = this.RowDefinitionsInternal.ListRange(cell.RowStart, cell.RowSpan); var columns = this.ColumnDefinitionsInternal.ListRange(cell.ColumnStart, cell.ColumnSpan); if (rows.Count == 0 || columns.Count == 0) { return; } var left = (nfloat)columns[0].Offset; var top = (nfloat)rows[0].Offset; var width = (nfloat)columns.Sum(x => x.ActualWidth); var height = (nfloat)rows.Sum(x => x.ActualHeight); if (left + width > finalSize.Width) { width = finalSize.Width - left; } if (width < 0) { width = 0; } if (top + height > finalSize.Height) { height = finalSize.Height - top; } if (height < 0) { height = 0; } RectangleF contentRectangle = new RectangleF(left, top, width, height); if (cell.Element.ReadLocalValue(UIElement.VerticalAlignmentProperty) != DependencyProperty.UnsetValue) { switch (cell.Element.VerticalAlignment) { case VerticalAlignment.Bottom: contentRectangle.Y = top + height - cell.MeasuredSize.Height; contentRectangle.Height = cell.MeasuredSize.Height; break; case VerticalAlignment.Center: contentRectangle.Y = top + height / 2f - cell.MeasuredSize.Height / 2f; contentRectangle.Height = cell.MeasuredSize.Height; break; case VerticalAlignment.Stretch: contentRectangle.Y = top; contentRectangle.Height = height; break; case VerticalAlignment.Top: contentRectangle.Y = top; contentRectangle.Height = cell.MeasuredSize.Height; break; } } else { if (cell.Element.ReadLocalValue(UIElement.HeightProperty) != DependencyProperty.UnsetValue || cell.Element.ReadValueFromStyle(UIElement.HeightProperty) != DependencyProperty.UnsetValue) { contentRectangle.Y = top + height / 2f - (nfloat)cell.Element.Height / 2f; contentRectangle.Height = (nfloat)cell.Element.Height; } else { contentRectangle.Y = top; contentRectangle.Height = height; } } if (cell.Element.ReadLocalValue(UIElement.HorizontalAlignmentProperty) != DependencyProperty.UnsetValue) { switch (cell.Element.HorizontalAlignment) { case HorizontalAlignment.Center: contentRectangle.X = left + width / 2f - cell.MeasuredSize.Width / 2f; contentRectangle.Width = cell.MeasuredSize.Width; break; case HorizontalAlignment.Left: contentRectangle.X = left; contentRectangle.Width = cell.MeasuredSize.Width; break; case HorizontalAlignment.Right: contentRectangle.X = left + width - cell.MeasuredSize.Width; contentRectangle.Width = cell.MeasuredSize.Width; break; case HorizontalAlignment.Stretch: contentRectangle.X = left; contentRectangle.Width = width; break; } } else { if (cell.Element.ReadLocalValue(UIElement.WidthProperty) != DependencyProperty.UnsetValue || cell.Element.ReadValueFromStyle(UIElement.WidthProperty) != DependencyProperty.UnsetValue) { contentRectangle.X = left + width / 2f - (nfloat)cell.Element.Width / 2f; contentRectangle.Width = (nfloat)cell.Element.Width; } else { contentRectangle.X = left; contentRectangle.Width = width; } } cell.Element.Arrange(contentRectangle); }
void UpdateCellBlocking(CPos cell) { using (new PerfSample("locomotor_cache")) { var actors = actorMap.GetActorsAt(cell); if (!actors.Any()) { blockingCache[cell] = new CellCache(default(LongBitSet <PlayerBitMask>), CellFlag.HasFreeSpace); return; } if (sharesCell && actorMap.HasFreeSubCell(cell)) { blockingCache[cell] = new CellCache(default(LongBitSet <PlayerBitMask>), CellFlag.HasFreeSpace); return; } var cellFlag = CellFlag.HasActor; var cellBlockedPlayers = default(LongBitSet <PlayerBitMask>); var cellCrushablePlayers = world.AllPlayersMask; foreach (var actor in actors) { var actorBlocksPlayers = world.AllPlayersMask; var crushables = actor.TraitsImplementing <ICrushable>(); var mobile = actor.OccupiesSpace as Mobile; var isMoving = mobile != null && mobile.CurrentMovementTypes.HasMovementType(MovementType.Horizontal); if (crushables.Any()) { cellFlag |= CellFlag.HasCrushableActor; foreach (var crushable in crushables) { cellCrushablePlayers = cellCrushablePlayers.Intersect(crushable.CrushableBy(actor, Info.Crushes)); } } else { cellCrushablePlayers = world.NoPlayersMask; } if (isMoving) { actorBlocksPlayers = actorBlocksPlayers.Except(actor.Owner.AlliedPlayersMask); cellFlag |= CellFlag.HasMovingActor; } // PERF: Only perform ITemporaryBlocker trait look-up if mod/map rules contain any actors that are temporary blockers if (world.RulesContainTemporaryBlocker) { // If there is a temporary blocker in this cell. if (actor.TraitOrDefault <ITemporaryBlocker>() != null) { cellFlag |= CellFlag.HasTemporaryBlocker; } } cellBlockedPlayers = cellBlockedPlayers.Union(actorBlocksPlayers); } blockingCache[cell] = new CellCache(cellBlockedPlayers, cellFlag, cellCrushablePlayers); } }