public override AdjustBoxResult AdjustXYToBeInBox(Point dst) { var abr = new AdjustBoxResult(); abr.Position = dst; abr.Box = InvalidBox; var numBoxes = _scumm.GetNumBoxes() - 1; var bestDist = 0xFF; for (int i = 0; i <= numBoxes; i++) { // MM v0 prioritizes lower boxes, other engines higher boxes var box = (byte)(_scumm.Game.Version == 0 ? i : numBoxes - i); var flags = _scumm.GetBoxFlags(box); if ((flags.HasFlag(BoxFlags.Invisible) && !((flags.HasFlag(BoxFlags.PlayerOnly) && !IsPlayer)))) continue; Point found; var dist = CheckXYInBoxBounds(box, dst, out found); // also merged with getClosestPtOnBox if (dist == 0) { abr.Position = found; abr.Box = box; break; } if (dist < bestDist) { bestDist = dist; abr.Position = found; abr.Box = box; } } return abr; }
public virtual AdjustBoxResult AdjustXYToBeInBox(Point dst) { var thresholdTable = new [] { 30, 80, 0 }; var abr = new AdjustBoxResult(); uint tmpDist, bestDist; int threshold, numBoxes; BoxFlags flags; byte bestBox; int box; int firstValidBox = _scumm.Game.Version < 5 ? 0 : 1; abr.Position = dst; abr.Box = InvalidBox; if (IgnoreBoxes) return abr; for (int tIdx = 0; tIdx < thresholdTable.Length; tIdx++) { threshold = thresholdTable[tIdx]; numBoxes = _scumm.GetNumBoxes() - 1; if (numBoxes < firstValidBox) return abr; bestDist = (_scumm.Game.Version >= 7) ? (uint)0x7FFFFFFF : (uint)0xFFFF; bestBox = InvalidBox; // We iterate (backwards) over all boxes, searching the one closest // to the desired coordinates. for (box = numBoxes; box >= firstValidBox; box--) { flags = _scumm.GetBoxFlags((byte)box); // Skip over invisible boxes if (flags.HasFlag(BoxFlags.Invisible) && !(flags.HasFlag(BoxFlags.PlayerOnly) && !IsPlayer)) continue; // For increased performance, we perform a quick test if // the coordinates can even be within a distance of 'threshold' // pixels of the box. if (threshold > 0 && _scumm.GetBoxCoordinates(box).InBoxQuickReject(dst, threshold)) continue; // Check if the point is contained in the box. If it is, // we don't have to search anymore. if (_scumm.CheckXYInBoxBounds(box, dst)) { abr.Position = dst; abr.Box = (byte)box; return abr; } // Find the point in the box which is closest to our point. Point pTmp; tmpDist = ScummMath.GetClosestPtOnBox(_scumm.GetBoxCoordinates(box), dst, out pTmp); // Check if the box is closer than the previous boxes. if (tmpDist < bestDist) { abr.Position = pTmp; if (tmpDist == 0) { abr.Box = (byte)box; return abr; } bestDist = tmpDist; bestBox = (byte)box; } } // If the closest ('best') box we found is within the threshold, or if // we are on the last run (i.e. threshold == 0), return that box. if (threshold == 0 || threshold * threshold >= bestDist) { abr.Box = bestBox; return abr; } } return abr; }