local DistanceTags = require "DistanceTags" ---@class LaneCursor ---@field lane TrafficLane ---@field driver TrafficDriver ---@field point integer ---@field edgePos number ---@field distance number ---@field index integer ---@field edgeCubic table ---@field edgeMeta EdgeMeta local LaneCursor = class('LaneCursor', class.Pool) ---@param lane TrafficLane ---@param edgeIndex integer ---@param edgePos number ---@param cursorIndex integer ---@param distance number ---@param driver TrafficDriver ---@return LaneCursor function LaneCursor:initialize(lane, edgeIndex, edgePos, cursorIndex, distance, driver) if self.lane then error('Already attached') end self.lane = lane self.point = edgeIndex self.edgePos = edgePos self.index = cursorIndex self.distance = distance self.driver = driver self.edgeCubic = lane.edgesCubic[edgeIndex] self.edgeMeta = lane.edgesMeta[edgeIndex] self.notFullyOnLane = false end function LaneCursor:__tostring() return string.format('', self.lane, self.distance, self.index) end function LaneCursor:detach() self.lane:stop(self) self.lane = nil class.recycle(self) end function LaneCursor:advance(speedKmh, dt) local lane = self.lane local point = self.point local edgeCubic = self.edgeCubic self.edgePos = self.edgePos + (speedKmh / 3.6) * edgeCubic.edgeLengthInv * dt while self.edgePos > 1 do point = point + 1 if lane.loop then if point > lane.size then point = 1 lane:restart(self) end elseif point >= lane.size then self:detach() return true end self.point = point local oldEdge = edgeCubic edgeCubic = lane.edgesCubic[point] self.edgeMeta = lane.edgesMeta[point] self.edgePos = (self.edgePos - 1) * oldEdge.edgeLength * edgeCubic.edgeLengthInv self.edgeCubic = edgeCubic end self.distance = edgeCubic.totalDistance + edgeCubic.edgeLength * self.edgePos return false end function LaneCursor:rearDistance() return self.distance - self.driver.dimensions.rear end ---@param pos vec3 function LaneCursor:syncPos(pos) self.point, self.edgePos = self.lane:worldToPointEdgePos(pos) if self.point == 0 then if DebugShapes then DebugShapes.pos = pos end error('Invalid state: '..tostring(pos) .. ', lane=' .. tostring(self.lane) .. ', car=' .. tostring(self.driver:getCar())) end end function LaneCursor:distanceToNextCar() local i = self.index - 1 if i == 0 then if self.lane.loop then local lastCursor = self.lane.orderedCars[self.lane.orderedCars.length] if lastCursor.driver ~= self.driver then return self.lane.totalDistance + lastCursor:rearDistance() - self.distance, lastCursor.driver:getCar(), DistanceTags.LaneCursorLoopAround else return 1e9, nil, DistanceTags.LaneCursorEmpty end end return 1e9, nil, DistanceTags.LaneCursorEmpty end local nextCursor = self.lane.orderedCars[i] return nextCursor:rearDistance() - self.distance, nextCursor.driver:getCar(), DistanceTags.LaneCursorCarInFront end function LaneCursor:calculateCurrentPosInto(v, estimate) return self.lane:interpolateInto(v, self.point, self.edgePos, estimate) end return class.emmy(LaneCursor, LaneCursor.initialize)