Add UI Engine and welcome screen

This commit is contained in:
JeremyStar™ 2024-01-17 20:49:59 +01:00
parent 147aab7784
commit 8a512b0e12
7 changed files with 349 additions and 5 deletions

View file

@ -25,6 +25,7 @@ logger="*res://src/logger.gd"
misc="*res://src/misc.gd"
preader="*res://src/preader.gd"
pmana="*res://src/pmana.gd"
ui_engine="*res://src/ui_engine.gd"
[display]
@ -33,7 +34,7 @@ window/size/viewport_height=540
[editor]
run/main_run_args="%command% ++ example"
run/main_run_args="%command% ++ "
export/convert_text_resources_to_binary=false
[editor_plugins]
@ -76,6 +77,12 @@ console={
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":96,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
editor_switchres={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":0,"key_label":4194335,"unicode":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194335,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
[rendering]

View file

@ -63,6 +63,7 @@ func _ready() -> void:
expressionscript.misc = get_node("/root/misc")
expressionscript.preader = get_node("/root/preader")
expressionscript.pmana = get_node("/root/pmana")
expressionscript.ui_engine = get_node("/root/ui_engine")
expressionscript.console = self
expressionscript.loader = get_node("/root/Presencode")
add_child(expressionscript)
@ -88,12 +89,12 @@ func _process(_delta: float) -> void:
# Change console position
position.x = position.x-cursor_offset.x
position.y = position.y-cursor_offset.y
# Prevent console from going out of scope
var position_new: Vector2 = check_violation()
if position != position_new:
position = position_new
# Set new cursor_origin
cursor_origin = cursor_position
# Prevent console from going out of scope
var position_new: Vector2 = check_violation()
if position != position_new:
position = position_new
# Helper function, prevents console from going out of scope
func check_violation() -> Vector2:

View file

@ -28,6 +28,7 @@ var logger: Node = null
var misc: Node = null
var preader: Node = null
var pmana: Node = null
var ui_engine: Node = null
# SceneTree
var console: Node = null
var loader: Node = null

View file

@ -134,6 +134,21 @@ func check_platform() -> void:
_: # Platform not supported
logger.error("The \"" + OS.get_name() + "\" operating system is not supported by Presencode. You can add support for that platform to Presencode yourself, if you want.")
# Returns the best common resolution
func get_best_resolution() -> Vector2i:
logger.info("Determining best resolution")
var screen_size: Vector2 = Vector2(DisplayServer.screen_get_size())
var resolutions: Array[Vector2] = [Vector2(960, 540), Vector2(1920, 1080), Vector2(2560, 1440), Vector2(3840, 2160)]
var closest_resolution: Vector2 = Vector2(NAN, NAN)
var closest_distance: float = INF
for resolution in resolutions:
var distance = screen_size.distance_to(resolution)
if distance < closest_distance:
closest_distance = distance
closest_resolution = resolution
if closest_resolution == Vector2(NAN, NAN): return Vector2i(960, 540)
else: return closest_resolution
# Check for manifest consistency
func check_manifest_consistency(manifest: Dictionary) -> misc.Error:
logger.diag("Checking manifest for consistency")

113
src/ui/welcome.gd Normal file
View file

@ -0,0 +1,113 @@
extends Node
func switch_mode() -> void:
DisplayServer.window_set_title("Presencode » Welcome")
update_splash()
@warning_ignore("integer_division")
func update_resolution(new_resolution: Vector2i) -> void:
var base: Button = get_node("Wallpaper/Welcome")
var wallpaper_size: Vector2 = Vector2(7440, 4822)
base.get_parent().size = Vector2(wallpaper_size.x*(new_resolution.x/wallpaper_size.x), wallpaper_size.y*(new_resolution.y/wallpaper_size.y))
base.size = Vector2(new_resolution.x*0.9, new_resolution.y*0.9)
base.position = Vector2(new_resolution.x*0.05, new_resolution.y*0.05)
base.add_theme_stylebox_override("normal", get_stylebox_blur(new_resolution))
base.add_theme_stylebox_override("hover", get_stylebox_blur(new_resolution))
base.add_theme_stylebox_override("pressed", get_stylebox_blur(new_resolution))
base.add_theme_stylebox_override("disabled", get_stylebox_blur(new_resolution))
for child in base.get_children(true):
for group in child.get_groups():
match(group):
"font":
child.add_theme_font_override("normal_font", ResourceLoader.load("res://assets/fonts/Inter/Regular.ttf"))
child.add_theme_font_override("bold_font", ResourceLoader.load("res://assets/fonts/Inter/Bold.ttf"))
child.add_theme_font_override("italics_font", ResourceLoader.load("res://assets/fonts/Inter/Italic.ttf"))
child.add_theme_font_override("bold_italics_font", ResourceLoader.load("res://assets/fonts/Inter/BoldItalic.ttf"))
child.add_theme_font_override("mono_font", ResourceLoader.load("res://assets/fonts/FiraCode/Regular.ttf"))
"font_normal":
child.add_theme_font_size_override("normal_font_size", new_resolution.x/40)
child.add_theme_font_size_override("bold_font_size", new_resolution.x/40)
child.add_theme_font_size_override("italics_font_size", new_resolution.x/40)
child.add_theme_font_size_override("bold_italics_font_size", new_resolution.x/40)
child.add_theme_font_size_override("mono_font_size", new_resolution.x/41.73913043478261)
"font_small":
child.add_theme_font_size_override("normal_font_size", new_resolution.x/53.33333333333333)
child.add_theme_font_size_override("bold_font_size", new_resolution.x/53.33333333333333)
child.add_theme_font_size_override("italics_font_size", new_resolution.x/53.33333333333333)
child.add_theme_font_size_override("bold_italics_font_size", new_resolution.x/53.33333333333333)
child.add_theme_font_size_override("mono_font_size", new_resolution.x/53.33333333333333)
"font_one": child.add_theme_font_override("font", ResourceLoader.load("res://assets/fonts/Inter/Regular.ttf"))
"font_one_normal": child.add_theme_font_size_override("font_size", new_resolution.x/40)
"font_one_small": child.add_theme_font_size_override("font_size", new_resolution.x/53.33333333333333)
base.get_node("Icon").size = Vector2(new_resolution.x/1.5, new_resolution.y/4.5)
base.get_node("Icon").position = Vector2(base.size.x/2-base.get_node("Icon").size.x/2, base.size.y*0.05)
base.get_node("Splash").size = Vector2(new_resolution.x/1.5, new_resolution.y/15.88235294117647)
base.get_node("Splash").position = Vector2(base.size.x/2-base.get_node("Splash").size.x/2, base.get_node("Icon").position.y+11*(new_resolution.y/49.09090909090909))
base.get_node("OpenButton").size = Vector2(new_resolution.x/4.403669724770642, new_resolution.y/14.21052631578947)
base.get_node("OpenButton").position = Vector2(base.size.x/16, base.size.y/2.410714285714286)
base.get_node("EditorButton").size = Vector2(new_resolution.x/4.403669724770642, new_resolution.y/14.21052631578947)
base.get_node("EditorButton").position = Vector2(base.size.x-base.get_node("OpenButton").position.x-base.get_node("EditorButton").size.x, base.size.y/2.410714285714286)
base.get_node("AboutText").size = Vector2(new_resolution.x/1.5, new_resolution.y/7.5)
base.get_node("AboutText").position = Vector2(base.size.x/2-base.get_node("AboutText").size.x/2, base.size.y-base.size.y/54-base.size.y/7.5)
@warning_ignore("integer_division")
func get_stylebox_blur(resolution_: Vector2i) -> StyleBoxFlat:
var stylebox: StyleBoxFlat = StyleBoxFlat.new()
stylebox.bg_color = Color8(0, 0, 0, 180)
stylebox.corner_radius_top_left = resolution_.x/30
stylebox.corner_radius_top_right = resolution_.x/30
stylebox.corner_radius_bottom_left = resolution_.x/30
stylebox.corner_radius_bottom_right = resolution_.x/30
return stylebox
func update_splash() -> void:
logger.diag("Updating splash text")
get_node("Wallpaper/Welcome/Splash").text = "[center]" + ["The first native code-based presentation viewer.", "Presenting your presentations since 2023", "Made using Godot", "nice", "[b]your mom[/b]", "Also try LibreOffice!", "... exists.", "making unprofessional presentations"].pick_random() + "[/center]"
func open_presentation_picker() -> void:
logger.info("Opening presentation")
var fd: FileDialog = FileDialog.new()
fd.access = FileDialog.ACCESS_FILESYSTEM
fd.current_path = "user://"
fd.file_mode = FileDialog.FILE_MODE_OPEN_FILE
fd.add_filter("*.pcpa", "")
fd.add_filter("*.zip", "")
fd.mode_overrides_title = false
fd.show_hidden_files = true
fd.title = "Open a Presencode presentation file"
fd.use_native_dialog = true
fd.cancel_button_text = "Cancel"
fd.ok_button_text = "Present"
fd.visible = true
fd.connect("file_selected", func(path: String): open_presentation(path))
add_child(fd)
func open_presentation(path: String) -> void:
if FileAccess.file_exists(path) and path.ends_with(".zip") or path.ends_with(".pcpa"): # .pcpa = presencode presentation archive
logger.info("Opening presentation archive")
preader.open_presentation(path, true)
elif DirAccess.dir_exists_absolute(path):
logger.info("Opening presentation directory")
preader.open_presentation(path, false)
else:
await logger.error("Presentation file/directory \"" + path + "\" not found")
# Read manifest & entrypoint files
preader.read_manifest()
preader.read_entrypoint()
# Update window properties
get_node("/root/Console").calculate_drag_area(preader.get_ratio_resolution())
DisplayServer.window_set_title("Presencode » Presenting \"" + preader.get_topic() + "\" by \"" + preader.get_authors() + "\"")
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
DisplayServer.window_set_size(preader.get_ratio_resolution())
DisplayServer.window_set_min_size(preader.get_ratio_resolution())
if get_node("/root/Presencode").config_window_size_support: get_node("/root/Presencode/WindowSizeSupport/EndPixel").position = Vector2(preader.get_ratio_resolution().x-1, preader.get_ratio_resolution().y-1)
get_tree().root.content_scale_size = preader.get_ratio_resolution()
get_tree().root.content_scale_mode = Window.CONTENT_SCALE_MODE_VIEWPORT
get_tree().root.content_scale_aspect = Window.CONTENT_SCALE_ASPECT_KEEP
get_tree().root.content_scale_factor = 1.0
await get_tree().process_frame
DisplayServer.window_set_position(misc.get_center(DisplayServer.screen_get_size(), DisplayServer.window_get_size()))
# Add entrypoint to SceneTree
get_tree().root.add_child(preader.get_entrypoint())
# Uninitialize UI Engine
ui_engine.uninitialize()

82
src/ui_engine.gd Normal file
View file

@ -0,0 +1,82 @@
extends Node
# Enums
enum UIMode {
UNKNOWN,
WELCOME
}
# Nodes
var loader: Control = null
var ui_mode_node: Control = null
# States
var initialized: bool = false
var ui_mode: UIMode = UIMode.UNKNOWN
var resolution: String = "960x540"
func initialize(loader_: Control) -> void:
if initialized:
logger.error("The UI Engine been initialized already")
return
logger.info("Initializing UI Engine")
loader = loader_
initialized = true
logger.diag("Switching to welcome mode")
switch_mode(UIMode.WELCOME)
update_resolution(misc.get_best_resolution())
logger.diag("Updating window properties")
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
DisplayServer.window_set_min_size(Vector2i(960, 540))
get_tree().root.content_scale_mode = Window.CONTENT_SCALE_MODE_VIEWPORT
get_tree().root.content_scale_aspect = Window.CONTENT_SCALE_ASPECT_KEEP
get_tree().root.content_scale_factor = 1.0
func uninitialize() -> void:
if !initialized:
logger.error("The UI Engine is not initialized.")
return
logger.info("Uninitializing UI Engine")
loader = null
initialized = false
resolution = "960x540"
ui_mode = UIMode.UNKNOWN
logger.info("Unloading UI mode")
ui_mode_node.queue_free()
ui_mode_node = null
func _process(_delta: float) -> void:
if !initialized: return
if Input.is_action_just_pressed("editor_switchres"):
match(resolution):
"960x540": update_resolution(Vector2i(1920, 1080))
"1920x1080": update_resolution(Vector2i(2560, 1440))
"2560x1440": update_resolution(Vector2i(3840, 2160))
"3840x2160": update_resolution(Vector2i(960, 540))
func switch_mode(mode: UIMode) -> void:
if !initialized:
logger.error("The UI Engine hasn't been initialized yet")
return
if mode == UIMode.UNKNOWN: return
logger.info("Switching to mode " + str(mode))
if ui_mode_node != null: loader.remove_child(ui_mode_node)
match(mode):
UIMode.WELCOME:
ui_mode_node = ResourceLoader.load("res://ui/Welcome.tscn").instantiate()
ui_mode = UIMode.WELCOME
loader.add_child(ui_mode_node)
ui_mode_node.switch_mode()
func update_resolution(new_resolution: Vector2i) -> void:
if !initialized:
logger.error("The UI Engine hasn't been initialized yet")
return
DisplayServer.window_set_size(new_resolution)
get_tree().root.content_scale_size = new_resolution
if get_node_or_null("/root/Console") != null: get_node("/root/Console").calculate_drag_area(new_resolution)
resolution = str(new_resolution.x) + "x" + str(new_resolution.y)
match(ui_mode):
UIMode.UNKNOWN: return
UIMode.WELCOME: ui_mode_node.update_resolution(new_resolution)
logger.diag("Set resolution to " + str(new_resolution.x) + "x" + str(new_resolution.y))

125
ui/Welcome.tscn Normal file
View file

@ -0,0 +1,125 @@
[gd_scene load_steps=6 format=3 uid="uid://b8byh8tp1kc6b"]
[ext_resource type="Texture2D" uid="uid://s10lveujhhqs" path="res://assets/images/Wallpaper.png" id="1_3cfcw"]
[ext_resource type="Script" path="res://src/ui/welcome.gd" id="1_rowat"]
[ext_resource type="Texture2D" uid="uid://41uwq5qahj23" path="res://assets/images/IconTextInverted.png" id="2_2w5c0"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0l23a"]
bg_color = Color(0, 0, 0, 0.705882)
corner_radius_top_left = 32
corner_radius_top_right = 32
corner_radius_bottom_right = 32
corner_radius_bottom_left = 32
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_sor5s"]
[node name="GUIWelcome" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_rowat")
[node name="Wallpaper" type="NinePatchRect" parent="."]
layout_mode = 0
offset_right = 960.0
offset_bottom = 540.0
texture = ExtResource("1_3cfcw")
[node name="Welcome" type="Button" parent="Wallpaper"]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -432.0
offset_top = -243.0
offset_right = 432.0
offset_bottom = 243.0
grow_horizontal = 2
grow_vertical = 2
theme_override_styles/normal = SubResource("StyleBoxFlat_0l23a")
theme_override_styles/hover = SubResource("StyleBoxFlat_0l23a")
theme_override_styles/pressed = SubResource("StyleBoxFlat_0l23a")
theme_override_styles/disabled = SubResource("StyleBoxFlat_0l23a")
theme_override_styles/focus = SubResource("StyleBoxEmpty_sor5s")
[node name="Icon" type="NinePatchRect" parent="Wallpaper/Welcome"]
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -320.0
offset_top = 24.3
offset_right = 320.0
offset_bottom = 144.3
grow_horizontal = 2
texture = ExtResource("2_2w5c0")
[node name="Splash" type="RichTextLabel" parent="Wallpaper/Welcome" groups=["font", "font_normal"]]
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -320.0
offset_top = 152.975
offset_right = 320.0
offset_bottom = 186.975
grow_horizontal = 2
mouse_filter = 2
bbcode_enabled = true
text = "[center]splash text[/center]"
scroll_active = false
[node name="AboutText" type="RichTextLabel" parent="Wallpaper/Welcome" groups=["font", "font_small"]]
layout_mode = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -320.0
offset_top = -92.0
offset_right = 320.0
offset_bottom = -20.0
grow_horizontal = 2
grow_vertical = 0
mouse_filter = 2
bbcode_enabled = true
text = "[center][i]Copyright (c) 2024[/i] [b]JeremyStar™ & Contributors[/b]
Licensed under the [b]GNU General Public License version 3[/b].
Thank you for using Presencode <3[/center]"
scroll_active = false
[node name="OpenButton" type="Button" parent="Wallpaper/Welcome" groups=["font_one", "font_one_normal"]]
layout_mode = 1
anchors_preset = 4
anchor_top = 0.5
anchor_bottom = 0.5
offset_left = 60.0
offset_top = -19.0
offset_right = 278.0
offset_bottom = 19.0
grow_vertical = 2
text = "Open presentation"
[node name="EditorButton" type="Button" parent="Wallpaper/Welcome" groups=["font_one", "font_one_normal"]]
layout_mode = 1
anchors_preset = 6
anchor_left = 1.0
anchor_top = 0.5
anchor_right = 1.0
anchor_bottom = 0.5
offset_left = -278.0
offset_top = -19.0
offset_right = -60.0
offset_bottom = 19.0
grow_horizontal = 0
grow_vertical = 2
text = "Edit presentation"
[connection signal="pressed" from="Wallpaper/Welcome" to="." method="update_splash"]
[connection signal="pressed" from="Wallpaper/Welcome/OpenButton" to="." method="open_presentation_picker"]