Skip to content

Head Tracking #7

@83BitTwitch

Description

@83BitTwitch

Hello. It's not and Issue, but I manage the same camera swing work for headtracking if you want to have a look and implement in to your mod. It really makes a difference when backing up to hook something. Thank you for the amazing mods

CabView = {}
CabView.modName = g_currentModName
CabView.specName = ("spec_%s.cabView"):format(g_currentModName)

function CabView.prerequisitesPresent(specializations)
return SpecializationUtil.hasSpecialization(Enterable, specializations)
end

function CabView.registerEventListeners(vehicleType)
SpecializationUtil.registerEventListener(vehicleType, "onLoad", CabView)
SpecializationUtil.registerEventListener(vehicleType, "onEnterVehicle", CabView)
SpecializationUtil.registerEventListener(vehicleType, "onLeaveVehicle", CabView)
SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", CabView)
SpecializationUtil.registerEventListener(vehicleType, "saveToXMLFile", CabView)
end

function CabView:saveToXMLFile(xmlFile, key)
local spec = self[CabView.specName]
if spec ~= nil and spec.seatHeightOffset ~= 0 then
local correctedKey = key:gsub(CabView.modName..".", "")
setXMLFloat(xmlFile.handle, correctedKey .. "#seatHeightOffset", spec.seatHeightOffset or 0)
end
end

function CabView:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
if self.isClient then
local spec = self[CabView.specName]
self:clearActionEventsTable(spec.actionEvents)
if isActiveForInputIgnoreSelection then
local _, actionEventId
_, actionEventId = self:addActionEvent(spec.actionEvents, "CABVIEW_LEAN_FORWARD", self, CabView.KeyDown_LeanForward, true, true, false, true, true, nil )
g_inputBinding:setActionEventTextVisibility(actionEventId, false)
_, actionEventId = self:addActionEvent(spec.actionEvents, "CABVIEW_LEAN_TOGGLE", self, CabView.KeyDown_LeanToggle, true, true, false, true, true, nil )
g_inputBinding:setActionEventTextVisibility(actionEventId, false)
_, actionEventId = self:addActionEvent(spec.actionEvents, "CABVIEW_RAISE_SEAT", self, CabView.KeyDown_SeatRaise, true, true, false, true, true, nil )
g_inputBinding:setActionEventTextVisibility(actionEventId, false)
_, actionEventId = self:addActionEvent(spec.actionEvents, "CABVIEW_LOWER_SEAT", self, CabView.KeyDown_SeatLower, true, true, false, true, true, nil )
g_inputBinding:setActionEventTextVisibility(actionEventId, false)
_, actionEventId = self:addActionEvent(spec.actionEvents, "CABVIEW_RESET_VIEW", self, CabView.KeyDown_ResetView, true, true, false, true, true, nil )
g_inputBinding:setActionEventTextVisibility(actionEventId, false)
end
end
end

function CabView:onLoad(savegame)
local spec = self[CabView.specName]
spec.restrictLean = (self.typeDesc == 'car' or self.typeDesc == 'truck' or self.typeName == 'carFillable')
if self.spec_enterable ~= nil then
for _, cameraBase in pairs(self.spec_enterable.cameras) do
if cameraBase.isInside then
spec.originalRotX = cameraBase.origRotX
spec.originalRotY = cameraBase.origRotY%(2*math.pi)
spec.originalRotZ = cameraBase.origRotZ
spec.rotationOffset = spec.originalRotY - math.pi
end
end
end
spec.seatHeightOffset = 0
if savegame ~= nil and savegame.xmlFile ~= nil then
spec.seatHeightOffset = getXMLFloat(savegame.xmlFile.handle, savegame.key .. ".cabView#seatHeightOffset") or 0
end
end

function CabView:onEnterVehicle(isControlling)
if isControlling then
local spec = self[CabView.specName]
spec.resetView = true
spec.lean = 0
end
end

function CabView:onLeaveVehicle()
local spec = self[CabView.specName]
spec.lean = 0
end

function CabView:KeyDown_LeanForward(_, inputValue)
local spec = self[CabView.specName]
if spec then spec.leanButtonPressed = (inputValue == 1) end
end

