Godot Version
v4.2.2.stable.official.15073afe3
Question
How does CanvasLayer offset work in relation to viewport?
Im trying to center my “level” on the y axis of viewport. For that Im calculating a scaling factor by givin a margin in pixels on the X axis.
I then calculate the middle point with a simple formula of d = (y - y.a)/2 where “a” is the scalling and “y” is the viewport.y
This is the result and its clearly not in the middle of the screen. The pink line is a draw_line positioned at “viewport.y/2”.
This is the structure (Im trying to mimic my main project structure).
This is the Node code:
extends Node
var viewport_size_rec
var viewport_size
var device_safe_area
var safe_area: Rect2i
var safe_area_top
var scaleFactor
var new_position
var dpi
@export var CanvasLayer_Level: CanvasLayer
func _ready():
_handle_screen_resize()
func clamp_safe_area(sa:Vector2i, vp: Vector2i) -> Vector2i:
if sa.x > vp.x:
sa.x = vp.x
if sa.y > vp.y:
sa.y = vp.y
return sa
func _handle_screen_resize():
var os_name = OS.get_name()
print(os_name)
if os_name == "Android" || os_name == "Windows" :
viewport_size_rec = get_viewport().get_visible_rect().size
viewport_size = get_viewport().size
device_safe_area = DisplayServer.get_display_safe_area()
if os_name == "Windows" :
device_safe_area.position = Vector2i(0,0) #this depends on which screen will game launch
device_safe_area.size = clamp_safe_area(device_safe_area.size, viewport_size)
safe_area.position = device_safe_area.position
safe_area.size = device_safe_area.size - Vector2i(960,0) # added safe marging on X axis
scaleFactor = float(safe_area.size.x)/float(viewport_size.x)
new_position = Vector2(
safe_area.position.x,
(viewport_size.y-(viewport_size.y * scaleFactor))*0.5)
CanvasLayer_Level.set_scale(Vector2(scaleFactor,scaleFactor))
CanvasLayer_Level.set_offset(new_position)
print("viewport_size_rec>",viewport_size_rec)
print("viewport_size>",viewport_size)
print("device_safe_area>",device_safe_area)
print("safe_area>",safe_area)
print("scaleFactor>",scaleFactor)
print("new_position>",new_position)
and the draw_line code:
extends Control
func _draw():
var viewport_size = get_viewport().get_visible_rect().size
var mid_y = viewport_size.y / 2
draw_line(Vector2(0, mid_y), Vector2(viewport_size.x, mid_y), Color.DEEP_PINK, 10)
The relevant project settings are:
Viewport Width: 800
Viewport Height: 360
Mode: Exclusive Fullscreen
Stretch Mode: canvas_items
Aspect: keep
This is my output:
Windows
viewport_size_rec>(800, 360)
viewport_size>(1920, 1080)
device_safe_area>[P: (0, 0), S: (1920, 1032)]
safe_area>[P: (0, 0), S: (960, 1032)]
scaleFactor>0.5
new_position>(0, 270)
My screen resolution is 1920x1080 and I set the “Safe Margin” to be -960 so that the scalling factor is 0.5 to make it easier to understand the pixel values.
My calculated new_position is (0, 270) which is correct given the formula but the offset is way off screen. What am I missing?
Thank you