// Make sure that the curve is valid void CheckForValidCurve() { //Debug.Log ("Checking for valid curve"); bool curveIsValid = true; // assume a valid curve, set to false if something is wrong // if the curve is null, not much curve there to check, set it to some default curve and skip the rest if (distributionCurve == null) { distributionCurve = DefaultCurve(); } // curve is not null, else { // check for at least some part of the curve being above zero AnimCurveRect tmpCurveRect = new AnimCurveRect(distributionCurve); if (tmpCurveRect.MaxY <= 0) { Debug.LogError("At least some part of the distribution curve has to be higher than zero."); curveIsValid = false; } // check for minimum amount of keyframes if (distributionCurve.keys.Length < 2) { Debug.LogError("A distribution curve needs at least two keyframes."); curveIsValid = false; } } if (!curveIsValid) { Debug.LogError("Not a valid distribution curve."); } }
// prebake the float numbers void PrebakeFloats(AnimationCurve curve, AnimCurveRect curveRect, int resolution) { prebakedFloats = new List <float>(); //get min and max x values and range float minX = curveRect.MinX; float maxX = curveRect.MaxX; float xRange = maxX - minX; // step for stepping from x to x float xStep = xRange / resolution; // vertical step / upwards float yStep = curveRect.MaxY / resolution; // for floats // for loop that goes through all relevant x coords determined by step float currentY = 0; for (float currentX = minX; currentX <= maxX; currentX += xStep) { while (currentY < curve.Evaluate(currentX)) { prebakedFloats.Add(currentX); currentY += yStep; } currentY = 0; } }
// constructor public NumberBakery(AnimationCurve curve, AnimCurveRect curveRect, int resolution) { // prebake lists of numbers PrebakeFloats(curve, curveRect, resolution); PrebakeInts(curve, curveRect, resolution); // give error messages if something failed if (prebakedFloats.Count < 1) { Debug.LogError("Could not prebake enough floats (" + prebakedFloats.Count + ") from distribution curve."); } if (prebakedInts.Count < 1) { Debug.LogError("Could not prebake enough ints (" + prebakedInts.Count + ") from distribution curve."); } // Debug.Log ("Pre-baked " + prebakedFloats.Count + " floats."); // Debug.Log ("Pre-baked " + prebakedInts.Count + " ints."); }
// update the curve data if the curve or settings have changed. called by the custom inspector. void UpdateCurveData() { //Debug.Log ("Updating Curve Data of " + gameObject.name); // make sure the curve has at least two keyframes and fulfills other requirements CheckForValidCurve(); // always calc the curve rect, it's needed in any case curveRect = new AnimCurveRect(distributionCurve); // either prebake numbers or clear bakery depending on mode if (randomizeMode == RandomizeMode.Pregenerate) { // instantiate number bakery numberBakery = new NumberBakery(distributionCurve, curveRect, prebakeResolution); } else // brute force mode, clear number bakery { numberBakery = null; } }
// prebake the ints void PrebakeInts(AnimationCurve curve, AnimCurveRect curveRect, int resolution) { prebakedInts = new List <int>(); //get min and max x values and range int minX = Mathf.RoundToInt(curveRect.MinX); int maxX = Mathf.RoundToInt(curveRect.MaxX); int xRange = maxX - minX; // step for stepping from x to x int xStep = Mathf.RoundToInt(xRange / resolution); if (xStep < 1) { xStep = 1; // don't allow zero steps... } // vertical step / upwards float yStep = curveRect.MaxY / resolution; // y step can be float as it's not used directly // fill int list // for loop that goes through all relevant x coords determined by step float currentY = 0; for (int currentX = minX; currentX <= maxX; currentX += xStep) { while (currentY < curve.Evaluate(currentX)) { prebakedInts.Add(currentX); currentY += yStep; } currentY = 0; } // sometimes, no ints can be generated due to rounding. fix that by adding the closest suitable int value(s) if (prebakedInts.Count == 0) { if (minX == maxX) { prebakedInts.Add(minX); // if minX and maxX are the same when rounded, just always return that value } else // otherwise, the curve will have some unusual shape that is especially nasty to ints (and probably not intended to return ints). try to add at least some int. // could throw a warning here, but it would get annoying / become spam if curve is not intended for ints // instead, try minX, maxX and avgX if they could be added { if (curve.Evaluate(minX) >= 0) { prebakedInts.Add(minX); } if (curve.Evaluate(maxX) >= 0) { prebakedInts.Add(maxX); } int avg = Mathf.RoundToInt((curveRect.MinX + curveRect.MaxX) / 2f); if (curve.Evaluate(avg) >= 0) { prebakedInts.Add(avg); } // if nothing worked, just put the average there. if (prebakedInts.Count == 0) { prebakedInts.Add(avg); } } } }