function CabView:KeyDown_LeanToggle(_, inputValue)
local spec = self[CabView.specName]
if spec and inputValue == 1 then spec.leanButtonPressed = not spec.leanButtonPressed end
end

function CabView:KeyDown_SeatRaise(_, inputValue)
local spec = self[CabView.specName]
if spec then spec.seatRaiseButtonPressed = (inputValue == 1) end
end

function CabView:KeyDown_SeatLower(_, inputValue)
local spec = self[CabView.specName]
if spec then spec.seatLowerButtonPressed = (inputValue == 1) end
end

function CabView:KeyDown_ResetView(_, inputValue)
local spec = self[CabView.specName]
if spec and inputValue == 1 then spec.resetView = true end
end

function CabView:vehicleCameraUpdate(superFunc, dt)
local spec = self.vehicle[CabView.specName]
if not spec then return superFunc(self, dt) end

superFunc(self, dt)

if self.isInside then
	local headTrackingActive = g_gameSettings:getValue("isHeadTrackingEnabled") and isHeadTrackingAvailable() and self.allowHeadTracking
	
	-- FIX: Limit Mouse Rotation to +/- 180 degrees (Stop the 360 spinning)
	if not headTrackingActive then
		local center = spec.originalRotY
		self.rotY = math.clamp(self.rotY, center - math.pi, center + math.pi)
	end

	local angle
	if headTrackingActive then
		local _, hyaw, _ = getHeadTrackingRotation()
		angle = hyaw or 0
	else
		angle = math.clamp(self.rotY-(math.pi+spec.rotationOffset), -math.pi, math.pi)
	end

	-- SEAT HEIGHT ADJUSTMENT
	if spec.seatRaiseButtonPressed then
		spec.seatHeightOffset = math.min(0.20, spec.seatHeightOffset + dt/5000)
	elseif spec.seatLowerButtonPressed then
		spec.seatHeightOffset = math.max(-0.20, spec.seatHeightOffset - dt/5000)
	end

	-- DIRECTIONAL LEAN (Mouse Only)
	if spec.leanButtonPressed and not headTrackingActive then
		spec.lean = math.min(0.4, spec.lean + dt/1000)
	else
		spec.lean = math.max(0, spec.lean - dt/1000)
	end

	local totalSide = 0
	local totalForward = 0
	local totalPitch = 0

	-- Apply Manual Lean (Mouse Only - Zoom into panels)
	if spec.lean > 0 then
		totalSide = spec.lean * math.sin(self.rotY - spec.originalRotY)
		totalForward = spec.lean * math.cos(self.rotY - spec.originalRotY)
	end

	-- AUTOMATIC HITCH VIEW
	if math.abs(angle) > math.pi/2 then
		local backRatio = (math.abs(angle) - math.pi/2) / (math.pi/2)
		local autoSide = 0
		local autoBack = 0

		if angle > math.pi/2 then autoSide = (angle-math.pi/2)/(2*math.pi) end
		if angle < -math.pi/2 then autoSide = (angle+math.pi/2)/(2*math.pi) end
		
		if not spec.restrictLean then
			-- Keep the limits we liked: 0.6 for tracker, 0.15 for mouse
			local maxSlide = headTrackingActive and 0.6 or 0.15
			local maxPitch = headTrackingActive and -0.45 or -0.20
			
			autoBack = -(maxSlide * backRatio) 
			totalPitch = maxPitch * backRatio
		end

		totalSide = totalSide + autoSide*math.cos(-spec.rotationOffset) - autoBack*math.sin(-spec.rotationOffset)
		totalForward = totalForward + autoSide*math.sin(-spec.rotationOffset) + autoBack*math.cos(-spec.rotationOffset)
	end

	-- APPLY TRANSLATION
	local tx, ty, tz = getTranslation(self.cameraPositionNode)
	setTranslation(self.cameraPositionNode, tx + totalSide, ty + spec.seatHeightOffset, tz + totalForward)

	-- APPLY PITCH
	if totalPitch ~= 0 then
		local rx, ry, rz = getRotation(self.cameraNode)
		setRotation(self.cameraNode, rx + totalPitch, ry, rz)
	end
end

end

VehicleCamera.update = Utils.overwrittenFunction(VehicleCamera.update, CabView.vehicleCameraUpdate)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions