LUADOC - Farming Simulator 19

Script v1.7.1.0

Engine v1.7.1.0

Foundation Reference

GuiTopDownCamera

Description
Top-down camera used for UI. Provides a birds-eye view for players when they need to interact with the world from the UI (e.g. placing objects, modifying terrain).
Functions

activate

Description
Activate the camera and change the game's viewpoint to it.
Definition
activate()
Code
166function GuiTopDownCamera:activate()
167 self.inputManager:setShowMouseCursor(true)
168 self:onInputModeChanged(self.inputManager:getLastInputMode())
169
170 self:updatePosition()
171
172 self.previousCamera = getCamera()
173 setCamera(self.camera)
174
175 if self.controlledPlayer ~= nil then
176 local x, y, z = getTranslation(self.controlledPlayer.rootNode)
177 self.lastPlayerPos[1], self.lastPlayerPos[2], self.lastPlayerPos[3] = x, y, z
178 self.lastPlayerTerrainHeight = getTerrainHeightAtWorldPos(self.terrainRootNode, x, 0, z)
179
180 self.controlledPlayer:onLeave()
181 end
182
183 if not self.cameraTransformInitialized then
184 -- only automatically reset the camera position on the first activation, otherwise remember it
185 self:resetToPlayer()
186 self.cameraTransformInitialized = true
187 end
188
189 self:registerActionEvents()
190 self.messageCenter:subscribe(MessageType.INPUT_MODE_CHANGED, self.onInputModeChanged, self)
191 self.isActive = true
192end

applyMovement

Description
Apply a movement to the camera (and view).
Definition
applyMovement(moveX X, moveZ Z, movementMultiplier Movement)
Arguments
moveXXdirection movement [-1, 1]
moveZZdirection movement [-1, 1]
movementMultiplierMovementspeed factor
Code
318function GuiTopDownCamera:applyMovement(moveX, moveZ, movementMultiplier, dt)
319 local dirX = math.sin(self.cameraRotY) * moveZ + math.cos(self.cameraRotY) * -moveX
320 local dirZ = math.cos(self.cameraRotY) * moveZ - math.sin(self.cameraRotY) * -moveX
321
322 local limit = self.terrainSize * 0.5 - GuiTopDownCamera.TERRAIN_BORDER
323 local moveFactor = dt * GuiTopDownCamera.MOVE_SPEED * movementMultiplier
324 self.cameraX = MathUtil.clamp(self.cameraX + dirX * moveFactor, -limit, limit)
325 self.cameraZ = MathUtil.clamp(self.cameraZ + dirZ * moveFactor, -limit, limit)
326
327 -- TODO: what's happening here? looks like a dampening effect to compensate for frame rate changes... not sure
328 self.zoomFactorUpdateDt = self.zoomFactorUpdateDt + dt
329 while self.zoomFactorUpdateDt > 30 do
330 self.zoomFactorUpdateDt = self.zoomFactorUpdateDt - 30
331 self.zoomFactor = MathUtil.clamp(0, 1, self.zoomFactor * 0.9 + self.targetZoomFactor * 0.1)
332 end
333end

createCameraNodes

Description
Create scene graph camera nodes.
Definition
createCameraNodes()
Return Values
intCameranode ID (view point, child of camera base node)
intCamerabase node ID (view target, parent of camera node)
Code
96function GuiTopDownCamera:createCameraNodes()
97 local camera = createCamera("TopDownCamera", math.rad(60), 1, 4000) -- camera view point node
98 local cameraBaseNode = createTransformGroup("topDownCameraBaseNode")-- camera base node, look-at target
99 link(cameraBaseNode, camera)
100 setRotation(camera, 0, math.rad(180) , 0)
101 setTranslation(camera, 0, 0, -5)
102 setRotation(cameraBaseNode, 0, 0 , 0)
103 setTranslation(cameraBaseNode, 0, 110, 0)
104
105 return camera, cameraBaseNode
106end

