main.gd 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. # The root Control node ("Main") and AspectRatioContainer nodes are the most important
  2. # pieces of this demo.
  3. # Both nodes have their Layout set to Full Rect
  4. # (with their rect spread across the whole viewport, and Anchor set to Full Rect).
  5. extends Control
  6. var base_window_size = Vector2(
  7. ProjectSettings.get_setting("display/window/size/viewport_width"),
  8. ProjectSettings.get_setting("display/window/size/viewport_height")
  9. )
  10. # These defaults match this demo's project settings. Adjust as needed if adapting this
  11. # in your own project.
  12. var stretch_mode = Window.CONTENT_SCALE_MODE_CANVAS_ITEMS
  13. var stretch_aspect = Window.CONTENT_SCALE_ASPECT_EXPAND
  14. var scale_factor = 1.0
  15. var gui_aspect_ratio = -1.0
  16. var gui_margin = 0.0
  17. @onready var panel = $Panel
  18. @onready var arc = $Panel/AspectRatioContainer
  19. func _ready():
  20. # The `resized` signal will be emitted when the window size changes, as the root Control node
  21. # is resized whenever the window size changes. This is because the root Control node
  22. # uses a Full Rect anchor, so its size will always be equal to the window size.
  23. resized.connect(self._on_resized)
  24. call_deferred("update_container")
  25. func update_container():
  26. # The code within this function needs to be run deferred to work around an issue with containers
  27. # having a 1-frame delay with updates.
  28. # Otherwise, `panel.size` returns a value of the previous frame, which results in incorrect
  29. # sizing of the inner AspectRatioContainer when using the Fit to Window setting.
  30. for _i in 2:
  31. if is_equal_approx(gui_aspect_ratio, -1.0):
  32. # Fit to Window. Tell the AspectRatioContainer to use the same aspect ratio as the window,
  33. # making the AspectRatioContainer not have any visible effect.
  34. arc.ratio = panel.size.aspect()
  35. # Apply GUI offset on the AspectRatioContainer's parent (Panel).
  36. # This also makes the GUI offset apply on controls located outside the AspectRatioContainer
  37. # (such as the inner side label in this demo).
  38. panel.offset_top = gui_margin
  39. panel.offset_bottom = -gui_margin
  40. else:
  41. # Constrained aspect ratio.
  42. arc.ratio = min(panel.size.aspect(), gui_aspect_ratio)
  43. # Adjust top and bottom offsets relative to the aspect ratio when it's constrained.
  44. # This ensures that GUI offset settings behave exactly as if the window had the
  45. # original aspect ratio size.
  46. panel.offset_top = gui_margin / gui_aspect_ratio
  47. panel.offset_bottom = -gui_margin / gui_aspect_ratio
  48. panel.offset_left = gui_margin
  49. panel.offset_right = -gui_margin
  50. func _on_gui_aspect_ratio_item_selected(index):
  51. match index:
  52. 0: # Fit to Window
  53. gui_aspect_ratio = -1.0
  54. 1: # 5:4
  55. gui_aspect_ratio = 5.0 / 4.0
  56. 2: # 4:3
  57. gui_aspect_ratio = 4.0 / 3.0
  58. 3: # 3:2
  59. gui_aspect_ratio = 3.0 / 2.0
  60. 4: # 16:10
  61. gui_aspect_ratio = 16.0 / 10.0
  62. 5: # 16:9
  63. gui_aspect_ratio = 16.0 / 9.0
  64. 6: # 21:9
  65. gui_aspect_ratio = 21.0 / 9.0
  66. call_deferred("update_container")
  67. func _on_resized():
  68. call_deferred("update_container")
  69. func _on_gui_margin_drag_ended(_value_changed):
  70. gui_margin = $"Panel/AspectRatioContainer/Panel/CenterContainer/Options/GUIMargin/HSlider".value
  71. $"Panel/AspectRatioContainer/Panel/CenterContainer/Options/GUIMargin/Value".text = str(gui_margin)
  72. call_deferred("update_container")
  73. func _on_window_base_size_item_selected(index):
  74. match index:
  75. 0: # 648×648 (1:1)
  76. base_window_size = Vector2(648, 648)
  77. 1: # 640×480 (4:3)
  78. base_window_size = Vector2(640, 480)
  79. 2: # 720×480 (3:2)
  80. base_window_size = Vector2(720, 480)
  81. 3: # 800×600 (4:3)
  82. base_window_size = Vector2(800, 600)
  83. 4: # 1152×648 (16:9)
  84. base_window_size = Vector2(1152, 648)
  85. 5: # 1280×720 (16:9)
  86. base_window_size = Vector2(1280, 720)
  87. 6: # 1280×800 (16:10)
  88. base_window_size = Vector2(1280, 800)
  89. 7: # 1680×720 (21:9)
  90. base_window_size = Vector2(1680, 720)
  91. get_viewport().content_scale_size = base_window_size
  92. call_deferred("update_container")
  93. func _on_window_stretch_mode_item_selected(index):
  94. stretch_mode = index
  95. get_viewport().content_scale_mode = stretch_mode
  96. # Disable irrelevant options when the stretch mode is Disabled.
  97. $"Panel/AspectRatioContainer/Panel/CenterContainer/Options/WindowBaseSize/OptionButton".disabled = stretch_mode == Window.CONTENT_SCALE_MODE_DISABLED
  98. $"Panel/AspectRatioContainer/Panel/CenterContainer/Options/WindowStretchAspect/OptionButton".disabled = stretch_mode == Window.CONTENT_SCALE_MODE_DISABLED
  99. func _on_window_stretch_aspect_item_selected(index):
  100. stretch_aspect = index
  101. get_viewport().content_scale_aspect = stretch_aspect
  102. func _on_window_scale_factor_drag_ended(_value_changed):
  103. scale_factor = $"Panel/AspectRatioContainer/Panel/CenterContainer/Options/WindowScaleFactor/HSlider".value
  104. $"Panel/AspectRatioContainer/Panel/CenterContainer/Options/WindowScaleFactor/Value".text = "%d%%" % (scale_factor * 100)
  105. get_viewport().content_scale_factor = scale_factor
  106. func _on_window_stretch_scale_mode_item_selected(index: int) -> void:
  107. get_viewport().content_scale_stretch = index