private static int getClosestSnappedOffset(BeatmapElement element, TimingPoint closestPoint, out int closestSnapDivisor) { // Gets the closest snap value in the beat. If multiple snaps // are found, then we also return a closestSnapIndex with // a value different than -1, in which case the note's snap // does not change and instead gets presented into the user. decimal snap = Convert.ToDecimal(element.GetClosestSnap()); decimal rawSnap = snap % BEAT_SNAP_DIVISOR_2; decimal snapDiff = snap - rawSnap; decimal result = snapsArray.BinarySearchClosest(rawSnap); decimal diff = Math.Abs(rawSnap - result); closestSnapDivisor = -1; // Diff = 0 or equal offsets means this element is exactly snapped. if (diff == 0 || closestPoint.Offset == element.Offset) { return(0); } // If we calculate that this object's new snap result // causes the offset not to be shifted, consider // it as snapped. decimal targetSnap = snapDiff + result; // Make the calculation by casting it to integer. If the offset are equal, these are snapped. int targetOffset = (int)(Convert.ToDecimal(closestPoint.Offset) + (targetSnap / BEAT_SNAP_DIVISOR_2 * Convert.ToDecimal(closestPoint.PointValue))); if ((int)element.Offset == targetOffset) { return(0); } return(targetOffset); }
private static int getSnapInBetween(BeatmapElement target1, BeatmapElement target2, double beatDuration) { double offsetDifference = target2.Offset - target1.Offset; double snap = (offsetDifference / beatDuration) * BEAT_SNAP_DIVISOR; int snapInt = Convert.ToInt32(snap); double fluctuation = Math.Abs(snap - snapInt); double targetOffset = target1.Offset + (snapInt / BEAT_SNAP_DIVISOR * beatDuration); if (fluctuation < 0.1d || Math.Abs(target2.Offset - targetOffset) < 1) { // We can consider this note as snapped in the end. // TODO Determine the behavior here: let the object unsnapped // if it is a hitsound, or show an error message. return(snapInt); } else { // The note is definitely unsnapped. Take this note as the 0 snap and // reset the final snap variable. // TODO Either fill this area with an error message // or throw an exception, or find another idea to process unsnapped notes. Console.WriteLine("Detected an unsnapped object with type \"" + target1.GetType() + "\", " + "and offset " + target1.Offset); return(-1); } }
private static void setOffsetOfElementToNewSnap(TimingPoint closestRedPoint, BeatmapElement element) { decimal snap = (decimal)element.GetSnap(); decimal pointValue = (decimal)closestRedPoint.PointValue; decimal finalResult = (decimal)closestRedPoint.Offset + (pointValue / (decimal)BEAT_SNAP_DIVISOR * snap); element.SetOffset((double)finalResult); }
public static double[] getRelativeSnap(List <TimingPoint> timingPoints, BeatmapElement target) { // First holds the true snap which is from the first point, // second holds the snap value from the closest timing point. double[] result = new double[2] { 0, 0 }; // If this is the first timing point or the element is snapped on the first timing point, // its actual and relative snaps should always equal to 0. Check the condition // and return it immediately. if (timingPoints.Count == 0 || (target.Offset == timingPoints[0].Offset && !timingPoints[0].IsInherited)) { return(result); } // Get the closest timing point to this target. TimingPoint closestPoint = SearchUtils.GetClosestTimingPoint(timingPoints, target.Offset); // Now, the beat snap divisor divides the beat to specific parts, and // we need to calculate both relative and actual snaps. // Actual snap would be closestPoint + relativeSnap while // relative snap is calculated by closest red point's point // value (a.k.a millis value between 2 beats, 60000 / BPM). // Diff of objects in millis calculated as decimal // for maximum precision. decimal diff = Convert.ToDecimal(target.Offset - closestPoint.Offset); // Relative snap value based on BEAT_SNAP_DIVISOR. decimal relativeSnap = diff * BEAT_SNAP_DIVISOR_2 / Convert.ToDecimal(closestPoint.PointValue); // Actual snap value. decimal actualSnap = Convert.ToDecimal(closestPoint.GetSnap()) + relativeSnap; // Set the results and return. First is actual snap // from the start of the map, second is relative // snap from the closest red point. result[0] = Convert.ToDouble(actualSnap); result[1] = Convert.ToDouble(relativeSnap); return(result); }