deactivate

Description
Disable this camera.
Definition
deactivate()
Code
196function GuiTopDownCamera:deactivate()
197 self.isActive = false
198 self.messageCenter:unsubscribeAll(self)
199 self:removeActionEvents()
200
201 local showCursor = self.controlledPlayer == nil and self.controlledVehicle == nil
202 self.inputManager:setShowMouseCursor(showCursor)
203
204 -- restore player position and previous camera
205 if self.controlledPlayer ~= nil then
206 local x,y,z = unpack(self.lastPlayerPos)
207 local currentPlayerTerrainHeight = getTerrainHeightAtWorldPos(self.terrainRootNode, x,0,z)
208 local deltaTerrainHeight = currentPlayerTerrainHeight - self.lastPlayerTerrainHeight
209 if deltaTerrainHeight > 0 then
210 y = y + deltaTerrainHeight
211 end
212
213 self.controlledPlayer:moveRootNodeToAbsolute(x, y, z)
214 self.controlledPlayer:onEnter(true)
215 end
216
217 if self.previousCamera ~= nil then
218 setCamera(self.previousCamera)
219 self.previousCamera = nil
220 end
221end

delete

Description
Definition
delete()
Code
110function GuiTopDownCamera:delete()
111 self:deactivate()
112 delete(self.cameraBaseNode) -- base node holds the camera as a child, this call deletes both
113 self.camera, self.cameraBaseNode = nil, nil
114end

determineMapPosition

Description
Determine the current camera position and orientation.
Definition
determineMapPosition()
Return Values
CameraXworld space position

Warning: Undefined array key "className" in /usr/www/users/giantw/gdn.giants-software.com/documentation_scripting_fs19.php on line 213
CameraZworld space position
CameraYrotation in radians
Code
259function GuiTopDownCamera:determineMapPosition()
260 return self.cameraX, 0, self.cameraZ, self.cameraRotY - math.rad(180)
261end

getIsActive

Description
Check if this camera is active.
Definition
getIsActive()
Code
225function GuiTopDownCamera:getIsActive()
226 return self.isActive
227end

getMouseEdgeScrollingMovement

Description
Get camera movement for mouse edge scrolling.
Definition
getMouseEdgeScrollingMovement()
Return Values
Xdirectionmovement [-1, 1]
Zdirectionmovement [-1, 1]
Code
345function GuiTopDownCamera:getMouseEdgeScrollingMovement()
346 -- TODO: what's the purpose of the added magic numbers?
347 local moveMarginStartX = 0.075 + 0.048 * 1.3
348 local moveMarginEndX = 0.075
349 local moveMarginStartY = 0.075 + 0.072
350 local moveMarginEndY = 0.075
351
352 local moveX, moveZ = 0, 0
353
354 if self.mousePosX >= 1 - moveMarginStartX then
355 moveX = math.min((moveMarginStartX - (1 - self.mousePosX)) / (moveMarginStartX - moveMarginEndX), 1)
356 elseif self.mousePosX <= moveMarginStartX then
357 moveX = -math.min((moveMarginStartX - self.mousePosX) / (moveMarginStartX - moveMarginEndX), 1)
358 end
359
360 if self.mousePosY >= 1 - moveMarginStartY then
361 moveZ = math.min((moveMarginStartY - (1 - self.mousePosY)) / (moveMarginStartY - moveMarginEndY), 1)
362 elseif self.mousePosY <= moveMarginStartY then
363 moveZ = -math.min((moveMarginStartY - self.mousePosY) / (moveMarginStartY - moveMarginEndY), 1)
364 end
365
366 return moveX, moveZ
367end

getPickRay

Description
Get a picking ray for the current camera orientation and cursor position.
Definition
getPickRay()
Code
265function GuiTopDownCamera:getPickRay()
266 return RaycastUtil.getCameraPickingRay(self.mousePosX, self.mousePosY, self.camera)
267end

hasRotationInput

