2025-06-09 15:07:26 +02:00

542 lines
17 KiB
Lua

require 'math'
--[[
keypoints: sorted array of {x, y} pairs ('x' values should increase strongly monotonic!), e.g. { {0, 0.9}, {0.4, 0}, {0.6, 0.2}, {0.8, 1.0} }
pos: a position on the 'x' axis, e.g. 0.5
return: the value corresponding to 'pos' that was linear interpolated from the 'keypoints' line chain (e.g. 0.1 for the example input data)
--]]
function roadbookMapInterpolated(keypoints, pos)
local idx = 1
while ((idx + 1 < #keypoints) and (pos > keypoints[idx + 1][1])) do
idx = idx + 1
end
local secondidx = math.min(#keypoints, idx + 1)
local k0 = keypoints[idx][1]
local v0 = keypoints[idx][2]
local k1 = keypoints[secondidx][1]
local v1 = keypoints[secondidx][2]
local lpos = 0.0
if (k1 > k0) then
lpos = math.min(1.0, math.max(0.0, (pos - k0) / (k1 - k0)))
end
local result = v0 * (1.0 - lpos) + v1 * lpos
print(pos, " ", idx, " ", secondidx, " ", k0, " ", v0, " ", k1, " ", v1, " ", lpos, " ", result)
return result
end
--[[
state: the guidance state
return:
opacity: the opacity of the deviate content
--]]
function roadbookDeviateContentOpacity(state)
if state == ROADBOOK_GUIDANCE_STATE_DEVIATE then
return 1.0
else
return 0.0
end
end
function roadbookAsiaCcpOpacity(state)
if state == ROADBOOK_GUIDANCE_STATE_CALCULATION_ASIA
or state == ROADBOOK_GUIDANCE_STATE_INACTIVE_ASIA
or state == ROADBOOK_GUIDANCE_STATE_OFFROAD_ASIA then
return 1.0
else
return 0.0
end
end
--[[
state: the guidance state
enabled: roadbook is selected
mapVisible: whether a map screen (which can contain the flying window) is visible
return:
visibility: the visibility of the destination information (as a bool)
opacity: the visibility of the destination information (as either 1.0 or 0.0)
--]]
function roadbookDestinationVisibility(state, enabled, mapVisible)
local ret = (not mapVisible) and enabled and
(state == ROADBOOK_GUIDANCE_STATE_ACTIVE
or state == ROADBOOK_GUIDANCE_STATE_OFFROAD
or state == ROADBOOK_GUIDANCE_STATE_DEVIATE
or state == ROADBOOK_GUIDANCE_STATE_OFFROAD_ASIA)
if ret then
return true, 1.0
else
return false, 0.0
end
end
--[[
state: the guidance state
isEce: should contain true for ECE or US
enabled: roadbook is selected
bendDelay: a delay time for the bend (usually negative)
currentBend: current bend of bend animation
bendThreshold: bending threashold if the content will be visible
return:
bend: the bend value for the road
contentVisible: the visibility of the roadbook panels
detailedContentVisible: the visibility of the detailed content
laneguidingVisible: the visibility of the three LG rows and the separator
compassVisible: the visibility of the (non asia) compass
--]]
function roadbookGuidanceStateRelated(state, isEce, enabled, bendDelay, currentBend, bendThreshold)
local panelsVisible = (state == ROADBOOK_GUIDANCE_STATE_ACTIVE or state == ROADBOOK_GUIDANCE_STATE_DEVIATE)
local roadBend = bendDelay
if panelsVisible then
roadBend = 1.0
end
local detailedContentVisible = (panelsVisible or state == ROADBOOK_GUIDANCE_STATE_INACTIVE_ASIA)
-- TODO: will this lead to instantly vanishing lane guiding on state change??
local lgVisible = (state == ROADBOOK_GUIDANCE_STATE_ACTIVE)
local compassVisible = isEce
local contentVisible = enabled and panelsVisible and (currentBend > bendThreshold)
return roadBend, contentVisible, enabled and detailedContentVisible, enabled and lgVisible, enabled and compassVisible
end
--[[
opacity: opacity to be used when visible
visible: if false, the resulting opacity will be 0
return:
effectiveOpacity: Either input opacity or 0, depending on "visible"
--]]
function roadbookEffectiveOpacity(opacity, visible)
if visible then
return opacity
else
return 0
end
end
--[[
progress: the progress of the bargraph
assetSize: size of the bargraph asset
return:
position: vertical bottom position of the bar graph component
size: vertical size of the bar graph component
--]]
function roadbookBargraphPlacement(progress, assetSize)
-- always at least 9 px high, as the bottom + top images have that size
local size = 9 + ( (assetSize.z - 2*6 - 9) * (100.0 - progress) / 100.0 )
return assetSize.z - 6.0 - size , size
end
--[[
currentOpacity: The current opacity for the whole widget
contentOpacity: The animated opacity for the content
loadingOpacity: The animated opacity for the loading indicator
return:
contentOpacity: Calculated opacity for the content
loadingOpacity: Calculated opacity for the loading indicator
--]]
function calculatePanelContentOpacity(currentOpacity, contentOpacity, loadingOpacity)
return currentOpacity * contentOpacity, currentOpacity * loadingOpacity
end
--[[
trafficIconsVisibility: [0, 1] for the visibility of traffic icons and divider bar (causes other elements to be shifted)
opacity: the current opacity of the widget
maxTextLineWidth: the maximum width of the text widget
xStartWithOutTrafficIcons: x-offset without traffic icons displayed
xStartWithTrafficIcons: x-offset with traffic icons displayed
return:
textLineSize: layout related size vector of the icon text line and the service icons
doubleTextLineSize: layout related size vector of the two-lined text widget
iconTextPosition: layout related position vector of the icon text line and the two-lined text widget
serviceIconPosition: layout related position vector of the service icons
directionPosition: layout related position vector of the direction arrow
trafficElementsOpacity: opacity of traffic related content
--]]
function roadbookFrontContentLayout(trafficIconsVisibility, opacity, maxTextLineWidth, xStartWithOutTrafficIcons, xStartWithTrafficIcons)
-- TODO: shift direction position less? (only 35px?)
local xOffset = roadbookMapInterpolated({{0.0, xStartWithOutTrafficIcons}, {0.6, xStartWithTrafficIcons}}, trafficIconsVisibility);
local trafficOpa = roadbookMapInterpolated({{0.7, 0.0}, {1.0, 1.0}}, trafficIconsVisibility);
local textLineSize = {x=maxTextLineWidth - xOffset, y=0, z=40}
local doubleTextLineSize = {x=maxTextLineWidth - xOffset, y=0, z=90}
local iconTextPosition = {x=25 + xOffset, y=0, z=-52}
local serviceIconPosition = {x=25 + xOffset, y=0, z=-97}
local directionPosition = {x=35 + xOffset, y=0, z=-212}
local trafficElementsOpacity = opacity * trafficOpa
return textLineSize, doubleTextLineSize, iconTextPosition, serviceIconPosition, directionPosition, trafficElementsOpacity
end
--[[
return:
tunnelIconOpacity: the current opacity for the widgets in tunnel maneuver layout
barGraphPosition: the bar graph widget position (not in tunnels, only normal and Asia Branch)
distancePosition: the distance text position for the widgets in non-tunnel maneuver layout
--]]
function roadboookBlowupContentLayout(isTunnelLayout, opacity, distanceVerticalOffset, distanceHorizontalOffset, barGraphVerticalOffset, barGraphHorizontalOffset)
local tunnelIconOpacity = 0.0
local px = 332
local py = -438
local of = 1.9 -- shadow/outline x/y offset
if isTunnelLayout then
tunnelIconOpacity = opacity
px = 234
end
py = py + distanceVerticalOffset
local barGraphPosition = {x=px + 170 + barGraphHorizontalOffset, y=0, z=py + 63 + barGraphVerticalOffset}
return tunnelIconOpacity, barGraphPosition, {x=px + distanceHorizontalOffset, y=0, z=py}
end
--[[
size: the given size vector
return: a size vector where z is divided by 2
--]]
function roadbookTrafficSegmentSize(size)
return {x = size.x, y = size.y, z = size.z/2}
end
function roadbookDelayOpacity(delayTimeString, baseOpacity)
if delayTimeString == "" then
return 0.0
end
return baseOpacity
end
--[[
guidanceState: the guidance state
headlineContentVisible: is there any DTD/ETA/... info visible?
return:
opacity of the black headline background
sortOrder of the black headline background
--]]
function roadbookHeadlineBackground(guidanceState, headlineContentVisible)
if headlineContentVisible and (guidanceState == ROADBOOK_GUIDANCE_STATE_OFFROAD or
guidanceState == ROADBOOK_GUIDANCE_STATE_OFFROAD_ASIA) then
return 1.0, 0
elseif guidanceState == ROADBOOK_GUIDANCE_STATE_CALCULATION or
guidanceState == ROADBOOK_GUIDANCE_STATE_CALCULATION_ASIA then
return 1.0, 6
else
return 0.0, 0
end
end
--[[
guidanceState: the guidance state
return:
opacity of the "Calculating route..." text
--]]
function roadbookHeadlineCalculatingText(guidanceState)
if guidanceState == ROADBOOK_GUIDANCE_STATE_CALCULATION or
guidanceState == ROADBOOK_GUIDANCE_STATE_CALCULATION_ASIA then
return 1.0
else
return 0.0
end
end
function roadbookLabelsGuidanceState(guidingStep, isDoubleManeuver, parentOpacity)
opacityDirection = parentOpacity
opacityDtM = parentOpacity
opacityComingRoad = parentOpacity
opacityGS3 = parentOpacity
layerEnabled = false
opacityFrame = parentOpacity
opacityFrameDoubleManeuver = 0.0
if guidingStep == ROADBOOK_GS_3_1 or guidingStep == ROADBOOK_GS_3_2 then
opacityComingRoad = 0.0
opacityDtM = 0.0
opacityComingRoad = 0.0
opacityDirection = 0.0
opacityFrameDoubleManeuver = 0.0
layerEnabled = true
else
opacityGS3 = 0.0
if isDoubleManeuver == true then
opacityDirection = parentOpacity * 0.5
opacityDtM = 0.0
opacityComingRoad = 0.0
opacityFrameDoubleManeuver = parentOpacity
opacityFrame = 0.0
elseif guidingStep == ROADBOOK_GS_1 or guidingStep == ROADBOOK_GS_0 then
opacityComingRoad = 0.0
end
end
return opacityDirection, opacityDtM, opacityComingRoad, opacityFrame, opacityFrameDoubleManeuver, opacityGS3, layerEnabled
end
function roadbookLabelsGuidanceLaneGuidingState(guidingStep, parentOpacity, useCutoutFrame)
opacity = parentOpacity
opacityCutoutFrame = parentOpacity
if guidingStep == ROADBOOK_GS_1 then
opacityCutoutFrame = 0.0
end
if useCutoutFrame == true then
opacityNormalFrame = parentOpacity - opacityCutoutFrame
else
opacityNormalFrame = parentOpacity
end
return opacity, opacityNormalFrame, opacityCutoutFrame
end
function roadbookLabelsGuidanceStateSize(guidingStep, width, showComingRoad)
height = 103.0
if guidingStep == ROADBOOK_GS_1 or guidingStep == ROADBOOK_GS_0 then
height = 60.0
elseif guidingStep == ROADBOOK_GS_3_1 or guidingStep == ROADBOOK_GS_3_2 then
height = 232.0
if showComingRoad then
height = height + 45.0
end
end
return { x=width, y=0.0, z=height }
end
function roadbookCurrentLaneIndicatorPosition(laneIndicatorPosition, basePosition)
xValue = laneIndicatorPosition
return { x=basePosition.x + xValue, y=basePosition.y, z=basePosition.z }
end
function roadbookLabelsGuidanceLanePosition(laneCount, offset)
width = 4.0 + 8.0 - 1.0 + laneCount * ( 36.0 + 4.0 )
width = width + offset;
height = 0.0
return { x=width, y=0.0, z=height }
end
function roadbookLabelsGuidanceBackgroundOpacity(parentOpacity, guidingStep)
opacityGS1 = parentOpacity
opacityGS2 = parentOpacity
if guidingStep == ROADBOOK_GS_1 then
opacityGS2 = 0
else
opacityGS1 = 0
end
return opacityGS1, opacityGS2
end
--[[
numberOfLanes: number of available lanes
currentLaneIndex: the index of the current lane
return:
visibility of the current lane
position of the current lane
position of the current lane separator
position of the current lane sector
--]]
function roadbookLabelLaneProperties(numberOfLanes, currentLaneIndex, positionOffset)
pos = -40.0 * ( numberOfLanes - currentLaneIndex )
separatorPos = pos - 4.0
positionOffset.x = positionOffset.x + pos
visibility = 0.0
if numberOfLanes >= currentLaneIndex and numberOfLanes ~= 0 then
visibility = 1.0
end
return visibility, positionOffset, { x=separatorPos, y=0.0, z=0.0 }, { x=pos, y=0.0, z=8.0 }
end
function roadbookLabelsComingRoadFadeDelay( opacityTo )
if opacityTo > 0 then
return 500
end
return 1
end
function roadbookLabelsBarGraphFadeDelay( opacityTo )
delay = 1
if opacityTo > 0 then
delay = 500
end
return delay
end
function roadbookLabelsHighguidingFadeDuration( opacityTo, animDuration )
duration = 1
if opacityTo > 0 then
duration = animDuration
end
return duration
end
function roadbookLabelsHighguidingSize( size, showComingRoad )
size.x = size.x - 12.0
size.z = size.z - 11.0
if showComingRoad then
size.z = size.z - 45.0
end
if size.x < 0.0 then
size.x = 0.0
end
if size.z < 0.0 then
size.z = 0.0
end
return size
end
function roadbookLabelsComingRoadLineSizeScript( width )
spacerWidth = 10.0
sizeX = width - spacerWidth - spacerWidth -- start and end spacers
return { x=sizeX, y=0.0, z=41.0 }
end
function roadbookLabelsDistanceLineSizeScript( width )
spacerWidth = 10.0
iconWidth = 113.0
iconRightBorderTransparency = 45.0
sizeX = width - iconWidth + iconRightBorderTransparency - spacerWidth - spacerWidth - spacerWidth -- spacers at start and end and between icon/distance
return { x=sizeX, y=0.0, z=41.0 }
end
function roadbookLabelLaneGS2BackgroundOpacity( opacity, useCutoutFrame )
if useCutoutFrame == true then
return opacity
end
return 0.0
end
function roadbookLabelsLaneGuidingBackgroundSize( guidingStep, gs1Size, gs2Size, useCutoutFrame )
if guidingStep == 1 then
return gs1Size
end
if useCutoutFrame == true then
return gs1Size
end
return gs2Size
end
function roadbookLabelsComingRoadBackgroundSize( size )
if size.z > 42.0 then
size.z = 42.0
end
size.x = size.x - 12.0
if size.x < 0.0 then
size.x = 0.0
end
return size
end
function roadbookLabelsComingRoadLineSize( size )
if size.z > 47.0 then
size.z = 47.0
end
size.x = size.x - 20.0
if size.x < 0.0 then
size.x = 0.0
end
return size
end
function roadbookLabelsComingRoadPosition( size )
size.x = 0.0
size.z = size.z - 47.0
return size
end
function roadbookTextOutlinePositions( size )
return { x=-size, y=0.0, z=-size }, { x=-size, y=0.0, z=size }, { x=size, y=0.0, z=-size }, { x=size, y=0.0, z=size }
end
--[[
widgetTopOffset: the amount of pixels that the layer widget (height = 485) is shifted downwards, with 0 it being aligned with the top of the screen
widgetWidth: the size of the texture image widget
widgetHeight: see above
widgetExtraOffset: a vec3 that is subtracted from the widgetWidth/Height (i.e. can be used to expand/shrink the widget size)
return:
a (x,y, w,h) texture coordinate vector
--]]
function roadbookAssetLayerMaskTexCoords(widgetTopOffset, widgetWidth, widgetHeight, widgetExtraOffset)
local texWidth = 32
local texHeight = 96
local texCoordW = (widgetWidth - widgetExtraOffset.x) / texWidth
local texCoordH = (widgetHeight - widgetExtraOffset.z) / texHeight
local texCoordStartOffsetY = (55.0 - widgetTopOffset) / texHeight
return { x=0.0, y=texCoordStartOffsetY, z=texCoordW, w=texCoordH }
end
--[[
carHeading: heading of the car [0..1[
return:
rotation value [0..360[
--]]
function roadbookFlatCompassScalesRotation(carHeading)
return { x=0.0, y=carHeading*360.0, z=0.0 }
end
--[[
offset: current offset [0..1]
range: +- threashold
return:
mapped value from [0-range..1+range]
--]]
function roadbookMapAlphaMaskValue( offset, range )
return ( 1.0 + range * 2.0 ) * offset - range
end
--[[
panelPos: current panel position [0.0..5.0] (S_FUTURE, S_FAR, S_NEAR, S_FRONT, S_BLOWUP, S_BEHIND)
blowUp: current blowup value
return:
previewContentOpacity
previewTrafficContentOpacity
fullContentOpacity
--]]
function roadbookMapPanelPositionToOpacity( panelPos, blowUp, isDeviate )
local S_FUTURE = 0.0
local S_FAR = 1.0
local S_NEAR = 2.0
local S_NEAR_FRONT = 2.5
local S_FRONT = 3.0
local S_FRONT_BLOWUP = 3.5
local S_BLOWUP = 4.0
local S_BEHIND = 5.0
if isDeviate == true then
return 0.0, 0.0, 0.0
end
panelPos = panelPos + 1
local previewContentOpacity = roadbookMapInterpolated({{S_FUTURE, 0.0}, {S_FAR, 0.29}, {S_NEAR, 0.55}, {S_NEAR_FRONT, 0.0}}, panelPos)
local previewTrafficContentOpacity = roadbookMapInterpolated({{S_FUTURE, 0.0}, {S_FAR, 0.6}, {S_NEAR, 0.8}, {S_NEAR_FRONT, 0.0}}, panelPos)
local fullContentOpacity = roadbookMapInterpolated({{S_NEAR_FRONT, 0.0}, {S_FRONT, 1.0}, {S_FRONT_BLOWUP, 0.0}, {S_BEHIND, 0.0}}, panelPos)
local blowUpScale = roadbookMapInterpolated({{1.0, 1.0}, {2.0, 0.0}}, blowUp)
fullContentOpacity = fullContentOpacity * blowUpScale
return previewContentOpacity, previewTrafficContentOpacity, fullContentOpacity
end