2024-01-14 05:58:43 +01:00
##############################################################################
### 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/misc.gd (Miscellaneous) ###
### ###
### This source file contains various small functions that do not fit into ###
### other source files. Shutting Presencode down, getting the center of an ###
### object or checking the manifest consistency are examples of this. ###
##############################################################################
extends Node
# Enums
enum Error {
OK ,
PREADER_NO_PRESENTATION_OPEN ,
PREADER_NO_MANIFEST ,
PREADER_MANIFEST_PARSING_FAILED ,
MANIFEST_INCONSISTENT ,
MANIFEST_INVALID_VERSION ,
MANIFEST_INVALID_PROGRAM ,
MANIFEST_INVALID_RATIO
}
# Manifest specification
const manifest_version : int = 1
const manifest_program : String = " Presencode "
# Configuration
## 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
# 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 " ] }
# Shutdown Presencode safely
func shutdown ( exitcode : int = 0 ) - > void :
2024-01-14 21:52:38 +01:00
logger . info ( " Shutting down (code " + str ( exitcode ) + " ) " )
2024-01-14 05:58:43 +01:00
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 as Godot executes code further even while it's exiting
await get_tree ( ) . create_timer ( 999 , true ) . timeout
# Calculate the center of a child inside its parent (Vector2i)
func get_center ( parent_size : Vector2i , child_size : Vector2i ) - > Vector2i :
@ warning_ignore ( " integer_division " )
return Vector2i ( parent_size . x / 2 - child_size . x / 2 , parent_size . y / 2 - child_size . y / 2 )
# Calculate the center of a child inside its parent (Vector2)
func get_center_float ( parent_size : Vector2 , child_size : Vector2 ) - > Vector2 :
return Vector2 ( parent_size . x / 2 - child_size . x / 2 , parent_size . y / 2 - child_size . y / 2 )
# 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 " "
# Check platform support
func check_platform ( ) - > void :
match ( OS . get_name ( ) ) :
" Linux " : pass
" Windows " : pass
_ : # Platform not supported
logger . error ( " The \" " + OS . get_name ( ) + " \" operating system is not supported by Presencode. You can add support for that platform to Presencode yourself, if you want. " )
# Check for manifest consistency
func check_manifest_consistency ( manifest : Dictionary ) - > misc . Error :
logger . diag ( " Checking manifest for consistency " )
# version
match ( manifest . get ( " version " ) ) :
null : return misc . Error . MANIFEST_INCONSISTENT
float ( 1 ) : pass
_ : return misc . Error . MANIFEST_INVALID_VERSION
logger . diag ( " Manifest passed \" version \" consistency check " )
# program
match ( manifest . get ( " program " ) ) :
null : return misc . Error . MANIFEST_INCONSISTENT
manifest_program : pass
_ : return misc . Error . MANIFEST_INVALID_PROGRAM
logger . diag ( " Manifest passed \" program \" consistency check " )
# topic
if manifest . get ( " topic " ) == null :
return misc . Error . MANIFEST_INCONSISTENT
elif typeof ( manifest . get ( " topic " ) ) != TYPE_STRING :
return misc . Error . MANIFEST_INCONSISTENT
logger . diag ( " Manifest passed \" topic \" consistency check " )
# authors
if manifest . get ( " authors " ) == null :
return misc . Error . MANIFEST_INCONSISTENT
elif typeof ( manifest . get ( " authors " ) ) != TYPE_ARRAY :
return misc . Error . MANIFEST_INCONSISTENT
for author in manifest . get ( " authors " ) :
if typeof ( author ) != TYPE_STRING :
return misc . Error . MANIFEST_INCONSISTENT
logger . diag ( " Manifest passed \" authors \" consistency check " )
# ratio
match ( manifest . get ( " ratio " ) ) :
null : return misc . Error . MANIFEST_INCONSISTENT
" 16:9 " : pass
" 4:3 " : pass
_ : return misc . Error . MANIFEST_INVALID_RATIO
logger . diag ( " Manifest passed \" ratio \" consistency check " )
# entrypoint
if manifest . get ( " entrypoint " ) == null :
return misc . Error . MANIFEST_INCONSISTENT
elif typeof ( manifest . get ( " entrypoint " ) ) != TYPE_STRING :
return misc . Error . MANIFEST_INCONSISTENT
elif ! manifest . get ( " entrypoint " ) . ends_with ( " .gd " ) :
return misc . Error . MANIFEST_INCONSISTENT
logger . diag ( " Manifest passed \" entrypoint \" consistency check " )
logger . diag ( " Manifest follows the Presencode Manifest Specification " )
return misc . Error . OK