Description
Check if the camera has rotation input for this frame. This is only valid before this instance's update() is called, because input values are then reset.
Definition
hasRotationInput()
Code
272function GuiTopDownCamera:hasRotationInput()
273 return self.inputRotate ~= 0
274end

mouseEvent

Description
Definition
mouseEvent()
Code
420function GuiTopDownCamera:mouseEvent(posX, posY, isDown, isUp, button)
421 if self.isMouseMode then
422 self.mousePosX = posX
423 self.mousePosY = posY
424 end
425end

new

Description
Create a new LandscapingScreenController instance.
Definition
new(table messageCenter, table l10n, table inputManager)
Arguments
tablemessageCenterMessageCenter reference for local event handling
tablel10nI18N reference for string localization.
tableinputManagerInputBinding reference for input action registration
Code
42function GuiTopDownCamera:new(subclass_mt, messageCenter, l10n, inputManager)
43 local self = setmetatable({}, subclass_mt or GuiTopDownCamera_mt)
44
45 self.messageCenter = messageCenter
46 self.l10n = l10n
47 self.inputManager = inputManager
48
49 self.controlledPlayer = nil
50 self.controlledVehicle = nil
51 self.hud = nil
52
53 self.terrainRootNode = nil
54 self.waterLevelHeight = 0
55 self.terrainSize = 0
56
57 self.previousCamera = nil
58 self.camera, self.cameraBaseNode = self:createCameraNodes()
59
60 self.isActive = false
61
62 self.cameraX = 0
63 self.cameraZ = 0
64 self.cameraRotY = math.rad(45)
65 self.cameraTransformInitialized = false
66
67 self.isMouseEdgeScrollingActive = true
68 self.isMouseMode = false
69 self.mousePosX = 0.5
70 self.mousePosY = 0.5
71 self.zoomFactor = 1
72 self.targetZoomFactor = 1
73 self.zoomFactorUpdateDt = 0
74
75 self.lastPlayerPos = {0, 0, 0} -- last known player position (actually on foot) before using this camera
76 self.lastPlayerTerrainHeight = 0
77
78 self.inputZoom = 0
79 self.inputZoomAnalog = false
80 self.inputMoveSide = 0
81 self.inputMoveForward = 0
82 self.inputRun = 0
83 self.inputRotate = 0
84
85 self.eventMoveSide = nil
86 self.eventMoveForward = nil
87 self.eventRotateCamera = nil
88
89 return self
90end

onInputModeChanged

Description
Called when the mouse input mode changes.
Definition
onInputModeChanged()
Code
528function GuiTopDownCamera:onInputModeChanged(inputMode)
529 self.isMouseMode = inputMode == GS_INPUT_HELP_MODE_KEYBOARD
530
531 if not self.isMouseMode then
532 self.mousePosX = 0.5
533 self.mousePosY = 0.5
534 end
535end

onInputRun

Description
Definition
onInputRun()
Code
516function GuiTopDownCamera:onInputRun(_, inputValue)
517 self.inputRun = inputValue
518end

onMoveForward

Description
Definition
onMoveForward()
Code
510function GuiTopDownCamera:onMoveForward(_, inputValue)
511 self.inputMoveForward = inputValue * GuiTopDownCamera.INPUT_MOVE_FACTOR
512end

onMoveSide

Description
Definition
onMoveSide()
Code
504function GuiTopDownCamera:onMoveSide(_, inputValue)
505 self.inputMoveSide = inputValue * GuiTopDownCamera.INPUT_MOVE_FACTOR
506end

onRotate

Description
Definition
onRotate()
Code
522function GuiTopDownCamera:onRotate(_, inputValue)
523 self.inputRotate = inputValue
524end

onZoom

