myspace / Lua /Camera.lua
sirnii's picture
Upload 1816 files
b6a38d7 verified
raw
history blame
8.21 kB
MapVar("g_SnapCameraEnabled", true)
local lCameraCollisionMask = const.cmCameraMask | const.cmTerrain
local lCameraCollisionQueryFlags = const.cqfSingleResult | const.cqfSorted
-- Returns the camera pos and lookat snapped to any collisions and rotated to avoid
-- the original ptCameraLookAt from being offscreen once the camera clamps to the terrain
function GetCameraSnapToObjectParams(pos, floor)
local ptCamera, ptCameraLookAt = cameraTac.GetPosLookAtEnd()
if not pos then return ptCamera, ptCameraLookAt end
pos = not pos:IsValidZ() and pos:SetTerrainZ() or pos
-- Used for restoring when camera messes up.
ptLastCameraPos, ptLastCameraLookAt = ptCamera, ptCameraLookAt
local cameraVector = ptCameraLookAt - ptCamera
ptCamera = pos - cameraVector
ptCameraLookAt = pos
-- Snap camera to camera collisions between pos and lookat.
-- This matters when the collision is low, like in the underground mines.
local first = true
collision.Collide(ptCamera, ptCameraLookAt - ptCamera, lCameraCollisionQueryFlags, 0, lCameraCollisionMask,
function(o, _, hitX, hitY, hitZ)
if not first then return end
first = false
ptCameraLookAt = point(hitX, hitY, hitZ)
ptCamera = ptCameraLookAt - cameraVector
end)
return ptCamera, ptCameraLookAt, floor or GetFloorOfPos(pos:xyz())
end
--Similar to GetCameraSnapToObjectParams, but it is only used for determining camera pos/lookat (with zoom taken into account) for DoPointsFitScreen
function GetCameraPosLookAtOnPos(pos)
local ptCamera, ptCameraLookAt = cameraTac.GetZoomedPosLookAtEnd()
if not pos then return ptCamera, ptCameraLookAt end
pos = not pos:IsValidZ() and pos:SetTerrainZ() or pos
local cameraVector = ptCameraLookAt - ptCamera
ptCamera = pos - cameraVector
ptCameraLookAt = pos
-- Snap camera to camera collisions between pos and lookat.
-- This matters when the collision is low, like in the underground mines.
local first = true
collision.Collide(ptCamera, ptCameraLookAt - ptCamera, lCameraCollisionQueryFlags, 0, lCameraCollisionMask,
function(o, _, hitX, hitY, hitZ)
if not first then return end
first = false
ptCameraLookAt = point(hitX, hitY, hitZ)
ptCamera = ptCameraLookAt - cameraVector
end)
return ptCamera, ptCameraLookAt
end
SnapCameraToObjInterpolationTimeDefault = 1000
function SnapCameraToObj(obj, force, floor, time, easingType)
if not g_SnapCameraEnabled then return end
if not cameraTac.IsActive() then return end
-- Dont snap the camera if requested by player input, and
-- other player input is already moving the camera. (217661)
if force == "player-input" then
force = false
if cameraTac.IsInputMovingCamera() then
return
end
end
local pos = IsValid(obj) and obj:GetPos() or obj
if IsPoint(pos) and ((not IsCameraLocked() and not gv_Deployment) or force) then
assert(not CurrentActionCamera)
local ptCamera, ptCameraLookAt, floor = GetCameraSnapToObjectParams(pos, floor)
local easing
if easingType and easingType ~= "none" then
easing = GetEasingIndex(easingType)
else
easing = hr.CameraTacPosEasing
end
time = time or SnapCameraToObjInterpolationTimeDefault
cameraTac.SetPosLookAtAndFloor(ptCamera, ptCameraLookAt, floor, time, easing)
return time, ptCamera, ptCameraLookAt
end
return 0
end
function SnapCameraToObjFloor(obj, force)
if not g_SnapCameraEnabled or cameraTac.GetIsInOverview() then return end
if not cameraTac.IsActive() then return end
if IsValid(obj) and (not IsCameraLocked() or force) then
local floor = GetFloorOfPos(obj:GetPosXYZ())
cameraTac.SetFloor(floor, hr.CameraTacInterpolatedMovementTime * 10, hr.CameraTacInterpolatedVerticalMovementTime * 10)
end
end
function DoesTargetFitOnScreen(self, target)
if GetUIStyleGamepad() then return false end
local paddingX, paddingY = const.Camera.CrosshairPaddingX, const.Camera.CrosshairPaddingY
local _, sx, sy = GameToScreenXY(target)
local crosshair_dimX, crosshair_dimY = ScaleXY(self.scale, paddingX, paddingY)
if sx - crosshair_dimX/2 < 0 or sy - crosshair_dimY/2 < 0 then
return false
end
local screen_size = UIL.GetScreenSize()
if sx + crosshair_dimX/2 >= screen_size:x() or sy + crosshair_dimY/2 >= screen_size:y() then
return false
end
return true
end
function IsOnScreen(target)
local screen_width, screen_height = UIL.GetScreenSize():xy()
local front, screen_x, screen_y = GameToScreenXY(target)
return front and screen_x > 0 and screen_y > 0 and screen_x < screen_width and screen_y < screen_height
end
function CameraPositionFromUnitOrientation(unit, time)
local ptCamera, ptCameraLookAt = GetCamera()
local cameraVector = ptCameraLookAt - ptCamera
if unit.entrance_marker then
local pos = unit.entrance_marker:GetPos()
if not pos:IsValidZ() then
pos = pos:SetTerrainZ()
end
local axis, marker_orient = unit.entrance_marker:GetOrientation()
local cam_orient = CalcOrientation(ptCamera, ptCameraLookAt)
local cameraVector = RotateAxis(cameraVector, axis, marker_orient - cam_orient)
ptCamera = pos - cameraVector
ptCameraLookAt = pos
local floor = GetFloorOfPos(pos:xyz())
cameraTac.SetPosLookAtAndFloor(ptCamera, ptCameraLookAt, floor, time or 1)
elseif time then -- use interpolation
local ptCamera, ptCameraLookAt = GetCamera()
if not ptCamera then
return
end
local pos = unit:GetPos()
if not pos:IsValidZ() then
pos = pos:SetTerrainZ()
end
ptCamera = pos - cameraVector
ptCameraLookAt = pos
local floor = GetFloorOfPos(ptCameraLookAt:xyz())
cameraTac.SetPosLookAtAndFloor(ptCamera, ptCameraLookAt, floor, time or 1)
else
ViewPos(unit:GetPos())
cameraTac.Rotate(-mapdata.MapOrientation * 60)
end
end
local max_trans_len = 15*guim
function HandleCameraTargetFixed(src, tar)
if not cameraTac.GetForceMaxZoom() or src == tar then return end
local t_pos = IsPoint(tar) and tar or tar:GetPos()
t_pos = not t_pos:IsValidZ() and t_pos:SetTerrainZ() or t_pos
local front, t_pos_sc = GameToScreen(t_pos)
local shrink = 300
local box = g_DesktopBox:grow(shrink, shrink, -shrink, -shrink)
if t_pos_sc:InBox(box) then return end
local ptCamera, ptCameraLookAt = GetCamera()
local s_pos = src:GetPos()
local trans_vector_tar = t_pos:SetZ(0) - s_pos:SetZ(0)
local len = s_pos:Dist2D(t_pos)/2
len = len > max_trans_len and max_trans_len or len
trans_vector_tar = SetLen(trans_vector_tar, len)
local trans_vector_src = s_pos:SetZ(0) - ptCameraLookAt:SetZ(0)
local trans_vector = trans_vector_src + trans_vector_tar
cameraTac.SetCamera(ptCamera + trans_vector , ptCameraLookAt + trans_vector, 500, "Sin out")
end
function ResetTacticalCamera()
local mapOrient = (mapdata.MapOrientation - 90) * 60
local ptCamera, ptCameraLookAt = GetCamera()
local cameraVector = ptCameraLookAt - ptCamera
local cam_orient = CalcOrientation(ptCamera, ptCameraLookAt)
if SelectedObj then
local pos = SelectedObj:GetPos():SetTerrainZ()
local cameraVector = RotateAxis(cameraVector, axis_z, mapOrient - cam_orient)
ptCamera = pos - cameraVector
ptCameraLookAt = pos
cameraTac.SetCamera(ptCamera, ptCameraLookAt)
else
cameraTac.Rotate(cam_orient - mapOrient)
end
cameraTac.SetFloor(0)
end
----
-- Camera changing floor when unit does
----
MapVar("floorFollowData", false)
local function lClearFollowRecord()
floorFollowData = false
end
OnMsg.ChangeMapDone = lClearFollowRecord
OnMsg.SelectedObjChange = lClearFollowRecord
OnMsg.TacCamFloorChanged = lClearFollowRecord
local function lFloorFollowRecord(unit)
if not table.find(Selection, unit) then return end
local currentFloor = cameraTac.GetFloor()
local movementStartFloor = GetFloorOfPos(unit:GetPosXYZ())
if movementStartFloor ~= currentFloor then return end
floorFollowData = {
unit = unit
}
end
OnMsg.UnitMovementStart = lFloorFollowRecord -- combat
OnMsg.UnitGoToStart = lFloorFollowRecord -- exploration
local function lFloorFollowCheckAndApply(unit)
if not floorFollowData then return end
if floorFollowData.unit ~= unit then return end
SnapCameraToObjFloor(unit)
lClearFollowRecord()
end
OnMsg.UnitMovementDone = lFloorFollowCheckAndApply
OnMsg.UnitGoTo = lFloorFollowCheckAndApply
--overwrite func to do SetAutoFovX
function SetCameraFov(fovX)
SetAutoFovX()
end