Update source code
- [Console.tscn, src/console.gd, src/console_info.gd, src/console_expressionscript.gd] Add (mostly uncommented) debugging console - [example/test.gd] Optimize example presentation controller - [src/loader.gd, src/pmana.gd] Move click overlay into Loader - [src/pmana.gd] Add check against invalid controller scripts - [src/pmana.gd] Create seperate pmana.shutdown() function to handle shutdowns during presentations - [src/preader.gd] Add checks against empty manifest variable - [src/preader.gd] Fix bug in get_authors() - Change/optimize various other smaller things
This commit is contained in:
parent
6f9bea644c
commit
e158173104
13 changed files with 866 additions and 15 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
# Godot 4+ specific ignores
|
||||
.godot/
|
||||
bin/
|
||||
|
|
97
Console.tscn
Normal file
97
Console.tscn
Normal file
|
@ -0,0 +1,97 @@
|
|||
[gd_scene load_steps=10 format=3 uid="uid://btyi16dkvbly1"]
|
||||
|
||||
[ext_resource type="Script" path="res://src/console.gd" id="1_viv5y"]
|
||||
[ext_resource type="FontFile" uid="uid://bl4vgye7bg8kf" path="res://docs/static/assets/fonts/FiraCode-Regular.ttf" id="2_ebuk0"]
|
||||
[ext_resource type="FontFile" uid="uid://b5qsng8gpvos3" path="res://docs/static/assets/fonts/FiraCode-Bold.ttf" id="3_102to"]
|
||||
[ext_resource type="FontFile" uid="uid://c5jkbqx10tj8e" path="res://docs/static/assets/fonts/FiraCode-Medium.ttf" id="4_jqfsc"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_u40jo"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_wj4aw"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ime8b"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_hjtld"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_xa0gg"]
|
||||
|
||||
[node name="Console" type="ColorRect"]
|
||||
offset_right = 767.0
|
||||
offset_bottom = 426.0
|
||||
script = ExtResource("1_viv5y")
|
||||
|
||||
[node name="Bar" type="ColorRect" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 2.5
|
||||
offset_top = 2.5
|
||||
offset_right = 764.5
|
||||
offset_bottom = 27.5
|
||||
color = Color(0.839216, 0.0196078, 0.196078, 1)
|
||||
|
||||
[node name="X1" type="Line2D" parent="Bar"]
|
||||
points = PackedVector2Array(760, 2, 739, 23)
|
||||
width = 2.0
|
||||
|
||||
[node name="X2" type="Line2D" parent="Bar"]
|
||||
points = PackedVector2Array(760, 23, 739, 2)
|
||||
width = 2.0
|
||||
|
||||
[node name="CloseButton" type="Button" parent="Bar"]
|
||||
layout_mode = 0
|
||||
offset_left = 737.0
|
||||
offset_right = 762.0
|
||||
offset_bottom = 25.0
|
||||
theme_override_styles/normal = SubResource("StyleBoxEmpty_u40jo")
|
||||
theme_override_styles/hover = SubResource("StyleBoxEmpty_wj4aw")
|
||||
theme_override_styles/pressed = SubResource("StyleBoxEmpty_ime8b")
|
||||
theme_override_styles/disabled = SubResource("StyleBoxEmpty_hjtld")
|
||||
theme_override_styles/focus = SubResource("StyleBoxEmpty_xa0gg")
|
||||
|
||||
[node name="DragButton" type="Button" parent="Bar"]
|
||||
layout_mode = 0
|
||||
offset_right = 737.0
|
||||
offset_bottom = 25.0
|
||||
theme_override_styles/normal = SubResource("StyleBoxEmpty_u40jo")
|
||||
theme_override_styles/hover = SubResource("StyleBoxEmpty_wj4aw")
|
||||
theme_override_styles/pressed = SubResource("StyleBoxEmpty_ime8b")
|
||||
theme_override_styles/disabled = SubResource("StyleBoxEmpty_hjtld")
|
||||
theme_override_styles/focus = SubResource("StyleBoxEmpty_xa0gg")
|
||||
|
||||
[node name="Shell" type="ColorRect" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 2.5
|
||||
offset_top = 27.5
|
||||
offset_right = 764.5
|
||||
offset_bottom = 423.5
|
||||
color = Color(0, 0, 0, 1)
|
||||
|
||||
[node name="Output" type="RichTextLabel" parent="Shell"]
|
||||
layout_mode = 0
|
||||
offset_right = 762.0
|
||||
offset_bottom = 361.0
|
||||
theme_override_fonts/normal_font = ExtResource("2_ebuk0")
|
||||
theme_override_fonts/bold_font = ExtResource("3_102to")
|
||||
theme_override_fonts/italics_font = ExtResource("2_ebuk0")
|
||||
theme_override_fonts/bold_italics_font = ExtResource("3_102to")
|
||||
theme_override_fonts/mono_font = ExtResource("2_ebuk0")
|
||||
theme_override_font_sizes/normal_font_size = 18
|
||||
theme_override_font_sizes/bold_font_size = 18
|
||||
theme_override_font_sizes/italics_font_size = 18
|
||||
theme_override_font_sizes/bold_italics_font_size = 18
|
||||
theme_override_font_sizes/mono_font_size = 18
|
||||
bbcode_enabled = true
|
||||
scroll_following = true
|
||||
|
||||
[node name="Input" type="TextEdit" parent="Shell"]
|
||||
layout_mode = 0
|
||||
offset_top = 361.0
|
||||
offset_right = 762.0
|
||||
offset_bottom = 396.0
|
||||
theme_override_colors/background_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_color = Color(1, 1, 1, 1)
|
||||
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="text_changed" from="Shell/Input" to="." method="input_changed"]
|
60
docs/docs/reference/console.md
Normal file
60
docs/docs/reference/console.md
Normal file
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Debugging console
|
||||
Presencode includes a debugging console that you can use to debug your presentation code, Presencode itself... or to have fun destroying Presencode from the inside.
|
||||
|
||||
## Accessing the debug console
|
||||
To make the debug console visible, press the `^` key on your keyboard.
|
||||
To get started, type `help` into the input box.
|
||||
|
||||
## Commands
|
||||
You can use these commands inside the debugging console:
|
||||
<table>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>Description</th>
|
||||
<th>Arguments</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>clear</td>
|
||||
<td>Clears the console output</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>exit</td>
|
||||
<td>Starts a fresh console session</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>shutdown</td>
|
||||
<td>Shuts Presencode down</td>
|
||||
<td>[exitcode: int = 0]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>help</td>
|
||||
<td>Displays information about certain topics</td>
|
||||
<td>[topic: String = "INDEX"]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>config</td>
|
||||
<td>Reads and writes to the in-memory configuration</td>
|
||||
<td>[get <key: String>|set <key: String> <value: Variant>|list]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>pmana</td>
|
||||
<td>Controls the Presentation Manager</td>
|
||||
<td>[register <version: int> <slides: int> <animations: bool> <quit_last_slide: bool> <controller: NodePath<String>>|unregister|change_slide <slide: int> [no_animations: bool = false]|clear_viewport|hide_log|show_log]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>preader</td>
|
||||
<td>Controls the Presentation Reader</td>
|
||||
<td><get <topic|authors|ratio|resolution>></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>arbitrary</td>
|
||||
<td>Execute arbitrary GDScript expressions</td>
|
||||
<td><gdscript expression></td>
|
||||
</tr>
|
||||
</table>
|
|
@ -78,6 +78,7 @@ func presentation_start(viewport_: Control) -> void:
|
|||
## without calling this function.
|
||||
func presentation_end() -> void:
|
||||
logger.diag("presentation_end() called")
|
||||
queue_free()
|
||||
|
||||
# Change the current slide to another one
|
||||
func change_slide(new_slide: int) -> void:
|
||||
|
|
|
@ -70,6 +70,12 @@ content_scale_switch={
|
|||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":71,"physical_keycode":0,"key_label":0,"unicode":103,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
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)
|
||||
]
|
||||
}
|
||||
|
||||
[rendering]
|
||||
|
||||
|
|
|
@ -46,7 +46,5 @@ func clicked() -> void:
|
|||
pmana.change_slide(pmana.current_slide+1, true)
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
# Move button to top
|
||||
get_tree().root.move_child(self, get_tree().root.get_child_count(true))
|
||||
# Scale clickoverlay to window size
|
||||
size = DisplayServer.window_get_size()
|
||||
|
|
457
src/console.gd
Normal file
457
src/console.gd
Normal file
|
@ -0,0 +1,457 @@
|
|||
##############################################################################
|
||||
### 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/console.gd (Debug console) ###
|
||||
### ###
|
||||
### This source file controls the debug console, which can be enabled by ###
|
||||
### pressing the ^ key. ###
|
||||
##############################################################################
|
||||
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")
|
||||
var expressionscript: Node = Node.new()
|
||||
|
||||
# Console information
|
||||
@onready var info: ConsoleInfo = ConsoleInfo.new()
|
||||
|
||||
# States
|
||||
var dragging: bool = false
|
||||
var drag_area: Vector2 = Vector2(0, 0)
|
||||
var cursor_origin: Vector2 = Vector2(0, 0)
|
||||
|
||||
func _ready() -> void:
|
||||
logger.info("Initializing debug console")
|
||||
position = Vector2(30, 30)
|
||||
calculate_drag_area()
|
||||
# Setup window dragging
|
||||
$Bar/DragButton.connect("button_down", func():
|
||||
dragging = true
|
||||
cursor_origin = get_tree().root.get_viewport().get_mouse_position()
|
||||
)
|
||||
$Bar/DragButton.connect("button_up", func():
|
||||
dragging = false
|
||||
cursor_origin = Vector2(0,0)
|
||||
)
|
||||
expressionscript.name = "ExpressionScript"
|
||||
expressionscript.set_script(ResourceLoader.load("res://src/console_expressionscript.gd"))
|
||||
expressionscript.logger = get_node("/root/logger")
|
||||
expressionscript.misc = get_node("/root/misc")
|
||||
expressionscript.preader = get_node("/root/preader")
|
||||
expressionscript.pmana = get_node("/root/pmana")
|
||||
expressionscript.console = self
|
||||
expressionscript.loader = get_node("/root/Presencode")
|
||||
add_child(expressionscript)
|
||||
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"):
|
||||
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
|
||||
# Prevent console from going out of scope
|
||||
var position_new: Vector2 = check_violation()
|
||||
if position != position_new:
|
||||
position = position_new
|
||||
# Set new cursor_origin
|
||||
cursor_origin = cursor_position
|
||||
|
||||
# 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:
|
||||
if input.text.contains("\n"):
|
||||
input.text = input.text.replace("\n", "")
|
||||
var input2: String = input.text
|
||||
input.text = ""
|
||||
input.editable = false
|
||||
await process_command(input2.split(" ", false))
|
||||
input.editable = true
|
||||
|
||||
# Process commands
|
||||
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
|
||||
match(command[0]):
|
||||
"clear":
|
||||
match(command.size()):
|
||||
_: append_output(info.get_error_string(info.ConsoleError.TOO_MANY_ARGUMENTS))
|
||||
output.text = ""
|
||||
"exit":
|
||||
match(command.size()):
|
||||
_: append_output(info.get_error_string(info.ConsoleError.TOO_MANY_ARGUMENTS))
|
||||
await process_command(PackedStringArray(["clear"]))
|
||||
append_output("""[color=#d60532]Welcome to the Presencode debug console!
|
||||
|
||||
To get started, enter \"help\". To close the console, press the X button.[color=white]""")
|
||||
"shutdown":
|
||||
append_output("Shutting down...")
|
||||
var exitcode: int = 0
|
||||
match(command.size()):
|
||||
1: exitcode = 0
|
||||
2: exitcode = int(command[1])
|
||||
_: append_output(info.get_error_string(info.ConsoleError.TOO_MANY_ARGUMENTS))
|
||||
pmana.shutdown(exitcode)
|
||||
"help":
|
||||
match(command.size()):
|
||||
1: append_output(info.get_help_topic(info.HelpTopic.INDEX))
|
||||
2:
|
||||
match(command[1]):
|
||||
"index": append_output(info.get_help_topic(info.HelpTopic.INDEX))
|
||||
"clear": append_output(info.get_help_topic(info.HelpTopic.CLEAR))
|
||||
"exit": append_output(info.get_help_topic(info.HelpTopic.EXIT))
|
||||
"shutdown": append_output(info.get_help_topic(info.HelpTopic.SHUTDOWN))
|
||||
"help": append_output(info.get_help_topic(info.HelpTopic.HELP))
|
||||
"config": append_output(info.get_help_topic(info.HelpTopic.CONFIG))
|
||||
"pmana": append_output(info.get_help_topic(info.HelpTopic.PMANA))
|
||||
"preader": append_output(info.get_help_topic(info.HelpTopic.PREADER))
|
||||
"arbitrary": append_output(info.get_help_topic(info.HelpTopic.ARBITRARY))
|
||||
_: append_output(info.get_error_string(info.ConsoleError.INVALID_HELP_TOPIC))
|
||||
_: append_output(info.get_error_string(info.ConsoleError.TOO_MANY_ARGUMENTS))
|
||||
"config":
|
||||
match(command.size()):
|
||||
1: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
_:
|
||||
match(command[1]):
|
||||
"list":
|
||||
match(command.size()):
|
||||
2:
|
||||
append_output("""These configuration keys can be used:
|
||||
Key | Type | Description
|
||||
LOGGER_ENABLED | bool | Toggles the logger
|
||||
LOGGER_DIAGNOSTIC | bool | Toggles diagnostic log output
|
||||
LOGGER_COLORED | bool | Toggles colored log output
|
||||
LOGGER_HARDFAIL | bool | Toggles hardfailing errors (don't set this to false)
|
||||
LOGGER_LOGSTRING | String | The logging template, variables: runtime, time, file, function, line, color, type, message
|
||||
PMANA_ALLOW_FULLSCREEN | bool | Toggles window mode switching
|
||||
MISC_SHUTDOWN_INVISIBLE | bool | Toggles if the window should be made invisible on shutdown, displays white texture if disabled""")
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_MANY_ARGUMENTS))
|
||||
"set":
|
||||
match(command.size()):
|
||||
2: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
3: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
_:
|
||||
match(command[2]):
|
||||
"LOGGER_ENABLED":
|
||||
match(get_boolean(" ".join(get_last(command, 2)))):
|
||||
BooleanState.TRUE:
|
||||
logger.config_enabled = true
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]true[/b].")
|
||||
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:
|
||||
logger.config_diagnostic = true
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]true[/b]")
|
||||
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:
|
||||
logger.config_colored = true
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]true[/b]")
|
||||
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:
|
||||
logger.config_hardfail = true
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]true[/b]")
|
||||
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)))
|
||||
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:
|
||||
pmana.config_allow_fullscreen = true
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]true[/b]")
|
||||
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:
|
||||
misc.config_shutdown_invisible = true
|
||||
append_output("Set \"" + str(command[2]) + "\" to [b]true[/b]")
|
||||
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"}))
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_CONFIG_KEY, {"key": command[2]}))
|
||||
"get":
|
||||
match(command.size()):
|
||||
2: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
3:
|
||||
match(command[2]):
|
||||
"LOGGER_ENABLED": append_output("[b]" + command[2] + "[/b] is set to [b]" + str(logger.config_enabled) + "[/b]")
|
||||
"LOGGER_DIAGNOSTIC": append_output("[b]" + command[2] + "[/b] is set to [b]" + str(logger.config_diagnostic) + "[/b]")
|
||||
"LOGGER_COLORED": append_output("[b]" + command[2] + "[/b] is set to [b]" + str(logger.config_colored) + "[/b]")
|
||||
"LOGGER_HARDFAIL": append_output("[b]" + command[2] + "[/b] is set to [b]" + str(logger.config_hardfail) + "[/b]")
|
||||
"LOGGER_LOGSTRING": append_output("\"" + command[2] + "[/b] is set to [b]\"" + logger.config_logstring + "\"[/b]")
|
||||
"PMANA_ALLOW_FULLSCREEN": append_output("[b]" + command[2] + "[/b] is set to [b]" + str(pmana.config_allow_fullscreen) + "[/b]")
|
||||
"MISC_SHUTDOWN_INVISIBLE": append_output("[b]" + command[2] + "[/b] is set to [b]" + str(misc.config_shutdown_invisible) + "[/b]")
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_CONFIG_KEY, {"key": command[2]}))
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_MANY_ARGUMENTS))
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_ARGUMENT))
|
||||
"pmana":
|
||||
match(command.size()):
|
||||
1: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
_:
|
||||
match(command[1]):
|
||||
"register":
|
||||
match(command.size()):
|
||||
1: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
2: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
3: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
4: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
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 animations_bool: bool = false
|
||||
var quit_last_slide: BooleanState = get_boolean(command[5])
|
||||
var quit_last_slide_bool: bool = false
|
||||
var controller: NodePath = NodePath(command[6])
|
||||
if version.x != 0:
|
||||
append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "int"}))
|
||||
return
|
||||
if slides.x != 0:
|
||||
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
|
||||
_:
|
||||
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
|
||||
_:
|
||||
append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_TYPE, {"expected_type": "bool"}))
|
||||
return
|
||||
if get_node(controller) == null or typeof(get_node(controller)) != TYPE_OBJECT:
|
||||
append_output(info.get_error_string(ConsoleInfo.ConsoleError.NOT_AN_OBJECT))
|
||||
return
|
||||
if get_node(controller).get_script() == null:
|
||||
append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_SCRIPT_ATTACHED))
|
||||
return
|
||||
@warning_ignore("narrowing_conversion")
|
||||
pmana.register(version.y, slides.y, animations_bool, quit_last_slide_bool, controller)
|
||||
append_output("A new presentation controller has been registered. Look into the Presencode log output if nothing happens.")
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_MANY_ARGUMENTS))
|
||||
"unregister":
|
||||
if !pmana.registered: append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_CONTROLLER_REGISTERED))
|
||||
else:
|
||||
await pmana.unregister()
|
||||
append_output("The current presentation controller has been unregistered.")
|
||||
"change_slide":
|
||||
match(command.size()):
|
||||
3:
|
||||
if !pmana.registered: append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_CONTROLLER_REGISTERED))
|
||||
else:
|
||||
var slide: Vector2i = 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"))
|
||||
4:
|
||||
if !pmana.registered: append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_CONTROLLER_REGISTERED))
|
||||
else:
|
||||
var slide: Vector2i = get_int_direct(command[2])
|
||||
match(slide.x):
|
||||
0:
|
||||
var no_animations: BooleanState = get_boolean(command[3])
|
||||
match(no_animations):
|
||||
BooleanState.TRUE:
|
||||
pmana.change_slide(slide.y, true)
|
||||
append_output("Switched to slide [b]" + str(slide.y) + "[/b] without animations")
|
||||
BooleanState.FALSE:
|
||||
pmana.change_slide(slide.y, false)
|
||||
append_output("Switched to slide [b]" + str(slide.y) + "[/b]")
|
||||
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.get_error_string(ConsoleInfo.ConsoleError.TOO_MANY_ARGUMENTS))
|
||||
"clear_viewport":
|
||||
if !pmana.registered: append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_CONTROLLER_REGISTERED))
|
||||
else:
|
||||
pmana.clear_viewport()
|
||||
append_output("The viewport has been cleared.")
|
||||
"hide_log":
|
||||
if !pmana.registered: append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_CONTROLLER_REGISTERED))
|
||||
else:
|
||||
pmana.hide_log()
|
||||
append_output("The log output is now [b]invisible[/b].")
|
||||
"show_log":
|
||||
if !pmana.registered: append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_CONTROLLER_REGISTERED))
|
||||
else:
|
||||
pmana.show_log()
|
||||
append_output("The log output is now [b]visible[/b].")
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_ARGUMENT))
|
||||
"preader":
|
||||
match(command.size()):
|
||||
1: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
_:
|
||||
match(command[1]):
|
||||
"get":
|
||||
match(command.size()):
|
||||
2: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_FEW_ARGUMENTS))
|
||||
3:
|
||||
match(command[2]):
|
||||
"topic":
|
||||
if preader.get_topic() == "": append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_PRESENTATION_OPEN))
|
||||
else: append_output("The presentation topic is [b]" + preader.get_topic() + "[/b]")
|
||||
"authors":
|
||||
if preader.get_authors() == "": append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_PRESENTATION_OPEN))
|
||||
else: append_output("The presentation author is/authors are: [b]" + preader.get_authors() + "[/b]")
|
||||
"ratio":
|
||||
if preader.get_ratio() == "": append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_PRESENTATION_OPEN))
|
||||
else: append_output("The presentation ratio is [b]" + preader.get_ratio() + "[/b]")
|
||||
"resolution":
|
||||
if preader.get_ratio_resolution() == Vector2i(0, 0): append_output(info.get_error_string(ConsoleInfo.ConsoleError.NO_PRESENTATION_OPEN))
|
||||
else:
|
||||
var resolution: Vector2i = preader.get_ratio_resolution()
|
||||
append_output("The presentation resolution is [b]" + str(resolution.x) + "x" + str(resolution.y) + "[/b].")
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_ARGUMENT))
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.TOO_MANY_ARGUMENTS))
|
||||
_: append_output(info.get_error_string(ConsoleInfo.ConsoleError.INVALID_ARGUMENT))
|
||||
"arbitrary":
|
||||
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: 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()}))
|
||||
else:
|
||||
var returned = expression.execute([], expressionscript)
|
||||
if expression.has_execute_failed():
|
||||
append_output(info.get_error_string(ConsoleInfo.ConsoleError.EXPRESSION_EXECUTION_FAILED, {"error": expression.get_error_text(), "returned": returned}))
|
||||
else:
|
||||
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
|
33
src/console_expressionscript.gd
Normal file
33
src/console_expressionscript.gd
Normal file
|
@ -0,0 +1,33 @@
|
|||
##############################################################################
|
||||
### 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/console_expressionscript.gd (Debug console expression playground) ###
|
||||
### ###
|
||||
### This file will be used as a script for executing arbitrary expressions ###
|
||||
### by the debugging console. ###
|
||||
##############################################################################
|
||||
extends Node
|
||||
|
||||
# @GlobalScope
|
||||
var logger: Node = null
|
||||
var misc: Node = null
|
||||
var preader: Node = null
|
||||
var pmana: Node = null
|
||||
# SceneTree
|
||||
var console: Node = null
|
||||
var loader: Node = null
|
156
src/console_info.gd
Normal file
156
src/console_info.gd
Normal file
|
@ -0,0 +1,156 @@
|
|||
##############################################################################
|
||||
### 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/console_info.gd (Debug console information) ###
|
||||
### ###
|
||||
### This source file holds console information such as help topics or ###
|
||||
### console errors. ###
|
||||
##############################################################################
|
||||
extends Node
|
||||
class_name ConsoleInfo
|
||||
|
||||
enum ConsoleError {
|
||||
OK,
|
||||
UNIMPLEMENTED,
|
||||
INVALID_COMMAND,
|
||||
TOO_MANY_ARGUMENTS,
|
||||
TOO_FEW_ARGUMENTS,
|
||||
INVALID_ARGUMENT,
|
||||
INVALID_TYPE,
|
||||
NOT_AN_OBJECT,
|
||||
NO_SCRIPT_ATTACHED,
|
||||
INVALID_HELP_TOPIC,
|
||||
INVALID_CONFIG_KEY,
|
||||
NO_PRESENTATION_OPEN,
|
||||
CONTROLLER_ALREADY_REGISTERED,
|
||||
NO_CONTROLLER_REGISTERED,
|
||||
EXPRESSION_PARSING_FAILED,
|
||||
EXPRESSION_EXECUTION_FAILED
|
||||
}
|
||||
enum HelpTopic {
|
||||
INDEX,
|
||||
CLEAR,
|
||||
EXIT,
|
||||
SHUTDOWN,
|
||||
HELP,
|
||||
CONFIG,
|
||||
PMANA,
|
||||
PREADER,
|
||||
ARBITRARY
|
||||
}
|
||||
|
||||
var error_color: String = "[color=red]"
|
||||
var internal_error_color: String = "[b][color=red]"
|
||||
|
||||
func _init() -> void:
|
||||
logger.diag("ConsoleInfo initialized")
|
||||
|
||||
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"]) + "]"
|
||||
|
||||
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))
|
||||
|
||||
func get_help_topic(topic: HelpTopic) -> String:
|
||||
match(topic):
|
||||
HelpTopic.INDEX:
|
||||
return """Command | Description
|
||||
clear | Clears the console output
|
||||
exit | Starts a fresh session
|
||||
shutdown | Shuts Presencode down
|
||||
help | Displays information about certain topics
|
||||
config | Reads and writes to the in-memory configuration
|
||||
pmana | Controls the Presentation Manager
|
||||
preader | Controls the Presentation Reader
|
||||
arbitrary | Execute arbitrary GDScript expressions
|
||||
|
||||
To view more information about one topic, type \"help [topic]\"."""
|
||||
HelpTopic.CLEAR:
|
||||
return """clear
|
||||
|
||||
Clears the console output."""
|
||||
HelpTopic.EXIT:
|
||||
return """exit
|
||||
|
||||
Clears the console output and starts a fresh session."""
|
||||
HelpTopic.SHUTDOWN:
|
||||
return """shutdown [exitcode: int = 0]
|
||||
|
||||
Shuts Presencode down, accepts a exitcode ranging from 0-255."""
|
||||
HelpTopic.HELP:
|
||||
return """help [topic: String = "INDEX"]
|
||||
|
||||
Displays useful information about commands."""
|
||||
HelpTopic.CONFIG:
|
||||
return """config [get <key: String>|set <key: String> <value: Variant>|list]
|
||||
|
||||
Returns, lists or overwrites Presencode's configuration. Lives in memory and cannot be saved to persistent storage."""
|
||||
HelpTopic.PMANA:
|
||||
return """pmana [register <version: int> <slides: int> <animations: bool> <quit_last_slide: bool> <controller: NodePath<String>>|unregister|change_slide <slide: int> [no_animations: bool = false]|clear_viewport|hide_log|show_log]
|
||||
|
||||
Calls functions belonging to the Presentation Manager."""
|
||||
HelpTopic.PREADER:
|
||||
return """preader <get <topic|authors|ratio|resolution>>
|
||||
|
||||
Calls functions belonging to the Presentation Reader"""
|
||||
HelpTopic.ARBITRARY:
|
||||
return """arbitrary <expression>
|
||||
|
||||
Executes arbitrary GDScript expressions.
|
||||
-> EXPERIMENTAL"""
|
||||
_:
|
||||
return generate_internal_error("Invalid HelpTopic \"" + str(topic) + "\"")
|
|
@ -124,6 +124,9 @@ ONLY VIEW PRESENCODE PRESENTATIONS IF YOU TRUST THE
|
|||
###################################################
|
||||
""")
|
||||
await get_tree().create_timer(5).timeout
|
||||
logger.info("Injecting console")
|
||||
var console: Control = 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
|
||||
# Open presentation archive/directory
|
||||
var path: String = "".join(OS.get_cmdline_user_args())
|
||||
|
@ -142,6 +145,7 @@ ONLY VIEW PRESENCODE PRESENTATIONS IF YOU TRUST THE
|
|||
preader.read_manifest()
|
||||
preader.read_entrypoint()
|
||||
# Update window properties
|
||||
console.calculate_drag_area(preader.get_ratio_resolution())
|
||||
DisplayServer.window_set_title("Presencode » Presenting \"" + preader.get_topic() + "\" by \"" + preader.get_authors() + "\"")
|
||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
|
||||
DisplayServer.window_set_size(preader.get_ratio_resolution())
|
||||
|
|
|
@ -53,7 +53,7 @@ func get_origin(n: int = 0) -> Dictionary:
|
|||
|
||||
# Shutdown Presencode safely
|
||||
func shutdown(exitcode: int = 0) -> void:
|
||||
logger.info("Shutting down")
|
||||
logger.info("Shutting down (code " + str(exitcode) + ")")
|
||||
get_tree().paused = true
|
||||
# Display white texture
|
||||
var npr: NinePatchRect = NinePatchRect.new()
|
||||
|
|
29
src/pmana.gd
29
src/pmana.gd
|
@ -51,6 +51,9 @@ func register(version: int, slides_: int, animations_: bool, quit_last_slide_: b
|
|||
# Check entrypoint version
|
||||
if version != entrypoint_version:
|
||||
await logger.error("Presentation entrypoint version does not match Presencode's entrypoint version")
|
||||
# Check controller nodepath
|
||||
if get_node(controller_) == null:
|
||||
await logger.error("The presentation controller could not be located.")
|
||||
# Set controller information
|
||||
slides = slides_
|
||||
animations = animations_
|
||||
|
@ -75,17 +78,18 @@ func register(version: int, slides_: int, animations_: bool, quit_last_slide_: b
|
|||
for function in lacking_functions:
|
||||
logger.warn("- " + function)
|
||||
logger.warn("Consult the documentation or take a look at the example presentation if you need help.")
|
||||
# Create clickoverlay
|
||||
clickoverlay = Button.new()
|
||||
clickoverlay.name = "ClickOverlay"
|
||||
clickoverlay.set_script(ResourceLoader.load("res://src/clickoverlay.gd"))
|
||||
get_tree().root.add_child(clickoverlay)
|
||||
await misc.shutdown(1)
|
||||
# Create 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
|
||||
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()
|
||||
|
@ -103,10 +107,11 @@ func unregister() -> void:
|
|||
animation_active = false
|
||||
config_allow_fullscreen = true
|
||||
# Remove clickoverlay
|
||||
get_tree().root.remove_child(clickoverlay)
|
||||
get_node("/root/Presencode/").remove_child(clickoverlay)
|
||||
clickoverlay = null
|
||||
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:
|
||||
|
@ -126,8 +131,7 @@ func change_slide(slide: int, no_animations: bool = false) -> void:
|
|||
# Quit after last slide?
|
||||
if quit_last_slide:
|
||||
logger.info("Ending presentation")
|
||||
await controller.presentation_end()
|
||||
await misc.shutdown(0)
|
||||
await shutdown()
|
||||
return
|
||||
else:
|
||||
logger.warn("Over max slides by " + str(slide-slides))
|
||||
|
@ -138,8 +142,7 @@ 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 controller.presentation_end()
|
||||
await misc.shutdown(0)
|
||||
await shutdown()
|
||||
return
|
||||
# Slide is not over max slides, continue slide change
|
||||
# Play switch away animation
|
||||
|
@ -186,6 +189,12 @@ func show_log() -> void:
|
|||
return
|
||||
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:
|
||||
# Fullscreen key combo
|
||||
|
|
|
@ -131,6 +131,7 @@ func read_entrypoint() -> misc.Error:
|
|||
# Check if manifest is loaded in memory
|
||||
if manifest == {}:
|
||||
logger.error("Manifest not loaded in memory, please call read_manifest() first")
|
||||
return misc.Error.PREADER_NO_MANIFEST
|
||||
# Create empty script variable
|
||||
var script: Script
|
||||
if directorypath == "":
|
||||
|
@ -169,21 +170,50 @@ func get_entrypoint() -> Node:
|
|||
|
||||
# Return presentation topic
|
||||
func get_topic() -> String:
|
||||
if !is_open:
|
||||
logger.error("No presentation is currently opened")
|
||||
return ""
|
||||
# Check if manifest is loaded in memory
|
||||
if manifest == {}:
|
||||
logger.error("Manifest not loaded in memory, please call read_manifest() first")
|
||||
return ""
|
||||
return manifest["topic"]
|
||||
|
||||
# Return presentation authors
|
||||
func get_authors() -> String:
|
||||
if !is_open:
|
||||
logger.error("No presentation is currently opened")
|
||||
return ""
|
||||
# Check if manifest is loaded in memory
|
||||
if manifest == {}:
|
||||
logger.error("Manifest not loaded in memory, please call read_manifest() first")
|
||||
return ""
|
||||
var authors: String = ""
|
||||
for author in manifest["authors"]:
|
||||
authors = authors + ", " + author
|
||||
if authors == "": authors = author
|
||||
else: authors = authors + ", " + author
|
||||
return authors
|
||||
|
||||
# Return display ratio
|
||||
func get_ratio() -> String:
|
||||
if !is_open:
|
||||
logger.error("No presentation is currently opened")
|
||||
return ""
|
||||
# Check if manifest is loaded in memory
|
||||
if manifest == {}:
|
||||
logger.error("Manifest not loaded in memory, please call read_manifest() first")
|
||||
return ""
|
||||
return manifest["ratio"]
|
||||
|
||||
# Return display resolution from display ratio
|
||||
func get_ratio_resolution() -> Vector2i:
|
||||
if !is_open:
|
||||
logger.error("No presentation is currently opened")
|
||||
return Vector2i(0, 0)
|
||||
# Check if manifest is loaded in memory
|
||||
if manifest == {}:
|
||||
logger.error("Manifest not loaded in memory, please call read_manifest() first")
|
||||
return Vector2i(0, 0)
|
||||
match(manifest["ratio"]):
|
||||
"16:9": return Vector2i(1920, 1080)
|
||||
"4:3": return Vector2i(1920, 1440)
|
||||
|
|
Loading…
Reference in a new issue