Description
Definition
onZoom()
Code
487function GuiTopDownCamera:onZoom(_, inputValue, direction, isAnalog, isMouse)
488 self.inputZoomAnalog = isAnalog
489
490 if inputValue ~= 0 then
491 local change = 0.2 * direction
492 if isAnalog then
493 change = change * 0.01 -- use a smaller factor, will be multiplied by delta time in update
494 elseif isMouse then -- UI mouse wheel zoom
495 change = change * InputBinding.MOUSE_WHEEL_INPUT_FACTOR
496 end
497
498 self.inputZoom = change
499 end
500end

registerActionEvents

Description
Register required action events for the camera.
Definition
registerActionEvents()
Code
440function GuiTopDownCamera:registerActionEvents()
441 local _, eventId = self.inputManager:registerActionEvent(InputAction.AXIS_MOVE_SIDE_PLAYER, self, self.onMoveSide, false, false, true, false)
442 self.inputManager:setActionEventTextVisibility(eventId, false)
443 self.eventMoveSide = eventId
444 _, eventId = self.inputManager:registerActionEvent(InputAction.AXIS_MOVE_FORWARD_PLAYER, self, self.onMoveForward, false, false, true, false)
445 self.inputManager:setActionEventTextVisibility(eventId, false)
446 self.eventMoveForward = eventId
447
448 _, eventId = self.inputManager:registerActionEvent(InputAction.AXIS_RUN, self, self.onInputRun, false, false, true, true)
449 self.inputManager:setActionEventTextVisibility(eventId, false)
450
451 _, eventId = self.inputManager:registerActionEvent(InputAction.AXIS_PLACEMENT_ROTATE_CAMERA, self, self.onRotate, false, false, true, true)
452 self.inputManager:setActionEventText(eventId, self.l10n:getText(GuiTopDownCamera.L10N_SYMBOL.ACTION_ROTATE_CAMERA))
453 self.eventRotateCamera = eventId
454
455 _, eventId = self.inputManager:registerActionEvent(InputAction.MENU_ACTIVATE, self, self.resetToPlayer, false, true, false, true)
456 self.inputManager:setActionEventText(eventId, self.l10n:getText(GuiTopDownCamera.L10N_SYMBOL.ACTION_RESET_CAMERA))
457
458 _, eventId = self.inputManager:registerActionEvent(InputAction.CAMERA_ZOOM_IN, self, self.onZoom, false, false, true, true, 1) -- 1 == zoom in
459 self.inputManager:setActionEventTextVisibility(eventId, false)
460 _, eventId = self.inputManager:registerActionEvent(InputAction.CAMERA_ZOOM_OUT, self, self.onZoom, false, false, true, true, -1) -- -1 == zoom out
461 self.inputManager:setActionEventTextVisibility(eventId, false)
462end

removeActionEvents

Description
Remove action events registered on this screen.
Definition
removeActionEvents()
Code
474function GuiTopDownCamera:removeActionEvents()
475 self.inputManager:removeActionEventsByTarget(self)
476end

reset

Description
Definition
reset()
Code
118function GuiTopDownCamera:reset()
119 self.cameraTransformInitialized = false
120 self.controlledPlayer = nil
121 self.controlledVehicle = nil
122 self.hud = nil
123 self.terrainRootNode = nil
124 self.waterLevelHeight = 0
125 self.terrainSize = 0
126 self.previousCamera = nil
127end

resetInputState

Description
Reset event input state.
Definition
resetInputState()
Code
429function GuiTopDownCamera:resetInputState()
430 self.inputZoom = 0
431 self.inputZoomAnalog = false
432 self.inputMoveSide = 0
433 self.inputMoveForward = 0
434 self.inputRun = 0
435 self.inputRotate = 0
436end

resetToPlayer

Description
Reset the camera position to the player's location.
Definition
resetToPlayer()
Code
240function GuiTopDownCamera:resetToPlayer()
241 local playerX, playerZ = 0, 0
242
243 if self.controlledPlayer ~= nil then
244 playerX, playerZ = self.lastPlayerPos[1], self.lastPlayerPos[3]
245 elseif self.controlledVehicle ~= nil then
246 local _
247 playerX, _, playerZ = getTranslation(self.controlledVehicle.rootNode)
248 end
249
250 self:setMapPosition(playerX, playerZ)
251end

