local DF = _G["DetailsFramework"] if (not DF or not DetailsFrameworkCanLoad) then return end local UnitExists = UnitExists local atan2 = math.atan2 local pi = math.pi local abs = math.abs local UnitPosition = UnitPosition local Clamp = Clamp local max = max local Lerp = Lerp SMALL_FLOAT = 0.000001 --namespace DF.Math = {} ---@class df_math : table ---@field GetUnitDistance fun(unitId1: unit, unitId2: unit) : number find distance between two units ---@field GetPointDistance fun(x1: number, y1: number, x2: number, y2: number) : number find distance between two points ---@field FindLookAtRotation fun(x1: number, y1: number, x2: number, y2: number) : number find a rotation for an object from a point to another point ---@field MapRangeClamped fun(inputX: number, inputY: number, outputX: number, outputY: number, value: number) : number find the value scale between two given values. e.g: value of 500 in a range 0-100 result in 10 in a scale for 0-10 ---@field MapRangeUnclamped fun(inputX: number, inputY: number, outputX: number, outputY: number, value: number) : number find the value scale between two given values. e.g: value of 75 in a range 0-100 result in 7.5 in a scale for 0-10 ---@field GetRangePercent fun(minValue: number, maxValue: number, value: number) : number find the normalized percent of the value in the range. e.g range of 200-400 and a value of 250 result in 0.25 ---@field GetRangeValue fun(minValue: number, maxValue: number, percent: number) : number find the value in the range given from a normalized percent. e.g range of 200-400 and a percent of 0.8 result in 360 ---@field GetColorRangeValue fun(r1: number, g1: number, b1: number, r2: number, g2: number, b2: number, value: number) : number, number, number find the color value in the range given from a normalized percent. e.g range of 200-400 and a percent of 0.8 result in 360 ---@field GetDotProduct fun(value1: table, value2: table) : number dot product of two 2D Vectors ---@field GetBezierPoint fun(value: number, point1: table, point2: table, point3: table) : number find a point in a bezier curve ---@field LerpNorm fun(minValue: number, maxValue: number, value: number) : number normalized value 0-1 result in the value on the range given, e.g 200-400 range with a value of .5 result in 300 ---@field LerpLinearColor fun(deltaTime: number, interpSpeed: number, r1: number, g1: number, b1: number, r2: number, g2: number, b2: number) : number, number, number change the color by the deltaTime ---@field IsNearlyEqual fun(value1: number, value2: number, tolerance: number) : boolean check if a number is near another number by a tolerance ---@field IsNearlyZero fun(value: number, tolerance: number) : boolean check if a number is near zero ---@field IsWithin fun(minValue: number, maxValue: number, value: number, isInclusive: boolean) : boolean check if a number is within a two other numbers, if isInclusive is true, it'll include the max value ---@field Clamp fun(minValue: number, maxValue: number, value: number) : number dont allow a number ot be lower or bigger than a certain range ---@field Round fun(num: number, numDecimalPlaces: number) : number cut fractions on a float ---@field GetObjectCoordinates fun(object: uiobject) : objectcoordinates return the coordinates of the four corners of an object ---find distance between two units ---@param unitId1 string ---@param unitId2 string function DF.Math.GetUnitDistance(unitId1, unitId2) if (UnitExists(unitId1) and UnitExists(unitId2)) then local u1X, u1Y = UnitPosition(unitId1) local u2X, u2Y = UnitPosition(unitId2) local dX = u2X - u1X local dY = u2Y - u1Y return ((dX*dX) + (dY*dY)) ^ .5 end return 0 end function DF.Math.GetPointDistance(x1, y1, x2, y2) local dX = x2 - x1 local dY = y2 - y1 return ((dX * dX) + (dY * dY)) ^ .5 end function DF.Math.FindLookAtRotation(x1, y1, x2, y2) return atan2(y2 - y1, x2 - x1) + pi end function DF.Math.MapRangeClamped(inputX, inputY, outputX, outputY, value) return DF.Math.GetRangeValue(outputX, outputY, Clamp(DF.Math.GetRangePercent(inputX, inputY, value), 0, 1)) end function DF.Math.MapRangeUnclamped(inputX, inputY, outputX, outputY, value) return DF.Math.GetRangeValue(outputX, outputY, DF.Math.GetRangePercent(inputX, inputY, value)) end function DF.Math.GetRangePercent(minValue, maxValue, value) return (value - minValue) / max((maxValue - minValue), SMALL_FLOAT) end function DF.Math.GetRangeValue(minValue, maxValue, percent) return Lerp(minValue, maxValue, percent) end function DF.Math.GetColorRangeValue(r1, g1, b1, r2, g2, b2, value) local newR = DF.Math.LerpNorm(r1, r2, value) local newG = DF.Math.LerpNorm(g1, g2, value) local newB = DF.Math.LerpNorm(b1, b2, value) return newR, newG, newB end function DF.Math.GetDotProduct(value1, value2) return (value1.x * value2.x) + (value1.y * value2.y) end function DF.Math.GetBezierPoint(value, point1, point2, point3) local bP1 = Lerp(point1, point2, value) local bP2 = Lerp(point2, point3, value) return Lerp(bP1, bP2, value) end function DF.Math.LerpNorm(minValue, maxValue, value) return (minValue + value * (maxValue - minValue)) end function DF.Math.LerpLinearColor(deltaTime, interpSpeed, r1, g1, b1, r2, g2, b2) deltaTime = deltaTime * interpSpeed local r = r1 + (r2 - r1) * deltaTime local g = g1 + (g2 - g1) * deltaTime local b = b1 + (b2 - b1) * deltaTime return r, g, b end function DF.Math.IsNearlyEqual(value1, value2, tolerance) tolerance = tolerance or SMALL_FLOAT return abs(value1 - value2) <= tolerance end function DF.Math.IsNearlyZero(value, tolerance) tolerance = tolerance or SMALL_FLOAT return abs(value) <= tolerance end function DF.Math.IsWithin(minValue, maxValue, value, isInclusive) if (isInclusive) then return ((value >= minValue) and (value <= maxValue)) else return ((value >= minValue) and (value < maxValue)) end end function DF.Math.Clamp(minValue, maxValue, value) return value < minValue and minValue or value < maxValue and value or maxValue end function DF.Math.Round(num, numDecimalPlaces) local mult = 10^(numDecimalPlaces or 0) return math.floor(num * mult + 0.5) / mult end --old calls, keeping for compatibility function DF:GetDistance_Unit(unit1, unit2) return DF.Math.GetUnitDistance(unit1, unit2) end function DF:GetDistance_Point(x1, y1, x2, y2) return DF.Math.GetPointDistance(x1, y1, x2, y2) end --find a rotation for an object from a point to another point function DF:FindLookAtRotation(x1, y1, x2, y2) return DF.Math.FindLookAtRotation(x1, y1, x2, y2) end --find the value scale between two given values. e.g: value of 500 in a range 0-100 result in 10 in a scale for 0-10 function DF:MapRangeClamped(inputX, inputY, outputX, outputY, value) return DF:GetRangeValue(outputX, outputY, Clamp(DF:GetRangePercent(inputX, inputY, value), 0, 1)) end --find the value scale between two given values. e.g: value of 75 in a range 0-100 result in 7.5 in a scale for 0-10 function DF:MapRangeUnclamped(inputX, inputY, outputX, outputY, value) return DF:GetRangeValue(outputX, outputY, DF:GetRangePercent(inputX, inputY, value)) end --find the normalized percent of the value in the range. e.g range of 200-400 and a value of 250 result in 0.25 function DF:GetRangePercent(minValue, maxValue, value) return (value - minValue) / max((maxValue - minValue), SMALL_FLOAT) end --find the value in the range given from a normalized percent. e.g range of 200-400 and a percent of 0.8 result in 360 function DF:GetRangeValue(minValue, maxValue, percent) return Lerp(minValue, maxValue, percent) end function DF:GetColorRangeValue(r1, g1, b1, r2, g2, b2, value) return DF.Math.GetColorRangeValue(r1, g1, b1, r2, g2, b2, value) end --dot product of two 2D Vectors function DF:GetDotProduct(value1, value2) return (value1.x * value2.x) + (value1.y * value2.y) end function DF:GetBezierPoint(value, point1, point2, point3) return DF.Math.GetBezierPoint(value, point1, point2, point3) end --normalized value 0-1 result in the value on the range given, e.g 200-400 range with a value of .5 result in 300 function DF:LerpNorm(minValue, maxValue, value) return (minValue + value * (maxValue - minValue)) end --change the color by the deltaTime function DF:LerpLinearColor(deltaTime, interpSpeed, r1, g1, b1, r2, g2, b2) return DF.Math.LerpLinearColor(deltaTime, interpSpeed, r1, g1, b1, r2, g2, b2) end --check if a number is near another number by a tolerance function DF:IsNearlyEqual(value1, value2, tolerance) tolerance = tolerance or SMALL_FLOAT return abs(value1 - value2) <= tolerance end --check if a number is near zero function DF:IsNearlyZero(value, tolerance) tolerance = tolerance or SMALL_FLOAT return abs(value) <= tolerance end --check if a number is within a two other numbers, if isInclusive is true, it'll include the max value function DF:IsWithin(minValue, maxValue, value, isInclusive) if (isInclusive) then return ((value >= minValue) and (value <= maxValue)) else return ((value >= minValue) and (value < maxValue)) end end --dont allow a number ot be lower or bigger than a certain range function DF:Clamp(minValue, maxValue, value) return value < minValue and minValue or value < maxValue and value or maxValue end --from http://lua-users.org/wiki/SimpleRound cut fractions on a float function DF:Round(num, numDecimalPlaces) local mult = 10^(numDecimalPlaces or 0) return math.floor(num * mult + 0.5) / mult end local BoundingBox = {} BoundingBox.CoordinatesData = { ["topleft"] = {["x"] = 'number', ["y"] = 'number'}, ["topright"] = {["x"] = 'number', ["y"] = 'number'}, ["bottomleft"] = {["x"] = 'number', ["y"] = 'number'}, ["bottomright"] = {["x"] = 'number', ["y"] = 'number'}, ["center"] = {["x"] = 'number', ["y"] = 'number'}, ["width"] = 'number', ["height"] = 'number', } ---@class objectcoordinates ---@field topleft {["x"]: number, ["y"]: number} ---@field topright {["x"]: number, ["y"]: number} ---@field bottomleft {["x"]: number, ["y"]: number} ---@field bottomright {["x"]: number, ["y"]: number} ---@field center {["x"]: number, ["y"]: number} ---@field width number ---@field height number ---@field left number ---@field right number ---@field top number ---@field bottom number ---return the coordinates of the four corners of an object ---@param object uiobject ---@return objectcoordinates function DF:GetObjectCoordinates(object) local centerX, centerY = object:GetCenter() local width = object:GetWidth() local height = object:GetHeight() local halfWidth = width / 2 local halfHeight = height / 2 return { ["width"] = width, ["height"] = height, ["left"] = centerX - halfWidth, ["right"] = centerX + halfWidth, ["top"] = centerY + halfHeight, ["bottom"] = centerY - halfHeight, ["center"] = {x = centerX, y = centerY}, ["topleft"] = {x = centerX - halfWidth, y = centerY + halfHeight}, ["topright"] = {x = centerX + halfWidth, y = centerY + halfHeight}, ["bottomleft"] = {x = centerX - halfWidth, y = centerY - halfHeight}, ["bottomright"] = {x = centerX + halfWidth, y = centerY - halfHeight}, } end function DF:ScaleBack() end