Script v1.7.1.0
- AI
- Animals
- Contracts
- Debug
- Economy
- Effects
- Events
- Farms
- GUI
- AnimalScreen
- AnimationElement
- BitmapElement
- BoxLayoutElement
- BreadcrumbsElement
- ButtonElement
- ButtonOverlay
- ChatWindow
- CheckedOptionElement
- ClearElement
- ContextActionDisplay
- DialogElement
- FieldInfoDisplay
- FillLevelsDisplay
- FlowLayoutElement
- FocusManager
- FrameElement
- FrameReferenceElement
- GameInfoDisplay
- GamePausedDisplay
- Gui
- GuiDataSource
- GuiElement
- GuiMixin
- GuiOverlay
- GuiProfile
- GuiSoundPlayer
- GuiTopDownCamera
- GuiUtils
- HUDDisplayElement
- HUDElement
- HUDFrameElement
- HUDPopupMessage
- HUDTextDisplay
- IndexChangeSubjectMixin
- IndexStateElement
- InGameIcon
- IngameMap
- IngameMapElement
- InputGlyphElement
- InputHelpDisplay
- ListElement
- ListItemElement
- MapHotspot
- MapOverlayGenerator
- MixerWagonHUDExtension
- MultiTextOptionElement
- MultiValueTween
- Overlay
- PagingElement
- PlaySampleMixin
- RenderElement
- RoundStatusBar
- ScreenElement
- SettingsModel
- SideNotification
- SliderElement
- SpeakerDisplay
- SpeedMeterDisplay
- StableListElement
- StatusBar
- TabbedMenu
- TabbedMenuFrameElement
- TabbedMenuWithDetails
- TableElement
- TableHeaderElement
- TextElement
- TextInputElement
- TimerElement
- ToggleButtonElement
- TopNotification
- Tween
- TweenSequence
- VehicleHUDExtension
- VehicleSchemaDisplay
- VideoElement
- Handtools
- I3d
- Materials
- Misc
- Objects
- Placeables
- Player
- Shop
- Sounds
- Specializations
- Triggers
- Utils
- Vehicles
- Weather
Engine v1.7.1.0
- AI
- Animation
- Camera
- Entity
- Fillplanes
- General
- I3D
- Input
- Lighting
- Math
- Network
- Node
- Overlays
- Particle System
- Physics
- Rendering
- Scenegraph
- Shape
- Sound
- Spline
- String
- Terrain Detail
- Text Rendering
- Tire Track
- XML
- general
Foundation Reference
GuiTopDownCamera
DescriptionTop-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
- applyMovement
- createCameraNodes
- deactivate
- delete
- determineMapPosition
- getIsActive
- getMouseEdgeScrollingMovement
- getPickRay
- hasRotationInput
- mouseEvent
- new
- onInputModeChanged
- onInputRun
- onMoveForward
- onMoveSide
- onRotate
- onZoom
- registerActionEvents
- removeActionEvents
- reset
- resetInputState
- resetToPlayer
- setControlledPlayer
- setControlledVehicle
- setHUD
- setMapPosition
- setMouseEdgeScrollingActive
- setMovementActive
- setTerrainRootNode
- setWaterLevelHeight
- showInputHelp
- update
- updateMovement
- updatePosition
activate
DescriptionActivate the camera and change the game's viewpoint to it.Definition
activate()Code
166 | function 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 |
192 | end |
applyMovement
DescriptionApply a movement to the camera (and view).Definition
applyMovement(moveX X, moveZ Z, movementMultiplier Movement)Arguments
moveX | X | direction movement [-1, 1] |
moveZ | Z | direction movement [-1, 1] |
movementMultiplier | Movement | speed factor |
318 | function 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 |
333 | end |
createCameraNodes
DescriptionCreate scene graph camera nodes.Definition
createCameraNodes()Return Values
int | Camera | node ID (view point, child of camera base node) |
int | Camera | base node ID (view target, parent of camera node) |
96 | function 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 |
106 | end |
deactivate
DescriptionDisable this camera.Definition
deactivate()Code
196 | function 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 |
221 | end |
delete
DescriptionDefinitiondelete()Code
110 | function 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 |
114 | end |
determineMapPosition
DescriptionDetermine the current camera position and orientation.Definition
determineMapPosition()Return Values
Camera | X | world space position |
Warning: Undefined array key "className" in /usr/www/users/giantw/gdn.giants-software.com/documentation_scripting_fs19.php on line 213 | ||
Camera | Z | world space position |
Camera | Y | rotation in radians |
259 | function GuiTopDownCamera:determineMapPosition() |
260 | return self.cameraX, 0, self.cameraZ, self.cameraRotY - math.rad(180) |
261 | end |
getIsActive
DescriptionCheck if this camera is active.Definition
getIsActive()Code
225 | function GuiTopDownCamera:getIsActive() |
226 | return self.isActive |
227 | end |
getMouseEdgeScrollingMovement
DescriptionGet camera movement for mouse edge scrolling.Definition
getMouseEdgeScrollingMovement()Return Values
X | direction | movement [-1, 1] |
Z | direction | movement [-1, 1] |
345 | function 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 |
367 | end |
getPickRay
DescriptionGet a picking ray for the current camera orientation and cursor position.Definition
getPickRay()Code
265 | function GuiTopDownCamera:getPickRay() |
266 | return RaycastUtil.getCameraPickingRay(self.mousePosX, self.mousePosY, self.camera) |
267 | end |
hasRotationInput
DescriptionCheck 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
272 | function GuiTopDownCamera:hasRotationInput() |
273 | return self.inputRotate ~= 0 |
274 | end |
mouseEvent
DescriptionDefinitionmouseEvent()Code
420 | function GuiTopDownCamera:mouseEvent(posX, posY, isDown, isUp, button) |
421 | if self.isMouseMode then |
422 | self.mousePosX = posX |
423 | self.mousePosY = posY |
424 | end |
425 | end |
new
DescriptionCreate a new LandscapingScreenController instance.Definition
new(table messageCenter, table l10n, table inputManager)Arguments
table | messageCenter | MessageCenter reference for local event handling |
table | l10n | I18N reference for string localization. |
table | inputManager | InputBinding reference for input action registration |
42 | function 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 |
90 | end |
onInputModeChanged
DescriptionCalled when the mouse input mode changes.Definition
onInputModeChanged()Code
528 | function 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 |
535 | end |
onInputRun
DescriptionDefinitiononInputRun()Code
516 | function GuiTopDownCamera:onInputRun(_, inputValue) |
517 | self.inputRun = inputValue |
518 | end |
onMoveForward
DescriptionDefinitiononMoveForward()Code
510 | function GuiTopDownCamera:onMoveForward(_, inputValue) |
511 | self.inputMoveForward = inputValue * GuiTopDownCamera.INPUT_MOVE_FACTOR |
512 | end |
onMoveSide
DescriptionDefinitiononMoveSide()Code
504 | function GuiTopDownCamera:onMoveSide(_, inputValue) |
505 | self.inputMoveSide = inputValue * GuiTopDownCamera.INPUT_MOVE_FACTOR |
506 | end |
onRotate
DescriptionDefinitiononRotate()Code
522 | function GuiTopDownCamera:onRotate(_, inputValue) |
523 | self.inputRotate = inputValue |
524 | end |
onZoom
DescriptionDefinitiononZoom()Code
487 | function 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 |
500 | end |
registerActionEvents
DescriptionRegister required action events for the camera.Definition
registerActionEvents()Code
440 | function 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) |
462 | end |
removeActionEvents
DescriptionRemove action events registered on this screen.Definition
removeActionEvents()Code
474 | function GuiTopDownCamera:removeActionEvents() |
475 | self.inputManager:removeActionEventsByTarget(self) |
476 | end |
reset
DescriptionDefinitionreset()Code
118 | function 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 |
127 | end |
resetInputState
DescriptionReset event input state.Definition
resetInputState()Code
429 | function 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 |
436 | end |
resetToPlayer
DescriptionReset the camera position to the player's location.Definition
resetToPlayer()Code
240 | function 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) |
251 | end |
setControlledPlayer
DescriptionSet the reference to the currently controlled Player instance. Clears the controlled vehicle reference if any has been set.Definition
setControlledPlayer()Code
151 | function GuiTopDownCamera:setControlledPlayer(player) |
152 | self.controlledPlayer = player |
153 | self.controlledVehicle = nil |
154 | end |
setControlledVehicle
DescriptionSet the reference to the currently controlled Vehicle instance. Clears the controlled player reference if any has been set.Definition
setControlledVehicle()Code
159 | function GuiTopDownCamera:setControlledVehicle(vehicle) |
160 | self.controlledVehicle = vehicle |
161 | self.controlledPlayer = nil |
162 | end |
setHUD
DescriptionSet the reference to the game HUD for custom input display settings.Definition
setHUD()Code
138 | function GuiTopDownCamera:setHUD(hud) |
139 | self.hud = hud |
140 | end |
setMapPosition
DescriptionSet the camera position on the map.Definition
setMapPosition(float mapX, float mapZ)Arguments
float | mapX | Map X position |
float | mapZ | Map Z position |
233 | function GuiTopDownCamera:setMapPosition(mapX, mapZ) |
234 | self.cameraX, self.cameraZ = mapX, mapZ |
235 | self:updatePosition() |
236 | end |
setMouseEdgeScrollingActive
DescriptionEnable or disable the mouse edge scrolling.Definition
setMouseEdgeScrollingActive()Code
337 | function GuiTopDownCamera:setMouseEdgeScrollingActive(isActive) |
338 | self.isMouseEdgeScrollingActive = isActive |
339 | end |
setMovementActive
DescriptionSet camera movement input activation state.Definition
setMovementActive()Code
480 | function GuiTopDownCamera:setMovementActive(isActive) |
481 | self.inputManager:setActionEventActive(self.eventMoveSide, isActive) |
482 | self.inputManager:setActionEventActive(self.eventMoveForward, isActive) |
483 | end |
setTerrainRootNode
DescriptionSet the current game's terrain's root node reference for terrain state queries and raycasts.Definition
setTerrainRootNode()Code
131 | function GuiTopDownCamera:setTerrainRootNode(terrainRootNode) |
132 | self.terrainRootNode = terrainRootNode |
133 | self.terrainSize = getTerrainSize(self.terrainRootNode) |
134 | end |
setWaterLevelHeight
DescriptionSet the water level height as defined in the current map's environment.Definition
setWaterLevelHeight()Code
144 | function GuiTopDownCamera:setWaterLevelHeight(waterLevelHeight) |
145 | self.waterLevelHeight = waterLevelHeight |
146 | end |
showInputHelp
DescriptionShow custom input help entries in the HUD.Definition
showInputHelp()Code
466 | function 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) |
470 | end |
update
DescriptionUpdate camera state.Definition
update()Code
371 | function GuiTopDownCamera:update(dt) |
372 | local multiplier = math.max(5 * self.inputRun, 1) |
373 | self:updateMovement(dt, multiplier) |
374 | |
375 | self:resetInputState() |
376 | end |
updateMovement
DescriptionUpdate camera position and orientation based on player input.Definition
updateMovement(dt Delta, movementMultiplier Speed)Arguments
dt | Delta | time in milliseconds |
movementMultiplier | Speed | factor for movement |
382 | function 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 |
413 | end |
updatePosition
DescriptionUpdate the camera position and orientation based on terrain and zoom state.Definition
updatePosition()Code
278 | function 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 |
311 | end |