setControlledPlayer

Description
Set the reference to the currently controlled Player instance. Clears the controlled vehicle reference if any has been set.
Definition
setControlledPlayer()
Code
151function GuiTopDownCamera:setControlledPlayer(player)
152 self.controlledPlayer = player
153 self.controlledVehicle = nil
154end

setControlledVehicle

Description
Set the reference to the currently controlled Vehicle instance. Clears the controlled player reference if any has been set.
Definition
setControlledVehicle()
Code
159function GuiTopDownCamera:setControlledVehicle(vehicle)
160 self.controlledVehicle = vehicle
161 self.controlledPlayer = nil
162end

setHUD

Description
Set the reference to the game HUD for custom input display settings.
Definition
setHUD()
Code
138function GuiTopDownCamera:setHUD(hud)
139 self.hud = hud
140end

setMapPosition

Description
Set the camera position on the map.
Definition
setMapPosition(float mapX, float mapZ)
Arguments
floatmapXMap X position
floatmapZMap Z position
Code
233function GuiTopDownCamera:setMapPosition(mapX, mapZ)
234 self.cameraX, self.cameraZ = mapX, mapZ
235 self:updatePosition()
236end

setMouseEdgeScrollingActive

Description
Enable or disable the mouse edge scrolling.
Definition
setMouseEdgeScrollingActive()
Code
337function GuiTopDownCamera:setMouseEdgeScrollingActive(isActive)
338 self.isMouseEdgeScrollingActive = isActive
339end

setMovementActive

Description
Set camera movement input activation state.
Definition
setMovementActive()
Code
480function GuiTopDownCamera:setMovementActive(isActive)
481 self.inputManager:setActionEventActive(self.eventMoveSide, isActive)
482 self.inputManager:setActionEventActive(self.eventMoveForward, isActive)
483end

setTerrainRootNode

Description
Set the current game's terrain's root node reference for terrain state queries and raycasts.
Definition
setTerrainRootNode()
Code
131function GuiTopDownCamera:setTerrainRootNode(terrainRootNode)
132 self.terrainRootNode = terrainRootNode
133 self.terrainSize = getTerrainSize(self.terrainRootNode)
134end

setWaterLevelHeight

Description
Set the water level height as defined in the current map's environment.
Definition
setWaterLevelHeight()
Code
144function GuiTopDownCamera:setWaterLevelHeight(waterLevelHeight)
145 self.waterLevelHeight = waterLevelHeight
146end

showInputHelp

Description
Show custom input help entries in the HUD.
Definition
showInputHelp()
Code
466function GuiTopDownCamera:showInputHelp()
467 -- note: these custom help entries need to be cleaned out by this camera's owner
468 self.hud:addCustomInputHelpEntry(InputAction.AXIS_MOVE_SIDE_PLAYER, InputAction.AXIS_MOVE_FORWARD_PLAYER, self.l10n:getText(GuiTopDownCamera.L10N_SYMBOL.ACTION_MOVE), true)
469 self.hud:addCustomInputHelpEntry(InputAction.CAMERA_ZOOM_IN, InputAction.CAMERA_ZOOM_OUT, self.l10n:getText(GuiTopDownCamera.L10N_SYMBOL.ACTION_ZOOM), true)
470end

update

Description
Update camera state.
Definition
update()
Code
371function GuiTopDownCamera:update(dt)
372 local multiplier = math.max(5 * self.inputRun, 1)
373 self:updateMovement(dt, multiplier)
374
375 self:resetInputState()
376end

updateMovement

