Partial source code rewrite
- [src/*] Update comments - [src/*] Improve code quality - [export_presets.cfg] All exports use a console wrapper now - [src/console.gd] Add highlighting for "arbitrary" command - [src/console.gd] Add special message if nothing has been typed in - [src/misc.gd, src/console.gd] Move BooleanState, get_last() (now called get_shortened_array), get_boolean(), get_int() and get_int_direct() into misc - [src/console_info.gd] Remove useless _init() function - [src/console_info.gd] Make get_error_string() function more compact - [Loader.tscn, src/loader.gd] Remove window size support and slow initialization functionality - [src/loader.gd] Remove warning on startup (will be reimplemented at some point, most likely graphically) - [src/loader.gd] Replaced append_log() function with a lambda - [src/loader.gd] Implement argument parser with configuration support - [src/loader.gd] Add Presencode version information as constants and format_version() function - [src/misc.gd] Reorganize functions - [src/pmana.gd] Add checks to avoid slide change collisions - [src/pmana.gd] Replace logger.warn() calls to "await logger.error()" calls - [src/pmana.gd, src/misc.gd, src/console.gd] Remove pmana.shutdown() function in favour of misc.shutdown() which now does the same - [src/preader.gd] Fix resource loading issues for presentation directories - [src/preader.gd] Move resource loading workaround into seperate function _read_resource_workaround() - [src/processor.gd, src/console.gd, src/loader.gd, src/pmana.gd, src/ui_engine.gd] Move all _process() functions into seperate file - [src/processor.gd, src/console.gd, src/loader.gd, src/pmana.gd, src/ui_engine.gd, src/ui/welcome.gd] Move everything dragging related (except variables) into processor.gd - [ui/Welcome.tscn, src/ui/welcome.gd] Add support for presentation directories - [src/ui/welcome.gd] Update splash text
This commit is contained in:
parent
19d3e8a0d0
commit
b5acd36479
21 changed files with 767 additions and 522 deletions
|
@ -93,5 +93,5 @@ theme_override_fonts/font = ExtResource("4_jqfsc")
|
|||
theme_override_font_sizes/font_size = 18
|
||||
placeholder_text = "Enter a command here"
|
||||
|
||||
[connection signal="pressed" from="Bar/CloseButton" to="." method="close_console"]
|
||||
[connection signal="pressed" from="Bar/CloseButton" to="." method="toggle_console"]
|
||||
[connection signal="text_changed" from="Shell/Input" to="." method="input_changed"]
|
||||
|
|
40
Loader.tscn
40
Loader.tscn
|
@ -8,43 +8,3 @@ offset_bottom = 1440.0
|
|||
size_flags_horizontal = 4
|
||||
color = Color(0, 0, 0, 1)
|
||||
script = ExtResource("1_dpffy")
|
||||
|
||||
[node name="WindowSizeSupport" type="Control" parent="."]
|
||||
anchors_preset = 0
|
||||
offset_right = 40.0
|
||||
offset_bottom = 40.0
|
||||
|
||||
[node name="EndPixel" type="ColorRect" parent="WindowSizeSupport"]
|
||||
layout_mode = 0
|
||||
offset_left = 1920.0
|
||||
offset_top = 1080.0
|
||||
offset_right = 1921.0
|
||||
offset_bottom = 1081.0
|
||||
|
||||
[node name="1920+" type="ColorRect" parent="WindowSizeSupport"]
|
||||
layout_mode = 0
|
||||
offset_right = 9999.0
|
||||
offset_bottom = 30.0
|
||||
|
||||
[node name="1920" type="ColorRect" parent="WindowSizeSupport"]
|
||||
layout_mode = 0
|
||||
offset_right = 1920.0
|
||||
offset_bottom = 30.0
|
||||
color = Color(0, 0, 1, 1)
|
||||
|
||||
[node name="1441" type="ColorRect" parent="WindowSizeSupport"]
|
||||
layout_mode = 0
|
||||
offset_right = 30.0
|
||||
offset_bottom = 9999.0
|
||||
|
||||
[node name="1440" type="ColorRect" parent="WindowSizeSupport"]
|
||||
layout_mode = 0
|
||||
offset_right = 30.0
|
||||
offset_bottom = 1440.0
|
||||
color = Color(1, 1, 0, 1)
|
||||
|
||||
[node name="1080" type="ColorRect" parent="WindowSizeSupport"]
|
||||
layout_mode = 0
|
||||
offset_right = 30.0
|
||||
offset_bottom = 1080.0
|
||||
color = Color(1, 0, 1, 1)
|
||||
|
|
32
docs/docs/reference/api/loader.md
Normal file
32
docs/docs/reference/api/loader.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Loader
|
||||
Initializes Presencode and holds the viewport while presenting.
|
||||
|
||||
## Enums
|
||||
### `VersionType`
|
||||
- values
|
||||
- `RELEASE`
|
||||
- `RELEASECANDIDATE`
|
||||
- `BETA`
|
||||
- `ALPHA`
|
||||
## Constants
|
||||
### `version_release`
|
||||
- type `int`
|
||||
- description `Contains the current release number (e.g. 1)`
|
||||
### `version_type`
|
||||
- type `VersionType`
|
||||
- description `Contains the current release type (e.g. VersionType.BETA)`
|
||||
### `version_typerelease`
|
||||
- type `int`
|
||||
- description `Contains the current release type version (e.g. 3)`
|
||||
### `format_version`
|
||||
- return type `String`
|
||||
- description `Replaces the variables %release%, %type_raw%, %type%, %type_short%, %type_technical% and %typerelease%.`
|
||||
- arguments
|
||||
- `format`
|
||||
- type `string`
|
||||
- mandatory `yes`
|
||||
- description `The string that you want to format`
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Logger
|
||||
|
|
|
@ -1,27 +1,45 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Miscellaneous (misc)
|
||||
Miscellaneous functions that do not fit into other scripts.
|
||||
|
||||
## Enums
|
||||
### `BooleanState`
|
||||
- values
|
||||
- `TRUE`
|
||||
- `FALSE`
|
||||
- `INVALID`
|
||||
## Variables
|
||||
### `config_shutdown_invisible`
|
||||
- type `bool`
|
||||
- description `Hides the main window on shutdown if true, displays a white texture on shutdown if false`
|
||||
## Functions
|
||||
### `shutdown`
|
||||
- return type `void`
|
||||
- description `Registers a new presentation controller`
|
||||
### `get_bool`
|
||||
- return type `BooleanState`
|
||||
- description `Retrieves a bool from a String`
|
||||
- arguments
|
||||
- `exitcode`
|
||||
- type `int`
|
||||
- mandatory `no`
|
||||
- description `DUDE DO YOU DON'T KNOW WHAT A EXITCODE IS?!`
|
||||
### `get_temporary_dir`
|
||||
- return type `String`
|
||||
- description `Return a temporary directory`
|
||||
- arguments `none`
|
||||
- `string`
|
||||
- type `String`
|
||||
- mandatory `yes`
|
||||
- description `The string that you want to convert into a bool`
|
||||
### `get_int`
|
||||
- return type `Vector2i`
|
||||
- description `Retrieves the next valid integer from an Array. Returns Vector2i(0, NUMBER) if successful, Vector2i(1, 0) if not`
|
||||
- arguments
|
||||
- `array`
|
||||
- type `Array`
|
||||
- mandatory `yes`
|
||||
- description `The array that you want to get an integer out of`
|
||||
### `get_int_direct`
|
||||
- return type `Vector2i`
|
||||
- description `Converts a String into an int. Returns Vector2i(0, NUMBER) if successful, Vector2i(1, 0) if not`
|
||||
- arguments
|
||||
- `string`
|
||||
- type `String`
|
||||
- mandatory `yes`
|
||||
- description `The string that you want to convert to an integer`
|
||||
### `get_center`
|
||||
- return type `Vector2i`
|
||||
- description `Calculates the center of a child inside its parent (Vector2i edition)`
|
||||
|
@ -46,18 +64,28 @@ Miscellaneous functions that do not fit into other scripts.
|
|||
- type `Vector2`
|
||||
- mandatory `yes`
|
||||
- description `The size of the child object`
|
||||
### `clear_viewport`
|
||||
- return type `void`
|
||||
- description `Clears the presentation viewport`
|
||||
- arguments `none`
|
||||
### `hide_log`
|
||||
- return type `void`
|
||||
- description `Hides log output`
|
||||
- arguments `none`
|
||||
### `show_log`
|
||||
- return type `void`
|
||||
- description `Unhides log output`
|
||||
### `get_shortened_array`
|
||||
- return type `Array`
|
||||
- description `Removes n items from an array (starting from the beginning)`
|
||||
- arguments
|
||||
- `array`
|
||||
- type `Array`
|
||||
- mandatory `yes`
|
||||
- description `The array that you want to shorten`
|
||||
- `skip`
|
||||
- type `int`
|
||||
- mandatory `yes`
|
||||
- description `The amount of items that you want to remove from the beginning.`
|
||||
- warning `This function automatically adds 1 to the skip variable. To only skip one element, use 0 (for example)`
|
||||
### `get_temporary_dir`
|
||||
- return type `String`
|
||||
- description `Return a temporary directory`
|
||||
- arguments `none`
|
||||
### `shutdown`
|
||||
- return type `void`
|
||||
- description `Ends the presentation and shuts Presencode down`
|
||||
- description `Registers a new presentation controller`
|
||||
- arguments
|
||||
- `exitcode`
|
||||
- type `int`
|
||||
- mandatory `no`
|
||||
- description `DUDE DO YOU DON'T KNOW WHAT A EXITCODE IS?!`
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
sidebar_position: 3
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# Presentation Manager (pmana)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
sidebar_position: 4
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Presentation Reader (preader)
|
||||
|
|
|
@ -18,7 +18,7 @@ encrypt_directory=false
|
|||
|
||||
custom_template/debug=""
|
||||
custom_template/release=""
|
||||
debug/export_console_wrapper=1
|
||||
debug/export_console_wrapper=2
|
||||
binary_format/embed_pck=true
|
||||
texture_format/bptc=true
|
||||
texture_format/s3tc=true
|
||||
|
@ -81,7 +81,7 @@ encrypt_directory=false
|
|||
|
||||
custom_template/debug=""
|
||||
custom_template/release=""
|
||||
debug/export_console_wrapper=1
|
||||
debug/export_console_wrapper=2
|
||||
binary_format/embed_pck=true
|
||||
texture_format/bptc=true
|
||||
texture_format/s3tc=true
|
||||
|
|
|
@ -26,6 +26,7 @@ misc="*res://src/misc.gd"
|
|||
preader="*res://src/preader.gd"
|
||||
pmana="*res://src/pmana.gd"
|
||||
ui_engine="*res://src/ui_engine.gd"
|
||||
processor="*res://src/processor.gd"
|
||||
|
||||
[display]
|
||||
|
||||
|
@ -73,8 +74,8 @@ content_scale_switch={
|
|||
}
|
||||
console={
|
||||
"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":96,"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":96,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
|
||||
"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":4194334,"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":4194334,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
editor_switchres={
|
||||
|
|
|
@ -23,9 +23,10 @@
|
|||
##############################################################################
|
||||
extends Button
|
||||
|
||||
# Setup clickoverlay
|
||||
# Initialize clickoverlay
|
||||
func _ready() -> void:
|
||||
# Set properties
|
||||
logger.diag("Initializing ClickOverlay")
|
||||
# Set button properties
|
||||
mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
position = Vector2i(0, 0)
|
||||
# Hide button
|
||||
|
@ -34,17 +35,13 @@ func _ready() -> void:
|
|||
add_theme_stylebox_override("pressed", StyleBoxEmpty.new())
|
||||
add_theme_stylebox_override("disabled", StyleBoxEmpty.new())
|
||||
add_theme_stylebox_override("focus", StyleBoxEmpty.new())
|
||||
# Connect "pressed" signal to function "clicked"
|
||||
# Connect pressed signal
|
||||
connect("pressed", Callable(self, "clicked"))
|
||||
# Simple fix for a bug
|
||||
await get_tree().process_frame
|
||||
clicked()
|
||||
|
||||
# Clicked event
|
||||
func clicked() -> void:
|
||||
# Increase current_slide by one
|
||||
logger.info("Navigating one slide forwards (click)")
|
||||
pmana.change_slide(pmana.current_slide+1, true)
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
# Scale clickoverlay to window size
|
||||
size = DisplayServer.window_get_size()
|
||||
|
|
207
src/console.gd
207
src/console.gd
|
@ -23,13 +23,6 @@
|
|||
##############################################################################
|
||||
extends ColorRect
|
||||
|
||||
# Enums
|
||||
enum BooleanState {
|
||||
TRUE,
|
||||
FALSE,
|
||||
INVALID
|
||||
}
|
||||
|
||||
# Nodes
|
||||
@onready var input: TextEdit = get_node("Shell/Input")
|
||||
@onready var output: RichTextLabel = get_node("Shell/Output")
|
||||
|
@ -43,20 +36,24 @@ var dragging: bool = false
|
|||
var drag_area: Vector2 = Vector2(0, 0)
|
||||
var cursor_origin: Vector2 = Vector2(0, 0)
|
||||
|
||||
# Initialize debug console
|
||||
func _ready() -> void:
|
||||
logger.info("Initializing debug console")
|
||||
# Set properties
|
||||
visible = false
|
||||
position = Vector2(30, 30)
|
||||
calculate_drag_area()
|
||||
# Calculate console drag area
|
||||
processor.update_dragging_area(processor.DragNode.CONSOLE)
|
||||
# Setup window dragging
|
||||
$Bar/DragButton.connect("button_down", func():
|
||||
$Bar/DragButton.connect("button_down", func() -> void:
|
||||
dragging = true
|
||||
cursor_origin = get_tree().root.get_viewport().get_mouse_position()
|
||||
)
|
||||
$Bar/DragButton.connect("button_up", func():
|
||||
$Bar/DragButton.connect("button_up", func() -> void:
|
||||
dragging = false
|
||||
cursor_origin = Vector2(0,0)
|
||||
)
|
||||
# Setup ExpressionScript (in which arbitrary expressions are run)
|
||||
expressionscript.name = "ExpressionScript"
|
||||
expressionscript.set_script(ResourceLoader.load("res://src/console_expressionscript.gd"))
|
||||
expressionscript.logger = get_node("/root/logger")
|
||||
|
@ -67,60 +64,18 @@ func _ready() -> void:
|
|||
expressionscript.console = self
|
||||
expressionscript.loader = get_node("/root/Presencode")
|
||||
add_child(expressionscript)
|
||||
# Reset console session
|
||||
await process_command(PackedStringArray(["exit"]))
|
||||
logger.info("Debug console initialized")
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
# Move to top
|
||||
get_tree().root.move_child(self, get_tree().root.get_child_count(true))
|
||||
# Visibility toggle key
|
||||
if Input.is_action_just_pressed("console"):
|
||||
# Toggle console visibility
|
||||
func toggle_console() -> void:
|
||||
logger.info("Toggling console visibility")
|
||||
visible = !visible
|
||||
if dragging:
|
||||
# Get new cursor position
|
||||
var cursor_position = get_tree().root.get_viewport().get_mouse_position()
|
||||
# If nothing changed, don't do anything
|
||||
if cursor_origin != cursor_position:
|
||||
# Calculate cursor offset
|
||||
var cursor_offset: Vector2 = Vector2(0, 0)
|
||||
cursor_offset.x = cursor_origin.x-cursor_position.x
|
||||
cursor_offset.y = cursor_origin.y-cursor_position.y
|
||||
# Change console position
|
||||
position.x = position.x-cursor_offset.x
|
||||
position.y = position.y-cursor_offset.y
|
||||
# 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:
|
||||
var new_position: Vector2 = position
|
||||
if position.x <= 0:
|
||||
new_position.x = 0
|
||||
elif position.x >= drag_area.x:
|
||||
new_position.x = drag_area.x
|
||||
if position.y <= 0:
|
||||
new_position.y = 0
|
||||
elif position.y >= drag_area.y:
|
||||
new_position.y = drag_area.y
|
||||
return new_position
|
||||
|
||||
# Calculates a new drag_area
|
||||
func calculate_drag_area(area: Vector2i = DisplayServer.window_get_size()) -> void:
|
||||
drag_area.x = area.x-size.x
|
||||
drag_area.y = area.y-size.y
|
||||
|
||||
# Close console on close button press
|
||||
func close_console() -> void:
|
||||
logger.info("Closing console")
|
||||
visible = false
|
||||
|
||||
# Input changed
|
||||
func input_changed() -> void:
|
||||
# Check for newline/enter
|
||||
if input.text.contains("\n"):
|
||||
input.text = input.text.replace("\n", "")
|
||||
var input2: String = input.text
|
||||
|
@ -128,13 +83,30 @@ func input_changed() -> void:
|
|||
input.editable = false
|
||||
await process_command(input2.split(" ", false))
|
||||
input.editable = true
|
||||
return
|
||||
# Highlight wrong/correct arbitrary gdscript expressions
|
||||
if input.text.begins_with("arbitrary ") and input.text != "arbitrary ":
|
||||
var expression_raw: String = " ".join(PackedStringArray(misc.get_shortened_array(input.text.split(" "), 0)))
|
||||
var expression: Expression = Expression.new()
|
||||
if expression.parse(expression_raw) == Error.OK: input.add_theme_color_override("font_color", Color.LIGHT_GREEN)
|
||||
else: input.add_theme_color_override("font_color", Color.LIGHT_CORAL)
|
||||
else: input.add_theme_color_override("font_color", Color8(255, 255, 255, 255))
|
||||
|
||||
# Write to console output
|
||||
func append_output(text: String, newline: bool = true) -> void:
|
||||
if newline: output.text = output.text + text + "\n"
|
||||
else: output.text = output.text + text
|
||||
|
||||
# Process commands
|
||||
## This function is completely undocumented, looking a bit through the function and
|
||||
## reading the append_output() calls should give you a rough understanding though.
|
||||
func process_command(command: PackedStringArray) -> void:
|
||||
logger.diag("Processing command [" + " ".join(command) + "]")
|
||||
await get_tree().process_frame
|
||||
append_output("[color=gray]$ " + " ".join(command) + "[color=white]")
|
||||
if command.size() == 0: return
|
||||
if command.size() == 0:
|
||||
append_output("[color=gray]$ *nothing*[color=white]\nI don't think that entering nothing does anything. Try running [b]help[/b].")
|
||||
return
|
||||
else: append_output("[color=gray]$ " + " ".join(command) + "[color=white]")
|
||||
match(command[0]):
|
||||
"clear":
|
||||
match(command.size()):
|
||||
|
@ -154,7 +126,7 @@ To get started, enter \"help\". To close the console, press the X button.[color=
|
|||
1: exitcode = 0
|
||||
2: exitcode = int(command[1])
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_MANY_ARGUMENTS))
|
||||
pmana.shutdown(exitcode)
|
||||
misc.shutdown(exitcode)
|
||||
"help":
|
||||
match(command.size()):
|
||||
1: append_output(info.get_help_topic(ConsoleInfo.HelpTopic.INDEX))
|
||||
|
@ -215,59 +187,59 @@ MISC_SHUTDOWN_INVISIBLE | bool | Toggles if the window should be made invisibl
|
|||
_:
|
||||
match(command[2]):
|
||||
"LOGGER_ENABLED":
|
||||
match(get_boolean(" ".join(get_last(command, 2)))):
|
||||
BooleanState.TRUE:
|
||||
match(misc.get_bool(" ".join(misc.get_shortened_array(command, 2)))):
|
||||
misc.BooleanState.TRUE:
|
||||
logger.config_enabled = true
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]true[/b].")
|
||||
BooleanState.FALSE:
|
||||
misc.BooleanState.FALSE:
|
||||
logger.config_enabled = false
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]false[/b]")
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "bool"}))
|
||||
"LOGGER_DIAGNOSTIC":
|
||||
match(get_boolean(" ".join(get_last(command, 2)))):
|
||||
BooleanState.TRUE:
|
||||
match(misc.get_bool(" ".join(misc.get_shortened_array(command, 2)))):
|
||||
misc.BooleanState.TRUE:
|
||||
logger.config_diagnostic = true
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]true[/b]")
|
||||
BooleanState.FALSE:
|
||||
misc.BooleanState.FALSE:
|
||||
logger.config_diagnostic = false
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]false[/b]")
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "bool"}))
|
||||
"LOGGER_COLORED":
|
||||
match(get_boolean(" ".join(get_last(command, 2)))):
|
||||
BooleanState.TRUE:
|
||||
match(misc.get_bool(" ".join(misc.get_shortened_array(command, 2)))):
|
||||
misc.BooleanState.TRUE:
|
||||
logger.config_colored = true
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]true[/b]")
|
||||
BooleanState.FALSE:
|
||||
misc.BooleanState.FALSE:
|
||||
logger.config_colored = false
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]false[/b]")
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "bool"}))
|
||||
"LOGGER_HARDFAIL":
|
||||
match(get_boolean(" ".join(get_last(command, 2)))):
|
||||
BooleanState.TRUE:
|
||||
match(misc.get_bool(" ".join(misc.get_shortened_array(command, 2)))):
|
||||
misc.BooleanState.TRUE:
|
||||
logger.config_hardfail = true
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]true[/b]")
|
||||
BooleanState.FALSE:
|
||||
misc.BooleanState.FALSE:
|
||||
logger.config_hardfail = false
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]false[/b]")
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "bool"}))
|
||||
"LOGGER_LOGSTRING":
|
||||
logger.config_logstring = " ".join(PackedStringArray(get_last(command, 2)))
|
||||
logger.config_logstring = " ".join(PackedStringArray(misc.get_shortened_array(command, 2)))
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]\"" + logger.config_logstring + "\"[/b]")
|
||||
"PMANA_ALLOW_FULLSCREEN":
|
||||
match(get_boolean(" ".join(get_last(command, 2)))):
|
||||
BooleanState.TRUE:
|
||||
match(misc.get_bool(" ".join(misc.get_shortened_array(command, 2)))):
|
||||
misc.BooleanState.TRUE:
|
||||
pmana.config_allow_fullscreen = true
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]true[/b]")
|
||||
BooleanState.FALSE:
|
||||
misc.BooleanState.FALSE:
|
||||
pmana.config_allow_fullscreen = false
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]false[/b]")
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "bool"}))
|
||||
"MISC_SHUTDOWN_INVISIBLE":
|
||||
match(get_boolean(" ".join(get_last(command, 2)))):
|
||||
BooleanState.TRUE:
|
||||
match(misc.get_bool(" ".join(misc.get_shortened_array(command, 2)))):
|
||||
misc.BooleanState.TRUE:
|
||||
misc.config_shutdown_invisible = true
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]true[/b]")
|
||||
BooleanState.FALSE:
|
||||
misc.BooleanState.FALSE:
|
||||
misc.config_shutdown_invisible = false
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]false[/b]")
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "bool"}))
|
||||
|
@ -301,11 +273,11 @@ MISC_SHUTDOWN_INVISIBLE | bool | Toggles if the window should be made invisibl
|
|||
5: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
6: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
7:
|
||||
var version: Vector2 = get_int_direct(command[2])
|
||||
var slides: Vector2 = get_int_direct(command[3])
|
||||
var animations: BooleanState = get_boolean(command[4])
|
||||
var version: Vector2 = misc.get_int_direct(command[2])
|
||||
var slides: Vector2 = misc.get_int_direct(command[3])
|
||||
var animations: misc.BooleanState = misc.get_bool(command[4])
|
||||
var animations_bool: bool = false
|
||||
var quit_last_slide: BooleanState = get_boolean(command[5])
|
||||
var quit_last_slide: misc.BooleanState = misc.get_bool(command[5])
|
||||
var quit_last_slide_bool: bool = false
|
||||
var controller: NodePath = NodePath(command[6])
|
||||
if version.x != 0:
|
||||
|
@ -315,14 +287,14 @@ MISC_SHUTDOWN_INVISIBLE | bool | Toggles if the window should be made invisibl
|
|||
append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "int"}))
|
||||
return
|
||||
match(animations):
|
||||
BooleanState.TRUE: animations_bool = true
|
||||
BooleanState.FALSE: animations_bool = false
|
||||
misc.BooleanState.TRUE: animations_bool = true
|
||||
misc.BooleanState.FALSE: animations_bool = false
|
||||
_:
|
||||
append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "bool"}))
|
||||
return
|
||||
match(quit_last_slide):
|
||||
BooleanState.TRUE: quit_last_slide_bool = true
|
||||
BooleanState.FALSE: quit_last_slide_bool = false
|
||||
misc.BooleanState.TRUE: quit_last_slide_bool = true
|
||||
misc.BooleanState.FALSE: quit_last_slide_bool = false
|
||||
_:
|
||||
append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "bool"}))
|
||||
return
|
||||
|
@ -346,31 +318,31 @@ MISC_SHUTDOWN_INVISIBLE | bool | Toggles if the window should be made invisibl
|
|||
3:
|
||||
if !pmana.registered: append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_CONTROLLER_REGISTERED))
|
||||
else:
|
||||
var slide: Vector2i = get_int_direct(command[2])
|
||||
var slide: Vector2i = misc.get_int_direct(command[2])
|
||||
match(slide.x):
|
||||
0:
|
||||
pmana.change_slide(slide.y)
|
||||
append_output("Switched to slide [b]" + str(slide.y) + "[/b]")
|
||||
1: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "int"}))
|
||||
_: append_output(info.generate_internal_error("Invalid get_int() status number"))
|
||||
_: append_output(info.generate_internal_error("Invalid misc.get_int() status number"))
|
||||
4:
|
||||
if !pmana.registered: append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_CONTROLLER_REGISTERED))
|
||||
else:
|
||||
var slide: Vector2i = get_int_direct(command[2])
|
||||
var slide: Vector2i = misc.get_int_direct(command[2])
|
||||
match(slide.x):
|
||||
0:
|
||||
var no_animations: BooleanState = get_boolean(command[3])
|
||||
var no_animations: misc.BooleanState = misc.get_bool(command[3])
|
||||
match(no_animations):
|
||||
BooleanState.TRUE:
|
||||
misc.BooleanState.TRUE:
|
||||
pmana.change_slide(slide.y, true)
|
||||
append_output("Switched to slide [b]" + str(slide.y) + "[/b] without animations")
|
||||
BooleanState.FALSE:
|
||||
misc.BooleanState.FALSE:
|
||||
pmana.change_slide(slide.y, false)
|
||||
append_output("Switched to slide [b]" + str(slide.y) + "[/b]")
|
||||
BooleanState.INVALID:
|
||||
misc.BooleanState.INVALID:
|
||||
append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "bool"}))
|
||||
1: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "int"}))
|
||||
_: append_output(info.generate_internal_error("Invalid get_int() status number"))
|
||||
_: append_output(info.generate_internal_error("Invalid misc.get_int() status number"))
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_MANY_ARGUMENTS))
|
||||
"get_slide":
|
||||
if !pmana.registered: append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_CONTROLLER_REGISTERED))
|
||||
|
@ -423,7 +395,7 @@ MISC_SHUTDOWN_INVISIBLE | bool | Toggles if the window should be made invisibl
|
|||
match(command.size()):
|
||||
1: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
_:
|
||||
var expression_raw: String = " ".join(PackedStringArray(get_last(command, 0)))
|
||||
var expression_raw: String = " ".join(PackedStringArray(misc.get_shortened_array(command, 0)))
|
||||
var expression: Expression = Expression.new()
|
||||
if expression.parse(expression_raw) != Error.OK:
|
||||
append_output(info.get_error_string(ConsoleInfo.ConsoleError.EXPRESSION_PARSING_FAILED, {"error": expression.get_error_text()}))
|
||||
|
@ -435,48 +407,3 @@ MISC_SHUTDOWN_INVISIBLE | bool | Toggles if the window should be made invisibl
|
|||
append_output("""Executed arbitrary expression successfully.
|
||||
Returned: """ + str(returned))
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_COMMAND))
|
||||
|
||||
# Helper function. I'm bad at explaining and naming things, just look at the code... please.
|
||||
func get_last(array: Array, n: int) -> Array:
|
||||
# Makes it easier
|
||||
n = n+1
|
||||
# Create new array
|
||||
var new_array: Array = []
|
||||
if n >= array.size():
|
||||
logger.error("n is bigger than array.size()")
|
||||
return []
|
||||
for value in array:
|
||||
if n == 0: # Append to new_array
|
||||
new_array.append(value)
|
||||
else: # Count down
|
||||
n = n-1
|
||||
return new_array
|
||||
|
||||
# Helper function. Tries to get a bool from an Array.
|
||||
func get_boolean(string: String) -> BooleanState:
|
||||
match(string):
|
||||
"true": return BooleanState.TRUE
|
||||
"false": return BooleanState.FALSE
|
||||
_: return BooleanState.INVALID
|
||||
|
||||
# Helper function. Tries to get a int from an Array.
|
||||
## Returns Vector2i(0, NUMBER) if successful
|
||||
## Returns Vector2i(1, 0) if not successful
|
||||
func get_int(array: Array) -> Vector2i:
|
||||
for value in array:
|
||||
if str(value).is_valid_int(): return Vector2i(0, int(value))
|
||||
return Vector2i(1, 0)
|
||||
|
||||
# Helper function. Tries to get a int from a String.
|
||||
## Returns Vector2i(0, NUMBER) if successful
|
||||
## Returns Vector2i(1, 0) if not successful
|
||||
func get_int_direct(string: String) -> Vector2i:
|
||||
if string.is_valid_int(): return Vector2i(0, int(string))
|
||||
else: return Vector2i(1, 0)
|
||||
|
||||
# Helper function. Appends text to output.text
|
||||
func append_output(text: String, newline: bool = true) -> void:
|
||||
if newline:
|
||||
output.text = output.text + text + "\n"
|
||||
else:
|
||||
output.text = output.text + text
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
extends Node
|
||||
class_name ConsoleInfo
|
||||
|
||||
# Enums
|
||||
enum ConsoleError {
|
||||
OK,
|
||||
UNIMPLEMENTED,
|
||||
|
@ -55,57 +56,38 @@ enum HelpTopic {
|
|||
ARBITRARY
|
||||
}
|
||||
|
||||
# Variables
|
||||
var error_color: String = "[color=red]"
|
||||
var internal_error_color: String = "[b][color=red]"
|
||||
|
||||
func _init() -> void:
|
||||
logger.diag("ConsoleInfo initialized")
|
||||
|
||||
# Generates an internal error
|
||||
func generate_internal_error(error: String) -> String:
|
||||
var origin = misc.get_origin()
|
||||
logger.warn("Debug console (" + origin["file"] + ":" + origin["function"] + ":" + str(origin["line"]) + ") experienced an internal error: " + error)
|
||||
return internal_error_color + "INTERNAL ERROR (" + error + ") [" + origin["file"] + ":" + origin["function"] + ":" + str(origin["line"]) + "]"
|
||||
|
||||
# Converts ConsoleError into a String
|
||||
func get_error_string(error: ConsoleError, context: Dictionary = {}) -> String:
|
||||
match(error):
|
||||
ConsoleError.OK:
|
||||
return generate_internal_error("ConsoleError.OK is not a valid error")
|
||||
ConsoleError.UNIMPLEMENTED:
|
||||
return error_color + "Function unimplemented, aborting."
|
||||
ConsoleError.INVALID_COMMAND:
|
||||
return error_color + "Invalid command. Execute \"help\" for a list of all available commands."
|
||||
ConsoleError.TOO_MANY_ARGUMENTS:
|
||||
return error_color + "Too many arguments."
|
||||
ConsoleError.TOO_FEW_ARGUMENTS:
|
||||
return error_color + "Too few arguments."
|
||||
ConsoleError.INVALID_ARGUMENT:
|
||||
return error_color + "Invalid argument."
|
||||
ConsoleError.INVALID_TYPE:
|
||||
return error_color + "Invalid type. Command expected type " + str(context["expected_type"]) + "."
|
||||
ConsoleError.NOT_AN_OBJECT:
|
||||
return error_color + "Invalid type. Command expected a valid NodePath."
|
||||
ConsoleError.NO_SCRIPT_ATTACHED:
|
||||
return error_color + "Invalid object. Command expected a script-attached object."
|
||||
ConsoleError.INVALID_HELP_TOPIC:
|
||||
return error_color + "Invalid help topic."
|
||||
ConsoleError.INVALID_CONFIG_KEY:
|
||||
return error_color + "Invalid config key \"" + str(context["key"]) + "\". Execute \"config list\" for a list of all config keys."
|
||||
ConsoleError.NO_PRESENTATION_OPEN:
|
||||
return error_color + "No presentation is currently open."
|
||||
ConsoleError.CONTROLLER_ALREADY_REGISTERED:
|
||||
return error_color + "A presentation controller has been registered already."
|
||||
ConsoleError.NO_CONTROLLER_REGISTERED:
|
||||
return error_color + "No presentation controller has been registered yet."
|
||||
ConsoleError.EXPRESSION_PARSING_FAILED:
|
||||
return error_color + """Could not parse arbitrary expression successfully.
|
||||
Error: """ + str(context["error"])
|
||||
ConsoleError.EXPRESSION_EXECUTION_FAILED:
|
||||
return error_color + """Could not execute arbitrary expression successfully.
|
||||
Error: """ + str(context["error"]) + """
|
||||
Returned: """ + str(context["returned"])
|
||||
_:
|
||||
return generate_internal_error("Invalid ConsoleError \"" + str(error) + "\", context: " + str(context))
|
||||
ConsoleError.OK: return generate_internal_error("ConsoleError.OK is not a valid error")
|
||||
ConsoleError.UNIMPLEMENTED: return error_color + "Function unimplemented, aborting."
|
||||
ConsoleError.INVALID_COMMAND: return error_color + "Invalid command. Execute \"help\" for a list of all available commands."
|
||||
ConsoleError.TOO_MANY_ARGUMENTS: return error_color + "Too many arguments."
|
||||
ConsoleError.TOO_FEW_ARGUMENTS: return error_color + "Too few arguments."
|
||||
ConsoleError.INVALID_ARGUMENT: return error_color + "Invalid argument."
|
||||
ConsoleError.INVALID_TYPE: return error_color + "Invalid type. Command expected type " + str(context["expected_type"]) + "."
|
||||
ConsoleError.NOT_AN_OBJECT: return error_color + "Invalid type. Command expected a valid NodePath."
|
||||
ConsoleError.NO_SCRIPT_ATTACHED: return error_color + "Invalid object. Command expected a script-attached object."
|
||||
ConsoleError.INVALID_HELP_TOPIC: return error_color + "Invalid help topic."
|
||||
ConsoleError.INVALID_CONFIG_KEY: return error_color + "Invalid config key \"" + str(context["key"]) + "\". Execute \"config list\" for a list of all config keys."
|
||||
ConsoleError.NO_PRESENTATION_OPEN: return error_color + "No presentation is currently open."
|
||||
ConsoleError.CONTROLLER_ALREADY_REGISTERED: return error_color + "A presentation controller has been registered already."
|
||||
ConsoleError.NO_CONTROLLER_REGISTERED: return error_color + "No presentation controller has been registered yet."
|
||||
ConsoleError.EXPRESSION_PARSING_FAILED: return error_color + "Could not parse arbitrary expression successfully.\nError: " + str(context["error"])
|
||||
ConsoleError.EXPRESSION_EXECUTION_FAILED: return error_color + "Could not execute arbitrary expression successfully.\nError: " + str(context["error"]) + "\nReturned: " + str(context["returned"])
|
||||
_: return generate_internal_error("Invalid ConsoleError \"" + str(error) + "\", context: " + str(context))
|
||||
|
||||
# Converts HelpTopic into a String
|
||||
func get_help_topic(topic: HelpTopic) -> String:
|
||||
match(topic):
|
||||
HelpTopic.INDEX:
|
||||
|
@ -158,5 +140,4 @@ Calls functions belonging to the Presentation Reader"""
|
|||
|
||||
Executes arbitrary GDScript expressions.
|
||||
-> EXPERIMENTAL"""
|
||||
_:
|
||||
return generate_internal_error("Invalid HelpTopic \"" + str(topic) + "\"")
|
||||
_: return generate_internal_error("Invalid HelpTopic \"" + str(topic) + "\"")
|
||||
|
|
193
src/loader.gd
193
src/loader.gd
|
@ -23,21 +23,26 @@
|
|||
##############################################################################
|
||||
extends Control
|
||||
|
||||
# Loader configuration
|
||||
## Window size support
|
||||
### This is/was used for configuring scaling
|
||||
var config_window_size_support: bool = false
|
||||
## Skip malicious scripts warning if running as debug build
|
||||
var config_skipwarning: bool = true
|
||||
## Slow init
|
||||
### I don't know why I put this here lol
|
||||
var config_slow_init: bool = false
|
||||
# Enums
|
||||
enum VersionType {
|
||||
RELEASE,
|
||||
RELEASECANDIDATE,
|
||||
BETA,
|
||||
ALPHA
|
||||
}
|
||||
|
||||
# Constants
|
||||
const version_release: int = 1
|
||||
const version_type: VersionType = VersionType.ALPHA
|
||||
const version_typerelease: int = 2
|
||||
|
||||
# Nodes
|
||||
var logrtl: RichTextLabel = null
|
||||
var console: Control = null
|
||||
|
||||
func _ready() -> void:
|
||||
#while true: await get_tree().create_timer(0.05).timeout
|
||||
misc.set_main_window_visibility(false)
|
||||
logger.info("Updating loader scene")
|
||||
# Rename loader scene
|
||||
name = "Presencode"
|
||||
|
@ -62,7 +67,7 @@ func _ready() -> void:
|
|||
logrtl.add_theme_font_size_override("normal_font_size", 14)
|
||||
logrtl.add_theme_font_size_override("bold_font_size", 14)
|
||||
## Connect to logger
|
||||
logger.connect("log_event", Callable(self, "append_log"))
|
||||
logger.connect("log_event", func(_type: logger.Types, _message: String, logstring: String) -> void: logrtl.text = get_node("/root/Presencode/Log").text + logstring + "\n")
|
||||
## Add to SceneTree
|
||||
add_child(logrtl)
|
||||
## Remove VScrollBar
|
||||
|
@ -74,14 +79,6 @@ func _ready() -> void:
|
|||
vsbar.add_theme_stylebox_override("grabber", StyleBoxEmpty.new())
|
||||
vsbar.add_theme_stylebox_override("grabber_highlight", StyleBoxEmpty.new())
|
||||
vsbar.add_theme_stylebox_override("grabber_pressed", StyleBoxEmpty.new())
|
||||
## Window size support
|
||||
if config_window_size_support:
|
||||
$WindowSizeSupport.modulate = Color8(255, 255, 255, 255)
|
||||
else:
|
||||
$WindowSizeSupport.modulate = Color8(255, 255, 255, 0)
|
||||
## Update process_mode
|
||||
logger.process_mode = Node.PROCESS_MODE_ALWAYS
|
||||
misc.process_mode = Node.PROCESS_MODE_ALWAYS
|
||||
## Initialize Presencode
|
||||
initialize()
|
||||
|
||||
|
@ -98,24 +95,77 @@ func initialize() -> void:
|
|||
Copyright (c) 2024 JeremyStarTM & Contributers
|
||||
Licensed under the GNU General Public License version 3
|
||||
""")
|
||||
if config_slow_init: await get_tree().create_timer(randf_range(0.2, 0.6)).timeout
|
||||
# Check for platform
|
||||
misc.check_platform()
|
||||
# Create temporary directory
|
||||
DirAccess.make_dir_recursive_absolute(misc.get_temporary_dir())
|
||||
# Load debug console
|
||||
logger.info("Injecting console")
|
||||
console = ResourceLoader.load("res://Console.tscn").instantiate()
|
||||
get_tree().root.add_child.call_deferred(console)
|
||||
if config_slow_init: await get_tree().create_timer(randf_range(0.1, 0.15)).timeout
|
||||
# Check for presentation path in commandline arguments
|
||||
# Open presentation archive/directory
|
||||
var path: String = " ".join(OS.get_cmdline_user_args())
|
||||
if OS.get_cmdline_user_args().size() == 0:
|
||||
# Initialize processor
|
||||
processor.initialize.call_deferred()
|
||||
# Process arguments
|
||||
var path: String = parse_arguments()
|
||||
# Update window properties
|
||||
misc.set_main_window_visibility(true)
|
||||
# Check path variable
|
||||
if path == "":
|
||||
ui_engine.initialize(self)
|
||||
else:
|
||||
await print_warning()
|
||||
await load_presentation(path)
|
||||
|
||||
# Process commandline arguments
|
||||
func parse_arguments() -> String:
|
||||
var path: String = ""
|
||||
var next_argument_value: String = ""
|
||||
for arg in OS.get_cmdline_user_args():
|
||||
match(next_argument_value):
|
||||
"logger_enabled":
|
||||
match(misc.get_bool(arg)):
|
||||
misc.BooleanState.TRUE: logger.config_enabled = true
|
||||
misc.BooleanState.FALSE: logger.config_enabled = false
|
||||
_: logger.error("Value \"" + arg + "\" does not match \"true\" or \"false\"")
|
||||
"logger_diagnostic":
|
||||
match(misc.get_bool(arg)):
|
||||
misc.BooleanState.TRUE: logger.config_diagnostic = true
|
||||
misc.BooleanState.FALSE: logger.config_diagnostic = false
|
||||
_: logger.error("Value \"" + arg + "\" does not match \"true\" or \"false\"")
|
||||
"logger_colored":
|
||||
match(misc.get_bool(arg)):
|
||||
misc.BooleanState.TRUE: logger.config_colored = true
|
||||
misc.BooleanState.FALSE: logger.config_colored = false
|
||||
_: logger.error("Value \"" + arg + "\" does not match \"true\" or \"false\"")
|
||||
"logger_hardfail":
|
||||
match(misc.get_bool(arg)):
|
||||
misc.BooleanState.TRUE: logger.config_hardfail = true
|
||||
misc.BooleanState.FALSE: logger.config_hardfail = false
|
||||
_: logger.error("Value \"" + arg + "\" does not match \"true\" or \"false\"")
|
||||
"logger_logstring": logger.config_logstring = arg
|
||||
"misc_shutdown_invisible":
|
||||
match(misc.get_bool(arg)):
|
||||
misc.BooleanState.TRUE: misc.config_shutdown_invisible = true
|
||||
misc.BooleanState.FALSE: misc.config_shutdown_invisible = false
|
||||
_: logger.error("Value \"" + arg + "\" does not match \"true\" or \"false\"")
|
||||
if next_argument_value != "":
|
||||
next_argument_value = ""
|
||||
continue
|
||||
match(arg):
|
||||
"--help": continue
|
||||
"--logger-enabled": next_argument_value = "logger_enabled"
|
||||
"--logger-diagnostic": next_argument_value = "logger_diagnostic"
|
||||
"--logger-colored": next_argument_value = "logger_colored"
|
||||
"--logger-hardfail": next_argument_value = "logger_hardfail"
|
||||
"--logger-logstring": next_argument_value = "logger_logstring"
|
||||
"--shutdown-invisible": next_argument_value = "misc_shutdown_invisible"
|
||||
_:
|
||||
# doesn't match any of the above, append to path instead
|
||||
## this causes an interesting side effect, which is best explained by an example:
|
||||
## C:/Users/Example User/Documents/Important --shutdown-invisible false Documents/Example --logger-colored false Presentation.pcpa
|
||||
if path == "": path = arg
|
||||
else: path = path + " " + arg
|
||||
return path
|
||||
|
||||
# Load a presentation from commandline arguments
|
||||
func load_presentation(path: String) -> void:
|
||||
if FileAccess.file_exists(path) and path.ends_with(".zip") or path.ends_with(".pcpa"): # .pcpa = presencode presentation archive
|
||||
|
@ -126,81 +176,52 @@ func load_presentation(path: String) -> void:
|
|||
preader.open_presentation(path, false)
|
||||
else:
|
||||
await logger.error("Presentation file/directory \"" + path + "\" not found")
|
||||
if config_slow_init: await get_tree().create_timer(randf_range(0.6, 1)).timeout
|
||||
return
|
||||
# Read manifest & entrypoint files
|
||||
preader.read_manifest()
|
||||
preader.read_entrypoint()
|
||||
# Update window properties
|
||||
console.calculate_drag_area(preader.get_ratio_resolution())
|
||||
processor.update_dragging_area(processor.DragNode.CONSOLE, 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 config_slow_init: await get_tree().create_timer(randf_range(0.1, 0.3)).timeout
|
||||
if config_window_size_support: $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()))
|
||||
if config_slow_init: await get_tree().create_timer(randf_range(1, 1.5)).timeout
|
||||
# Add entrypoint to SceneTree
|
||||
get_tree().root.add_child(preader.get_entrypoint())
|
||||
|
||||
# seeeeeeeeeeeeelf explanitory
|
||||
func _process(_delta: float) -> void:
|
||||
# Move to top
|
||||
get_tree().root.move_child(self, get_tree().root.get_child_count(true)-1)
|
||||
# Change sizes
|
||||
size = DisplayServer.window_get_size()
|
||||
if typeof(logrtl) == TYPE_OBJECT:
|
||||
logrtl.size = DisplayServer.window_get_size()
|
||||
if config_window_size_support: move_child($WindowSizeSupport, get_child_count(true))
|
||||
# Fullscreen key combo
|
||||
if pmana.config_allow_fullscreen and Input.is_action_just_pressed("fullscreen"):
|
||||
if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_WINDOWED:
|
||||
# window is windowed, set to fullscreen mode
|
||||
logger.info("Switched to fullscreen mode")
|
||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
|
||||
else:
|
||||
# window is in fullscreen (or something else) mode, set to windowed mode
|
||||
logger.info("Switched to windowed mode")
|
||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
|
||||
# Content scale switch combo
|
||||
if Input.is_action_just_pressed("content_scale_switch"):
|
||||
match(get_tree().root.content_scale_stretch):
|
||||
Window.CONTENT_SCALE_STRETCH_FRACTIONAL:
|
||||
logger.info("Switching to fractional scaling")
|
||||
get_tree().root.content_scale_stretch = Window.CONTENT_SCALE_STRETCH_INTEGER
|
||||
Window.CONTENT_SCALE_STRETCH_INTEGER:
|
||||
logger.info("Switching to integer scaling")
|
||||
get_tree().root.content_scale_stretch = Window.CONTENT_SCALE_STRETCH_FRACTIONAL
|
||||
_:
|
||||
logger.error("Invalid content_scale_stretch value")
|
||||
|
||||
# Append log output to logrtl.text
|
||||
func append_log(_type: logger.Types, _message: String, log_str: String) -> void:
|
||||
logrtl.text = $Log.text + log_str + "\n"
|
||||
|
||||
func print_warning() -> void:
|
||||
if !config_skipwarning and OS.is_debug_build():
|
||||
logger.warn("""Displaying warning
|
||||
###################################################
|
||||
##### !!! WARNING !!! WARNING !!! WARNING !!! #####
|
||||
###################################################
|
||||
Presentations made with Presencode perform
|
||||
malicious actions such as collect your passwords,
|
||||
encrypt your files, display you unwanted ads,
|
||||
install other malware, etc..
|
||||
|
||||
ONLY VIEW PRESENCODE PRESENTATIONS IF YOU TRUST THE
|
||||
AUTHOR AND HAVE VERIFIED THE PRESENTATION SCRIPT!
|
||||
YOU HAVE 5 SECONDS TO EXIT PRESENCODE
|
||||
|
||||
YOU HAVE BEEN WARNED.
|
||||
###################################################
|
||||
##### !!! WARNING !!! WARNING !!! WARNING !!! #####
|
||||
###################################################
|
||||
""")
|
||||
await get_tree().create_timer(5).timeout
|
||||
func format_version(format: String) -> String:
|
||||
var version: String = format
|
||||
var version_type_normal: String = ""
|
||||
var version_type_short: String = ""
|
||||
var version_type_technical: String = ""
|
||||
match(version_type):
|
||||
VersionType.RELEASE:
|
||||
version_type_normal = "Release"
|
||||
version_type_short = "Release"
|
||||
version_type_technical = "r"
|
||||
VersionType.RELEASECANDIDATE:
|
||||
version_type_normal = "Releasecandidate"
|
||||
version_type_short = "RC"
|
||||
version_type_technical = "rc"
|
||||
VersionType.BETA:
|
||||
version_type_normal = "Beta"
|
||||
version_type_short = "Beta"
|
||||
version_type_technical = "b"
|
||||
VersionType.ALPHA:
|
||||
version_type_normal = "Alpha"
|
||||
version_type_short = "Alpha"
|
||||
version_type_technical = "a"
|
||||
_: logger.info("Invalid version type \"" + str(version_type) + "\"")
|
||||
version = version.replace("%release%", str(version_release))
|
||||
version = version.replace("%type_raw%", str(version_type))
|
||||
version = version.replace("%type%", version_type_normal)
|
||||
version = version.replace("%type_short%", version_type_short)
|
||||
version = version.replace("%type_technical%", version_type_technical)
|
||||
version = version.replace("%typerelease%", str(version_typerelease))
|
||||
return version
|
||||
|
|
|
@ -35,7 +35,9 @@ var config_enabled: bool = true
|
|||
var config_diagnostic: bool = true
|
||||
## Toggle colored output
|
||||
var config_colored: bool = true
|
||||
## Exit Presencode on error? (don't set this to false)
|
||||
## Makes errors fail hard
|
||||
### Shuts Presencode down if error() is called
|
||||
### HIGHLY RECOMMENDED TO LEAVE ENABLED
|
||||
var config_hardfail: bool = true
|
||||
## Logging template
|
||||
### Variables (begin and end with '%'): runtime, time, file, function, line, color, type, message
|
||||
|
|
171
src/misc.gd
171
src/misc.gd
|
@ -35,8 +35,13 @@ enum Error {
|
|||
MANIFEST_INVALID_PROGRAM,
|
||||
MANIFEST_INVALID_RATIO
|
||||
}
|
||||
enum BooleanState {
|
||||
TRUE,
|
||||
FALSE,
|
||||
INVALID
|
||||
}
|
||||
|
||||
# Manifest specification
|
||||
# Constants
|
||||
const manifest_version: int = 1
|
||||
const manifest_program: String = "Presencode"
|
||||
|
||||
|
@ -44,45 +49,46 @@ const manifest_program: String = "Presencode"
|
|||
## Make window invisible on shutdown
|
||||
### Hides the main window on shutdown if true
|
||||
### Displays RenderingServer.get_white_texture() if false instead
|
||||
var config_shutdown_invisible: bool = true
|
||||
var config_shutdown_invisible: bool = false
|
||||
|
||||
# Get call origin from stacktrace
|
||||
func get_origin(n: int = 0) -> Dictionary:
|
||||
var stack: Dictionary = get_stack()[2+n]
|
||||
return {"file": stack["source"].replace("user://", "").replace("res://", ""), "line": stack["line"], "function": stack["function"]}
|
||||
# Helper function to retrieve a bool from a String
|
||||
func get_bool(string: String) -> BooleanState:
|
||||
match(string):
|
||||
"true": return BooleanState.TRUE
|
||||
"false": return BooleanState.FALSE
|
||||
_: return BooleanState.INVALID
|
||||
|
||||
# Shutdown Presencode safely
|
||||
func shutdown(exitcode: int = 0) -> void:
|
||||
logger.info("Shutting down (code " + str(exitcode) + ")")
|
||||
get_tree().paused = true
|
||||
# Display white texture
|
||||
var npr: NinePatchRect = NinePatchRect.new()
|
||||
npr.name = "OverlayTexture"
|
||||
npr.texture = ImageTexture.create_from_image(RenderingServer.texture_2d_get(RenderingServer.get_white_texture()))
|
||||
npr.size = Vector2(100000, 100000)
|
||||
npr.position = Vector2(-50000, -50000)
|
||||
get_tree().root.add_child(npr)
|
||||
get_tree().root.move_child(npr, get_tree().root.get_child_count(true))
|
||||
# Window stuff
|
||||
if config_shutdown_invisible:
|
||||
# Make window invisible
|
||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_BORDERLESS, true)
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_RESIZE_DISABLED, true)
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_NO_FOCUS, true)
|
||||
DisplayServer.window_set_min_size(Vector2i(1, 1))
|
||||
DisplayServer.window_set_size(Vector2i(1, 1))
|
||||
DisplayServer.window_set_position(Vector2i(0, 0))
|
||||
logger.diag("Removing temporary directory")
|
||||
# Remove tempdir
|
||||
DirAccess.remove_absolute(get_temporary_dir())
|
||||
# Wait for all log messages to be printed to console/log
|
||||
logger.diag("Waiting for log messages")
|
||||
await get_tree().create_timer(0.25, true).timeout
|
||||
print("Exiting!")
|
||||
get_tree().quit(exitcode)
|
||||
# Insanely long timer to prevent Godot from executing code during exit
|
||||
await get_tree().create_timer(999, true).timeout
|
||||
# Helper function to retrieve the next valid int from an Array
|
||||
## Returns Vector2i(0, NUMBER) if successful
|
||||
## Returns Vector2i(1, 0) if not successful
|
||||
func get_int(array: Array) -> Vector2i:
|
||||
for value in array:
|
||||
if str(value).is_valid_int(): return Vector2i(0, int(value))
|
||||
return Vector2i(1, 0)
|
||||
|
||||
# Helper function to retrieve a int from a String
|
||||
## Returns Vector2i(0, NUMBER) if successful
|
||||
## Returns Vector2i(1, 0) if not successful
|
||||
func get_int_direct(string: String) -> Vector2i:
|
||||
if string.is_valid_int(): return Vector2i(0, int(string))
|
||||
else: return Vector2i(1, 0)
|
||||
|
||||
# Returns a shortened array, by skipping "skip" Items
|
||||
func get_shortened_array(array: Array, skip: int) -> Array:
|
||||
# We want to remove at least one item
|
||||
skip = skip+1
|
||||
# Create new array
|
||||
var new_array: Array = []
|
||||
if skip >= array.size():
|
||||
logger.error("n is bigger than array.size()")
|
||||
return []
|
||||
# Loop through array
|
||||
for value in array:
|
||||
if skip == 0: # Append to new_array
|
||||
new_array.append(value)
|
||||
else: # Count down
|
||||
skip = skip-1
|
||||
return new_array
|
||||
|
||||
# Calculate the center of a child inside its parent (Vector2i)
|
||||
func get_center(parent_size: Vector2i, child_size: Vector2i) -> Vector2i:
|
||||
|
@ -105,26 +111,10 @@ func get_sign_float(number: float) -> float:
|
|||
elif number < 0: return -1
|
||||
else: return 0
|
||||
|
||||
# Return path to temporary directory
|
||||
## This function tries to utilize the operating system's temporary directory.
|
||||
## If all of them can't be used, it falls back to "user://temp" instead.
|
||||
func get_temporary_dir() -> String:
|
||||
match(OS.get_name()):
|
||||
"Linux": # Use "/tmp" or fallback
|
||||
if DirAccess.dir_exists_absolute("/tmp"):
|
||||
return "/tmp/presencode"
|
||||
else:
|
||||
return "user://temp"
|
||||
"Windows": # Use "%USERPROFILE%/AppData/Local/Temp/Presencode" or "C:/Users/%USERNAME%/AppData/Local/Temp/Presencode" or fallback
|
||||
if OS.get_environment("USERPROFILE") != "" and DirAccess.dir_exists_absolute(OS.get_environment("USERPROFILE").replace("\\", "/")):
|
||||
return OS.get_environment("USERPROFILE").replace("\\", "/") + "/AppData/Local/Temp/Presencode"
|
||||
elif OS.get_environment("USERNAME") != "" and DirAccess.dir_exists_absolute("C:/Users/" + OS.get_environment("USERNAME")):
|
||||
return "C:/Users/" + OS.get_environment("USERNAME") + "/AppData/Local/Temp/Presencode"
|
||||
else:
|
||||
return "user://temp"
|
||||
_: # Platform not supported
|
||||
logger.warn("The " + OS.get_name() + " platform is not supported by Presencode. You can add support for that platform to Presencode yourself, if you want.")
|
||||
return ""
|
||||
# Get call origin from stacktrace
|
||||
func get_origin(n: int = 0) -> Dictionary:
|
||||
var stack: Dictionary = get_stack()[2+n]
|
||||
return {"file": stack["source"].replace("user://", "").replace("res://", ""), "line": stack["line"], "function": stack["function"]}
|
||||
|
||||
# Check platform support
|
||||
func check_platform() -> void:
|
||||
|
@ -149,7 +139,70 @@ func get_best_resolution() -> Vector2i:
|
|||
if closest_resolution == Vector2(NAN, NAN): return Vector2i(960, 540)
|
||||
else: return closest_resolution
|
||||
|
||||
# Check for manifest consistency
|
||||
# Return path to temporary directory
|
||||
## This function tries to utilize the operating system's temporary directory.
|
||||
## If all of them can't be used, it falls back to "user://temp" instead.
|
||||
func get_temporary_dir() -> String:
|
||||
match(OS.get_name()):
|
||||
"Linux": # Use "/tmp" or fallback
|
||||
if DirAccess.dir_exists_absolute("/tmp"):
|
||||
return "/tmp/presencode"
|
||||
else:
|
||||
return "user://temp"
|
||||
"Windows": # Use "%USERPROFILE%/AppData/Local/Temp/Presencode" or "C:/Users/%USERNAME%/AppData/Local/Temp/Presencode" or fallback
|
||||
if OS.get_environment("USERPROFILE") != "" and DirAccess.dir_exists_absolute(OS.get_environment("USERPROFILE").replace("\\", "/")):
|
||||
return OS.get_environment("USERPROFILE").replace("\\", "/") + "/AppData/Local/Temp/Presencode"
|
||||
elif OS.get_environment("USERNAME") != "" and DirAccess.dir_exists_absolute("C:/Users/" + OS.get_environment("USERNAME")):
|
||||
return "C:/Users/" + OS.get_environment("USERNAME") + "/AppData/Local/Temp/Presencode"
|
||||
else:
|
||||
return "user://temp"
|
||||
_: # Platform not supported
|
||||
logger.warn("The " + OS.get_name() + " platform is not supported by Presencode. You can add support for that platform to Presencode yourself, if you want.")
|
||||
return ""
|
||||
|
||||
# Shutdown Presencode safely
|
||||
func shutdown(exitcode: int = 0) -> void:
|
||||
logger.info("Shutting down (code " + str(exitcode) + ")")
|
||||
get_tree().paused = true
|
||||
# Call controller's presentation_end() function if a controller is registered
|
||||
if pmana.registered: await pmana.controller.presentation_end()
|
||||
# Display white texture
|
||||
var npr: NinePatchRect = NinePatchRect.new()
|
||||
npr.name = "OverlayTexture"
|
||||
npr.texture = ImageTexture.create_from_image(RenderingServer.texture_2d_get(RenderingServer.get_white_texture()))
|
||||
npr.size = Vector2(100000, 100000)
|
||||
npr.position = Vector2(-50000, -50000)
|
||||
get_tree().root.add_child(npr)
|
||||
get_tree().root.move_child(npr, get_tree().root.get_child_count(true))
|
||||
# Set window properties
|
||||
if config_shutdown_invisible: set_main_window_visibility(false)
|
||||
# Remove temporary directory
|
||||
logger.diag("Removing temporary directory")
|
||||
DirAccess.remove_absolute(get_temporary_dir())
|
||||
# Wait for all log messages to be printed to console/log
|
||||
logger.diag("Waiting for log messages")
|
||||
await get_tree().create_timer(0.25, true).timeout
|
||||
print("Exiting!")
|
||||
get_tree().quit(exitcode)
|
||||
# Insanely long timer to prevent Godot from executing code during exit
|
||||
await get_tree().create_timer(999, true).timeout
|
||||
|
||||
# Makes the window invisible/visible
|
||||
func set_main_window_visibility(visible: bool) -> void:
|
||||
if DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_WINDOWED: DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED, true)
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_BORDERLESS, !visible)
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_RESIZE_DISABLED, !visible)
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_NO_FOCUS, !visible)
|
||||
if visible:
|
||||
DisplayServer.window_set_min_size(Vector2i(960, 540))
|
||||
DisplayServer.window_set_size(Vector2i(960, 540))
|
||||
DisplayServer.window_set_position(get_center(DisplayServer.screen_get_size(), DisplayServer.window_get_size()))
|
||||
else:
|
||||
DisplayServer.window_set_min_size(Vector2i(1, 1))
|
||||
DisplayServer.window_set_size(Vector2i(1, 1))
|
||||
DisplayServer.window_set_position(Vector2i(0, 0))
|
||||
|
||||
# Checks for manifest consistency
|
||||
func check_manifest_consistency(manifest: Dictionary) -> misc.Error:
|
||||
logger.diag("Checking manifest for consistency")
|
||||
|
||||
|
|
71
src/pmana.gd
71
src/pmana.gd
|
@ -26,6 +26,10 @@ extends Node
|
|||
# Constants
|
||||
const entrypoint_version: int = 1
|
||||
|
||||
# Nodes
|
||||
var clickoverlay: Button = null
|
||||
var viewport: Control = null
|
||||
|
||||
# Configuration
|
||||
var config_allow_fullscreen: bool = true
|
||||
|
||||
|
@ -39,8 +43,7 @@ var quit_last_slide: bool = true
|
|||
var registered: bool = false
|
||||
var current_slide: int = -1
|
||||
var animation_active: bool = false
|
||||
var clickoverlay: Button = null
|
||||
var viewport: Control = null
|
||||
var action_running: bool = false
|
||||
|
||||
# Register a controller
|
||||
func register(version: int, slides_: int, animations_: bool, quit_last_slide_: bool, controller_: NodePath) -> void:
|
||||
|
@ -55,11 +58,13 @@ func register(version: int, slides_: int, animations_: bool, quit_last_slide_: b
|
|||
if get_node(controller_) == null:
|
||||
await logger.error("The presentation controller could not be located.")
|
||||
# Set controller information
|
||||
logger.diag("Setting controller information")
|
||||
slides = slides_
|
||||
animations = animations_
|
||||
quit_last_slide = quit_last_slide_
|
||||
controller = get_node(controller_)
|
||||
# Check for essential functions
|
||||
# Check for required functions
|
||||
logger.diag("Check for required functions")
|
||||
var lacking_functions: Array = []
|
||||
var check_functions: Array = ["change_slide", "presentation_start", "presentation_end"] ## Base functions
|
||||
## "display_end_slide" function
|
||||
|
@ -80,19 +85,21 @@ func register(version: int, slides_: int, animations_: bool, quit_last_slide_: b
|
|||
logger.warn("Consult the documentation or take a look at the example presentation if you need help.")
|
||||
await misc.shutdown(1)
|
||||
# Create presentation viewport
|
||||
logger.diag("Creating presentation viewport")
|
||||
viewport = Control.new()
|
||||
viewport.name = "Viewport"
|
||||
viewport.size = preader.get_ratio_resolution()
|
||||
viewport.position = Vector2(0, 0)
|
||||
get_node("/root/Presencode").add_child(viewport)
|
||||
# Create clickoverlay
|
||||
logger.diag("Creating clickoverlay")
|
||||
clickoverlay = Button.new()
|
||||
clickoverlay.name = "ClickOverlay"
|
||||
clickoverlay.set_script(ResourceLoader.load("res://src/clickoverlay.gd"))
|
||||
get_node("/root/Presencode").add_child(clickoverlay)
|
||||
# Did you know that every big galaxy contains a massive black hole in it's center?
|
||||
registered = true
|
||||
# Invoke presentation_start()
|
||||
# Invoke controller's presentation_start()
|
||||
controller.presentation_start(viewport)
|
||||
|
||||
# Unregister a controller
|
||||
|
@ -101,17 +108,23 @@ func unregister() -> void:
|
|||
logger.warn("No presentation controller has been registered yet. Please call register() first.")
|
||||
return
|
||||
logger.info("Unregistering presentation controller")
|
||||
# Reset to default values
|
||||
while action_running:
|
||||
logger.warn("Waiting for action to finish")
|
||||
await get_tree().create_timer(1).timeout
|
||||
# Reset variables to default values
|
||||
logger.diag("Resetting variables")
|
||||
registered = false
|
||||
current_slide = -1
|
||||
animation_active = false
|
||||
config_allow_fullscreen = true
|
||||
# Remove clickoverlay
|
||||
# Remove nodes
|
||||
logger.diag("Removing node")
|
||||
## Remove clickoverlay
|
||||
get_node("/root/Presencode/").remove_child(clickoverlay)
|
||||
clickoverlay = null
|
||||
## Remove viewport
|
||||
get_node("/root/Presencode/").remove_child(viewport)
|
||||
viewport = null
|
||||
await get_tree().process_frame
|
||||
|
||||
# Change slide
|
||||
func change_slide(slide: int, no_animations: bool = false) -> void:
|
||||
|
@ -131,7 +144,7 @@ func change_slide(slide: int, no_animations: bool = false) -> void:
|
|||
# Quit after last slide?
|
||||
if quit_last_slide:
|
||||
logger.info("Ending presentation")
|
||||
await shutdown()
|
||||
await misc.shutdown(0)
|
||||
return
|
||||
else:
|
||||
logger.warn("Over max slides by " + str(slide-slides))
|
||||
|
@ -142,33 +155,30 @@ func change_slide(slide: int, no_animations: bool = false) -> void:
|
|||
return
|
||||
else: # End presentation (slide is over max slides by two or more)
|
||||
logger.info("Ending presentation")
|
||||
await shutdown()
|
||||
await misc.shutdown(0)
|
||||
return
|
||||
# Slide is not over max slides, continue slide change
|
||||
action_running = true
|
||||
# Play switch away animation
|
||||
if animations and !no_animations:
|
||||
await controller.animation_switch_away(current_slide, slide)
|
||||
# Check if controller has unregistered during animation
|
||||
if !registered:
|
||||
logger.warn("The current presentation controller has been unregistered during execution, aborting")
|
||||
return
|
||||
if !registered: logger.error("The current presentation controller has been unregistered during execution")
|
||||
# Change slide
|
||||
await controller.change_slide(slide)
|
||||
# Check if controller has unregistered during animation
|
||||
if !registered:
|
||||
logger.warn("The current presentation controller has been unregistered during execution, aborting")
|
||||
return
|
||||
# Check if controller has unregistered during slide change
|
||||
if !registered: logger.error("The current presentation controller has been unregistered during execution")
|
||||
# Set current_slide to new slide
|
||||
current_slide = slide
|
||||
# Play switch to animation
|
||||
if animations and !no_animations:
|
||||
await controller.animation_switch_to(current_slide, slide)
|
||||
if animations and !no_animations: await controller.animation_switch_to(current_slide, slide)
|
||||
|
||||
# Clear the viewport
|
||||
func clear_viewport() -> void:
|
||||
if !registered:
|
||||
logger.warn("No presentation controller has been registered yet. Please call register() first.")
|
||||
return
|
||||
logger.diag("Clearing viewport")
|
||||
if viewport.get_child_count(true) == 0:
|
||||
logger.warn("No children found in viewport")
|
||||
return
|
||||
|
@ -180,6 +190,7 @@ func hide_log() -> void:
|
|||
if !registered:
|
||||
logger.warn("No presentation controller has been registered yet. Please call register() first.")
|
||||
return
|
||||
logger.diag("Hiding log")
|
||||
get_node("/root/Presencode/Log").modulate = Color8(255, 255, 255, 0)
|
||||
|
||||
# Show log output
|
||||
|
@ -187,27 +198,5 @@ func show_log() -> void:
|
|||
if !registered:
|
||||
logger.warn("No presentation controller has been registered yet. Please call register() first.")
|
||||
return
|
||||
logger.diag("Showing log")
|
||||
get_node("/root/Presencode/Log").modulate = Color8(255, 255, 255, 255)
|
||||
|
||||
# Helper function. Shutdown Presencode
|
||||
func shutdown(exitcode: int = 0) -> void:
|
||||
logger.diag("Shutting down Presencode from Presentation Manager")
|
||||
if registered: await controller.presentation_end()
|
||||
await misc.shutdown(exitcode)
|
||||
|
||||
# Runs every frame (duh)
|
||||
func _process(_delta: float) -> void:
|
||||
if !registered: return
|
||||
# Navigation key combos
|
||||
if Input.is_action_pressed("slide_forwards") and Input.is_action_pressed("slide_backwards"): return
|
||||
else:
|
||||
if get_node_or_null("/root/Console") == null or !get_node("/root/Console").visible:
|
||||
if Input.is_action_just_pressed("slide_forwards"):
|
||||
# Increase current_slide by one
|
||||
logger.info("Navigating one slide forwards (key)")
|
||||
change_slide(current_slide+1)
|
||||
elif Input.is_action_just_pressed("slide_backwards"):
|
||||
# Decrease current_slide by one
|
||||
logger.info("Navigating one slide backwards (key)")
|
||||
|
||||
change_slide(current_slide-1)
|
||||
|
|
|
@ -25,7 +25,10 @@
|
|||
##############################################################################
|
||||
extends Node
|
||||
|
||||
# Reading
|
||||
# States
|
||||
var is_open: bool = false
|
||||
|
||||
# Reading support
|
||||
var directorypath: String = ""
|
||||
var ziphandler: ZIPReader = ZIPReader.new()
|
||||
|
||||
|
@ -33,10 +36,7 @@ var ziphandler: ZIPReader = ZIPReader.new()
|
|||
var manifest: Dictionary = {}
|
||||
var entrypoint: Node = null
|
||||
|
||||
# States
|
||||
var is_open: bool = false
|
||||
|
||||
# Opening a presentation
|
||||
# Open a presentation archive/directory
|
||||
func open_presentation(path: String, zip: bool) -> Error:
|
||||
if is_open:
|
||||
logger.warn("Another presentation is still in memory")
|
||||
|
@ -53,7 +53,7 @@ func open_presentation(path: String, zip: bool) -> Error:
|
|||
is_open = true
|
||||
return Error.OK
|
||||
|
||||
# Close the currently open presentation
|
||||
# Close opened presentation
|
||||
func close_presentation() -> Error:
|
||||
if !is_open:
|
||||
logger.warn("No presentation is currently opened")
|
||||
|
@ -120,14 +120,11 @@ func read_resource(path: String) -> Resource:
|
|||
file.store_buffer(resource_bytes)
|
||||
file.close()
|
||||
var resource: Resource = null
|
||||
if path.ends_with(".ttf") or path.ends_with(".otf") or path.ends_with(".woff") or path.ends_with(".woff2"):
|
||||
resource = FontFile.new()
|
||||
resource.load_dynamic_font(misc.get_temporary_dir() + "/" + str(split_path[split_path.size()-1]))
|
||||
elif path.ends_with(".png") or path.ends_with(".jpg") or path.ends_with(".svg") or path.ends_with(".ktx") or path.ends_with(".tga") or path.ends_with(".webp"):
|
||||
resource = Image.load_from_file(misc.get_temporary_dir() + "/" + str(split_path[split_path.size()-1]))
|
||||
else:
|
||||
# Attempt workaround to mitigate loading issues
|
||||
resource = _read_resource_workaround(misc.get_temporary_dir() + "/" + str(split_path[split_path.size()-1]))
|
||||
if resource == null: # Workaround did not work, load resource normally
|
||||
resource = ResourceLoader.load(misc.get_temporary_dir() + "/" + str(split_path[split_path.size()-1]))
|
||||
if resource == null:
|
||||
if resource == null: # Resource could not be read
|
||||
logger.warn("Resource could not be read, resource is null")
|
||||
return null
|
||||
return resource
|
||||
|
@ -135,13 +132,29 @@ func read_resource(path: String) -> Resource:
|
|||
if !FileAccess.file_exists(directorypath + "/" + path):
|
||||
logger.error("Requested resource is missing in presentation directory")
|
||||
return null
|
||||
var resource: Resource = ResourceLoader.load(directorypath + "/" + path)
|
||||
if resource == null:
|
||||
var resource: Resource = null
|
||||
# Attempt workaround to mitigate loading issues
|
||||
resource = _read_resource_workaround(directorypath + "/" + path)
|
||||
if resource == null: # Workaround did not work, load resource normally
|
||||
resource = ResourceLoader.load(directorypath + "/" + path)
|
||||
if resource == null: # Resource could not be read
|
||||
logger.warn("Resource could not be read, resource is null")
|
||||
return null
|
||||
return resource
|
||||
|
||||
# Read a resource from the presentation archive/directory (unsafe)
|
||||
# Workaround to make loading certain resources possible, even if outside res:// and user://
|
||||
func _read_resource_workaround(path: String) -> Resource:
|
||||
var resource: Resource = null
|
||||
if path.ends_with(".ttf") or path.ends_with(".otf") or path.ends_with(".woff") or path.ends_with(".woff2"):
|
||||
# Font workaround
|
||||
resource = FontFile.new()
|
||||
resource.load_dynamic_font(path)
|
||||
elif path.ends_with(".png") or path.ends_with(".jpg") or path.ends_with(".svg") or path.ends_with(".ktx") or path.ends_with(".tga") or path.ends_with(".webp"):
|
||||
# Image workaround
|
||||
resource = Image.load_from_file(path)
|
||||
return resource
|
||||
|
||||
# Read a resource from the presentation archive/directory (unsafe, without workaround)
|
||||
func read_resource_unsafe(path: String) -> Resource:
|
||||
if !is_open:
|
||||
logger.warn("No presentation is currently opened")
|
||||
|
@ -173,7 +186,7 @@ func read_resource_unsafe(path: String) -> Resource:
|
|||
return null
|
||||
return resource
|
||||
|
||||
# Check if a file exists in presentation archive/direcoty
|
||||
# Check if file exists in presentation archive/directory
|
||||
func file_exists(path: String) -> bool:
|
||||
if !is_open:
|
||||
logger.warn("No presentation is currently opened")
|
||||
|
@ -232,7 +245,7 @@ func get_entrypoint() -> Node:
|
|||
return null
|
||||
return entrypoint
|
||||
|
||||
# Return presentation topic
|
||||
# Return the presentation topic
|
||||
func get_topic() -> String:
|
||||
if !is_open:
|
||||
logger.warn("No presentation is currently opened")
|
||||
|
@ -243,7 +256,7 @@ func get_topic() -> String:
|
|||
return ""
|
||||
return manifest["topic"]
|
||||
|
||||
# Return presentation authors
|
||||
# Return the presentation authors
|
||||
func get_authors() -> String:
|
||||
if !is_open:
|
||||
logger.warn("No presentation is currently opened")
|
||||
|
@ -258,7 +271,7 @@ func get_authors() -> String:
|
|||
else: authors = authors + ", " + author
|
||||
return authors
|
||||
|
||||
# Return display ratio
|
||||
# Return the presentation display ratio
|
||||
func get_ratio() -> String:
|
||||
if !is_open:
|
||||
logger.warn("No presentation is currently opened")
|
||||
|
@ -269,7 +282,7 @@ func get_ratio() -> String:
|
|||
return ""
|
||||
return manifest["ratio"]
|
||||
|
||||
# Return display resolution from display ratio
|
||||
# Return the display resolution (derived from display ratio)
|
||||
func get_ratio_resolution() -> Vector2i:
|
||||
if !is_open:
|
||||
logger.warn("No presentation is currently opened")
|
||||
|
|
172
src/processor.gd
Normal file
172
src/processor.gd
Normal file
|
@ -0,0 +1,172 @@
|
|||
##############################################################################
|
||||
### PRESENCODE SOURCE FILE ###
|
||||
### Copyright (c) 2024 JeremyStarTM & Contributors ###
|
||||
### Licensed under the GNU General Public License v3 ###
|
||||
### ###
|
||||
### This program is free software: you can redistribute it and/or modify ###
|
||||
### it under the terms of the GNU General Public License as published by ###
|
||||
### the Free Software Foundation, either version 3 of the License, or ###
|
||||
### (at your option) any later version. ###
|
||||
### ###
|
||||
### This program is distributed in the hope that it will be useful, ###
|
||||
### but WITHOUT ANY WARRANTY; without even the implied warranty of ###
|
||||
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ###
|
||||
### GNU General Public License for more details. ###
|
||||
### ###
|
||||
### You should have received a copy of the GNU General Public License ###
|
||||
### along with this program. If not, see <https://www.gnu.org/licenses/>. ###
|
||||
##############################################################################
|
||||
### src/processor.gd (Processor) ###
|
||||
### ###
|
||||
### This source file is solely used for doing things every frame. This ###
|
||||
### includes (for example) input handling, updating sizes, etc.. ###
|
||||
##############################################################################
|
||||
extends Node
|
||||
|
||||
# Enums
|
||||
enum DragNode {
|
||||
CONSOLE
|
||||
}
|
||||
|
||||
# Nodes
|
||||
var nodes: Array[Node] = [null, null]
|
||||
var loader: Node = null
|
||||
var console: Node = null
|
||||
|
||||
# States
|
||||
var initialized: bool = false
|
||||
|
||||
# Initialize processor
|
||||
func initialize() -> void:
|
||||
logger.diag("Initializing processor")
|
||||
loader = get_node("/root/Presencode")
|
||||
console = get_node("/root/Console")
|
||||
nodes = [
|
||||
loader,
|
||||
console
|
||||
]
|
||||
initialized = true
|
||||
|
||||
# What did you expect?
|
||||
func _process(_delta: float) -> void:
|
||||
if !initialized: return
|
||||
move_to_top()
|
||||
handle_keys()
|
||||
change_sizes()
|
||||
update_dragging()
|
||||
|
||||
# Move elements to top
|
||||
func move_to_top() -> void:
|
||||
if !initialized: return
|
||||
var index: int = get_tree().root.get_child_count(true)
|
||||
for node in nodes:
|
||||
get_tree().root.move_child(node, index)
|
||||
index = index-1
|
||||
|
||||
# Handles key inputs
|
||||
func handle_keys() -> void:
|
||||
if !initialized: return
|
||||
# Global
|
||||
## Scaling method
|
||||
if Input.is_action_just_pressed("content_scale_switch"):
|
||||
match(get_tree().root.content_scale_stretch):
|
||||
Window.CONTENT_SCALE_STRETCH_FRACTIONAL: # Current scaling mode is integer scaling
|
||||
logger.info("Switched to integer scaling")
|
||||
get_tree().root.content_scale_stretch = Window.CONTENT_SCALE_STRETCH_INTEGER
|
||||
Window.CONTENT_SCALE_STRETCH_INTEGER: # Current scaling mode is fractional scaling
|
||||
logger.info("Switched to fractional scaling")
|
||||
get_tree().root.content_scale_stretch = Window.CONTENT_SCALE_STRETCH_FRACTIONAL
|
||||
_: # Invalid value
|
||||
logger.error("Invalid content_scale_stretch value")
|
||||
# Presentation Manager
|
||||
## Fullscreen
|
||||
if pmana.config_allow_fullscreen and Input.is_action_just_pressed("fullscreen"):
|
||||
if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_WINDOWED: # Window is windowed, set to fullscreen mode
|
||||
logger.info("Switched to fullscreen mode")
|
||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
|
||||
else: # Window is in fullscreen (or something else) mode, set to windowed mode
|
||||
logger.info("Switched to windowed mode")
|
||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
|
||||
## Navigation
|
||||
if pmana.registered and Input.is_action_pressed("slide_forwards") and Input.is_action_pressed("slide_backwards"): return
|
||||
else:
|
||||
if get_node_or_null("/root/Console") == null or !get_node("/root/Console").visible:
|
||||
if Input.is_action_just_pressed("slide_forwards"): # Increase current_slide by one
|
||||
logger.info("Navigated one slide forwards")
|
||||
pmana.change_slide(pmana.current_slide+1)
|
||||
elif Input.is_action_just_pressed("slide_backwards"): # Decrease current_slide by one
|
||||
logger.info("Navigated one slide backwards")
|
||||
pmana.change_slide(pmana.current_slide-1)
|
||||
# Console
|
||||
## Visibility toggle
|
||||
if Input.is_action_just_pressed("console"): console.toggle_console()
|
||||
# UI Engine
|
||||
## Switch resolution
|
||||
if ui_engine.initialized and Input.is_action_just_pressed("editor_switchres"):
|
||||
match(ui_engine.resolution):
|
||||
"960x540": ui_engine.update_resolution(Vector2i(1920, 1080))
|
||||
"1920x1080": ui_engine.update_resolution(Vector2i(2560, 1440))
|
||||
"2560x1440": ui_engine.update_resolution(Vector2i(3840, 2160))
|
||||
"3840x2160": ui_engine.update_resolution(Vector2i(960, 540))
|
||||
|
||||
# Change sizes
|
||||
func change_sizes() -> void:
|
||||
if !initialized: return
|
||||
# Loader
|
||||
loader.size = DisplayServer.window_get_size()
|
||||
if typeof(loader.logrtl) == TYPE_OBJECT:
|
||||
loader.logrtl.size = DisplayServer.window_get_size()
|
||||
# ClickOverlay
|
||||
if get_node_or_null("/root/Presencode/ClickOverlay") != null: get_node("/root/Presencode/ClickOverlay").size = DisplayServer.window_get_size()
|
||||
|
||||
# Makes dragging windows possible
|
||||
func update_dragging() -> void:
|
||||
if !initialized: return
|
||||
# Console
|
||||
if console.dragging:
|
||||
# Get new cursor position
|
||||
var cursor_position = get_tree().root.get_viewport().get_mouse_position()
|
||||
if console.cursor_origin != cursor_position: # If mouse didn't move, don't execute further
|
||||
# Calculate cursor offset
|
||||
var cursor_offset: Vector2 = Vector2(0, 0)
|
||||
cursor_offset.x = console.cursor_origin.x-cursor_position.x
|
||||
cursor_offset.y = console.cursor_origin.y-cursor_position.y
|
||||
# Change console position
|
||||
console.position.x = console.position.x-cursor_offset.x
|
||||
console.position.y = console.position.y-cursor_offset.y
|
||||
# Set new console.cursor_origin
|
||||
console.cursor_origin = cursor_position
|
||||
# Prevent console from going out of scope
|
||||
var position_new: Vector2 = await check_dragging_area_violation(DragNode.CONSOLE)
|
||||
if console.position != position_new:
|
||||
console.position = position_new
|
||||
|
||||
# Calculate drag area
|
||||
func update_dragging_area(dragnode: DragNode, area: Vector2i = DisplayServer.window_get_size()) -> void:
|
||||
while !initialized:
|
||||
logger.diag("Waiting for Processor to initialize")
|
||||
await get_tree().create_timer(0.25).timeout
|
||||
match(dragnode):
|
||||
DragNode.CONSOLE:
|
||||
logger.diag("Updating drag area for CONSOLE")
|
||||
console.drag_area.x = area.x-console.size.x
|
||||
console.drag_area.y = area.y-console.size.y
|
||||
_: await logger.error("Invalid DragNode \"" + str(dragnode) + "\"")
|
||||
|
||||
# Check against drag area violations
|
||||
func check_dragging_area_violation(dragnode: DragNode) -> Vector2:
|
||||
if !initialized: await logger.error("Processor is not initialized yet.")
|
||||
var new_position: Vector2 = Vector2(0, 0)
|
||||
match(dragnode):
|
||||
DragNode.CONSOLE:
|
||||
new_position = console.position
|
||||
if console.position.x <= 0:
|
||||
new_position.x = 0
|
||||
elif console.position.x >= console.drag_area.x:
|
||||
new_position.x = console.drag_area.x
|
||||
if console.position.y <= 0:
|
||||
new_position.y = 0
|
||||
elif console.position.y >= console.drag_area.y:
|
||||
new_position.y = console.drag_area.y
|
||||
_: await logger.error("Invalid DragNode \"" + str(dragnode) + "\"")
|
||||
return new_position
|
|
@ -1,3 +1,25 @@
|
|||
##############################################################################
|
||||
### PRESENCODE SOURCE FILE ###
|
||||
### Copyright (c) 2024 JeremyStarTM & Contributors ###
|
||||
### Licensed under the GNU General Public License v3 ###
|
||||
### ###
|
||||
### This program is free software: you can redistribute it and/or modify ###
|
||||
### it under the terms of the GNU General Public License as published by ###
|
||||
### the Free Software Foundation, either version 3 of the License, or ###
|
||||
### (at your option) any later version. ###
|
||||
### ###
|
||||
### This program is distributed in the hope that it will be useful, ###
|
||||
### but WITHOUT ANY WARRANTY; without even the implied warranty of ###
|
||||
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ###
|
||||
### GNU General Public License for more details. ###
|
||||
### ###
|
||||
### You should have received a copy of the GNU General Public License ###
|
||||
### along with this program. If not, see <https://www.gnu.org/licenses/>. ###
|
||||
##############################################################################
|
||||
### src/ui/welcome.gd (Welcome UI) ###
|
||||
### ###
|
||||
### This source file controls the welcome user interface scene. ###
|
||||
##############################################################################
|
||||
extends Node
|
||||
|
||||
func switch_mode() -> void:
|
||||
|
@ -43,10 +65,12 @@ func update_resolution(new_resolution: Vector2i) -> void:
|
|||
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("OpenArchiveButton").size = Vector2(new_resolution.x/4.403669724770642, new_resolution.y/14.21052631578947)
|
||||
base.get_node("OpenArchiveButton").position = Vector2(base.size.x/16, base.size.y/2.410714285714286)
|
||||
base.get_node("OpenDirButton").size = Vector2(new_resolution.x/4.403669724770642, new_resolution.y/14.21052631578947)
|
||||
base.get_node("OpenDirButton").position = Vector2(base.size.x/16, base.get_node("OpenArchiveButton").position.y+base.get_node("OpenArchiveButton").size.y+base.size.y/108)
|
||||
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("EditorButton").position = Vector2(base.size.x-base.get_node("OpenArchiveButton").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)
|
||||
|
||||
|
@ -60,7 +84,7 @@ func get_stylebox_blur(resolution_: Vector2i) -> StyleBoxFlat:
|
|||
stylebox.corner_radius_bottom_right = resolution_.x/30
|
||||
return stylebox
|
||||
|
||||
func open_presentation_picker() -> void:
|
||||
func open_presentation_archive_picker() -> void:
|
||||
logger.info("Opening presentation")
|
||||
var fd: FileDialog = FileDialog.new()
|
||||
fd.access = FileDialog.ACCESS_FILESYSTEM
|
||||
|
@ -70,12 +94,28 @@ func open_presentation_picker() -> void:
|
|||
fd.add_filter("*.zip", "")
|
||||
fd.mode_overrides_title = false
|
||||
fd.show_hidden_files = true
|
||||
fd.title = "Open a Presencode presentation file"
|
||||
fd.title = "Open a Presencode presentation archive"
|
||||
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))
|
||||
fd.connect("file_selected", func(path: String) -> void: open_presentation(path))
|
||||
add_child(fd)
|
||||
|
||||
func open_presentation_dir_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_DIR
|
||||
fd.mode_overrides_title = false
|
||||
fd.show_hidden_files = true
|
||||
fd.title = "Open a Presencode presentation directory"
|
||||
fd.use_native_dialog = true
|
||||
fd.cancel_button_text = "Cancel"
|
||||
fd.ok_button_text = "Present"
|
||||
fd.visible = true
|
||||
fd.connect("dir_selected", func(path: String) -> void: open_presentation(path))
|
||||
add_child(fd)
|
||||
|
||||
func open_presentation(path: String) -> void:
|
||||
|
@ -91,12 +131,11 @@ func open_presentation(path: String) -> void:
|
|||
preader.read_manifest()
|
||||
preader.read_entrypoint()
|
||||
# Update window properties
|
||||
get_node("/root/Console").calculate_drag_area(preader.get_ratio_resolution())
|
||||
processor.update_dragging_area(processor.DragNode.CONSOLE, 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
|
||||
|
@ -109,12 +148,17 @@ func open_presentation(path: String) -> void:
|
|||
ui_engine.uninitialize()
|
||||
|
||||
func update_splash() -> void:
|
||||
logger.diag("Updating splash text")
|
||||
get_node("Wallpaper/Welcome/Splash").text = "[center]" + [
|
||||
var splash: String = ""
|
||||
var splash_ok: bool = false
|
||||
while !splash_ok:
|
||||
splash = [
|
||||
"The first native code-based presentation viewer.", # Tagline
|
||||
"Presenting your presentations since 2023!", # Inspired by LulzSec's "Laughing at your security since 2011!"
|
||||
"Made using Godot", # FACT
|
||||
"nice", # nice :)
|
||||
"100% open source", # FACT
|
||||
"'s icons were made with figlet", # FACT
|
||||
"This text was inspired by Minecraft", # It is!
|
||||
"nice", # nice
|
||||
"[b]your mom[/b]", # idk why i put this in
|
||||
"Also try LibreOffice!", # Inspired by Minecraft's "Also play Terraria" and Terraria's "Also play Minecraft"
|
||||
"... exists.", # We finished the sentence.
|
||||
|
@ -129,11 +173,13 @@ func update_splash() -> void:
|
|||
"Extra spicy!", # Where did I leave my chilli?
|
||||
"--- Debugging process stopped ---", # Godot message after stopping a debug build
|
||||
"/effect @s 16 99999 255 true", # Infinite (or rather, veeeery long) night vision command for Minecraft 1.12.2
|
||||
"This text was inspired by Minecraft", # It is!
|
||||
"In this update we made the app much better for you.", # Parody of mobile game/application developers simply putting "We made the app better for you" into their changelog without mentioning any of the changes they've made.
|
||||
"NVIDIA fuck you", # Reference to Linus Torvalds
|
||||
"100% open source", # FACT
|
||||
"is made by idiots.", # if you're working on Presencode or using it you're probably not the smartest person on earth
|
||||
"'s icons were made with figlet", # FACT
|
||||
"https://billgates.sex is real" # Reference to MattKC
|
||||
].pick_random() + "[/center]"
|
||||
"https://billgates.sex is real", # Reference to MattKC
|
||||
"happy :)", # happy :)
|
||||
"E" # E
|
||||
].pick_random()
|
||||
if splash == get_node("Wallpaper/Welcome/Splash").text.replace("[center]", "").replace("[/center]", ""): logger.warn("Got same splash text, picking another one")
|
||||
else: splash_ok = true
|
||||
get_node("Wallpaper/Welcome/Splash").text = "[center]" + splash + "[/center]"
|
||||
|
|
|
@ -15,16 +15,22 @@ var initialized: bool = false
|
|||
var ui_mode: UIMode = UIMode.UNKNOWN
|
||||
var resolution: String = "960x540"
|
||||
|
||||
# Initialize engine
|
||||
func initialize(loader_: Control) -> void:
|
||||
if initialized:
|
||||
logger.error("The UI Engine been initialized already")
|
||||
return
|
||||
logger.info("Initializing UI Engine")
|
||||
# Set variables
|
||||
loader = loader_
|
||||
initialized = true
|
||||
# Switch mode
|
||||
logger.diag("Switching to welcome mode")
|
||||
switch_mode(UIMode.WELCOME)
|
||||
# Update resolution to next best
|
||||
logger.diag("Updating resolution to next best resolution")
|
||||
update_resolution(misc.get_best_resolution())
|
||||
# Update window properties
|
||||
logger.diag("Updating window properties")
|
||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
|
||||
DisplayServer.window_set_min_size(Vector2i(960, 540))
|
||||
|
@ -32,50 +38,54 @@ func initialize(loader_: Control) -> void:
|
|||
get_tree().root.content_scale_aspect = Window.CONTENT_SCALE_ASPECT_KEEP
|
||||
get_tree().root.content_scale_factor = 1.0
|
||||
|
||||
# Uninitialize engine
|
||||
func uninitialize() -> void:
|
||||
if !initialized:
|
||||
logger.error("The UI Engine is not initialized.")
|
||||
return
|
||||
logger.info("Uninitializing UI Engine")
|
||||
# Reset variables
|
||||
loader = null
|
||||
initialized = false
|
||||
resolution = "960x540"
|
||||
ui_mode = UIMode.UNKNOWN
|
||||
logger.info("Unloading UI mode")
|
||||
# Unload current 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))
|
||||
|
||||
# Switch UI mode
|
||||
func switch_mode(mode: UIMode) -> void:
|
||||
if !initialized:
|
||||
logger.error("The UI Engine hasn't been initialized yet")
|
||||
return
|
||||
if mode == UIMode.UNKNOWN: return
|
||||
if mode == UIMode.UNKNOWN: await logger.error("Invalid UI mode \"" + str(mode) + "\"")
|
||||
logger.info("Switching to mode " + str(mode))
|
||||
# Remove current UI mode node
|
||||
if ui_mode_node != null: loader.remove_child(ui_mode_node)
|
||||
# Load UI node into ui_mode_node and set ui_mode
|
||||
match(mode):
|
||||
UIMode.WELCOME:
|
||||
ui_mode_node = ResourceLoader.load("res://ui/Welcome.tscn").instantiate()
|
||||
ui_mode = UIMode.WELCOME
|
||||
# Add UI mode node to Loader
|
||||
loader.add_child(ui_mode_node)
|
||||
# UI mode node's switch_mode() takes over
|
||||
ui_mode_node.switch_mode()
|
||||
|
||||
# Updates the resolution
|
||||
func update_resolution(new_resolution: Vector2i) -> void:
|
||||
if !initialized:
|
||||
logger.error("The UI Engine hasn't been initialized yet")
|
||||
return
|
||||
# Update window properties
|
||||
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)
|
||||
# Calculate new console drag area
|
||||
processor.update_dragging_area(processor.DragNode.CONSOLE)
|
||||
# Update resolution variable
|
||||
resolution = str(new_resolution.x) + "x" + str(new_resolution.y)
|
||||
# Call current UI mode's update_resolution() function
|
||||
match(ui_mode):
|
||||
UIMode.UNKNOWN: return
|
||||
UIMode.WELCOME: ui_mode_node.update_resolution(new_resolution)
|
||||
|
|
|
@ -94,7 +94,7 @@ 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"]]
|
||||
[node name="OpenArchiveButton" type="Button" parent="Wallpaper/Welcome" groups=["font_one", "font_one_normal"]]
|
||||
layout_mode = 1
|
||||
anchors_preset = 4
|
||||
anchor_top = 0.5
|
||||
|
@ -104,7 +104,19 @@ offset_top = -19.0
|
|||
offset_right = 278.0
|
||||
offset_bottom = 19.0
|
||||
grow_vertical = 2
|
||||
text = "Open presentation"
|
||||
text = "Open archive"
|
||||
|
||||
[node name="OpenDirButton" 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 = 24.0
|
||||
offset_right = 278.0
|
||||
offset_bottom = 62.0
|
||||
grow_vertical = 2
|
||||
text = "Open directory"
|
||||
|
||||
[node name="EditorButton" type="Button" parent="Wallpaper/Welcome" groups=["font_one", "font_one_normal"]]
|
||||
layout_mode = 1
|
||||
|
@ -122,4 +134,5 @@ 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"]
|
||||
[connection signal="pressed" from="Wallpaper/Welcome/OpenArchiveButton" to="." method="open_presentation_archive_picker"]
|
||||
[connection signal="pressed" from="Wallpaper/Welcome/OpenDirButton" to="." method="open_presentation_dir_picker"]
|
||||
|
|
Loading…
Reference in a new issue