Description
Update camera position and orientation based on player input.
Definition
updateMovement(dt Delta, movementMultiplier Speed)
Arguments
dtDeltatime in milliseconds
movementMultiplierSpeedfactor for movement
Code
382function GuiTopDownCamera:updateMovement(dt, movementMultiplier)
383 local zoomTimeFactor = self.inputZoomAnalog and 0.002 * dt or 0.2
384 local zoomChange = self.targetZoomFactor - self.inputZoom * zoomTimeFactor
385 if self.inputZoom < 0 then
386 self.targetZoomFactor = math.min(zoomChange, 1)
387 elseif self.inputZoom > 0 then
388 self.targetZoomFactor = math.max(zoomChange, 0)
389 end
390
391 local moveX = self.inputMoveSide * dt
392 local moveZ = -self.inputMoveForward * dt -- inverted to make it consistent
393
394 local hasViewChanged = false
395 if self.inputRotate ~= 0 then
396 local rotChange = dt * self.inputRotate * GuiTopDownCamera.ROTATION_SPEED * movementMultiplier
397 self.cameraRotY = self.cameraRotY + rotChange
398 hasViewChanged = true
399 end
400
401 if moveX == 0 and moveZ == 0 and self.isMouseEdgeScrollingActive then
402 moveX, moveZ = self:getMouseEdgeScrollingMovement()
403 end
404
405 if hasViewChanged or moveX ~= 0 or moveZ ~= 0 or math.abs(self.zoomFactor - self.targetZoomFactor) > 0.001 then
406 self:applyMovement(moveX, moveZ, movementMultiplier, dt)
407 hasViewChanged = true
408 end
409
410 if hasViewChanged then
411 self:updatePosition()
412 end
413end

updatePosition

Description
Update the camera position and orientation based on terrain and zoom state.
Definition
updatePosition()
Code
278function GuiTopDownCamera:updatePosition()
279 local samplingGridStep = 2 -- terrain sampling step distance in meters
280 local cameraTargetHeight = self.waterLevelHeight
281
282 -- sample the terrain height around the camera
283 for x = -samplingGridStep, samplingGridStep, samplingGridStep do
284 for z = -samplingGridStep, samplingGridStep, samplingGridStep do
285 local sampleTerrainHeight = getTerrainHeightAtWorldPos(self.terrainRootNode, self.cameraX + x, 0, self.cameraZ + z)
286 cameraTargetHeight = math.max(cameraTargetHeight, sampleTerrainHeight)
287 end
288 end
289
290 local rotationX = math.rad(GuiTopDownCamera.ROTATION_MIN_X + self.zoomFactor * GuiTopDownCamera.ROTATION_RANGE_X)
291 local cameraZ = GuiTopDownCamera.DISTANCE_MIN_Z + self.zoomFactor * GuiTopDownCamera.DISTANCE_RANGE_Z
292
293 setTranslation(self.camera, 0, 0, cameraZ)
294 setRotation(self.cameraBaseNode, rotationX, self.cameraRotY, 0)
295 setTranslation(self.cameraBaseNode, self.cameraX, cameraTargetHeight, self.cameraZ)
296
297 -- check if new camera position is close to or even under terrain
298 local cameraX, cameraY, cameraZ = getWorldTranslation(self.camera)
299 local terrainHeight = self.waterLevelHeight
300 for x = -samplingGridStep, samplingGridStep, samplingGridStep do
301 for z = -samplingGridStep, samplingGridStep, samplingGridStep do
302 local sampleTerrainHeight = getTerrainHeightAtWorldPos(self.terrainRootNode, cameraX + x, 0, cameraZ + z)
303 terrainHeight = math.max(terrainHeight, sampleTerrainHeight)
304 end
305 end
306
307 if cameraY < terrainHeight + GuiTopDownCamera.GROUND_DISTANCE_MIN_Y then
308 cameraTargetHeight = cameraTargetHeight + (terrainHeight - cameraY + GuiTopDownCamera.GROUND_DISTANCE_MIN_Y)
309 setTranslation(self.cameraBaseNode, self.cameraX, cameraTargetHeight, self.cameraZ)
310 end
311end