├── .export_config ├── custom.py └── godotos.build ├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── Art ├── Folder Icons │ ├── folder.png │ ├── folder.png.import │ ├── game.png │ ├── game.png.import │ ├── image.png │ ├── image.png.import │ ├── text_file.png │ └── text_file.png.import ├── Godot Logo.png ├── Godot Logo.png.import ├── Icons │ ├── Start Menu Button.png │ ├── Start Menu Button.png.import │ ├── cog.png │ ├── cog.png.import │ ├── corner-handle.png │ ├── corner-handle.png.import │ ├── expand.png │ ├── expand.png.import │ ├── power-button.png │ ├── power-button.png.import │ ├── shrink.png │ └── shrink.png.import ├── Pixel_32.png └── Pixel_32.png.import ├── CONTRIBUTING.md ├── Default Files ├── Credits.txt ├── GodotOS Handbook.txt ├── Welcome.txt ├── default wall.webp ├── default wall.webp.import ├── wallpaper_chill.webp ├── wallpaper_chill.webp.import ├── wallpaper_minimalism.webp └── wallpaper_minimalism.webp.import ├── Games ├── Cube Scene │ ├── cube.gd │ ├── cube.gd.uid │ └── cube_scene.tscn ├── Godotris │ ├── Block │ │ ├── Block.tscn │ │ ├── godotris_block.gd │ │ └── godotris_block.gd.uid │ ├── Game │ │ ├── godotris_game.gd │ │ ├── godotris_game.gd.uid │ │ ├── godotris_game.tscn │ │ ├── godotris_input_handler.gd │ │ ├── godotris_input_handler.gd.uid │ │ ├── godotris_piece_spawner.gd │ │ └── godotris_piece_spawner.gd.uid │ ├── Grid │ │ ├── godotris_grid.gd │ │ ├── godotris_grid.gd.uid │ │ └── grid.tscn │ ├── Piece │ │ ├── godotris_piece.gd │ │ ├── godotris_piece.gd.uid │ │ ├── i_piece.tscn │ │ ├── j_piece.tscn │ │ ├── l_piece.tscn │ │ ├── o_piece.tscn │ │ ├── s_piece.tscn │ │ ├── t_piece.tscn │ │ └── z_piece.tscn │ └── PieceHolder │ │ ├── godotris_piece_holder.gd │ │ ├── godotris_piece_holder.gd.uid │ │ ├── piece_holder.tres │ │ └── piece_holder.tscn ├── Pong │ ├── Scenes │ │ ├── pong_main_menu.tscn │ │ ├── pong_multiplayer.tscn │ │ ├── pong_singleplayer.tscn │ │ └── pong_survival.tscn │ └── Scripts │ │ ├── pong_ball.gd │ │ ├── pong_ball.gd.uid │ │ ├── pong_enemy.gd │ │ ├── pong_enemy.gd.uid │ │ ├── pong_enemy_fail_area.gd │ │ ├── pong_enemy_fail_area.gd.uid │ │ ├── pong_main_menu.gd │ │ ├── pong_main_menu.gd.uid │ │ ├── pong_player.gd │ │ ├── pong_player.gd.uid │ │ ├── pong_player_fail_area.gd │ │ ├── pong_player_fail_area.gd.uid │ │ ├── pong_singleplayer_manager.gd │ │ ├── pong_singleplayer_manager.gd.uid │ │ ├── pong_survival_manager.gd │ │ └── pong_survival_manager.gd.uid ├── Snake │ ├── SnakeBestScoreLabel.gd │ ├── SnakeBestScoreLabel.gd.uid │ ├── SnakeBoard.gd │ ├── SnakeBoard.gd.uid │ ├── SnakeGameOver.gd │ ├── SnakeGameOver.gd.uid │ ├── SnakeLabel.gd │ ├── SnakeLabel.gd.uid │ └── snake_scene.tscn └── Super Bit Boy │ ├── Other Scenes │ ├── bit_boy_camera.gd │ ├── bit_boy_camera.gd.uid │ └── bit_boy_camera.tscn │ └── Scenes │ ├── Exit │ ├── bit_boy_exit.gd │ ├── bit_boy_exit.gd.uid │ └── bit_boy_exit.tscn │ ├── Levels │ ├── bit_boy_scene_manager.gd │ ├── bit_boy_scene_manager.gd.uid │ ├── level_1.tscn │ ├── level_2.tscn │ ├── level_3.tscn │ ├── level_4.tscn │ ├── level_5.tscn │ ├── level_6.tscn │ ├── level_7.tscn │ ├── level_8.tscn │ ├── level_9.tscn │ └── test.tscn │ └── Player │ ├── bit_boy_player.gd │ ├── bit_boy_player.gd.uid │ └── bit_boy_player.tscn ├── LICENSE ├── README.md ├── Scenes ├── Autoloads │ ├── Context Menu │ │ ├── context_menu.tscn │ │ ├── context_menu_manager.gd │ │ ├── context_menu_manager.gd.uid │ │ ├── context_menu_option.gd │ │ ├── context_menu_option.gd.uid │ │ ├── context_menu_option.tscn │ │ ├── context_menu_seperator.tscn │ │ ├── right_click_handler.gd │ │ ├── right_click_handler.gd.uid │ │ └── right_click_handler.tscn │ ├── CopyPaste Manager │ │ ├── copy_paste_manager.gd │ │ ├── copy_paste_manager.gd.uid │ │ └── copy_paste_manager.tscn │ ├── Default Values │ │ ├── default_values.gd │ │ ├── default_values.gd.uid │ │ └── default_values.tscn │ ├── GlobalValues │ │ ├── global_values.gd │ │ ├── global_values.gd.uid │ │ └── global_values.tscn │ ├── Hotkey Manager │ │ ├── hotkey_manager.gd │ │ ├── hotkey_manager.gd.uid │ │ └── hotkey_manager.tscn │ └── Notification Manager │ │ ├── notification.gd │ │ ├── notification.gd.uid │ │ ├── notification.tscn │ │ ├── notification_manager.gd │ │ ├── notification_manager.gd.uid │ │ └── notification_manager.tscn ├── Containers │ ├── smooth_container.gd │ └── smooth_container.gd.uid ├── Desktop │ ├── desktop_folder.gd │ ├── desktop_folder.gd.uid │ ├── folder.tscn │ ├── folder_title_edit.gd │ └── folder_title_edit.gd.uid ├── Main │ ├── BaseFileManager.gd │ ├── BaseFileManager.gd.uid │ ├── Boot Splash │ │ ├── boot_splash.gd │ │ ├── boot_splash.gd.uid │ │ └── boot_splash.tscn │ ├── MainScene.tscn │ ├── desktop_file_manager.gd │ ├── desktop_file_manager.gd.uid │ ├── wallpaper.gd │ └── wallpaper.gd.uid ├── Misc │ └── Benchmark Tester │ │ ├── benchmark_test.gd │ │ ├── benchmark_test.gd.uid │ │ └── benchmark_test.tscn ├── Taskbar │ ├── power_button.gd │ ├── power_button.gd.uid │ ├── settings_button.gd │ ├── settings_button.gd.uid │ ├── start_button.gd │ ├── start_button.gd.uid │ ├── start_menu_option.gd │ ├── start_menu_option.gd.uid │ ├── start_menu_option.tscn │ ├── taskbar.tscn │ ├── taskbar_button.gd │ ├── taskbar_button.gd.uid │ ├── taskbar_button.tscn │ ├── taskbar_time.gd │ └── taskbar_time.gd.uid └── Window │ ├── File Manager │ ├── file_manager_window.gd │ ├── file_manager_window.gd.uid │ └── file_manager_window.tscn │ ├── Game Window │ ├── game_pause_manager.gd │ ├── game_pause_manager.gd.uid │ ├── game_window.gd │ ├── game_window.gd.uid │ ├── game_window.tscn │ └── pause_screen.tscn │ ├── Image Viewer │ ├── image_viewer.gd │ ├── image_viewer.gd.uid │ └── image_viewer.tscn │ ├── Settings Window │ ├── background_color_picker.gd │ ├── background_color_picker.gd.uid │ ├── max_fps_options.gd │ ├── max_fps_options.gd.uid │ ├── remove_wallpaper.gd │ ├── remove_wallpaper.gd.uid │ ├── scaling_spinbox.gd │ ├── scaling_spinbox.gd.uid │ ├── settings_window.tscn │ ├── stretch_wallpaper.gd │ ├── stretch_wallpaper.gd.uid │ ├── window_options.gd │ └── window_options.gd.uid │ ├── Text Editor │ ├── saved_notification.tscn │ ├── text_editor.gd │ ├── text_editor.gd.uid │ └── text_editor.tscn │ ├── Window.tscn │ ├── resize_drag_spot.gd │ ├── resize_drag_spot.gd.uid │ ├── window.gd │ └── window.gd.uid ├── export_presets.cfg ├── icon.svg ├── icon.svg.import └── project.godot /.export_config/custom.py: -------------------------------------------------------------------------------- 1 | target="template_release" 2 | debug_symbols="no" 3 | optimize="size" 4 | lto="full" 5 | 6 | deprecated="no" 7 | vulkan="no" 8 | use_volk="no" 9 | openxr="no" 10 | minizip="no" 11 | 12 | modules_enabled_by_default="no" 13 | module_gdscript_enabled="yes" 14 | module_text_server_adv_enabled="yes" 15 | module_freetype_enabled="yes" 16 | module_msdfgen_enabled="yes" 17 | module_godot_physics_2d_enabled="yes" 18 | module_svg_enabled="yes" 19 | module_webp_enabled="yes" 20 | module_jpg_enabled="yes" -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Normalize EOL for all files that Git considers text files. 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | ko_fi: popcar2 4 | buy_me_a_coffee: popcar2 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | -------------------------------------------------------------------------------- /Art/Folder Icons/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Art/Folder Icons/folder.png -------------------------------------------------------------------------------- /Art/Folder Icons/folder.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cjve37ywrq6qo" 6 | path="res://.godot/imported/folder.png-432376f0c260cb685d01907224d6ef61.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Art/Folder Icons/folder.png" 14 | dest_files=["res://.godot/imported/folder.png-432376f0c260cb685d01907224d6ef61.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=true 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Art/Folder Icons/game.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Art/Folder Icons/game.png -------------------------------------------------------------------------------- /Art/Folder Icons/game.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://2sqrvihn1cjq" 6 | path="res://.godot/imported/game.png-00f8b32b4cd933063ab0fcb1cfcdc81f.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Art/Folder Icons/game.png" 14 | dest_files=["res://.godot/imported/game.png-00f8b32b4cd933063ab0fcb1cfcdc81f.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=true 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Art/Folder Icons/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Art/Folder Icons/image.png -------------------------------------------------------------------------------- /Art/Folder Icons/image.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cyinbpw4xinft" 6 | path="res://.godot/imported/image.png-ae8ecb29514d4019c31b8eb6a79ad04a.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Art/Folder Icons/image.png" 14 | dest_files=["res://.godot/imported/image.png-ae8ecb29514d4019c31b8eb6a79ad04a.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=true 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Art/Folder Icons/text_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Art/Folder Icons/text_file.png -------------------------------------------------------------------------------- /Art/Folder Icons/text_file.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dsn8vkallqpml" 6 | path="res://.godot/imported/text_file.png-1de846637aae3e88fc7a48d7bdb11d59.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Art/Folder Icons/text_file.png" 14 | dest_files=["res://.godot/imported/text_file.png-1de846637aae3e88fc7a48d7bdb11d59.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=true 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Art/Godot Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Art/Godot Logo.png -------------------------------------------------------------------------------- /Art/Godot Logo.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://b7m5up7nr6tko" 6 | path="res://.godot/imported/Godot Logo.png-e26d9f46a447af0910135a5ed15f5df7.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Art/Godot Logo.png" 14 | dest_files=["res://.godot/imported/Godot Logo.png-e26d9f46a447af0910135a5ed15f5df7.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Art/Icons/Start Menu Button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Art/Icons/Start Menu Button.png -------------------------------------------------------------------------------- /Art/Icons/Start Menu Button.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dyucn32xje8bj" 6 | path="res://.godot/imported/Start Menu Button.png-8392a29c1b047537b66b69add601c274.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Art/Icons/Start Menu Button.png" 14 | dest_files=["res://.godot/imported/Start Menu Button.png-8392a29c1b047537b66b69add601c274.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=true 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Art/Icons/cog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Art/Icons/cog.png -------------------------------------------------------------------------------- /Art/Icons/cog.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cwnaaut64gd15" 6 | path="res://.godot/imported/cog.png-6c700f0105be617bcc41a1b71a142a95.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Art/Icons/cog.png" 14 | dest_files=["res://.godot/imported/cog.png-6c700f0105be617bcc41a1b71a142a95.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=true 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Art/Icons/corner-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Art/Icons/corner-handle.png -------------------------------------------------------------------------------- /Art/Icons/corner-handle.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://detscivjcbnpi" 6 | path="res://.godot/imported/corner-handle.png-f885fef1c574bf3b932ae42ac790f4a3.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Art/Icons/corner-handle.png" 14 | dest_files=["res://.godot/imported/corner-handle.png-f885fef1c574bf3b932ae42ac790f4a3.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Art/Icons/expand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Art/Icons/expand.png -------------------------------------------------------------------------------- /Art/Icons/expand.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://1ockgc20p033" 6 | path="res://.godot/imported/expand.png-0cfa2f4dc161ed96abbe3fc8e4a4d9f3.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Art/Icons/expand.png" 14 | dest_files=["res://.godot/imported/expand.png-0cfa2f4dc161ed96abbe3fc8e4a4d9f3.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=true 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Art/Icons/power-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Art/Icons/power-button.png -------------------------------------------------------------------------------- /Art/Icons/power-button.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dnvmy7l1wrerh" 6 | path="res://.godot/imported/power-button.png-1a7633ab29b13f254220ed1150445eca.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Art/Icons/power-button.png" 14 | dest_files=["res://.godot/imported/power-button.png-1a7633ab29b13f254220ed1150445eca.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Art/Icons/shrink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Art/Icons/shrink.png -------------------------------------------------------------------------------- /Art/Icons/shrink.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://c0h3xyk6do1qy" 6 | path="res://.godot/imported/shrink.png-bac8c86fef1e3298b4934770985d3baf.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Art/Icons/shrink.png" 14 | dest_files=["res://.godot/imported/shrink.png-bac8c86fef1e3298b4934770985d3baf.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=true 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Art/Pixel_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Art/Pixel_32.png -------------------------------------------------------------------------------- /Art/Pixel_32.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bwxnhif5h1cck" 6 | path="res://.godot/imported/Pixel_32.png-2d3558ded06eab7de6af7267b3a01768.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Art/Pixel_32.png" 14 | dest_files=["res://.godot/imported/Pixel_32.png-2d3558ded06eab7de6af7267b3a01768.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=true 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to GodotOS 2 | 3 | Thanks for coming by! Here are some general contributing tips: 4 | 5 | * Please make your variables and functions statically typed. 6 | * Try to follow the [GDScript style guide](https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_styleguide.html) as closely as you can (though this isn't entirely required) 7 | * If you're planning on submitting a PR for a major feature or drastic change, please discuss it with me first. 8 | 9 | # Adding your game/app to GodotOS 10 | 11 | One thing I will always welcome is more games! There are just a few notes I have before you try to submit a PR for your game. 12 | 13 | * **Try to make your game as small as you can.** GodotOS is built in mind to run on the web, so any large files can greatly detract from its loading times and portability. 14 | This doesn't mean you can't have SFX or sprites, just use them in moderation! 15 | As a rule of thumb, try to make your game under 1 megabyte. Consider compressing your assets, going for a pixel-art or minimalist style, using a sprite atlas, etc. 16 | * Don't use autoloads in your game since it would have to always be running for the entire application. If you **really** need an autoload, consider passing data through save files or adding a node in `/root/`. 17 | Remember to delete it on window exit if you're doing this! 18 | * Avoid using functions that affect the entire scene such as `get_tree().change_scene_to_file()`. This will affect GodotOS as a whole, not just your game. Check the official games included for examples on how to safely change scenes only for the game window. 19 | * Make sure your scene and script names less generic. If you have a player and the game is called Super Bit Boy for example, call it `bit_boy_player.gd` instead of `player.gd`. 20 | 21 | That's it. Good luck! 22 | -------------------------------------------------------------------------------- /Default Files/Credits.txt: -------------------------------------------------------------------------------- 1 | GodotOS was created by popcar2. 2 | 3 | Contact me: popcar@protonmail.com 4 | 5 | I enjoy making creating games and toys. 6 | If you'd like to see more, please consider donating, even if it's only a dollar or two: 7 | 8 | https://ko-fi.com/popcar2 9 | 10 | --- Other credits --- 11 | * Default wallpaper was created by Haseeb Jamil 12 | ( https://unsplash.com/photos/snow-capped-mountain-at-night-3s85IxVDyXE ) 13 | * File icons are from FlatIcon. 14 | * Misc icons are from game-icons. 15 | * Extra wallpapers made by lydex256, implemented by DayNiz 16 | 17 | --- Game credits --- 18 | * Pong & Super Bit Boy by popcar2 19 | * Godotris by MrakDun-desu 20 | * Snake by jean-philippe-martin 21 | -------------------------------------------------------------------------------- /Default Files/GodotOS Handbook.txt: -------------------------------------------------------------------------------- 1 | Welcome to GodotOS! This handbook will show in detail all the things you can do here. 2 | 3 | Chapters: 4 | 1. Handling windows 5 | 2. Managing files 6 | 3. Managing settings 7 | 4. Playing games 8 | 9 | ----- CHAPTER 1: HANDLING WINDOWS ----- 10 | To open a new window, you can either double click a file or open a game through the start menu in the bottom left of the screen. 11 | Judging by the fact that you're reading this, you already figured out how to open files. Congratulations! 12 | 13 | You can drag a window by holding left click on the top bar and moving your mouse. You cannot move windows outside of the screen. 14 | You can resize a window by dragging the bottom right corner of the window. Hold shift while dragging to maintain the aspect ratio. 15 | In the top left of a window are three buttons: Minimize, Maximize, and Close. 16 | Every window spawned has a taskbar button that spawns next to the start menu (bottom left of the screen). Clicking that window's taskbar button will minimize or restore the window. 17 | 18 | Notice the COLORS of each window. Every window type has a specific color theme: 19 | * Blue windows are text editors (like this one!) 20 | * Green windows are file managers 21 | * Yellow windows are images 22 | * Purple windows are games 23 | 24 | ----- CHAPTER 2: MANAGING FILES ----- 25 | GodotOS uses real folders and files that are stored in your system. 26 | Where they're stored depends on the operating system, but you can use "CTRL + SHIFT + F" to open your files outside of GodotOS (try it now!) 27 | Note that people using GodotOS on the web can't access their files due to browser restrictions :( 28 | 29 | You import your files into GodotOS by either dragging them over GodotOS or placing them in your own file manager. The changes will sync immediately. 30 | To export your files, simply open the files in your file manager (CTRL + SHIFT + F) and copy them out. 31 | 32 | Only supported files will be seen by GodotOS. These are currently: 33 | * Image files (JPG, PNG, WEBP) 34 | * Text files (TXT, MD) 35 | 36 | Inside of GodotOS, you can right click in empty spaces to create folders and text files. 37 | You can also right click to copy or cut folders and files anywhere else. 38 | Right click in an empty space to paste your files. This can be in the desktop or in a file manager window. 39 | 40 | You may also rename files and move them to trash. 41 | Note that moving files to trash does NOT delete them, but instead moves them to your system's trash. 42 | 43 | Hotkeys you would expect to work do actually work (Ctrl+C, Ctrl+X, Ctrl+V, F2, DELETE). 44 | 45 | GodotOS currently can't browse other files in your system. This is mainly for your safety, as it's not 100% stable and I don't want you to lose any important stuff. 46 | The second reason is to reinforce that GodotOS is not a serious project, and shouldn't be used as an actual replacement for your real operating system! 47 | 48 | ----- CHAPTER 3: MANAGING SETTINGS ----- 49 | To access the settings menu, click on the start button (bottom left), then click on the cog icon next to the power button. 50 | The settings allows you to customize many things, including your screen scale, fullscreen mode, background color, and more! 51 | 52 | Many of these settings can also be changed via hotkeys: 53 | * Increase Scale: Ctrl + 54 | * Decrease Scale: Ctrl - 55 | * Enter/Exit Fullscreen: Alt Enter / F11 56 | 57 | Here you can remove your current wallpaper (you can add one by right clicking an image file). 58 | You can change your background color, which is visible only if there is no wallpaper applied. 59 | 60 | ----- CHAPTER 4: PLAYING GAMES ----- 61 | Now for some fun! GodotOS currently comes packaged with 4 basic games: Pong, Super Bit Boy, Snake, and Godotris. 62 | Note that hopefully more games will be added in the future! 63 | You can access these from the start menu in the bottom left. 64 | 65 | All games automatically pause when minimized, and automatically continue when restored. 66 | 67 | There are 3 modes in Pong: 68 | * Singleplayer - The default mode against an AI. Use the up and down arrow keys to move. 69 | * Survival - Try to last as long as possible with an increasingly speedy ball. 70 | * Multiplayer - Play locally with a friend. The 2nd paddle is controlled with W and S. 71 | 72 | Super Bit Boy, on the other hand, is a 2D platformer inspired by Super Meat Boy! 73 | Move left and right with the arrow keys or A and D, jump with space or Z. 74 | 75 | In Snake, your goal is to eat fruits and get longer. Don't bite yourself or hit the wall! 76 | Use the arrow keys to move. The game keeps track of your high score until it's closed. 77 | 78 | Godotris the classic falling-blocks game made for GodotOS. Clear lines and aim for a high score! 79 | -------------------------------------------------------------------------------- /Default Files/Welcome.txt: -------------------------------------------------------------------------------- 1 | Welcome to GodotOS! 2 | 3 | GodotOS is a fake operating system where 4 | you can play games, manage folders, 5 | view images, and edit text files! 6 | 7 | Here are some shortcuts to get you started: 8 | * Fullscreen: Alt + Enter or F11 9 | * Open (real) File Manager: Ctrl + Shift + F 10 | * Close ALL Windows: Ctrl + Shift + Delete 11 | 12 | If you need more info, read the GodotOS Handbook! 13 | It's in this very same folder. 14 | -------------------------------------------------------------------------------- /Default Files/default wall.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Default Files/default wall.webp -------------------------------------------------------------------------------- /Default Files/default wall.webp.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /Default Files/wallpaper_chill.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Default Files/wallpaper_chill.webp -------------------------------------------------------------------------------- /Default Files/wallpaper_chill.webp.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /Default Files/wallpaper_minimalism.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popcar2/GodotOS/d3a19ba50bb45f58cd222a673e6c73c9ef37c731/Default Files/wallpaper_minimalism.webp -------------------------------------------------------------------------------- /Default Files/wallpaper_minimalism.webp.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /Games/Cube Scene/cube.gd: -------------------------------------------------------------------------------- 1 | extends MeshInstance3D 2 | 3 | # Called every frame. 'delta' is the elapsed time since the previous frame. 4 | func _process(delta: float) -> void: 5 | rotation_degrees.x += 30 * delta 6 | rotation_degrees.z += 30 * delta 7 | -------------------------------------------------------------------------------- /Games/Cube Scene/cube.gd.uid: -------------------------------------------------------------------------------- 1 | uid://paulxnd8hmgt 2 | -------------------------------------------------------------------------------- /Games/Cube Scene/cube_scene.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://vd6e1ofpyhwd"] 2 | 3 | [ext_resource type="Script" uid="uid://paulxnd8hmgt" path="res://Games/Cube Scene/cube.gd" id="1_xfqds"] 4 | 5 | [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_0bl4j"] 6 | sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) 7 | ground_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) 8 | 9 | [sub_resource type="Sky" id="Sky_6qpvj"] 10 | sky_material = SubResource("ProceduralSkyMaterial_0bl4j") 11 | 12 | [sub_resource type="Environment" id="Environment_ebenn"] 13 | background_mode = 2 14 | sky = SubResource("Sky_6qpvj") 15 | tonemap_mode = 2 16 | 17 | [sub_resource type="BoxMesh" id="BoxMesh_m3ng8"] 18 | 19 | [node name="Cube Scene" type="Node3D"] 20 | 21 | [node name="WorldEnvironment" type="WorldEnvironment" parent="."] 22 | environment = SubResource("Environment_ebenn") 23 | 24 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] 25 | transform = Transform3D(-0.866023, -0.433016, 0.250001, 0, 0.499998, 0.866027, -0.500003, 0.749999, -0.43301, 0, 0, 0) 26 | shadow_enabled = true 27 | 28 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."] 29 | mesh = SubResource("BoxMesh_m3ng8") 30 | script = ExtResource("1_xfqds") 31 | 32 | [node name="Camera3D" type="Camera3D" parent="."] 33 | transform = Transform3D(1, 0, 0, 0, 0.866025, 0.5, 0, -0.5, 0.866025, 0, 2, 4) 34 | current = true 35 | 36 | [node name="CanvasLayer" type="CanvasLayer" parent="."] 37 | 38 | [node name="Control" type="Control" parent="CanvasLayer"] 39 | layout_mode = 3 40 | anchors_preset = 15 41 | anchor_right = 1.0 42 | anchor_bottom = 1.0 43 | grow_horizontal = 2 44 | grow_vertical = 2 45 | mouse_filter = 2 46 | 47 | [node name="RichTextLabel" type="RichTextLabel" parent="CanvasLayer/Control"] 48 | layout_mode = 1 49 | anchors_preset = 5 50 | anchor_left = 0.5 51 | anchor_right = 0.5 52 | offset_left = -303.0 53 | offset_top = 28.0 54 | offset_right = 303.0 55 | offset_bottom = 163.0 56 | grow_horizontal = 2 57 | mouse_filter = 2 58 | theme_override_colors/font_outline_color = Color(0, 0, 0, 1) 59 | theme_override_constants/outline_size = 20 60 | theme_override_font_sizes/normal_font_size = 32 61 | bbcode_enabled = true 62 | text = "[center]This is a test scene for 3D viewports. 63 | Sadly the cube doesn't do anything. Carry on." 64 | fit_content = true 65 | -------------------------------------------------------------------------------- /Games/Godotris/Block/Block.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://ddpkw5l32ogx2"] 2 | 3 | [ext_resource type="Script" uid="uid://dxmw86xjvx7pq" path="res://Games/Godotris/Block/godotris_block.gd" id="1_xp0iy"] 4 | 5 | [sub_resource type="Gradient" id="Gradient_hw1qf"] 6 | offsets = PackedFloat32Array(1) 7 | colors = PackedColorArray(1, 1, 1, 1) 8 | 9 | [sub_resource type="GradientTexture2D" id="GradientTexture2D_vv7n2"] 10 | gradient = SubResource("Gradient_hw1qf") 11 | width = 32 12 | height = 32 13 | 14 | [node name="Block" type="Sprite2D"] 15 | texture = SubResource("GradientTexture2D_vv7n2") 16 | script = ExtResource("1_xp0iy") 17 | -------------------------------------------------------------------------------- /Games/Godotris/Block/godotris_block.gd: -------------------------------------------------------------------------------- 1 | extends Sprite2D 2 | 3 | class_name GodotrisBlock 4 | 5 | signal cleared 6 | 7 | func clear() -> void: 8 | cleared.emit() 9 | queue_free() 10 | -------------------------------------------------------------------------------- /Games/Godotris/Block/godotris_block.gd.uid: -------------------------------------------------------------------------------- 1 | uid://dxmw86xjvx7pq 2 | -------------------------------------------------------------------------------- /Games/Godotris/Game/godotris_game.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | class_name GodotrisGame 4 | 5 | @export var start_menu: CanvasItem 6 | @export var end_menu: CanvasItem 7 | @export var countdown_timer: Timer 8 | @export var countdown_label: Label 9 | @export var score_label: Label 10 | @export var level_label: Label 11 | @export var lines_label: Label 12 | @export var piece_spawner: GodotrisPieceSpawner 13 | @export var input_handler: GodotrisInputHandler 14 | @export var grid: GodotrisGrid 15 | 16 | const level_droptimes: Array[int] = [ 17 | 16 * 48, 18 | 16 * 43, 19 | 16 * 38, 20 | 16 * 33, 21 | 16 * 28, 22 | 16 * 23, 23 | 16 * 18, 24 | 16 * 13, 25 | 16 * 8, 26 | 16 * 6, 27 | 16 * 5, 28 | 16 * 5, 29 | 16 * 5, 30 | 16 * 4, 31 | 16 * 4, 32 | 16 * 4, 33 | 16 * 3, 34 | 16 * 3, 35 | 16 * 3, 36 | 16 * 2, 37 | 16 * 2, 38 | 16 * 2, 39 | 16 * 2, 40 | 16 * 2, 41 | 16 * 2, 42 | 16 * 2, 43 | 16 * 2, 44 | 16 * 2, 45 | 16 * 2, 46 | 16 * 1 47 | ] 48 | 49 | var ticks_left := 3 50 | var current_score := 0 51 | var current_level := 0 52 | var lines_cleared := 0 53 | var total_lines_cleared := 0 54 | 55 | func start_game() -> void: 56 | grid.clear_all_blocks() 57 | piece_spawner.initialize() 58 | start_menu.hide() 59 | end_menu.hide() 60 | ticks_left = 3 61 | current_score = 0 62 | current_level = 0 63 | lines_cleared = 0 64 | total_lines_cleared = 0 65 | update_score() 66 | update_level() 67 | update_lines() 68 | countdown_label.show() 69 | countdown_label.text = str(ticks_left) 70 | countdown_timer.start() 71 | 72 | func end_game() -> void: 73 | end_menu.show() 74 | 75 | func on_timer_tick() -> void: 76 | ticks_left -= 1 77 | countdown_label.text = str(ticks_left) 78 | if ticks_left == 0: 79 | countdown_label.text = "Start!" 80 | countdown_label.hide() 81 | countdown_timer.stop() 82 | input_handler.request_piece() 83 | 84 | func on_piece_placed(count: int) -> void: 85 | if count == 0: 86 | return 87 | 88 | var addition: int 89 | match count: 90 | 1: 91 | addition = 40 92 | 2: 93 | addition = 100 94 | 3: 95 | addition = 300 96 | 4: 97 | addition = 1200 98 | 99 | addition *= current_level + 1 100 | current_score += addition 101 | lines_cleared += count 102 | total_lines_cleared += count 103 | update_lines() 104 | update_score() 105 | if lines_cleared >= 10: 106 | lines_cleared -= 10 107 | current_level += 1 108 | update_level() 109 | 110 | func on_piece_softdropped() -> void: 111 | current_score += 1 112 | update_score() 113 | 114 | func on_piece_harddropped(lines: int) -> void: 115 | current_score += lines * 2 116 | update_score() 117 | 118 | func update_score() -> void: 119 | score_label.text = "Score: " + str(current_score) 120 | 121 | func update_level() -> void: 122 | level_label.text = "Level: " + str(current_level) 123 | input_handler.update_droptime(level_droptimes[current_level]) 124 | 125 | func update_lines() -> void: 126 | lines_label.text = "Lines cleared: " + str(total_lines_cleared) 127 | -------------------------------------------------------------------------------- /Games/Godotris/Game/godotris_game.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bqeau4wrni0hd 2 | -------------------------------------------------------------------------------- /Games/Godotris/Game/godotris_input_handler.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | class_name GodotrisInputHandler 4 | 5 | @export var das := 167 6 | @export var arr := 33 7 | @export var sdf := 5 8 | @export var piece_spawner: GodotrisPieceSpawner 9 | @export var grid: GodotrisGrid 10 | 11 | enum DasStatus { 12 | Inactive, 13 | Left, 14 | LeftCharging, 15 | Right, 16 | RightCharging 17 | } 18 | 19 | const MAX_INT := 9223372036854775807 20 | 21 | signal piece_softdropped 22 | signal piece_harddropped(lines: int) 23 | 24 | var active_piece: GodotrisPiece 25 | var normal_drop_time: int 26 | var drop_time: int 27 | var last_drop := MAX_INT 28 | var last_move := MAX_INT 29 | var das_status := DasStatus.Inactive 30 | 31 | func stop_control() -> void: 32 | active_piece = null 33 | 34 | func on_piece_placed(_lines_cleared: int = 0) -> void: 35 | request_piece() 36 | 37 | func update_droptime(new_value: int) -> void: 38 | if normal_drop_time == drop_time: 39 | drop_time = new_value 40 | else: 41 | @warning_ignore("integer_division") 42 | drop_time = max(new_value / sdf, 16) 43 | 44 | normal_drop_time = new_value 45 | 46 | func request_piece() -> void: 47 | active_piece = piece_spawner.spawn_new_piece() 48 | last_drop = Time.get_ticks_msec() 49 | 50 | func _input(event: InputEvent) -> void: 51 | var action_time := Time.get_ticks_msec() 52 | if !(event is InputEventKey): 53 | return 54 | 55 | match event.keycode: 56 | KEY_SPACE: 57 | if !event.is_pressed() or active_piece == null: 58 | return 59 | 60 | var movement := Vector2i.UP 61 | while grid.can_place(active_piece, movement): 62 | movement += Vector2i.UP 63 | movement -= Vector2i.UP 64 | 65 | active_piece.position += Vector2.DOWN * grid.BLOCK_SIZE * (-movement.y) 66 | piece_harddropped.emit(-movement.y) 67 | var tmp := active_piece 68 | stop_control() 69 | grid.place(tmp) 70 | KEY_DOWN: 71 | if event.is_pressed(): 72 | # if softdrop is activated already, we need to return 73 | # because otherwise droptime is set more often than it should 74 | if drop_time != normal_drop_time: 75 | return 76 | @warning_ignore("integer_division") 77 | drop_time = max(normal_drop_time / sdf, 16) 78 | last_drop = action_time - drop_time 79 | else: 80 | drop_time = normal_drop_time 81 | last_drop = action_time 82 | KEY_UP: 83 | if event.is_pressed() and active_piece != null: 84 | active_piece.rotate(PI / 2) 85 | if !grid.can_place(active_piece): 86 | active_piece.rotate(-PI / 2) 87 | KEY_RIGHT: 88 | if event.is_pressed(): 89 | if das_status == DasStatus.RightCharging or das_status == DasStatus.Right: 90 | return 91 | das_status = DasStatus.RightCharging 92 | last_move = action_time 93 | 94 | if active_piece != null: 95 | if grid.can_place(active_piece, Vector2i.RIGHT): 96 | active_piece.position += Vector2.RIGHT * grid.BLOCK_SIZE 97 | else: 98 | das_status = DasStatus.Inactive 99 | last_move = MAX_INT 100 | KEY_LEFT: 101 | if event.is_pressed(): 102 | if das_status == DasStatus.LeftCharging or das_status == DasStatus.Left: 103 | return 104 | das_status = DasStatus.LeftCharging 105 | last_move = action_time 106 | 107 | if active_piece != null: 108 | if grid.can_place(active_piece, Vector2i.LEFT): 109 | active_piece.position += Vector2.LEFT * grid.BLOCK_SIZE 110 | else: 111 | das_status = DasStatus.Inactive 112 | last_move = MAX_INT 113 | 114 | func _process(_delta: float) -> void: 115 | var process_time := Time.get_ticks_msec() 116 | if active_piece == null: 117 | return 118 | 119 | handle_gravity(process_time) 120 | handle_das(process_time) 121 | 122 | func handle_gravity(process_time: int) -> void: 123 | while process_time >= last_drop + drop_time: 124 | # i have to reverse the vertical vector since godot has directions messed up 125 | if grid.can_place(active_piece, Vector2i.UP): 126 | active_piece.position += Vector2.DOWN * grid.BLOCK_SIZE 127 | last_drop = last_drop + drop_time 128 | if drop_time != normal_drop_time: 129 | piece_softdropped.emit() 130 | else: 131 | var tmp := active_piece 132 | stop_control() 133 | grid.place(tmp) 134 | break 135 | 136 | func handle_das(time: int) -> void: 137 | match das_status: 138 | DasStatus.RightCharging: 139 | if time >= last_move + das: 140 | das_status = DasStatus.Right 141 | last_move += das 142 | handle_das(time) 143 | DasStatus.LeftCharging: 144 | if time >= last_move + das: 145 | das_status = DasStatus.Left 146 | last_move += das 147 | handle_das(time) 148 | DasStatus.Right: 149 | while time >= last_move + arr: 150 | last_move += arr 151 | if grid.can_place(active_piece, Vector2i.RIGHT): 152 | active_piece.position += Vector2i.RIGHT * grid.BLOCK_SIZE 153 | DasStatus.Left: 154 | while time >= last_move + arr: 155 | last_move += arr 156 | if grid.can_place(active_piece, Vector2i.LEFT): 157 | active_piece.position += Vector2i.LEFT * grid.BLOCK_SIZE 158 | DasStatus.Inactive: 159 | pass 160 | -------------------------------------------------------------------------------- /Games/Godotris/Game/godotris_input_handler.gd.uid: -------------------------------------------------------------------------------- 1 | uid://mjpwklg2y31n 2 | -------------------------------------------------------------------------------- /Games/Godotris/Game/godotris_piece_spawner.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | class_name GodotrisPieceSpawner 4 | 5 | @export var previews: Array[GodotrisPieceHolder] 6 | @export var pieces: Dictionary 7 | @export var grid: GodotrisGrid 8 | 9 | signal cant_spawn 10 | 11 | var available_pieces: Array[String] = ["i", "s", "z", "o", "j", "l", "t"] 12 | var current_pieces: Array[String] = ["i", "s", "z", "o", "j", "l", "t"] 13 | 14 | # implementation of the 7-bag randomizer 15 | func get_random_piece() -> PackedScene: 16 | if current_pieces.is_empty(): 17 | current_pieces.append_array(available_pieces) 18 | 19 | var piece_name: String = current_pieces.pick_random() 20 | current_pieces.erase(piece_name) 21 | 22 | return pieces[piece_name] 23 | 24 | func add_to_previews(new_piece: GodotrisPiece) -> GodotrisPiece: 25 | for preview in previews: 26 | new_piece = preview.swap_piece(new_piece) 27 | 28 | return new_piece 29 | 30 | func initialize() -> void: 31 | for preview in previews: 32 | var new_piece_scn := get_random_piece() 33 | var new_piece: GodotrisPiece = new_piece_scn.instantiate() 34 | var old_piece := preview.swap_piece(new_piece) 35 | if old_piece != null: 36 | old_piece.queue_free() 37 | 38 | func spawn_new_piece() -> GodotrisPiece: 39 | var new_piece := add_to_previews(get_random_piece().instantiate()) 40 | 41 | new_piece.reparent(grid) 42 | new_piece.position = new_piece.spawn_offset 43 | if !grid.can_place(new_piece): 44 | cant_spawn.emit() 45 | new_piece.queue_free() 46 | return null 47 | 48 | return new_piece 49 | -------------------------------------------------------------------------------- /Games/Godotris/Game/godotris_piece_spawner.gd.uid: -------------------------------------------------------------------------------- 1 | uid://buj6f65mrody6 2 | -------------------------------------------------------------------------------- /Games/Godotris/Grid/godotris_grid.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | class_name GodotrisGrid 4 | 5 | @export var grid_dimensions: Vector2i = Vector2i(10, 20) 6 | 7 | const BLOCK_SIZE = 32.0 8 | 9 | signal piece_placed(lines_cleared: int) 10 | 11 | var blocks: Array[Array] = [] 12 | 13 | func clear_all_blocks() -> void: 14 | for line: Array in blocks: 15 | for block: GodotrisBlock in line: 16 | if block != null: 17 | block.clear() 18 | 19 | blocks.clear() 20 | 21 | func local_to_grid(pos: Vector2) -> Vector2i: 22 | pos /= BLOCK_SIZE 23 | var grid_pos := Vector2i(floor(pos.x), floor(pos.y)) 24 | grid_pos.y -= grid_dimensions.y - 1 25 | grid_pos.y = -grid_pos.y 26 | return grid_pos 27 | 28 | func position_empty(pos: Vector2, offset := Vector2i()) -> bool: 29 | var grid_pos := local_to_grid(pos) + offset 30 | 31 | if grid_pos.x < 0 or grid_pos.x >= grid_dimensions.x or grid_pos.y < 0: 32 | return false 33 | 34 | if blocks.size() <= grid_pos.y: 35 | return true 36 | 37 | return blocks[grid_pos.y][grid_pos.x] == null 38 | 39 | func can_place(piece: GodotrisPiece, offset := Vector2i()) -> bool: 40 | for block: GodotrisBlock in piece.get_children(): 41 | if !position_empty(block.global_position - global_position, offset): 42 | return false 43 | 44 | return true 45 | 46 | func place(piece: GodotrisPiece) -> void: 47 | for block: GodotrisBlock in piece.get_children(): 48 | var grid_pos := local_to_grid(block.global_position - global_position) 49 | 50 | while blocks.size() <= grid_pos.y: 51 | blocks.append([]) 52 | for i: int in range(grid_dimensions.x): 53 | blocks[blocks.size() - 1].append(null) 54 | 55 | blocks[grid_pos.y][grid_pos.x] = block 56 | 57 | check_and_clear_lines() 58 | 59 | func check_and_clear_lines() -> void: 60 | var i := blocks.size() 61 | var lines_to_clear: Array[int] = [] 62 | while i >= 0: 63 | i -= 1 64 | var line: Array = blocks[i] 65 | var is_full := true 66 | for pos: GodotrisBlock in line: 67 | if pos == null: 68 | is_full = false 69 | break 70 | 71 | if !is_full: 72 | continue 73 | 74 | lines_to_clear.append(i) 75 | 76 | if lines_to_clear.size() > 0: 77 | clear_lines(lines_to_clear) 78 | 79 | piece_placed.emit(lines_to_clear.size()) 80 | 81 | func clear_lines(lines: Array[int]) -> void: 82 | @warning_ignore("integer_division") 83 | var end_index := grid_dimensions.x / 2 84 | var start_index := end_index - 1 85 | 86 | while start_index >= 0: 87 | for line_index: int in lines: 88 | blocks[line_index][start_index].clear() 89 | blocks[line_index][end_index].clear() 90 | 91 | start_index -= 1 92 | end_index += 1 93 | var timer := get_tree().create_timer(0.05) 94 | await timer.timeout 95 | 96 | for line_index: int in lines: 97 | blocks.remove_at(line_index) 98 | for y: int in range(line_index, blocks.size()): 99 | for block: GodotrisBlock in blocks[y]: 100 | if block == null: 101 | continue 102 | block.global_position += Vector2.DOWN * BLOCK_SIZE 103 | -------------------------------------------------------------------------------- /Games/Godotris/Grid/godotris_grid.gd.uid: -------------------------------------------------------------------------------- 1 | uid://d1qdfv6gggaqu 2 | -------------------------------------------------------------------------------- /Games/Godotris/Piece/godotris_piece.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | class_name GodotrisPiece 4 | 5 | @export var spawn_offset: Vector2i 6 | @export var container_offset: Vector2i 7 | 8 | var child_count: int 9 | 10 | func _ready() -> void: 11 | child_count = get_child_count() 12 | for block: GodotrisBlock in get_children(): 13 | block.connect("cleared", on_block_cleared) 14 | 15 | func on_block_cleared() -> void: 16 | child_count -= 1 17 | if child_count == 0: 18 | queue_free() 19 | -------------------------------------------------------------------------------- /Games/Godotris/Piece/godotris_piece.gd.uid: -------------------------------------------------------------------------------- 1 | uid://mwugeohylsl8 2 | -------------------------------------------------------------------------------- /Games/Godotris/Piece/i_piece.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://corveaa2iq24x"] 2 | 3 | [ext_resource type="Script" uid="uid://mwugeohylsl8" path="res://Games/Godotris/Piece/godotris_piece.gd" id="1_453ij"] 4 | [ext_resource type="PackedScene" uid="uid://ddpkw5l32ogx2" path="res://Games/Godotris/Block/Block.tscn" id="2_bjywt"] 5 | 6 | [sub_resource type="Gradient" id="Gradient_v6um0"] 7 | offsets = PackedFloat32Array(1) 8 | colors = PackedColorArray(0, 1, 1, 1) 9 | 10 | [sub_resource type="GradientTexture2D" id="GradientTexture2D_in6n4"] 11 | gradient = SubResource("Gradient_v6um0") 12 | width = 32 13 | height = 32 14 | 15 | [node name="IPiece" type="Node2D"] 16 | script = ExtResource("1_453ij") 17 | spawn_offset = Vector2i(160, 0) 18 | container_offset = Vector2i(80, 32) 19 | 20 | [node name="Block" parent="." instance=ExtResource("2_bjywt")] 21 | position = Vector2(-48, 16) 22 | rotation = -3.14159 23 | texture = SubResource("GradientTexture2D_in6n4") 24 | 25 | [node name="Block2" parent="." instance=ExtResource("2_bjywt")] 26 | position = Vector2(48, 16) 27 | rotation = -3.14159 28 | texture = SubResource("GradientTexture2D_in6n4") 29 | 30 | [node name="Block3" parent="." instance=ExtResource("2_bjywt")] 31 | position = Vector2(16, 16) 32 | rotation = -3.14159 33 | texture = SubResource("GradientTexture2D_in6n4") 34 | 35 | [node name="Block4" parent="." instance=ExtResource("2_bjywt")] 36 | position = Vector2(-16, 16) 37 | rotation = -3.14159 38 | texture = SubResource("GradientTexture2D_in6n4") 39 | -------------------------------------------------------------------------------- /Games/Godotris/Piece/j_piece.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://cuxy2r5ex7lxa"] 2 | 3 | [ext_resource type="Script" uid="uid://mwugeohylsl8" path="res://Games/Godotris/Piece/godotris_piece.gd" id="1_cooja"] 4 | [ext_resource type="PackedScene" uid="uid://ddpkw5l32ogx2" path="res://Games/Godotris/Block/Block.tscn" id="2_qfksp"] 5 | 6 | [sub_resource type="Gradient" id="Gradient_dmevm"] 7 | offsets = PackedFloat32Array(1) 8 | colors = PackedColorArray(0, 0, 1, 1) 9 | 10 | [sub_resource type="GradientTexture2D" id="GradientTexture2D_ng2xg"] 11 | gradient = SubResource("Gradient_dmevm") 12 | width = 32 13 | height = 32 14 | 15 | [node name="JPiece" type="Node2D"] 16 | script = ExtResource("1_cooja") 17 | spawn_offset = Vector2i(144, 16) 18 | container_offset = Vector2i(80, 64) 19 | 20 | [node name="Block" parent="." instance=ExtResource("2_qfksp")] 21 | position = Vector2(-32, -32) 22 | texture = SubResource("GradientTexture2D_ng2xg") 23 | 24 | [node name="Block2" parent="." instance=ExtResource("2_qfksp")] 25 | position = Vector2(32, 0) 26 | texture = SubResource("GradientTexture2D_ng2xg") 27 | 28 | [node name="Block3" parent="." instance=ExtResource("2_qfksp")] 29 | texture = SubResource("GradientTexture2D_ng2xg") 30 | 31 | [node name="Block4" parent="." instance=ExtResource("2_qfksp")] 32 | position = Vector2(-32, 0) 33 | texture = SubResource("GradientTexture2D_ng2xg") 34 | -------------------------------------------------------------------------------- /Games/Godotris/Piece/l_piece.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://b7kkiimno5ae5"] 2 | 3 | [ext_resource type="Script" uid="uid://mwugeohylsl8" path="res://Games/Godotris/Piece/godotris_piece.gd" id="1_ur6g8"] 4 | [ext_resource type="PackedScene" uid="uid://ddpkw5l32ogx2" path="res://Games/Godotris/Block/Block.tscn" id="2_v8mip"] 5 | 6 | [sub_resource type="Gradient" id="Gradient_5hh2t"] 7 | offsets = PackedFloat32Array(1) 8 | colors = PackedColorArray(1, 0.509804, 0, 1) 9 | 10 | [sub_resource type="GradientTexture2D" id="GradientTexture2D_xarx0"] 11 | gradient = SubResource("Gradient_5hh2t") 12 | width = 32 13 | height = 32 14 | 15 | [node name="LPiece" type="Node2D"] 16 | script = ExtResource("1_ur6g8") 17 | spawn_offset = Vector2i(144, 16) 18 | container_offset = Vector2i(80, 64) 19 | 20 | [node name="Block" parent="." instance=ExtResource("2_v8mip")] 21 | position = Vector2(-32, 0) 22 | texture = SubResource("GradientTexture2D_xarx0") 23 | metadata/_edit_use_anchors_ = true 24 | 25 | [node name="Block2" parent="." instance=ExtResource("2_v8mip")] 26 | texture = SubResource("GradientTexture2D_xarx0") 27 | metadata/_edit_use_anchors_ = true 28 | 29 | [node name="Block3" parent="." instance=ExtResource("2_v8mip")] 30 | position = Vector2(32, 0) 31 | texture = SubResource("GradientTexture2D_xarx0") 32 | metadata/_edit_use_anchors_ = true 33 | 34 | [node name="Block4" parent="." instance=ExtResource("2_v8mip")] 35 | position = Vector2(32, -32) 36 | texture = SubResource("GradientTexture2D_xarx0") 37 | metadata/_edit_use_anchors_ = true 38 | -------------------------------------------------------------------------------- /Games/Godotris/Piece/o_piece.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://ddf8eap1k00yb"] 2 | 3 | [ext_resource type="Script" uid="uid://mwugeohylsl8" path="res://Games/Godotris/Piece/godotris_piece.gd" id="1_mqown"] 4 | [ext_resource type="PackedScene" uid="uid://ddpkw5l32ogx2" path="res://Games/Godotris/Block/Block.tscn" id="2_ce740"] 5 | 6 | [sub_resource type="Gradient" id="Gradient_x44id"] 7 | offsets = PackedFloat32Array(1) 8 | colors = PackedColorArray(1, 1, 0, 1) 9 | 10 | [sub_resource type="GradientTexture2D" id="GradientTexture2D_h4l31"] 11 | gradient = SubResource("Gradient_x44id") 12 | width = 32 13 | height = 32 14 | 15 | [node name="OPiece" type="Node2D"] 16 | script = ExtResource("1_mqown") 17 | spawn_offset = Vector2i(160, 0) 18 | container_offset = Vector2i(80, 48) 19 | 20 | [node name="Block" parent="." instance=ExtResource("2_ce740")] 21 | position = Vector2(-16, 16) 22 | texture = SubResource("GradientTexture2D_h4l31") 23 | 24 | [node name="Block2" parent="." instance=ExtResource("2_ce740")] 25 | position = Vector2(16, 16) 26 | texture = SubResource("GradientTexture2D_h4l31") 27 | 28 | [node name="Block3" parent="." instance=ExtResource("2_ce740")] 29 | position = Vector2(16, -16) 30 | texture = SubResource("GradientTexture2D_h4l31") 31 | 32 | [node name="Block4" parent="." instance=ExtResource("2_ce740")] 33 | position = Vector2(-16, -16) 34 | texture = SubResource("GradientTexture2D_h4l31") 35 | -------------------------------------------------------------------------------- /Games/Godotris/Piece/s_piece.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://bu55cplk7o7ja"] 2 | 3 | [ext_resource type="Script" uid="uid://mwugeohylsl8" path="res://Games/Godotris/Piece/godotris_piece.gd" id="1_nt4a8"] 4 | [ext_resource type="PackedScene" uid="uid://ddpkw5l32ogx2" path="res://Games/Godotris/Block/Block.tscn" id="2_jy7b8"] 5 | 6 | [sub_resource type="Gradient" id="Gradient_1y0wq"] 7 | offsets = PackedFloat32Array(1) 8 | colors = PackedColorArray(0, 1, 0, 1) 9 | 10 | [sub_resource type="GradientTexture2D" id="GradientTexture2D_xg7oo"] 11 | gradient = SubResource("Gradient_1y0wq") 12 | width = 32 13 | height = 32 14 | 15 | [node name="SPiece" type="Node2D"] 16 | script = ExtResource("1_nt4a8") 17 | spawn_offset = Vector2i(144, 16) 18 | container_offset = Vector2i(80, 64) 19 | 20 | [node name="Block" parent="." instance=ExtResource("2_jy7b8")] 21 | texture = SubResource("GradientTexture2D_xg7oo") 22 | metadata/_edit_use_anchors_ = true 23 | 24 | [node name="Block2" parent="." instance=ExtResource("2_jy7b8")] 25 | position = Vector2(-32, 0) 26 | texture = SubResource("GradientTexture2D_xg7oo") 27 | metadata/_edit_use_anchors_ = true 28 | 29 | [node name="Block3" parent="." instance=ExtResource("2_jy7b8")] 30 | position = Vector2(0, -32) 31 | texture = SubResource("GradientTexture2D_xg7oo") 32 | metadata/_edit_use_anchors_ = true 33 | 34 | [node name="Block4" parent="." instance=ExtResource("2_jy7b8")] 35 | position = Vector2(32, -32) 36 | texture = SubResource("GradientTexture2D_xg7oo") 37 | metadata/_edit_use_anchors_ = true 38 | -------------------------------------------------------------------------------- /Games/Godotris/Piece/t_piece.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://dfa5tvxkoi4ii"] 2 | 3 | [ext_resource type="Script" uid="uid://mwugeohylsl8" path="res://Games/Godotris/Piece/godotris_piece.gd" id="1_km4jt"] 4 | [ext_resource type="PackedScene" uid="uid://ddpkw5l32ogx2" path="res://Games/Godotris/Block/Block.tscn" id="2_kdkdp"] 5 | 6 | [sub_resource type="Gradient" id="Gradient_ahtic"] 7 | offsets = PackedFloat32Array(1) 8 | colors = PackedColorArray(0.513726, 0, 1, 1) 9 | 10 | [sub_resource type="GradientTexture2D" id="GradientTexture2D_t3xc7"] 11 | gradient = SubResource("Gradient_ahtic") 12 | width = 32 13 | height = 32 14 | 15 | [node name="TPiece" type="Node2D"] 16 | script = ExtResource("1_km4jt") 17 | spawn_offset = Vector2i(144, 16) 18 | container_offset = Vector2i(80, 64) 19 | 20 | [node name="Block" parent="." instance=ExtResource("2_kdkdp")] 21 | texture = SubResource("GradientTexture2D_t3xc7") 22 | 23 | [node name="Block2" parent="." instance=ExtResource("2_kdkdp")] 24 | position = Vector2(32, 0) 25 | texture = SubResource("GradientTexture2D_t3xc7") 26 | 27 | [node name="Block3" parent="." instance=ExtResource("2_kdkdp")] 28 | position = Vector2(0, -32) 29 | texture = SubResource("GradientTexture2D_t3xc7") 30 | 31 | [node name="Block4" parent="." instance=ExtResource("2_kdkdp")] 32 | position = Vector2(-32, 0) 33 | texture = SubResource("GradientTexture2D_t3xc7") 34 | -------------------------------------------------------------------------------- /Games/Godotris/Piece/z_piece.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://ntmchus4unn0"] 2 | 3 | [ext_resource type="Script" uid="uid://mwugeohylsl8" path="res://Games/Godotris/Piece/godotris_piece.gd" id="1_rltuv"] 4 | [ext_resource type="PackedScene" uid="uid://ddpkw5l32ogx2" path="res://Games/Godotris/Block/Block.tscn" id="2_ugd3p"] 5 | 6 | [sub_resource type="Gradient" id="Gradient_fndsu"] 7 | offsets = PackedFloat32Array(1) 8 | colors = PackedColorArray(1, 0, 0, 1) 9 | 10 | [sub_resource type="GradientTexture2D" id="GradientTexture2D_d2ygd"] 11 | gradient = SubResource("Gradient_fndsu") 12 | width = 32 13 | height = 32 14 | 15 | [node name="ZPiece" type="Node2D"] 16 | script = ExtResource("1_rltuv") 17 | spawn_offset = Vector2i(144, 16) 18 | container_offset = Vector2i(80, 64) 19 | 20 | [node name="Block" parent="." instance=ExtResource("2_ugd3p")] 21 | texture = SubResource("GradientTexture2D_d2ygd") 22 | 23 | [node name="Block2" parent="." instance=ExtResource("2_ugd3p")] 24 | position = Vector2(32, 0) 25 | texture = SubResource("GradientTexture2D_d2ygd") 26 | 27 | [node name="Block3" parent="." instance=ExtResource("2_ugd3p")] 28 | position = Vector2(0, -32) 29 | texture = SubResource("GradientTexture2D_d2ygd") 30 | 31 | [node name="Block4" parent="." instance=ExtResource("2_ugd3p")] 32 | position = Vector2(-32, -32) 33 | texture = SubResource("GradientTexture2D_d2ygd") 34 | -------------------------------------------------------------------------------- /Games/Godotris/PieceHolder/godotris_piece_holder.gd: -------------------------------------------------------------------------------- 1 | extends Panel 2 | 3 | class_name GodotrisPieceHolder 4 | 5 | var current_piece: GodotrisPiece = null 6 | 7 | func swap_piece(new_piece: GodotrisPiece) -> GodotrisPiece: 8 | var tmp := current_piece 9 | current_piece = new_piece 10 | 11 | add_child(current_piece) 12 | current_piece.position = current_piece.container_offset 13 | 14 | return tmp 15 | -------------------------------------------------------------------------------- /Games/Godotris/PieceHolder/godotris_piece_holder.gd.uid: -------------------------------------------------------------------------------- 1 | uid://4rd0y0bvnn80 2 | -------------------------------------------------------------------------------- /Games/Godotris/PieceHolder/piece_holder.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="StyleBoxFlat" format=3 uid="uid://dk7t88f1jcvln"] 2 | 3 | [resource] 4 | bg_color = Color(0, 0, 0, 1) 5 | border_width_top = 3 6 | border_width_right = 3 7 | border_width_bottom = 3 8 | -------------------------------------------------------------------------------- /Games/Godotris/PieceHolder/piece_holder.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://b1xykl5fledwa"] 2 | 3 | [ext_resource type="StyleBox" uid="uid://dk7t88f1jcvln" path="res://Games/Godotris/PieceHolder/piece_holder.tres" id="1_4bbpr"] 4 | [ext_resource type="Script" uid="uid://4rd0y0bvnn80" path="res://Games/Godotris/PieceHolder/godotris_piece_holder.gd" id="1_k6oki"] 5 | 6 | [node name="PieceHolder" type="Panel"] 7 | custom_minimum_size = Vector2(160, 96) 8 | theme_override_styles/panel = ExtResource("1_4bbpr") 9 | script = ExtResource("1_k6oki") 10 | -------------------------------------------------------------------------------- /Games/Pong/Scenes/pong_main_menu.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=3 uid="uid://dui0012ehv8h0"] 2 | 3 | [ext_resource type="Script" uid="uid://bybio3o0igxpy" path="res://Games/Pong/Scripts/pong_main_menu.gd" id="1_jwauq"] 4 | 5 | [sub_resource type="Gradient" id="Gradient_beqym"] 6 | offsets = PackedFloat32Array(0) 7 | colors = PackedColorArray(0, 0, 0, 1) 8 | 9 | [sub_resource type="GradientTexture1D" id="GradientTexture1D_d5rf6"] 10 | gradient = SubResource("Gradient_beqym") 11 | width = 1 12 | 13 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6x20d"] 14 | bg_color = Color(0, 0, 0, 1) 15 | border_width_left = 8 16 | border_width_top = 8 17 | border_width_right = 8 18 | border_width_bottom = 8 19 | border_color = Color(1, 1, 1, 1) 20 | 21 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_gfm2w"] 22 | bg_color = Color(0.239216, 0.239216, 0.239216, 1) 23 | border_width_left = 8 24 | border_width_top = 8 25 | border_width_right = 8 26 | border_width_bottom = 8 27 | border_color = Color(1, 1, 1, 1) 28 | 29 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_wxonl"] 30 | bg_color = Color(1, 1, 1, 1) 31 | 32 | [node name="Pong Main Menu" type="Control"] 33 | layout_mode = 3 34 | anchors_preset = 15 35 | anchor_right = 1.0 36 | anchor_bottom = 1.0 37 | grow_horizontal = 2 38 | grow_vertical = 2 39 | mouse_filter = 1 40 | script = ExtResource("1_jwauq") 41 | 42 | [node name="TextureRect" type="TextureRect" parent="."] 43 | layout_mode = 1 44 | anchors_preset = 15 45 | anchor_right = 1.0 46 | anchor_bottom = 1.0 47 | grow_horizontal = 2 48 | grow_vertical = 2 49 | texture = SubResource("GradientTexture1D_d5rf6") 50 | 51 | [node name="TitleText" type="RichTextLabel" parent="."] 52 | layout_mode = 1 53 | anchors_preset = 5 54 | anchor_left = 0.5 55 | anchor_right = 0.5 56 | offset_left = -400.0 57 | offset_top = 75.0 58 | offset_right = 400.0 59 | offset_bottom = 275.0 60 | grow_horizontal = 2 61 | mouse_filter = 2 62 | theme_override_font_sizes/normal_font_size = 96 63 | bbcode_enabled = true 64 | text = "[center]PONG" 65 | 66 | [node name="MainContainer" type="VBoxContainer" parent="."] 67 | layout_mode = 1 68 | anchors_preset = 7 69 | anchor_left = 0.5 70 | anchor_top = 1.0 71 | anchor_right = 0.5 72 | anchor_bottom = 1.0 73 | offset_left = -225.0 74 | offset_top = -400.0 75 | offset_right = 225.0 76 | grow_horizontal = 2 77 | grow_vertical = 0 78 | theme_override_constants/separation = 50 79 | 80 | [node name="SingleplayerBtn" type="Button" parent="MainContainer"] 81 | custom_minimum_size = Vector2(0, 125) 82 | layout_mode = 2 83 | focus_mode = 0 84 | theme_override_font_sizes/font_size = 64 85 | theme_override_styles/normal = SubResource("StyleBoxFlat_6x20d") 86 | theme_override_styles/hover = SubResource("StyleBoxFlat_gfm2w") 87 | theme_override_styles/pressed = SubResource("StyleBoxFlat_wxonl") 88 | text = "Singleplayer" 89 | 90 | [node name="MultiplayerBtn" type="Button" parent="MainContainer"] 91 | custom_minimum_size = Vector2(0, 125) 92 | layout_mode = 2 93 | focus_mode = 0 94 | theme_override_font_sizes/font_size = 64 95 | theme_override_styles/normal = SubResource("StyleBoxFlat_6x20d") 96 | theme_override_styles/hover = SubResource("StyleBoxFlat_gfm2w") 97 | theme_override_styles/pressed = SubResource("StyleBoxFlat_wxonl") 98 | text = "Multiplayer" 99 | 100 | [node name="SingleplayerContainer" type="VBoxContainer" parent="."] 101 | visible = false 102 | layout_mode = 1 103 | anchors_preset = 7 104 | anchor_left = 0.5 105 | anchor_top = 1.0 106 | anchor_right = 0.5 107 | anchor_bottom = 1.0 108 | offset_left = -225.0 109 | offset_top = -400.0 110 | offset_right = 225.0 111 | grow_horizontal = 2 112 | grow_vertical = 0 113 | theme_override_constants/separation = 50 114 | 115 | [node name="RegularSingleBtn" type="Button" parent="SingleplayerContainer"] 116 | custom_minimum_size = Vector2(0, 125) 117 | layout_mode = 2 118 | focus_mode = 0 119 | theme_override_font_sizes/font_size = 64 120 | theme_override_styles/normal = SubResource("StyleBoxFlat_6x20d") 121 | theme_override_styles/hover = SubResource("StyleBoxFlat_gfm2w") 122 | theme_override_styles/pressed = SubResource("StyleBoxFlat_wxonl") 123 | text = "Regular" 124 | 125 | [node name="SurvivalSingleBtn" type="Button" parent="SingleplayerContainer"] 126 | custom_minimum_size = Vector2(0, 125) 127 | layout_mode = 2 128 | focus_mode = 0 129 | theme_override_font_sizes/font_size = 64 130 | theme_override_styles/normal = SubResource("StyleBoxFlat_6x20d") 131 | theme_override_styles/hover = SubResource("StyleBoxFlat_gfm2w") 132 | theme_override_styles/pressed = SubResource("StyleBoxFlat_wxonl") 133 | text = "Survival" 134 | 135 | [connection signal="pressed" from="MainContainer/SingleplayerBtn" to="." method="_on_singleplayer_btn_pressed"] 136 | [connection signal="pressed" from="MainContainer/MultiplayerBtn" to="." method="_on_multiplayer_btn_pressed"] 137 | [connection signal="pressed" from="SingleplayerContainer/RegularSingleBtn" to="." method="_on_regular_single_btn_pressed"] 138 | [connection signal="pressed" from="SingleplayerContainer/SurvivalSingleBtn" to="." method="_on_survival_single_btn_pressed"] 139 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_ball.gd: -------------------------------------------------------------------------------- 1 | extends CharacterBody2D 2 | 3 | var collision_data: KinematicCollision2D 4 | 5 | @export var speed_gain_percent: float = 1.03 6 | @export var rand_angle: float = 50 7 | 8 | func _ready() -> void: 9 | velocity = Vector2(400,0) 10 | 11 | func _physics_process(delta: float) -> void: 12 | collision_data = move_and_collide(velocity * delta) 13 | if collision_data: 14 | if collision_data.get_collider() is CharacterBody2D: 15 | if abs(velocity.x) < 700: 16 | velocity.x *= speed_gain_percent 17 | elif abs(velocity.x) < 1000: 18 | velocity.x *= speed_gain_percent - 0.025 19 | else: 20 | velocity.x *= speed_gain_percent - 0.028 21 | velocity.y += (global_position.y - collision_data.get_collider().global_position.y) * 4 22 | velocity.y += randf_range(-rand_angle, rand_angle) 23 | velocity = velocity.bounce(collision_data.get_normal()) 24 | velocity.y = clamp(velocity.y, -1000, 1000) 25 | 26 | func reset_ball() -> void: 27 | if get_parent().player_score >= 3 or get_parent().enemy_score >= 3: 28 | return 29 | 30 | velocity = Vector2.ZERO 31 | global_position = Vector2.ZERO 32 | 33 | await get_tree().create_timer(1).timeout 34 | velocity = Vector2(300, 0) 35 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_ball.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bs6tax1wxufkp 2 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_enemy.gd: -------------------------------------------------------------------------------- 1 | extends CharacterBody2D 2 | 3 | const SPEED = 5.8 4 | 5 | var ball: CharacterBody2D 6 | 7 | func _ready() -> void: 8 | ball = $"../Ball" 9 | 10 | func _physics_process(delta: float) -> void: 11 | global_position.y = move_toward(global_position.y, ball.global_position.y, SPEED) 12 | 13 | move_and_collide(velocity * delta) 14 | 15 | position.y = clamp(position.y, -264, 264) 16 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_enemy.gd.uid: -------------------------------------------------------------------------------- 1 | uid://djuup8btqvpab 2 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_enemy_fail_area.gd: -------------------------------------------------------------------------------- 1 | extends Area2D 2 | 3 | func _on_body_entered(body: Node2D) -> void: 4 | if body.name == "Ball": 5 | get_parent().player_score += 1 6 | body.reset_ball() 7 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_enemy_fail_area.gd.uid: -------------------------------------------------------------------------------- 1 | uid://brw5t4xl7hndq 2 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_main_menu.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | func load_scene(path: String) -> void: 4 | var next_scene: Node2D = load(path).instantiate() 5 | add_sibling(next_scene) 6 | queue_free() 7 | 8 | func _on_singleplayer_btn_pressed() -> void: 9 | $MainContainer.visible = false 10 | $SingleplayerContainer.visible = true 11 | $TitleText.text = "[center]SINGLEPLAYER" 12 | 13 | func _on_regular_single_btn_pressed() -> void: 14 | load_scene("res://Games/Pong/Scenes/pong_singleplayer.tscn") 15 | 16 | func _on_survival_single_btn_pressed() -> void: 17 | load_scene("res://Games/Pong/Scenes/pong_survival.tscn") 18 | 19 | func _on_multiplayer_btn_pressed() -> void: 20 | load_scene("res://Games/Pong/Scenes/pong_multiplayer.tscn") 21 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_main_menu.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bybio3o0igxpy 2 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_player.gd: -------------------------------------------------------------------------------- 1 | extends CharacterBody2D 2 | 3 | const SPEED = 250.0 4 | 5 | @export var up_axis: String = "ui_up" 6 | @export var down_axis: String = "ui_down" 7 | 8 | var up_input: bool 9 | var down_input: bool 10 | 11 | func _input(event: InputEvent) -> void: 12 | # For some reason get_action_strength() wouldn't work in multiplayer, 13 | # only one player could move at the same time 14 | if event.is_action_pressed(up_axis): 15 | up_input = true 16 | if event.is_action_released(up_axis): 17 | up_input = false 18 | if event.is_action_pressed(down_axis): 19 | down_input = event.is_action_pressed(down_axis) 20 | if event.is_action_released(down_axis): 21 | down_input = false 22 | 23 | 24 | func _physics_process(delta: float) -> void: 25 | if up_input: 26 | velocity.y = -SPEED 27 | elif down_input: 28 | velocity.y = SPEED 29 | else: 30 | velocity.y = move_toward(velocity.x, 0, SPEED) 31 | 32 | move_and_collide(velocity * delta) 33 | 34 | position.y = clamp(position.y, -264, 264) 35 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_player.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cy0d05k2sudu5 2 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_player_fail_area.gd: -------------------------------------------------------------------------------- 1 | extends Area2D 2 | 3 | func _on_body_entered(body: Node2D) -> void: 4 | if body.name == "Ball": 5 | get_parent().enemy_score += 1 6 | body.reset_ball() 7 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_player_fail_area.gd.uid: -------------------------------------------------------------------------------- 1 | uid://58oaqyk4r3ub 2 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_singleplayer_manager.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | # These are for changing in multiplayer 4 | @export var player_won_text: String = "You won!" 5 | @export var enemy_won_text: String = "You lost..." 6 | @export var restart_scene_string: String = "res://Games/Pong/Scenes/pong_singleplayer.tscn" 7 | 8 | var player_score: int : 9 | set(score): 10 | player_score = score 11 | $"Player Score Text".text = str(score) 12 | if score >= 3: 13 | $"Game Over Screen".visible = true 14 | $"Game Over Screen/Game Over Title".text = "[center]%s" % player_won_text 15 | var enemy_score: int : 16 | set(score): 17 | enemy_score = score 18 | $"Enemy Score Text".text = str(score) 19 | if score >= 3: 20 | $"Game Over Screen".visible = true 21 | $"Game Over Screen/Game Over Title".text = "[center]%s" % enemy_won_text 22 | 23 | func load_scene(path: String) -> void: 24 | var next_scene: Node = load(path).instantiate() 25 | add_sibling(next_scene) 26 | queue_free() 27 | 28 | func _on_restart_btn_pressed() -> void: 29 | load_scene(restart_scene_string) 30 | 31 | func _on_main_menu_btn_pressed() -> void: 32 | load_scene("res://Games/Pong/Scenes/pong_main_menu.tscn") 33 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_singleplayer_manager.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bjigiyom43bx5 2 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_survival_manager.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | var game_over: bool 4 | 5 | var time_elapsed: float 6 | 7 | func load_scene(path: String) -> void: 8 | var next_scene: Node = load(path).instantiate() 9 | add_sibling(next_scene) 10 | queue_free() 11 | 12 | func _physics_process(delta: float) -> void: 13 | if game_over: 14 | return 15 | 16 | time_elapsed += delta 17 | $"Timer Text".text = "%02d:%02d" % [time_elapsed / 60, time_elapsed as int % 60] 18 | 19 | func _on_player_fail_area_body_entered(_body: Node2D) -> void: 20 | game_over = true 21 | await get_tree().create_timer(0.5).timeout 22 | $"Game Over Screen".visible = true 23 | $"Timer Text".visible = false 24 | $"Game Over Screen/Game Over Title".text = "[center]You survived for %02d:%02d" % [time_elapsed / 60, time_elapsed as int % 60] 25 | 26 | func _on_restart_btn_pressed() -> void: 27 | load_scene("res://Games/Pong/Scenes/pong_survival.tscn") 28 | 29 | func _on_main_menu_btn_pressed() -> void: 30 | load_scene("res://Games/Pong/Scenes/pong_main_menu.tscn") 31 | -------------------------------------------------------------------------------- /Games/Pong/Scripts/pong_survival_manager.gd.uid: -------------------------------------------------------------------------------- 1 | uid://b4qdqhwk3y63w 2 | -------------------------------------------------------------------------------- /Games/Snake/SnakeBestScoreLabel.gd: -------------------------------------------------------------------------------- 1 | extends RichTextLabel 2 | 3 | var best_score: int = 0 4 | 5 | func _on_board_game_ended(final_score: int) -> void: 6 | if final_score <= best_score: return 7 | best_score = final_score 8 | 9 | # Update the high score display on the next game, so the player 10 | # can easily see on the "game over" screen that they beat the 11 | # current high score. 12 | func _on_restart_button_pressed() -> void: 13 | self.text = "Best: " + str(best_score) 14 | -------------------------------------------------------------------------------- /Games/Snake/SnakeBestScoreLabel.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cvxcqhf0g1uhd 2 | -------------------------------------------------------------------------------- /Games/Snake/SnakeBoard.gd: -------------------------------------------------------------------------------- 1 | extends Sprite2D 2 | 3 | class_name SnakeBoard 4 | 5 | # This script runs basically the whole "snake" game. 6 | # It lives in the rectangle where we display the game. 7 | 8 | # Eat the apples, avoid hitting the wall or yourself! 9 | # Careful, you get longer as you eat more apples. 10 | # Also, every 50 points you move a bit faster. 11 | # Can you beat your high score? 12 | 13 | signal score_updated(old_score:int, new_score:int) 14 | signal game_ended(final_score:int) 15 | 16 | var board_image: Image 17 | var sizeX := 68 18 | var sizeY := 32 19 | @export var bg_color: Color = Color.BLACK 20 | @export var snake_color: Color = Color.WHITE 21 | @export var apple_color: Color = Color.GREEN 22 | # position of the snake's head 23 | var head: Vector2i = Vector2i(1,1) 24 | # position of the elments of the snake's body 25 | # (front of list = front of snake) 26 | var body: Array[Vector2i] = [] 27 | # direction it's going 28 | var dir: Vector2i = Vector2i(1,0) 29 | var initial_length := 5 30 | var length_increase := 10 31 | var time: float = 0.0 32 | var initial_fps := 20 33 | var time_per_tick := 1.0/initial_fps 34 | var increase_fps_every := 50 35 | # We keep a list of inputs to allow (right,down) on the same frame to be 36 | # interpreted as "turn right this frame, then down on the next frame." 37 | var inputs: Array[Vector2i] = [] 38 | var score:= 0 39 | var apple: Vector2i = Vector2i(10,10) 40 | var playing:= true 41 | 42 | 43 | # Called when the node enters the scene tree for the first time. 44 | func _ready() -> void: 45 | board_image = Image.new() 46 | board_image = Image.create_empty(sizeX, sizeY, false, Image.FORMAT_RGB8) 47 | self.texture = ImageTexture.create_from_image(board_image) 48 | init_game() 49 | 50 | # Called every frame. 'delta' is the elapsed time since the previous frame. 51 | func _process(delta: float) -> void: 52 | if !playing: return 53 | time += delta; 54 | while time>time_per_tick: 55 | time -= time_per_tick; 56 | tick() 57 | 58 | # Called when a key is pressed (or released, technically) 59 | func _input(event: InputEvent) -> void: 60 | if !playing: return 61 | if (event is InputEventMouseMotion and event.relative.length_squared()>1.0): 62 | Input.mouse_mode = Input.MOUSE_MODE_VISIBLE 63 | if !(event is InputEventKey and event.is_pressed()): 64 | return 65 | match event.keycode: 66 | KEY_DOWN: 67 | inputs.push_back(Vector2i(0,1)) 68 | KEY_LEFT: 69 | inputs.push_back(Vector2i(-1,0)) 70 | KEY_RIGHT: 71 | inputs.push_back(Vector2i(1,0)) 72 | KEY_UP: 73 | inputs.push_back(Vector2i(0,-1)) 74 | 75 | func start_game() -> void: 76 | init_game() 77 | playing = true 78 | 79 | func init_game() -> void: 80 | time_per_tick = 1.0/initial_fps 81 | inc_score(-score) 82 | board_image.fill(bg_color) 83 | self.texture.update(board_image) 84 | head = Vector2i(1,1) 85 | body = [] 86 | dir = Vector2i(1,0) 87 | for i in range(initial_length): 88 | body.push_back(head) 89 | place_apple() 90 | Input.mouse_mode = Input.MOUSE_MODE_HIDDEN 91 | 92 | func place_apple() -> void: 93 | var attempts:= 200 94 | while (attempts > 0): 95 | attempts -= 1 96 | var pos := Vector2i(1+randi_range(0, sizeX-3), 1+randi_range(0, sizeY-3)) 97 | var pix: Color = board_image.get_pixel(pos.x, pos.y) 98 | # This should be very unlikely to happen, but the "attempts>0" check is here so 99 | # if we don't find a good spot for an apple then we still place one 100 | # at random anyways. It's better to have an apple over the snake's body 101 | # (visual glitch but still winnable) rather than to not have an apple at all 102 | # (then the player is stuck). 103 | if (pix!=bg_color and attempts>0): continue 104 | apple = pos 105 | board_image.set_pixel(apple.x, apple.y, apple_color) 106 | return 107 | print("Unable to place apple (?), this shouldn't happen it's a bug.") 108 | 109 | func inc_score(delta: int) -> void: 110 | score += delta 111 | @warning_ignore("integer_division") 112 | var fps:int = initial_fps + (score/increase_fps_every) 113 | time_per_tick = 1.0/fps 114 | score_updated.emit(score) 115 | 116 | func eat_apple() -> void: 117 | inc_score(10) 118 | place_apple() 119 | for i in range(length_increase): 120 | body.push_back(body[-1]) 121 | 122 | func game_over() -> void: 123 | playing = false 124 | Input.mouse_mode = Input.MOUSE_MODE_VISIBLE 125 | game_ended.emit(score) 126 | 127 | func in_bounds(pos: Vector2i) -> bool: 128 | return !(pos.x<0 || pos.y<0 || pos.x >= self.sizeX || pos.y >= self.sizeY) 129 | 130 | # Run one frame of the game. Pops from inputs. 131 | func tick() -> void: 132 | if inputs: 133 | var new_dir: Vector2i = inputs.pop_front() 134 | # ignore command to go backwards 135 | if new_dir != -dir: 136 | dir = new_dir 137 | head += dir 138 | if !in_bounds(head): 139 | # hit the edge, you die 140 | game_over() 141 | return 142 | var gone: Vector2i = body.pop_back() 143 | body.push_front(head) 144 | var pix: Color = board_image.get_pixel(head.x, head.y) 145 | # Always redraw the apple just in case it's over the snake body 146 | # (see place_apple). 147 | board_image.set_pixel(apple.x, apple.y, apple_color) 148 | board_image.set_pixel(head.x, head.y, snake_color) 149 | board_image.set_pixel(gone.x, gone.y, bg_color) 150 | self.texture.update(board_image) 151 | if pix == snake_color: 152 | # self-collision, you die. 153 | game_over() 154 | return 155 | elif pix == apple_color: 156 | eat_apple() 157 | 158 | func _on_play_button_pressed() -> void: 159 | start_game() 160 | -------------------------------------------------------------------------------- /Games/Snake/SnakeBoard.gd.uid: -------------------------------------------------------------------------------- 1 | uid://det8w80ts5qm8 2 | -------------------------------------------------------------------------------- /Games/Snake/SnakeGameOver.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | signal new_game_should_start 4 | 5 | func _on_board_game_ended(_final_score: int) -> void: 6 | self.show() 7 | 8 | func _on_button_pressed() -> void: 9 | self.hide() 10 | new_game_should_start.emit() 11 | -------------------------------------------------------------------------------- /Games/Snake/SnakeGameOver.gd.uid: -------------------------------------------------------------------------------- 1 | uid://d05cq0k5yj2fc 2 | -------------------------------------------------------------------------------- /Games/Snake/SnakeLabel.gd: -------------------------------------------------------------------------------- 1 | extends RichTextLabel 2 | 3 | func _on_board_score_updated(new_score: int) -> void: 4 | self.text = "Score: " + str(new_score) 5 | -------------------------------------------------------------------------------- /Games/Snake/SnakeLabel.gd.uid: -------------------------------------------------------------------------------- 1 | uid://rqcrafnl1ub1 2 | -------------------------------------------------------------------------------- /Games/Snake/snake_scene.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=9 format=3 uid="uid://6e6rkceymrxy"] 2 | 3 | [ext_resource type="Script" uid="uid://det8w80ts5qm8" path="res://Games/Snake/SnakeBoard.gd" id="1_vn6nx"] 4 | [ext_resource type="Script" uid="uid://rqcrafnl1ub1" path="res://Games/Snake/SnakeLabel.gd" id="2_36w75"] 5 | [ext_resource type="Script" uid="uid://cvxcqhf0g1uhd" path="res://Games/Snake/SnakeBestScoreLabel.gd" id="3_3qlc5"] 6 | [ext_resource type="Script" uid="uid://d05cq0k5yj2fc" path="res://Games/Snake/SnakeGameOver.gd" id="3_fyb7g"] 7 | 8 | [sub_resource type="Gradient" id="Gradient_lott4"] 9 | colors = PackedColorArray(0, 0.745098, 0, 1, 1, 1, 1, 1) 10 | 11 | [sub_resource type="GradientTexture2D" id="GradientTexture2D_d3c20"] 12 | gradient = SubResource("Gradient_lott4") 13 | width = 1152 14 | height = 648 15 | fill_from = Vector2(0.204128, 0.611621) 16 | fill_to = Vector2(0, 0) 17 | 18 | [sub_resource type="Gradient" id="Gradient_sbx2e"] 19 | 20 | [sub_resource type="GradientTexture2D" id="GradientTexture2D_mt1rj"] 21 | gradient = SubResource("Gradient_sbx2e") 22 | width = 68 23 | height = 32 24 | 25 | [node name="SnakeScene" type="Control"] 26 | layout_mode = 3 27 | anchors_preset = 15 28 | anchor_right = 1.0 29 | anchor_bottom = 1.0 30 | grow_horizontal = 2 31 | grow_vertical = 2 32 | mouse_filter = 2 33 | 34 | [node name="Background" type="Sprite2D" parent="."] 35 | texture = SubResource("GradientTexture2D_d3c20") 36 | centered = false 37 | 38 | [node name="Board" type="Sprite2D" parent="Background"] 39 | texture_filter = 1 40 | position = Vector2(576, 281) 41 | scale = Vector2(16, 16) 42 | texture = SubResource("GradientTexture2D_mt1rj") 43 | script = ExtResource("1_vn6nx") 44 | 45 | [node name="GameOver" type="Control" parent="."] 46 | visible = false 47 | layout_mode = 1 48 | anchors_preset = 15 49 | anchor_right = 1.0 50 | anchor_bottom = 1.0 51 | grow_horizontal = 2 52 | grow_vertical = 2 53 | mouse_filter = 2 54 | script = ExtResource("3_fyb7g") 55 | 56 | [node name="GameOverLabel" type="RichTextLabel" parent="GameOver"] 57 | layout_mode = 1 58 | anchors_preset = 8 59 | anchor_left = 0.5 60 | anchor_top = 0.5 61 | anchor_right = 0.5 62 | anchor_bottom = 0.5 63 | offset_left = -204.0 64 | offset_top = -166.0 65 | offset_right = 204.0 66 | offset_bottom = -56.0 67 | grow_horizontal = 2 68 | grow_vertical = 2 69 | mouse_filter = 2 70 | theme_override_colors/font_outline_color = Color(0, 0, 0, 1) 71 | theme_override_constants/outline_size = 12 72 | theme_override_font_sizes/normal_font_size = 64 73 | bbcode_enabled = true 74 | text = "[center]Game Over!" 75 | 76 | [node name="RestartButton" type="Button" parent="GameOver"] 77 | layout_mode = 1 78 | anchors_preset = 8 79 | anchor_left = 0.5 80 | anchor_top = 0.5 81 | anchor_right = 0.5 82 | anchor_bottom = 0.5 83 | offset_left = -197.5 84 | offset_top = -49.0 85 | offset_right = 197.5 86 | offset_bottom = 49.0 87 | grow_horizontal = 2 88 | grow_vertical = 2 89 | theme_override_font_sizes/font_size = 64 90 | text = "Play again" 91 | 92 | [node name="ScoreLabel" type="RichTextLabel" parent="."] 93 | layout_mode = 1 94 | anchors_preset = 2 95 | anchor_top = 1.0 96 | anchor_bottom = 1.0 97 | offset_left = 40.0 98 | offset_top = -101.0 99 | offset_right = 440.0 100 | offset_bottom = -11.0 101 | grow_vertical = 0 102 | mouse_filter = 2 103 | theme_override_font_sizes/normal_font_size = 64 104 | text = "Score: 0" 105 | script = ExtResource("2_36w75") 106 | 107 | [node name="BestScoreLabel" type="RichTextLabel" parent="."] 108 | layout_mode = 1 109 | anchors_preset = 3 110 | anchor_left = 1.0 111 | anchor_top = 1.0 112 | anchor_right = 1.0 113 | anchor_bottom = 1.0 114 | offset_left = -400.0 115 | offset_top = -100.0 116 | offset_bottom = -10.0 117 | grow_horizontal = 0 118 | grow_vertical = 0 119 | mouse_filter = 2 120 | theme_override_font_sizes/bold_italics_font_size = 64 121 | theme_override_font_sizes/italics_font_size = 64 122 | theme_override_font_sizes/mono_font_size = 64 123 | theme_override_font_sizes/normal_font_size = 64 124 | theme_override_font_sizes/bold_font_size = 64 125 | text = "Best: 0" 126 | script = ExtResource("3_3qlc5") 127 | 128 | [connection signal="game_ended" from="Background/Board" to="GameOver" method="_on_board_game_ended"] 129 | [connection signal="game_ended" from="Background/Board" to="BestScoreLabel" method="_on_board_game_ended"] 130 | [connection signal="score_updated" from="Background/Board" to="ScoreLabel" method="_on_board_score_updated"] 131 | [connection signal="new_game_should_start" from="GameOver" to="Background/Board" method="_on_play_button_pressed"] 132 | [connection signal="pressed" from="GameOver/RestartButton" to="GameOver" method="_on_button_pressed"] 133 | [connection signal="pressed" from="GameOver/RestartButton" to="BestScoreLabel" method="_on_restart_button_pressed"] 134 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Other Scenes/bit_boy_camera.gd: -------------------------------------------------------------------------------- 1 | extends Camera2D 2 | 3 | @onready var player: BitBoyPlayer = $"../Player" 4 | 5 | func _ready() -> void: 6 | make_current() 7 | 8 | func _physics_process(_delta: float) -> void: 9 | # Yes I know this isn't how you're supposed to use lerp but it works alright 10 | global_position = lerp(global_position, player.global_position, 0.1) 11 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Other Scenes/bit_boy_camera.gd.uid: -------------------------------------------------------------------------------- 1 | uid://65kr3tt4jbk2 2 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Other Scenes/bit_boy_camera.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://chfpq4oi0dogc"] 2 | 3 | [ext_resource type="Script" uid="uid://65kr3tt4jbk2" path="res://Games/Super Bit Boy/Other Scenes/bit_boy_camera.gd" id="1_uvdeb"] 4 | 5 | [sub_resource type="Gradient" id="Gradient_yyofs"] 6 | offsets = PackedFloat32Array(0) 7 | colors = PackedColorArray(0, 0, 0, 1) 8 | 9 | [sub_resource type="GradientTexture1D" id="GradientTexture1D_xxn30"] 10 | gradient = SubResource("Gradient_yyofs") 11 | width = 1920 12 | 13 | [node name="Camera2D" type="Camera2D"] 14 | zoom = Vector2(0.75, 0.75) 15 | position_smoothing_speed = 7.0 16 | script = ExtResource("1_uvdeb") 17 | 18 | [node name="Sprite2D" type="Sprite2D" parent="."] 19 | scale = Vector2(1, 1920) 20 | texture = SubResource("GradientTexture1D_xxn30") 21 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Exit/bit_boy_exit.gd: -------------------------------------------------------------------------------- 1 | extends Area2D 2 | 3 | func _on_body_entered(body: Node2D) -> void: 4 | if body is BitBoyPlayer: 5 | body.win() 6 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Exit/bit_boy_exit.gd.uid: -------------------------------------------------------------------------------- 1 | uid://euby5h52vpr7 2 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Exit/bit_boy_exit.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://b3u7st4i1algn"] 2 | 3 | [ext_resource type="Script" uid="uid://euby5h52vpr7" path="res://Games/Super Bit Boy/Scenes/Exit/bit_boy_exit.gd" id="1_s358w"] 4 | [ext_resource type="Texture2D" uid="uid://bwxnhif5h1cck" path="res://Art/Pixel_32.png" id="2_5apsu"] 5 | 6 | [sub_resource type="RectangleShape2D" id="RectangleShape2D_am6qy"] 7 | size = Vector2(48, 48) 8 | 9 | [node name="Exit" type="Area2D"] 10 | script = ExtResource("1_s358w") 11 | 12 | [node name="Sprite2D" type="Sprite2D" parent="."] 13 | modulate = Color(0, 0.862745, 0.392157, 1) 14 | scale = Vector2(1.5, 1.5) 15 | texture = ExtResource("2_5apsu") 16 | 17 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 18 | shape = SubResource("RectangleShape2D_am6qy") 19 | 20 | [connection signal="body_entered" from="." to="." method="_on_body_entered"] 21 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Levels/bit_boy_scene_manager.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | @export var next_level_number: int = -1 4 | var is_loading: bool 5 | 6 | func reload_scene() -> void: 7 | if is_loading: 8 | return 9 | 10 | is_loading = true 11 | var current_scene: Node = load(scene_file_path).instantiate() 12 | add_sibling(current_scene) 13 | queue_free() 14 | 15 | func load_next_scene() -> void: 16 | if is_loading: 17 | return 18 | 19 | is_loading = true 20 | var next_scene: Node = load("res://Games/Super Bit Boy/Scenes/Levels/level_%d.tscn" % next_level_number).instantiate() 21 | add_sibling(next_scene) 22 | queue_free() 23 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Levels/bit_boy_scene_manager.gd.uid: -------------------------------------------------------------------------------- 1 | uid://5s567w1vfwab 2 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Levels/level_1.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=8 format=4 uid="uid://t3fobsr7gklg"] 2 | 3 | [ext_resource type="Script" uid="uid://5s567w1vfwab" path="res://Games/Super Bit Boy/Scenes/Levels/bit_boy_scene_manager.gd" id="1_yi0p1"] 4 | [ext_resource type="PackedScene" uid="uid://chfpq4oi0dogc" path="res://Games/Super Bit Boy/Other Scenes/bit_boy_camera.tscn" id="2_4pma2"] 5 | [ext_resource type="Texture2D" uid="uid://bwxnhif5h1cck" path="res://Art/Pixel_32.png" id="3_75lam"] 6 | [ext_resource type="PackedScene" uid="uid://bxv24mjcranba" path="res://Games/Super Bit Boy/Scenes/Player/bit_boy_player.tscn" id="4_bfb5o"] 7 | [ext_resource type="PackedScene" uid="uid://b3u7st4i1algn" path="res://Games/Super Bit Boy/Scenes/Exit/bit_boy_exit.tscn" id="5_38t8g"] 8 | 9 | [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_kk343"] 10 | texture = ExtResource("3_75lam") 11 | texture_region_size = Vector2i(32, 32) 12 | 0:0/next_alternative_id = 2 13 | 0:0/0 = 0 14 | 0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) 15 | 0:0/1 = 1 16 | 0:0/1/modulate = Color(1, 0, 0, 1) 17 | 0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(-10.6667, -10.6667, 10.6667, -10.6667, 10.6667, 10.6667, -10.6667, 10.6667) 18 | 0:0/1/custom_data_0 = true 19 | 20 | [sub_resource type="TileSet" id="TileSet_k0n52"] 21 | tile_size = Vector2i(32, 32) 22 | physics_layer_0/collision_layer = 1 23 | custom_data_layer_0/name = "instakill" 24 | custom_data_layer_0/type = 1 25 | sources/1 = SubResource("TileSetAtlasSource_kk343") 26 | 27 | [node name="Level 1" type="Node2D"] 28 | script = ExtResource("1_yi0p1") 29 | next_level_number = 2 30 | 31 | [node name="Camera2D" parent="." instance=ExtResource("2_4pma2")] 32 | 33 | [node name="Layer0" type="TileMapLayer" parent="."] 34 | modulate = Color(0.615686, 0.615686, 0.615686, 1) 35 | use_parent_material = true 36 | tile_map_data = PackedByteArray("AAD+/wEAAQAAAAAAAAD+/wIAAQAAAAAAAAD//wEAAQAAAAAAAAD//wIAAQAAAAAAAAAAAAEAAQAAAAAAAAAAAAIAAQAAAAAAAAABAAEAAQAAAAAAAAABAAIAAQAAAAAAAAACAAEAAQAAAAAAAAACAAIAAQAAAAAAAAADAAEAAQAAAAAAAAADAAIAAQAAAAAAAAAEAAEAAQAAAAAAAAAEAAIAAQAAAAAAAAAFAAEAAQAAAAAAAAAFAAIAAQAAAAAAAAD8/wEAAQAAAAAAAAD8/wIAAQAAAAAAAAD9/wEAAQAAAAAAAAD9/wIAAQAAAAAAAAAEAAAAAQAAAAAAAAAFAAAAAQAAAAAAAAAGAAAAAQAAAAAAAAAGAAEAAQAAAAAAAAAGAAIAAQAAAAAAAAAHAAAAAQAAAAAAAAAHAAEAAQAAAAAAAAAHAAIAAQAAAAAAAAAIAP7/AQAAAAAAAAAIAP//AQAAAAAAAAAIAAAAAQAAAAAAAAAIAAEAAQAAAAAAAAAIAAIAAQAAAAAAAAAJAP7/AQAAAAAAAAAJAP//AQAAAAAAAAAJAAAAAQAAAAAAAAAJAAEAAQAAAAAAAAAJAAIAAQAAAAAAAAAEAP//AQAAAAAAAAAFAP//AQAAAAAAAAAGAP//AQAAAAAAAAAHAP//AQAAAAAAAAAIAPz/AQAAAAAAAAAIAP3/AQAAAAAAAAAJAPz/AQAAAAAAAAAJAP3/AQAAAAAAAAAKAPz/AQAAAAAAAAAKAP3/AQAAAAAAAAAKAP7/AQAAAAAAAAAKAP//AQAAAAAAAAAKAAAAAQAAAAAAAAAKAAEAAQAAAAAAAAAKAAIAAQAAAAAAAAALAPz/AQAAAAAAAAALAP3/AQAAAAAAAAALAP7/AQAAAAAAAAALAP//AQAAAAAAAAALAAAAAQAAAAAAAAALAAEAAQAAAAAAAAALAAIAAQAAAAAAAAAMAPz/AQAAAAAAAAAMAP3/AQAAAAAAAAAMAP7/AQAAAAAAAAAMAP//AQAAAAAAAAAMAAAAAQAAAAAAAAAMAAEAAQAAAAAAAAAMAAIAAQAAAAAAAAASAPz/AQAAAAAAAAASAP3/AQAAAAAAAAASAP7/AQAAAAAAAAASAP//AQAAAAAAAAASAAAAAQAAAAAAAAASAAEAAQAAAAAAAAASAAIAAQAAAAAAAAATAPz/AQAAAAAAAAATAP3/AQAAAAAAAAATAP7/AQAAAAAAAAATAP//AQAAAAAAAAATAAAAAQAAAAAAAAATAAEAAQAAAAAAAAATAAIAAQAAAAAAAAAUAPz/AQAAAAAAAAAUAP3/AQAAAAAAAAAUAP7/AQAAAAAAAAAUAP//AQAAAAAAAAAUAAAAAQAAAAAAAAAUAAEAAQAAAAAAAAAUAAIAAQAAAAAAAAAVAPz/AQAAAAAAAAAVAP3/AQAAAAAAAAAVAP7/AQAAAAAAAAAVAP//AQAAAAAAAAAVAAAAAQAAAAAAAAAVAAEAAQAAAAAAAAAVAAIAAQAAAAAAAAAWAPz/AQAAAAAAAAAWAP3/AQAAAAAAAAAWAP7/AQAAAAAAAAAWAP//AQAAAAAAAAAWAAAAAQAAAAAAAAAWAAEAAQAAAAAAAAAWAAIAAQAAAAAAAAAbAPn/AQAAAAAAAAAbAPr/AQAAAAAAAAAbAPv/AQAAAAAAAAAbAPz/AQAAAAAAAAAbAP3/AQAAAAAAAAAbAP7/AQAAAAAAAAAbAP//AQAAAAAAAAAbAAAAAQAAAAAAAAAbAAEAAQAAAAAAAAAbAAIAAQAAAAAAAAAcAPn/AQAAAAAAAAAcAPr/AQAAAAAAAAAcAPv/AQAAAAAAAAAcAPz/AQAAAAAAAAAcAP3/AQAAAAAAAAAcAP7/AQAAAAAAAAAcAP//AQAAAAAAAAAcAAAAAQAAAAAAAAAcAAEAAQAAAAAAAAAcAAIAAQAAAAAAAAATAPT/AQAAAAAAAAATAPX/AQAAAAAAAAAUAPT/AQAAAAAAAAAUAPX/AQAAAAAAAAAVAPT/AQAAAAAAAAAVAPX/AQAAAAAAAAAWAPT/AQAAAAAAAAAWAPX/AQAAAAAAAAASAPT/AQAAAAAAAAASAPX/AQAAAAAAAAAIAPP/AQAAAAAAAAAIAPT/AQAAAAAAAAAJAPP/AQAAAAAAAAAJAPT/AQAAAAAAAAAKAPP/AQAAAAAAAAAKAPT/AQAAAAAAAAALAPP/AQAAAAAAAAALAPT/AQAAAAAAAAAMAPP/AQAAAAAAAAAMAPT/AQAAAAAAAAAdAPn/AQAAAAAAAAAdAPr/AQAAAAAAAAAdAPv/AQAAAAAAAAAdAPz/AQAAAAAAAAAdAP3/AQAAAAAAAAAdAP7/AQAAAAAAAAAdAP//AQAAAAAAAAAdAAAAAQAAAAAAAAAdAAEAAQAAAAAAAAAdAAIAAQAAAAAAAAAeAPn/AQAAAAAAAAAeAPr/AQAAAAAAAAAeAPv/AQAAAAAAAAAeAAAAAQAAAAAAAAAeAAEAAQAAAAAAAAAeAAIAAQAAAAAAAAAeAP//AQAAAAAAAAAeAP7/AQAAAAAAAAAeAP3/AQAAAAAAAAAeAPz/AQAAAAAAAAARAPz/AQAAAAAAAAARAP3/AQAAAAAAAAARAP7/AQAAAAAAAAARAP//AQAAAAAAAAARAAAAAQAAAAAAAAARAAEAAQAAAAAAAAARAAIAAQAAAAAAAAA=") 37 | tile_set = SubResource("TileSet_k0n52") 38 | rendering_quadrant_size = 32 39 | navigation_enabled = false 40 | 41 | [node name="Player" parent="." instance=ExtResource("4_bfb5o")] 42 | 43 | [node name="Exit" parent="." instance=ExtResource("5_38t8g")] 44 | position = Vector2(336, -440) 45 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Levels/level_4.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=4 uid="uid://dujrsjsrhhiok"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://t3fobsr7gklg" path="res://Games/Super Bit Boy/Scenes/Levels/level_1.tscn" id="1_v5afu"] 4 | 5 | [node name="Level 4" instance=ExtResource("1_v5afu")] 6 | next_level_number = 5 7 | 8 | [node name="Layer0" parent="." index="1"] 9 | tile_map_data = PackedByteArray("AAD+/wEAAQAAAAAAAAD+/wIAAQAAAAAAAAD//wEAAQAAAAAAAAD//wIAAQAAAAAAAAAAAAEAAQAAAAAAAAAAAAIAAQAAAAAAAAABAAEAAQAAAAAAAAABAAIAAQAAAAAAAAACAAEAAQAAAAAAAAACAAIAAQAAAAAAAAADAAEAAQAAAAAAAAADAAIAAQAAAAAAAAAEAAEAAQAAAAAAAQAEAAIAAQAAAAAAAAAFAAEAAQAAAAAAAQAFAAIAAQAAAAAAAAD8/wEAAQAAAAAAAAD8/wIAAQAAAAAAAAD9/wEAAQAAAAAAAAD9/wIAAQAAAAAAAAAGAAEAAQAAAAAAAQAGAAIAAQAAAAAAAAAHAAEAAQAAAAAAAQAHAAIAAQAAAAAAAAAIAAEAAQAAAAAAAQAIAAIAAQAAAAAAAAAJAAEAAQAAAAAAAQAJAAIAAQAAAAAAAAAKAAEAAQAAAAAAAQAKAAIAAQAAAAAAAAALAAEAAQAAAAAAAQALAAIAAQAAAAAAAAAMAAEAAQAAAAAAAAAMAAIAAQAAAAAAAAASAAEAAQAAAAAAAQASAAIAAQAAAAAAAAATAAEAAQAAAAAAAQATAAIAAQAAAAAAAAAUAAEAAQAAAAAAAQAUAAIAAQAAAAAAAAAVAAEAAQAAAAAAAQAVAAIAAQAAAAAAAAAWAAEAAQAAAAAAAQAWAAIAAQAAAAAAAAAbAAEAAQAAAAAAAAAbAAIAAQAAAAAAAAAcAAEAAQAAAAAAAAAcAAIAAQAAAAAAAAAdAAEAAQAAAAAAAAAdAAIAAQAAAAAAAAAeAAEAAQAAAAAAAAAeAAIAAQAAAAAAAAARAAEAAQAAAAAAAQARAAIAAQAAAAAAAAANAAIAAQAAAAAAAAAOAAIAAQAAAAAAAAAPAAIAAQAAAAAAAAAQAAIAAQAAAAAAAAANAAEAAQAAAAAAAAAOAAEAAQAAAAAAAAAPAAEAAQAAAAAAAAAQAAEAAQAAAAAAAQAXAAEAAQAAAAAAAQAYAAEAAQAAAAAAAQAZAAEAAQAAAAAAAQAaAAEAAQAAAAAAAQAXAAIAAQAAAAAAAAAYAAIAAQAAAAAAAAAZAAIAAQAAAAAAAAAaAAIAAQAAAAAAAAAfAAEAAQAAAAAAAAAfAAIAAQAAAAAAAAAgAAEAAQAAAAAAAAAgAAIAAQAAAAAAAAAhAAEAAQAAAAAAAAAhAAIAAQAAAAAAAAAiAAEAAQAAAAAAAAAiAAIAAQAAAAAAAAAjAAEAAQAAAAAAAAAjAAIAAQAAAAAAAAAkAAEAAQAAAAAAAAAkAAIAAQAAAAAAAAAlAAEAAQAAAAAAAAAlAAIAAQAAAAAAAAAmAAEAAQAAAAAAAAAmAAIAAQAAAAAAAAAnAAEAAQAAAAAAAAAnAAIAAQAAAAAAAAAoAAEAAQAAAAAAAAAoAAIAAQAAAAAAAAApAAEAAQAAAAAAAAApAAIAAQAAAAAAAAAqAAEAAQAAAAAAAAAqAAIAAQAAAAAAAAArAAEAAQAAAAAAAAArAAIAAQAAAAAAAAAsAAEAAQAAAAAAAAAsAAIAAQAAAAAAAAAtAAEAAQAAAAAAAAAtAAIAAQAAAAAAAAAuAAEAAQAAAAAAAAAuAAIAAQAAAAAAAAAvAAEAAQAAAAAAAAAvAAIAAQAAAAAAAAAwAAEAAQAAAAAAAAAwAAIAAQAAAAAAAAAxAAEAAQAAAAAAAAAxAAIAAQAAAAAAAAAyAAEAAQAAAAAAAAAyAAIAAQAAAAAAAAAzAAEAAQAAAAAAAAAzAAIAAQAAAAAAAAA0AAEAAQAAAAAAAAA0AAIAAQAAAAAAAAA1AAEAAQAAAAAAAAA1AAIAAQAAAAAAAAAgAPz/AQAAAAAAAQAgAP3/AQAAAAAAAQAgAP7/AQAAAAAAAQAgAP//AQAAAAAAAQAhAPz/AQAAAAAAAQAhAP3/AQAAAAAAAQAhAP7/AQAAAAAAAQAhAP//AQAAAAAAAQAhAAAAAQAAAAAAAQAgAAAAAQAAAAAAAQAoAP7/AQAAAAAAAQAoAP//AQAAAAAAAQAoAAAAAQAAAAAAAQApAP7/AQAAAAAAAQApAP//AQAAAAAAAQApAAAAAQAAAAAAAQAqAP7/AQAAAAAAAQAqAP//AQAAAAAAAQAqAAAAAQAAAAAAAQArAP7/AQAAAAAAAQArAP//AQAAAAAAAQArAAAAAQAAAAAAAQAsAP7/AQAAAAAAAQAsAP//AQAAAAAAAQAsAAAAAQAAAAAAAQAtAP7/AQAAAAAAAQAtAP//AQAAAAAAAQAtAAAAAQAAAAAAAQA=") 10 | navigation_enabled = false 11 | 12 | [node name="Exit" parent="." index="3"] 13 | position = Vector2(1672, 8) 14 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Levels/level_6.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=4 uid="uid://bx2smsox65681"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://t3fobsr7gklg" path="res://Games/Super Bit Boy/Scenes/Levels/level_1.tscn" id="1_lwyqn"] 4 | 5 | [node name="Level 6" instance=ExtResource("1_lwyqn")] 6 | next_level_number = 7 7 | 8 | [node name="Layer0" parent="." index="1"] 9 | tile_map_data = PackedByteArray("AAD+/wEAAQAAAAAAAAD+/wIAAQAAAAAAAAD//wEAAQAAAAAAAAD//wIAAQAAAAAAAAAAAAEAAQAAAAAAAAAAAAIAAQAAAAAAAAABAAEAAQAAAAAAAAABAAIAAQAAAAAAAAAEAPr/AQAAAAAAAAADAPr/AQAAAAAAAAACAPr/AQAAAAAAAAACAPv/AQAAAAAAAAADAPv/AQAAAAAAAAAEAPv/AQAAAAAAAAAFAPv/AQAAAAAAAAAGAPv/AQAAAAAAAAAHAPv/AQAAAAAAAAAFAPr/AQAAAAAAAQAGAPr/AQAAAAAAAQAHAPr/AQAAAAAAAQD8/+3/AQAAAAAAAAD8/+7/AQAAAAAAAAD8/+//AQAAAAAAAAD8//D/AQAAAAAAAAD8//H/AQAAAAAAAAD8//L/AQAAAAAAAAD8//P/AQAAAAAAAAD8//T/AQAAAAAAAAD8//X/AQAAAAAAAAD8//b/AQAAAAAAAAD7//b/AQAAAAAAAAD7//f/AQAAAAAAAAD8//f/AQAAAAAAAAD7//X/AQAAAAAAAAD7//T/AQAAAAAAAAD7//P/AQAAAAAAAAD7//L/AQAAAAAAAAD7//H/AQAAAAAAAAD7//D/AQAAAAAAAAD7/+//AQAAAAAAAAD7/+7/AQAAAAAAAAD7/+3/AQAAAAAAAAD2//b/AQAAAAAAAAD1//b/AQAAAAAAAAD0//b/AQAAAAAAAADz//b/AQAAAAAAAADz//f/AQAAAAAAAAD0//f/AQAAAAAAAAD1//f/AQAAAAAAAAD2//f/AQAAAAAAAADu/+7/AQAAAAAAAADt/+7/AQAAAAAAAADt/+//AQAAAAAAAADt//D/AQAAAAAAAADt//H/AQAAAAAAAADt//L/AQAAAAAAAADt//P/AQAAAAAAAADt//T/AQAAAAAAAADt//X/AQAAAAAAAADt//b/AQAAAAAAAADt//f/AQAAAAAAAADu//f/AQAAAAAAAADu//b/AQAAAAAAAADu//X/AQAAAAAAAADu//T/AQAAAAAAAADu//P/AQAAAAAAAADu//L/AQAAAAAAAADu//H/AQAAAAAAAADu//D/AQAAAAAAAADu/+//AQAAAAAAAADu/+3/AQAAAAAAAQDt/+3/AQAAAAAAAQDj/+3/AQAAAAAAAADi/+3/AQAAAAAAAADh/+3/AQAAAAAAAADg/+3/AQAAAAAAAADg/+7/AQAAAAAAAADh/+7/AQAAAAAAAADi/+7/AQAAAAAAAADj/+7/AQAAAAAAAADj/+//AQAAAAAAAADj//D/AQAAAAAAAADj//H/AQAAAAAAAADj//L/AQAAAAAAAADj//P/AQAAAAAAAADj//T/AQAAAAAAAADj//X/AQAAAAAAAADj//b/AQAAAAAAAADj//f/AQAAAAAAAADi//f/AQAAAAAAAADi//b/AQAAAAAAAADi//X/AQAAAAAAAADi//T/AQAAAAAAAADi//P/AQAAAAAAAADi//L/AQAAAAAAAADi//H/AQAAAAAAAADi//D/AQAAAAAAAADi/+//AQAAAAAAAAA=") 10 | navigation_enabled = false 11 | 12 | [node name="Exit" parent="." index="3"] 13 | position = Vector2(-1000, -632) 14 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Levels/level_7.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=8 format=4 uid="uid://c8sl1hy61anw3"] 2 | 3 | [ext_resource type="Script" uid="uid://5s567w1vfwab" path="res://Games/Super Bit Boy/Scenes/Levels/bit_boy_scene_manager.gd" id="1_ris1d"] 4 | [ext_resource type="PackedScene" uid="uid://chfpq4oi0dogc" path="res://Games/Super Bit Boy/Other Scenes/bit_boy_camera.tscn" id="2_6wxcj"] 5 | [ext_resource type="Texture2D" uid="uid://bwxnhif5h1cck" path="res://Art/Pixel_32.png" id="3_bc8ps"] 6 | [ext_resource type="PackedScene" uid="uid://bxv24mjcranba" path="res://Games/Super Bit Boy/Scenes/Player/bit_boy_player.tscn" id="4_7qker"] 7 | [ext_resource type="PackedScene" uid="uid://b3u7st4i1algn" path="res://Games/Super Bit Boy/Scenes/Exit/bit_boy_exit.tscn" id="5_rxqvu"] 8 | 9 | [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_kk343"] 10 | texture = ExtResource("3_bc8ps") 11 | texture_region_size = Vector2i(32, 32) 12 | 0:0/next_alternative_id = 2 13 | 0:0/0 = 0 14 | 0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) 15 | 0:0/1 = 1 16 | 0:0/1/modulate = Color(1, 0, 0, 1) 17 | 0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(-10.6667, -10.6667, 10.6667, -10.6667, 10.6667, 10.6667, -10.6667, 10.6667) 18 | 0:0/1/custom_data_0 = true 19 | 20 | [sub_resource type="TileSet" id="TileSet_k0n52"] 21 | tile_size = Vector2i(32, 32) 22 | physics_layer_0/collision_layer = 1 23 | custom_data_layer_0/name = "instakill" 24 | custom_data_layer_0/type = 1 25 | sources/1 = SubResource("TileSetAtlasSource_kk343") 26 | 27 | [node name="Level 7" type="Node2D"] 28 | script = ExtResource("1_ris1d") 29 | next_level_number = 8 30 | 31 | [node name="Camera2D" parent="." instance=ExtResource("2_6wxcj")] 32 | 33 | [node name="Layer0" type="TileMapLayer" parent="."] 34 | modulate = Color(0.615686, 0.615686, 0.615686, 1) 35 | use_parent_material = true 36 | tile_map_data = PackedByteArray("AAD+/wEAAQAAAAAAAAD//wEAAQAAAAAAAAAAAAEAAQAAAAAAAAABAAEAAQAAAAAAAAACAAEAAQAAAAAAAAD9/wEAAQAAAAAAAAD9/wIAAQAAAAAAAAD+/wIAAQAAAAAAAAD//wIAAQAAAAAAAAAAAAIAAQAAAAAAAAABAAIAAQAAAAAAAAACAAIAAQAAAAAAAAADAAEAAQAAAAAAAAADAAIAAQAAAAAAAAAEAAEAAQAAAAAAAAAEAAIAAQAAAAAAAAAFAAEAAQAAAAAAAAAFAAIAAQAAAAAAAAAHAPz/AQAAAAAAAAAHAP3/AQAAAAAAAQAIAPz/AQAAAAAAAAAIAP3/AQAAAAAAAQAJAPz/AQAAAAAAAAAJAP3/AQAAAAAAAQAGAAEAAQAAAAAAAAAGAAIAAQAAAAAAAAAHAAEAAQAAAAAAAQAHAAIAAQAAAAAAAQAIAAEAAQAAAAAAAQAIAAIAAQAAAAAAAQAJAAEAAQAAAAAAAQAJAAIAAQAAAAAAAQAHAP7/AQAAAAAAAQAHAP//AQAAAAAAAQAHAAAAAQAAAAAAAQAIAP7/AQAAAAAAAQAIAP//AQAAAAAAAQAIAAAAAQAAAAAAAQAJAP7/AQAAAAAAAQAJAP//AQAAAAAAAQAJAAAAAQAAAAAAAQAHAO7/AQAAAAAAAQAHAO//AQAAAAAAAQAHAPD/AQAAAAAAAQAHAPH/AQAAAAAAAQAIAO7/AQAAAAAAAQAIAO//AQAAAAAAAQAIAPD/AQAAAAAAAQAIAPH/AQAAAAAAAQAJAO7/AQAAAAAAAQAJAO//AQAAAAAAAQAJAPD/AQAAAAAAAQAJAPH/AQAAAAAAAQAHAPv/AQAAAAAAAAAIAPv/AQAAAAAAAAAJAPv/AQAAAAAAAAAHAPn/AQAAAAAAAQAHAPr/AQAAAAAAAAAIAPn/AQAAAAAAAQAIAPr/AQAAAAAAAAAJAPn/AQAAAAAAAQAJAPr/AQAAAAAAAAAKAAEAAQAAAAAAAQAKAAIAAQAAAAAAAQALAAEAAQAAAAAAAQALAAIAAQAAAAAAAQAMAAEAAQAAAAAAAQAMAAIAAQAAAAAAAQANAAEAAQAAAAAAAQANAAIAAQAAAAAAAQAOAAEAAQAAAAAAAQAOAAIAAQAAAAAAAQAPAAEAAQAAAAAAAQAPAAIAAQAAAAAAAQAQAAEAAQAAAAAAAQAQAAIAAQAAAAAAAQARAAEAAQAAAAAAAQARAAIAAQAAAAAAAQASAAEAAQAAAAAAAQASAAIAAQAAAAAAAQATAAEAAQAAAAAAAQATAAIAAQAAAAAAAQAUAAEAAQAAAAAAAQAUAAIAAQAAAAAAAQAHAPL/AQAAAAAAAQAIAPL/AQAAAAAAAQAJAPL/AQAAAAAAAQAHAPP/AQAAAAAAAQAIAPP/AQAAAAAAAQAJAPP/AQAAAAAAAQAVAAEAAQAAAAAAAAAVAAIAAQAAAAAAAAAWAAEAAQAAAAAAAAAWAAIAAQAAAAAAAAAXAAEAAQAAAAAAAAAXAAIAAQAAAAAAAAAYAAEAAQAAAAAAAAAYAAIAAQAAAAAAAAAZAAEAAQAAAAAAAAAZAAIAAQAAAAAAAAAaAAEAAQAAAAAAAAAaAAIAAQAAAAAAAAAbAAEAAQAAAAAAAAAbAAIAAQAAAAAAAAAcAAEAAQAAAAAAAAAcAAIAAQAAAAAAAAA=") 37 | tile_set = SubResource("TileSet_k0n52") 38 | rendering_quadrant_size = 32 39 | navigation_enabled = false 40 | 41 | [node name="Player" parent="." instance=ExtResource("4_7qker")] 42 | 43 | [node name="Exit" parent="." instance=ExtResource("5_rxqvu")] 44 | position = Vector2(904, 8) 45 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Levels/level_8.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=4 uid="uid://dgq3l7xgb6fgo"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://t3fobsr7gklg" path="res://Games/Super Bit Boy/Scenes/Levels/level_1.tscn" id="1_70jjr"] 4 | 5 | [node name="Level 8" instance=ExtResource("1_70jjr")] 6 | next_level_number = 9 7 | 8 | [node name="Layer0" parent="." index="1"] 9 | tile_map_data = PackedByteArray("AAD+/wEAAQAAAAAAAAD+/wIAAQAAAAAAAAD//wEAAQAAAAAAAAD//wIAAQAAAAAAAAAAAAEAAQAAAAAAAAAAAAIAAQAAAAAAAAABAAEAAQAAAAAAAAABAAIAAQAAAAAAAAACAAEAAQAAAAAAAAACAAIAAQAAAAAAAAADAAEAAQAAAAAAAAADAAIAAQAAAAAAAAD8/wEAAQAAAAAAAAD8/wIAAQAAAAAAAAD9/wEAAQAAAAAAAAD9/wIAAQAAAAAAAAAFAPv/AQAAAAAAAAAGAPv/AQAAAAAAAAAHAPv/AQAAAAAAAAD9//n/AQAAAAAAAAD8//n/AQAAAAAAAQD7//n/AQAAAAAAAQD6//n/AQAAAAAAAQD4//D/AQAAAAAAAQD4//H/AQAAAAAAAQD4//L/AQAAAAAAAQD4/+3/AQAAAAAAAAD4/+7/AQAAAAAAAAD4/+//AQAAAAAAAAD4//P/AQAAAAAAAAD4//T/AQAAAAAAAAD4//X/AQAAAAAAAAD//+j/AQAAAAAAAAD//+n/AQAAAAAAAAD//+r/AQAAAAAAAAD//+v/AQAAAAAAAAD//+z/AQAAAAAAAAD//+f/AQAAAAAAAQAJAOz/AQAAAAAAAQAKAOz/AQAAAAAAAQALAOz/AQAAAAAAAQAMAOz/AQAAAAAAAQANAOz/AQAAAAAAAQAOAOz/AQAAAAAAAQAPAOz/AQAAAAAAAAAQAOz/AQAAAAAAAAARAOz/AQAAAAAAAAASAOz/AQAAAAAAAAATAOb/AQAAAAAAAAASAOb/AQAAAAAAAAAEAN3/AQAAAAAAAAADAN3/AQAAAAAAAAANAOH/AQAAAAAAAAD+/9X/AQAAAAAAAAD+/9b/AQAAAAAAAAD+/9f/AQAAAAAAAAD+/9j/AQAAAAAAAAD+/9D/AQAAAAAAAAD+/9H/AQAAAAAAAAD+/9L/AQAAAAAAAAD+/9P/AQAAAAAAAAD9/9T/AQAAAAAAAQD+/9T/AQAAAAAAAQD//9T/AQAAAAAAAQAFAM//AQAAAAAAAAAGAM//AQAAAAAAAAAHAM//AQAAAAAAAAAIAM//AQAAAAAAAAA=") 10 | navigation_enabled = false 11 | 12 | [node name="Exit" parent="." index="3"] 13 | position = Vector2(264, -1592) 14 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Levels/level_9.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=4 uid="uid://bpmgyuhkxtukf"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://t3fobsr7gklg" path="res://Games/Super Bit Boy/Scenes/Levels/level_1.tscn" id="1_643c7"] 4 | 5 | [node name="Level 9" instance=ExtResource("1_643c7")] 6 | next_level_number = 1 7 | 8 | [node name="Layer0" parent="." index="1"] 9 | tile_map_data = PackedByteArray("AAD+/wEAAQAAAAAAAAD+/wIAAQAAAAAAAAD//wEAAQAAAAAAAAD//wIAAQAAAAAAAAAAAAEAAQAAAAAAAAAAAAIAAQAAAAAAAAABAAEAAQAAAAAAAAABAAIAAQAAAAAAAAACAAEAAQAAAAAAAAACAAIAAQAAAAAAAAADAAEAAQAAAAAAAAADAAIAAQAAAAAAAAAEAAEAAQAAAAAAAAAEAAIAAQAAAAAAAAAFAAEAAQAAAAAAAAAFAAIAAQAAAAAAAAD8/wEAAQAAAAAAAAD8/wIAAQAAAAAAAAD9/wEAAQAAAAAAAAD9/wIAAQAAAAAAAAAGAAEAAQAAAAAAAAAGAAIAAQAAAAAAAAAHAAAAAQAAAAAAAAAHAAEAAQAAAAAAAAAHAAIAAQAAAAAAAAAIAP7/AQAAAAAAAAAIAP//AQAAAAAAAAAIAAAAAQAAAAAAAAAIAAEAAQAAAAAAAAAIAAIAAQAAAAAAAAAHAP//AQAAAAAAAAAIAPz/AQAAAAAAAAAIAP3/AQAAAAAAAAAIAPT/AQAAAAAAAAD3/wEAAQAAAAAAAAD4/wEAAQAAAAAAAAD5/wEAAQAAAAAAAAD6/wEAAQAAAAAAAAD7/wEAAQAAAAAAAAD7/wIAAQAAAAAAAAD6/wIAAQAAAAAAAAD5/wIAAQAAAAAAAAD4/wIAAQAAAAAAAAD3/wIAAQAAAAAAAAD3/wAAAQAAAAAAAAD3////AQAAAAAAAAD3//7/AQAAAAAAAAD3//3/AQAAAAAAAAD3//z/AQAAAAAAAAD3//v/AQAAAAAAAAD3//r/AQAAAAAAAAD3//n/AQAAAAAAAAD3//j/AQAAAAAAAAD3//f/AQAAAAAAAAD3//b/AQAAAAAAAAD3//X/AQAAAAAAAAD3//T/AQAAAAAAAAD4//T/AQAAAAAAAAD5//T/AQAAAAAAAAD6//T/AQAAAAAAAAD7//T/AQAAAAAAAAD8//T/AQAAAAAAAAD9//T/AQAAAAAAAAD+//T/AQAAAAAAAAD///T/AQAAAAAAAAAAAPT/AQAAAAAAAAABAPT/AQAAAAAAAAACAPT/AQAAAAAAAAADAPT/AQAAAAAAAAAEAPT/AQAAAAAAAAAFAPT/AQAAAAAAAAAGAPT/AQAAAAAAAAAHAPT/AQAAAAAAAAAIAPX/AQAAAAAAAAAIAPb/AQAAAAAAAAAIAPf/AQAAAAAAAAAIAPj/AQAAAAAAAAAIAPn/AQAAAAAAAAAIAPr/AQAAAAAAAAAIAPv/AQAAAAAAAAAHAP7/AQAAAAAAAAAHAP3/AQAAAAAAAAAHAPz/AQAAAAAAAAAHAPv/AQAAAAAAAAAHAPr/AQAAAAAAAAAHAPn/AQAAAAAAAAAHAPj/AQAAAAAAAAAHAPf/AQAAAAAAAAAHAPb/AQAAAAAAAAAHAPX/AQAAAAAAAAAGAPX/AQAAAAAAAAAFAPX/AQAAAAAAAAAEAPX/AQAAAAAAAAADAPX/AQAAAAAAAAACAPX/AQAAAAAAAAABAPX/AQAAAAAAAAAAAPX/AQAAAAAAAAD///X/AQAAAAAAAAD+//X/AQAAAAAAAAD9//X/AQAAAAAAAAD8//X/AQAAAAAAAAD7//X/AQAAAAAAAAD6//X/AQAAAAAAAAD5//X/AQAAAAAAAAD4//X/AQAAAAAAAAD4//b/AQAAAAAAAAD4//f/AQAAAAAAAAD4//j/AQAAAAAAAAD4//n/AQAAAAAAAAD4//r/AQAAAAAAAAD4//v/AQAAAAAAAAD4//z/AQAAAAAAAAD4//3/AQAAAAAAAAD4//7/AQAAAAAAAAD4/wAAAQAAAAAAAAD4////AQAAAAAAAAA=") 10 | 11 | [node name="Exit" parent="." index="3"] 12 | position = Vector2(1632, -120) 13 | 14 | [node name="RichTextLabel" type="RichTextLabel" parent="." index="4"] 15 | offset_left = -216.0 16 | offset_top = -312.0 17 | offset_right = 216.0 18 | offset_bottom = -216.0 19 | theme_override_font_sizes/normal_font_size = 64 20 | bbcode_enabled = true 21 | text = "[center]YOU WIN!" 22 | 23 | [node name="RichTextLabel2" type="RichTextLabel" parent="." index="5"] 24 | offset_left = -216.0 25 | offset_top = -216.0 26 | offset_right = 216.0 27 | offset_bottom = -120.0 28 | theme_override_font_sizes/normal_font_size = 26 29 | bbcode_enabled = true 30 | text = "[center]More levels in the future... Maybe." 31 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Levels/test.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=9 format=3 uid="uid://b7c1q7v5qtx28"] 2 | 3 | [ext_resource type="Script" uid="uid://65kr3tt4jbk2" path="res://Games/Super Bit Boy/Other Scenes/bit_boy_camera.gd" id="1_1vy60"] 4 | [ext_resource type="Script" uid="uid://5s567w1vfwab" path="res://Games/Super Bit Boy/Scenes/Levels/bit_boy_scene_manager.gd" id="1_mbrs5"] 5 | [ext_resource type="Texture2D" uid="uid://bwxnhif5h1cck" path="res://Art/Pixel_32.png" id="1_uhyve"] 6 | [ext_resource type="PackedScene" uid="uid://bxv24mjcranba" path="res://Games/Super Bit Boy/Scenes/Player/bit_boy_player.tscn" id="2_aaiv1"] 7 | 8 | [sub_resource type="Gradient" id="Gradient_yyofs"] 9 | offsets = PackedFloat32Array(0) 10 | colors = PackedColorArray(0, 0, 0, 1) 11 | 12 | [sub_resource type="GradientTexture1D" id="GradientTexture1D_xxn30"] 13 | gradient = SubResource("Gradient_yyofs") 14 | width = 1920 15 | 16 | [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_kk343"] 17 | texture = ExtResource("1_uhyve") 18 | texture_region_size = Vector2i(32, 32) 19 | 0:0/next_alternative_id = 2 20 | 0:0/0 = 0 21 | 0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) 22 | 0:0/1 = 1 23 | 0:0/1/modulate = Color(1, 0, 0, 1) 24 | 0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(-10.6667, -10.6667, 10.6667, -10.6667, 10.6667, 10.6667, -10.6667, 10.6667) 25 | 0:0/1/custom_data_0 = true 26 | 27 | [sub_resource type="TileSet" id="TileSet_k0n52"] 28 | tile_size = Vector2i(32, 32) 29 | physics_layer_0/collision_layer = 1 30 | custom_data_layer_0/name = "instakill" 31 | custom_data_layer_0/type = 1 32 | sources/1 = SubResource("TileSetAtlasSource_kk343") 33 | 34 | [node name="Test Scene" type="Node2D"] 35 | script = ExtResource("1_mbrs5") 36 | 37 | [node name="Camera2D" type="Camera2D" parent="."] 38 | process_callback = 0 39 | position_smoothing_enabled = true 40 | position_smoothing_speed = 7.0 41 | script = ExtResource("1_1vy60") 42 | 43 | [node name="Sprite2D" type="Sprite2D" parent="Camera2D"] 44 | scale = Vector2(1, 1920) 45 | texture = SubResource("GradientTexture1D_xxn30") 46 | 47 | [node name="TileMap" type="TileMap" parent="."] 48 | modulate = Color(0.615686, 0.615686, 0.615686, 1) 49 | tile_set = SubResource("TileSet_k0n52") 50 | rendering_quadrant_size = 32 51 | format = 2 52 | layer_0/tile_data = PackedInt32Array(262143, 1, 0, 196608, 1, 0, 196609, 1, 0, 262142, 1, 0, 262141, 1, 0, 262140, 1, 0, 262139, 1, 0, 327675, 1, 0, 327676, 1, 0, 327677, 1, 0, 327678, 1, 0, 327679, 1, 0, 262144, 1, 0, 262145, 1, 0, 262146, 1, 0, 196610, 1, 0, 196611, 1, 0, 262147, 1, 0, -327675, 1, 0, -262139, 1, 0, -65531, 1, 0, 5, 1, 0, 65541, 1, 0, 131077, 1, 0, 196613, 1, 0, 262149, 1, 0, 262148, 1, 0, 327674, 1, 0, 262138, 1, 0, 196602, 1, 0, 131066, 1, 0, 65530, 1, 0, -6, 1, 0, -196614, 1, 0, -262150, 1, 0, -327686, 1, 0, -327687, 1, 0, -262151, 1, 0, -196615, 1, 0, -131079, 1, 0, -65543, 1, 0, 262137, 1, 0, 327673, 1, 0, 196601, 1, 0, 131065, 1, 0, 65529, 1, 0, -7, 1, 0, -458758, 1, 0, -393222, 1, 0, -393223, 1, 0, -458759, 1, 0, -393211, 1, 0, -458747, 1, 0, -524283, 1, 0, 196612, 1, 0, 262150, 1, 0, 196614, 1, 0, 131078, 1, 0, 65542, 1, 0, 6, 1, 0, -65530, 1, 0, -131066, 1, 0, -196602, 1, 0, -262138, 1, 0, -327674, 1, 0, -393210, 1, 0, -458746, 1, 0, -524282, 1, 0, -65542, 1, 65536, -131078, 1, 65536, -196603, 1, 65536, -131067, 1, 65536) 53 | 54 | [node name="Player" parent="." instance=ExtResource("2_aaiv1")] 55 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Player/bit_boy_player.gd: -------------------------------------------------------------------------------- 1 | extends CharacterBody2D 2 | class_name BitBoyPlayer 3 | 4 | const ACCELERATION: float = 50.0 5 | const SPEED: float = 400.0 6 | const JUMP_VELOCITY: float = -600.0 7 | const GRAVITY: float = 980.0 8 | 9 | var is_dead: bool 10 | var bonus_velocity: Vector2 11 | 12 | var x_direction: float 13 | var left_walljump_active: bool 14 | var right_walljump_active: bool 15 | 16 | # TODO put input in _input() which for some reason is a pain in the ass 17 | 18 | func _physics_process(delta: float) -> void: 19 | if is_dead: 20 | return 21 | 22 | if not is_on_floor(): 23 | velocity.y += GRAVITY * delta 24 | 25 | if Input.is_action_just_pressed("jump"): 26 | if is_on_floor(): 27 | velocity.y = JUMP_VELOCITY 28 | elif left_walljump_active: 29 | walljump(true) 30 | elif right_walljump_active: 31 | walljump(false) 32 | 33 | x_direction = Input.get_axis("move_left", "move_right") 34 | if x_direction: 35 | velocity.x += x_direction * ACCELERATION 36 | else: 37 | velocity.x = move_toward(velocity.x, 0, ACCELERATION / 2) 38 | 39 | if velocity.x > 400: 40 | velocity.x = move_toward(velocity.x, 400, ACCELERATION) 41 | elif velocity.x < -400: 42 | velocity.x = move_toward(velocity.x, -400, ACCELERATION) 43 | 44 | if velocity.y < -750: 45 | velocity.y = move_toward(velocity.y, -750, ACCELERATION) 46 | 47 | velocity += bonus_velocity 48 | if bonus_velocity: 49 | bonus_velocity.x = move_toward(bonus_velocity.x, 0, ACCELERATION) 50 | bonus_velocity.y = move_toward(bonus_velocity.y, 0, ACCELERATION) 51 | 52 | if velocity.y > 2000: 53 | die() 54 | 55 | move_and_slide() 56 | 57 | detect_custom_tile_data() 58 | 59 | func walljump(left: bool) -> void: 60 | if velocity.y > 0: 61 | velocity.y = JUMP_VELOCITY * 0.90 62 | else: 63 | velocity.y += JUMP_VELOCITY * 0.90 64 | if left: 65 | velocity.x = 400 66 | bonus_velocity.x += 150 67 | else: 68 | velocity.x = -400 69 | bonus_velocity.x -= 150 70 | 71 | func die() -> void: 72 | is_dead = true 73 | velocity = Vector2.ZERO 74 | bonus_velocity = Vector2.ZERO 75 | modulate = Color.CRIMSON 76 | await get_tree().create_timer(0.75).timeout 77 | get_parent().reload_scene() 78 | 79 | func win() -> void: 80 | is_dead = true # Just so the player stops moving around 81 | velocity = Vector2.ZERO 82 | bonus_velocity = Vector2.ZERO 83 | modulate = Color.SPRING_GREEN 84 | await get_tree().create_timer(0.75).timeout 85 | get_parent().load_next_scene() 86 | 87 | func detect_custom_tile_data() -> void: 88 | for i in range(get_slide_collision_count()): 89 | var collision: KinematicCollision2D = get_slide_collision(i) 90 | if collision.get_collider() is TileMapLayer: 91 | var tilemap_layer: TileMapLayer = collision.get_collider() 92 | var tile_coords: Vector2i = tilemap_layer.get_coords_for_body_rid(collision.get_collider_rid()) 93 | var tile_data: TileData = tilemap_layer.get_cell_tile_data(tile_coords) 94 | if tile_data.get_custom_data("instakill"): 95 | die() 96 | 97 | func _on_left_wall_jump_area_2d_body_entered(body: Node2D) -> void: 98 | if body is StaticBody2D or body is TileMapLayer: 99 | left_walljump_active = true 100 | 101 | func _on_left_wall_jump_area_2d_body_exited(body: Node2D) -> void: 102 | if body is StaticBody2D or body is TileMapLayer: 103 | left_walljump_active = false 104 | 105 | func _on_right_wall_jump_area_2d_body_entered(body: Node2D) -> void: 106 | if body is StaticBody2D or body is TileMapLayer: 107 | right_walljump_active = true 108 | 109 | func _on_right_wall_jump_area_2d_body_exited(body: Node2D) -> void: 110 | if body is StaticBody2D or body is TileMapLayer: 111 | right_walljump_active = false 112 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Player/bit_boy_player.gd.uid: -------------------------------------------------------------------------------- 1 | uid://b0iyafva2jgrt 2 | -------------------------------------------------------------------------------- /Games/Super Bit Boy/Scenes/Player/bit_boy_player.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://bxv24mjcranba"] 2 | 3 | [ext_resource type="Script" uid="uid://b0iyafva2jgrt" path="res://Games/Super Bit Boy/Scenes/Player/bit_boy_player.gd" id="1_pr5ix"] 4 | 5 | [sub_resource type="RectangleShape2D" id="RectangleShape2D_adjwb"] 6 | size = Vector2(32, 32) 7 | 8 | [sub_resource type="Gradient" id="Gradient_njy6s"] 9 | offsets = PackedFloat32Array(1) 10 | colors = PackedColorArray(1, 1, 1, 1) 11 | 12 | [sub_resource type="GradientTexture1D" id="GradientTexture1D_fxqk7"] 13 | gradient = SubResource("Gradient_njy6s") 14 | width = 32 15 | 16 | [sub_resource type="RectangleShape2D" id="RectangleShape2D_nc7re"] 17 | size = Vector2(10, 30) 18 | 19 | [node name="Player" type="CharacterBody2D"] 20 | script = ExtResource("1_pr5ix") 21 | 22 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 23 | shape = SubResource("RectangleShape2D_adjwb") 24 | 25 | [node name="Sprite2D" type="Sprite2D" parent="."] 26 | scale = Vector2(1, 32) 27 | texture = SubResource("GradientTexture1D_fxqk7") 28 | 29 | [node name="Wall Jump Areas" type="Node2D" parent="."] 30 | 31 | [node name="LeftWallJumpArea2D" type="Area2D" parent="Wall Jump Areas"] 32 | 33 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Wall Jump Areas/LeftWallJumpArea2D"] 34 | position = Vector2(-18, 0) 35 | shape = SubResource("RectangleShape2D_nc7re") 36 | 37 | [node name="RightWallJumpArea2D" type="Area2D" parent="Wall Jump Areas"] 38 | 39 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Wall Jump Areas/RightWallJumpArea2D"] 40 | position = Vector2(18, 0) 41 | shape = SubResource("RectangleShape2D_nc7re") 42 | 43 | [connection signal="body_entered" from="Wall Jump Areas/LeftWallJumpArea2D" to="." method="_on_left_wall_jump_area_2d_body_entered"] 44 | [connection signal="body_exited" from="Wall Jump Areas/LeftWallJumpArea2D" to="." method="_on_left_wall_jump_area_2d_body_exited"] 45 | [connection signal="body_entered" from="Wall Jump Areas/RightWallJumpArea2D" to="." method="_on_right_wall_jump_area_2d_body_entered"] 46 | [connection signal="body_exited" from="Wall Jump Areas/RightWallJumpArea2D" to="." method="_on_right_wall_jump_area_2d_body_exited"] 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GodotOS | [Trailer](https://www.youtube.com/watch?v=44LcozXequw) 2 | 3 | Welcome to GodotOS, an operating system interface created entirely in Godot! Browse folders, edit text files, view images, play games, and more in one cohesive polished interface that can even be used on the web! 4 | 5 | ![image](https://github.com/popcar2/GodotOS/assets/16920817/cf2bb818-4135-46fb-8cfe-43879a826fcc) 6 | 7 | GodotOS is more of a toy than a serious project. It's meant to push the limits on UI design in Godot while creating a desktop that is minimalist, distraction-free, and aesthetically pleasing. 8 | 9 | Aside from that, GodotOS is also meant to be a hub for small games and experiences that can easily be bundled in. Want to add your own game to the start menu? Check the [contributing guide!](CONTRIBUTING.md) 10 | 11 | # Download 12 | 13 | * Try the web version on [Itch.io page](https://popcar2.itch.io/godotos) 14 | * Download all versions from the [releases page](https://github.com/popcar2/GodotOS/releases) 15 | 16 | # Credits 17 | 18 | * GodotOS was made by me, popcar2. 19 | * [Default wallpaper](https://unsplash.com/photos/snow-capped-mountain-at-night-3s85IxVDyXE) was made by Haseeb Jamil. 20 | * Misc icons are from [game-icons](https://game-icons.net/). 21 | * Folder icons are from [flaticon](https://www.flaticon.com/) 22 | * Additionals Wallpapers are by [lydex256](https://github.com/lydex256). 23 | * "Godotris" by [MrakDun-desu](https://github.com/MrakDun-desu) 24 | * "Snake" by [jean-philippe-martin](https://github.com/jean-philippe-martin) 25 | 26 | --- 27 | 28 | Note: GodotOS is not actually an operating system, it's an application with an interface resembling one. 29 | 30 | **GodotOS is not affiliated with Godot Engine developers or the Godot Foundation.** 31 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Context Menu/context_menu.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://b2hpvnoxdgfvn"] 2 | 3 | [ext_resource type="Script" uid="uid://bqorxst7bapxa" path="res://Scenes/Autoloads/Context Menu/context_menu_manager.gd" id="1_kg358"] 4 | [ext_resource type="PackedScene" uid="uid://ctmotds7d1sr1" path="res://Scenes/Autoloads/Context Menu/context_menu_option.tscn" id="2_v21do"] 5 | [ext_resource type="PackedScene" uid="uid://dc6higwdbswel" path="res://Scenes/Autoloads/Context Menu/context_menu_seperator.tscn" id="3_ygltd"] 6 | 7 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_qnd7w"] 8 | bg_color = Color(0.2, 0.2, 0.25098, 1) 9 | corner_radius_top_left = 15 10 | corner_radius_top_right = 15 11 | corner_radius_bottom_right = 15 12 | corner_radius_bottom_left = 15 13 | 14 | [node name="Context Menu" type="Panel"] 15 | clip_contents = true 16 | offset_right = 160.0 17 | offset_bottom = 200.0 18 | theme_override_styles/panel = SubResource("StyleBoxFlat_qnd7w") 19 | script = ExtResource("1_kg358") 20 | 21 | [node name="VBoxContainer" type="VBoxContainer" parent="."] 22 | layout_mode = 1 23 | anchors_preset = 15 24 | anchor_right = 1.0 25 | anchor_bottom = 1.0 26 | offset_left = 5.0 27 | offset_top = 5.0 28 | offset_right = -5.0 29 | offset_bottom = -5.0 30 | grow_horizontal = 2 31 | grow_vertical = 2 32 | mouse_filter = 2 33 | 34 | [node name="Context Menu Option" parent="VBoxContainer" instance=ExtResource("2_v21do")] 35 | layout_mode = 2 36 | 37 | [node name="HSeparator" parent="VBoxContainer" instance=ExtResource("3_ygltd")] 38 | layout_mode = 2 39 | 40 | [connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"] 41 | [connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"] 42 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Context Menu/context_menu_manager.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bqorxst7bapxa 2 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Context Menu/context_menu_option.gd: -------------------------------------------------------------------------------- 1 | extends Panel 2 | class_name ContextMenuOption 3 | 4 | ## One of the options that are clickable inside of a context menu. 5 | ## Used by context_menu_manager. 6 | 7 | signal option_clicked() 8 | 9 | func _gui_input(event: InputEvent) -> void: 10 | if event is InputEventMouseButton and event.button_index == 1 and event.is_pressed(): 11 | option_clicked.emit() 12 | 13 | func _on_mouse_entered() -> void: 14 | var tween: Tween = create_tween() 15 | tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC) 16 | tween.tween_property(self, "self_modulate:a", 1, 0.2) 17 | 18 | func _on_mouse_exited() -> void: 19 | var tween: Tween = create_tween() 20 | tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC) 21 | tween.tween_property(self, "self_modulate:a", 0.2, 0.2) 22 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Context Menu/context_menu_option.gd.uid: -------------------------------------------------------------------------------- 1 | uid://vib2acjns3ka 2 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Context Menu/context_menu_option.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://ctmotds7d1sr1"] 2 | 3 | [ext_resource type="Script" uid="uid://vib2acjns3ka" path="res://Scenes/Autoloads/Context Menu/context_menu_option.gd" id="1_n16mt"] 4 | 5 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_xn8jj"] 6 | bg_color = Color(0, 0.792157, 0.952941, 0.72549) 7 | corner_radius_top_left = 12 8 | corner_radius_top_right = 12 9 | corner_radius_bottom_right = 12 10 | corner_radius_bottom_left = 12 11 | 12 | [node name="Context Menu Option" type="Panel"] 13 | self_modulate = Color(1, 1, 1, 0.2) 14 | custom_minimum_size = Vector2(0, 30) 15 | mouse_filter = 1 16 | theme_override_styles/panel = SubResource("StyleBoxFlat_xn8jj") 17 | script = ExtResource("1_n16mt") 18 | 19 | [node name="CenterContainer" type="CenterContainer" parent="."] 20 | layout_mode = 1 21 | anchors_preset = 15 22 | anchor_right = 1.0 23 | anchor_bottom = 1.0 24 | offset_left = -65.0 25 | offset_right = 85.0 26 | grow_horizontal = 2 27 | grow_vertical = 2 28 | mouse_filter = 2 29 | 30 | [node name="Option Text" type="RichTextLabel" parent="CenterContainer"] 31 | unique_name_in_owner = true 32 | custom_minimum_size = Vector2(150, 0) 33 | layout_mode = 2 34 | mouse_filter = 2 35 | text = "Hello, World!" 36 | fit_content = true 37 | 38 | [connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"] 39 | [connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"] 40 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Context Menu/context_menu_seperator.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://dc6higwdbswel"] 2 | 3 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ruojt"] 4 | bg_color = Color(0.258824, 0.258824, 0.321569, 1) 5 | border_width_left = 1 6 | border_width_top = 1 7 | border_width_right = 1 8 | border_width_bottom = 1 9 | border_color = Color(0.258824, 0.258824, 0.321569, 1) 10 | corner_radius_top_left = 12 11 | corner_radius_top_right = 12 12 | corner_radius_bottom_right = 12 13 | corner_radius_bottom_left = 12 14 | corner_detail = 12 15 | anti_aliasing_size = 0.1 16 | 17 | [node name="HSeparator" type="HSeparator"] 18 | theme_override_styles/separator = SubResource("StyleBoxFlat_ruojt") 19 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Context Menu/right_click_handler.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | ## This is added by context_menu_handler to any node that enters the tree 4 | ## That is of group "right_click_enabled" 5 | ## So the context menu manager can detect when something is right clicked. 6 | 7 | # NOTE: This class might not be necessary when Godot 4.3 comes out, which includes 8 | # a function that can globally find control nodes. 9 | 10 | func _ready() -> void: 11 | get_parent().gui_input.connect(_parent_gui_input) 12 | 13 | func _parent_gui_input(event: InputEvent) -> void: 14 | if event is InputEventMouseButton and event.button_index == 2 and event.is_pressed(): 15 | ContextMenu.handle_right_click(get_parent()) 16 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Context Menu/right_click_handler.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bp8o5ttpv22b1 2 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Context Menu/right_click_handler.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://c0r424y7glqu4"] 2 | 3 | [ext_resource type="Script" uid="uid://bp8o5ttpv22b1" path="res://Scenes/Autoloads/Context Menu/right_click_handler.gd" id="1_8oxm2"] 4 | 5 | [node name="RightClickHandler" type="Node"] 6 | script = ExtResource("1_8oxm2") 7 | -------------------------------------------------------------------------------- /Scenes/Autoloads/CopyPaste Manager/copy_paste_manager.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cb6g2tw1ikimw 2 | -------------------------------------------------------------------------------- /Scenes/Autoloads/CopyPaste Manager/copy_paste_manager.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://mv3dwdjmlm58"] 2 | 3 | [ext_resource type="Script" uid="uid://cb6g2tw1ikimw" path="res://Scenes/Autoloads/CopyPaste Manager/copy_paste_manager.gd" id="1_cvn0g"] 4 | 5 | [node name="CopyPasteManager" type="Node"] 6 | script = ExtResource("1_cvn0g") 7 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Default Values/default_values.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | ## Sets some default values on startup and handles saving/loading user preferences 3 | 4 | var wallpaper_name: String 5 | var wallpaper_stretch_mode: TextureRect.StretchMode # int from 0 to 6 6 | @onready var background_color_rect: ColorRect = $"/root/Control/BackgroundColor" 7 | @onready var wallpaper: Wallpaper = $"/root/Control/Wallpaper" 8 | 9 | func _ready() -> void: 10 | DisplayServer.window_set_min_size(Vector2i(600, 525)) 11 | 12 | #NOTE: Vsync is disabled due to input lag: https://github.com/godotengine/godot/issues/75830 13 | #NOTE: Web can't get screen refresh rate 14 | var new_max_fps: int = int(DisplayServer.screen_get_refresh_rate()) 15 | if new_max_fps == -1: 16 | Engine.max_fps = 60 17 | else: 18 | Engine.max_fps = new_max_fps 19 | 20 | 21 | if wallpaper == null or background_color_rect == null: 22 | printerr("default_values.gd: Couldn't find wallpaper (are you debugging a scene?)") 23 | return 24 | 25 | if FileAccess.file_exists("user://user_preferences.txt"): 26 | load_state() 27 | else: 28 | save_state() 29 | 30 | func save_state() -> void: 31 | var save_dict: Dictionary = { 32 | "wallpaper_name": wallpaper_name, 33 | "wallpaper_stretch_mode": wallpaper_stretch_mode, 34 | "background_color": background_color_rect.color.to_html(), 35 | "zoom_level": get_window().content_scale_factor 36 | } 37 | 38 | var json_string: String = JSON.stringify(save_dict) 39 | 40 | var save_file: FileAccess = FileAccess.open("user://user_preferences.txt", FileAccess.WRITE) 41 | save_file.store_line(json_string) 42 | 43 | func load_state() -> void: 44 | var save_file: FileAccess = FileAccess.open("user://user_preferences.txt", FileAccess.READ) 45 | 46 | var json_string: String = save_file.get_line() 47 | var json: JSON = JSON.new() 48 | var parse_result: Error = json.parse(json_string) 49 | if parse_result != OK: 50 | printerr("default_values.gd: Failed to parse user preferences file!") 51 | return 52 | 53 | var save_dict: Dictionary = json.get_data() 54 | 55 | wallpaper_name = save_dict.wallpaper_name 56 | if !wallpaper_name.is_empty(): 57 | wallpaper.apply_wallpaper_from_path(wallpaper_name) 58 | 59 | if save_dict.has(wallpaper_stretch_mode): 60 | wallpaper_stretch_mode = save_dict.wallpaper_stretch_mode 61 | else: 62 | wallpaper_stretch_mode = 6 63 | wallpaper.apply_wallpaper_stretch_mode(wallpaper_stretch_mode) 64 | 65 | background_color_rect.color = Color.from_string(save_dict.background_color, Color.from_rgba8(77, 77, 77)) 66 | get_window().content_scale_factor = save_dict.zoom_level 67 | 68 | ## Copies the wallpaper to root GodotOS folder so it can load it again later. 69 | ## It doesn't use the actual wallpaper file since it can be removed/deleted. 70 | func save_wallpaper(wallpaper_file: FakeFolder) -> void: 71 | delete_wallpaper() 72 | 73 | var from: String = "user://files/%s/%s" % [wallpaper_file.folder_path, wallpaper_file.folder_name] 74 | var to: String = "user://%s" % wallpaper_file.folder_name 75 | DirAccess.copy_absolute(from, to) 76 | wallpaper_name = wallpaper_file.folder_name 77 | save_state() 78 | 79 | func delete_wallpaper() -> void: 80 | if !wallpaper_name.is_empty(): 81 | DirAccess.remove_absolute("user://%s" % wallpaper_name) 82 | wallpaper_name = "" 83 | save_state() 84 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Default Values/default_values.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bovrf6mkkyel8 2 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Default Values/default_values.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://do3amaigaxq01"] 2 | 3 | [ext_resource type="Script" uid="uid://bovrf6mkkyel8" path="res://Scenes/Autoloads/Default Values/default_values.gd" id="1_7jt5b"] 4 | 5 | [node name="Default Values" type="Node"] 6 | script = ExtResource("1_7jt5b") 7 | -------------------------------------------------------------------------------- /Scenes/Autoloads/GlobalValues/global_values.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | ## Global values that are useful for many classes to see. 4 | ## There isn't much here but I still wanted this to be separate from DefaultValues 5 | 6 | ## The current selected window 7 | var selected_window: FakeWindow 8 | -------------------------------------------------------------------------------- /Scenes/Autoloads/GlobalValues/global_values.gd.uid: -------------------------------------------------------------------------------- 1 | uid://dp6eii4lmnhuh 2 | -------------------------------------------------------------------------------- /Scenes/Autoloads/GlobalValues/global_values.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://dnr2whboi3cm8"] 2 | 3 | [ext_resource type="Script" uid="uid://dp6eii4lmnhuh" path="res://Scenes/Autoloads/GlobalValues/global_values.gd" id="1_17jpm"] 4 | 5 | [node name="GlobalValues" type="Node"] 6 | script = ExtResource("1_17jpm") 7 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Hotkey Manager/hotkey_manager.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | ## Handles general hotkeys in GodotOS. Not all of them are here though. 4 | 5 | func _input(event: InputEvent) -> void: 6 | if event.is_action_pressed("kill_all_windows"): 7 | for window in get_tree().get_nodes_in_group("window"): 8 | window._on_close_button_pressed() 9 | if event.is_action_pressed("fullscreen"): 10 | if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN || DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN: 11 | DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) 12 | else: 13 | DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN) 14 | if event.is_action_pressed("open_in_file_manager"): 15 | if OS.has_feature("web"): 16 | NotificationManager.spawn_notification("GodotOS can't let you browse files on a browser. Download GodotOS to import/export files!") 17 | else: 18 | OS.shell_show_in_file_manager(ProjectSettings.globalize_path("user://files/")) 19 | 20 | #TODO notification for zoom levels 21 | if event.is_action_pressed("zoom_in"): 22 | if get_window().content_scale_factor < 4: 23 | get_window().content_scale_factor += 0.125 24 | DefaultValues.save_state() 25 | elif event.is_action_pressed("zoom_out"): 26 | if get_window().content_scale_factor > 0.25: 27 | get_window().content_scale_factor -= 0.125 28 | DefaultValues.save_state() 29 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Hotkey Manager/hotkey_manager.gd.uid: -------------------------------------------------------------------------------- 1 | uid://e6lyob4ik8i2 2 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Hotkey Manager/hotkey_manager.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://b0rebfqhlcmhp"] 2 | 3 | [ext_resource type="Script" uid="uid://e6lyob4ik8i2" path="res://Scenes/Autoloads/Hotkey Manager/hotkey_manager.gd" id="1_lg507"] 4 | 5 | [node name="Hotkey Manager" type="Node"] 6 | script = ExtResource("1_lg507") 7 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Notification Manager/notification.gd: -------------------------------------------------------------------------------- 1 | extends Panel 2 | 3 | func _ready() -> void: 4 | adjust_width() 5 | play_animation() 6 | 7 | func adjust_width() -> void: 8 | while true: 9 | if $"Notification Text".get_line_count() > 1: 10 | size.x += 20 11 | position.x -= 20 12 | else: 13 | size.x += 10 14 | position.x -= 10 15 | return 16 | 17 | func play_animation() -> void: 18 | var tween: Tween = create_tween() 19 | tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_SINE) 20 | tween.tween_property(self, "position:y", position.y - 75, 3) 21 | 22 | await get_tree().create_timer(2).timeout 23 | var fade: Tween = create_tween() 24 | fade.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_SINE) 25 | await fade.tween_property(self, "modulate:a", 0, 1.5).finished 26 | queue_free() 27 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Notification Manager/notification.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cv6vbo4w5ecmt 2 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Notification Manager/notification.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://dgrw5q1qwsr33"] 2 | 3 | [ext_resource type="Script" uid="uid://cv6vbo4w5ecmt" path="res://Scenes/Autoloads/Notification Manager/notification.gd" id="1_0ehe8"] 4 | 5 | [node name="Notification" type="Panel"] 6 | anchors_preset = 3 7 | anchor_left = 1.0 8 | anchor_top = 1.0 9 | anchor_right = 1.0 10 | anchor_bottom = 1.0 11 | offset_left = -60.0 12 | offset_top = -110.0 13 | offset_right = -20.0 14 | offset_bottom = -50.0 15 | grow_horizontal = 0 16 | grow_vertical = 0 17 | mouse_filter = 2 18 | script = ExtResource("1_0ehe8") 19 | 20 | [node name="Notification Text" type="RichTextLabel" parent="."] 21 | layout_mode = 1 22 | anchors_preset = 14 23 | anchor_top = 0.5 24 | anchor_right = 1.0 25 | anchor_bottom = 0.5 26 | grow_horizontal = 2 27 | grow_vertical = 2 28 | theme_override_font_sizes/normal_font_size = 24 29 | bbcode_enabled = true 30 | text = "[center]Hello, World!" 31 | fit_content = true 32 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Notification Manager/notification_manager.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | ## Spawns notifications in the bottom right of the screen. 4 | ## Often used to show errors or file actions (copying, pasting). 5 | 6 | const notification_scene: PackedScene = preload("res://Scenes/Autoloads/Notification Manager/notification.tscn") 7 | 8 | func spawn_notification(text: String) -> void: 9 | var new_notification: Control = notification_scene.instantiate() 10 | new_notification.get_node("Notification Text").text = "[center]%s" % text 11 | add_child(new_notification) 12 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Notification Manager/notification_manager.gd.uid: -------------------------------------------------------------------------------- 1 | uid://du2ifgmx4m0qq 2 | -------------------------------------------------------------------------------- /Scenes/Autoloads/Notification Manager/notification_manager.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://c5rok2ine5c1c"] 2 | 3 | [ext_resource type="Script" uid="uid://du2ifgmx4m0qq" path="res://Scenes/Autoloads/Notification Manager/notification_manager.gd" id="1_xb1dn"] 4 | 5 | [node name="Notification Manager" type="Control"] 6 | layout_mode = 3 7 | anchors_preset = 15 8 | anchor_right = 1.0 9 | anchor_bottom = 1.0 10 | grow_horizontal = 2 11 | grow_vertical = 2 12 | mouse_filter = 2 13 | script = ExtResource("1_xb1dn") 14 | -------------------------------------------------------------------------------- /Scenes/Containers/smooth_container.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | class_name SmoothContainer 3 | 4 | ## Smoothly tweens all children into place. Used in file managers. 5 | 6 | @export_enum("Horizontal", "Vertical") var direction: String = "Horizontal" 7 | ## How often the update function runs, in seconds. Low values are performance intensive! 8 | @export var poll_rate: float = 0.15 9 | ## The speed of the Tween animation, in seconds. 10 | @export var animation_speed: float = 0.5 11 | 12 | @export_group("Spacing") 13 | @export var horizontal_spacing: int = 10 14 | @export var vertical_spacing: int = 10 15 | 16 | @export_group("Margins") 17 | @export var left_margin: int 18 | @export var up_margin: int 19 | @export var right_margin: int 20 | @export var down_margin: int 21 | 22 | ## Global Tween so it doesn't create one each time the function runs 23 | var tween: Tween 24 | ## Bool used to check if there's a cooldown or not 25 | var just_updated: bool 26 | ## Global Vector2 to calculate the next position of each container child 27 | var next_position: Vector2 28 | 29 | ## How many folders make up a line (column or row) 30 | var line_count: int 31 | 32 | var start_min_size: Vector2 33 | 34 | func _ready() -> void: 35 | # I don't know why but having a container parent forces this node's size to be (0, 0) in the first frame 36 | await get_tree().physics_frame 37 | start_min_size = custom_minimum_size 38 | update_positions(false) 39 | 40 | func update_positions(update_again: bool = true) -> void: 41 | if just_updated: 42 | return 43 | 44 | if update_again: 45 | cooldown_update() 46 | 47 | next_position = Vector2(left_margin, up_margin) 48 | if tween: tween.kill() 49 | 50 | if direction == "Horizontal": 51 | update_horizontal_direction() 52 | elif direction == "Vertical": 53 | update_vertical_direction() 54 | 55 | func update_horizontal_direction() -> void: 56 | var new_line_count: int = 0 57 | line_count = 0 58 | 59 | var tallest_child: int = 0 60 | 61 | for child: Node in get_children(): 62 | if !(child is FakeFolder): 63 | continue 64 | 65 | if next_position.x + right_margin + child.size.x > size.x: 66 | next_position.x = left_margin 67 | next_position.y += tallest_child + vertical_spacing 68 | tallest_child = 0 69 | 70 | line_count = new_line_count 71 | new_line_count = 0 72 | 73 | if child.position != next_position: 74 | if tween == null or !tween.is_running(): 75 | restore_tween() 76 | tween.tween_property(child, "position", next_position, animation_speed) 77 | 78 | if child.size.y > tallest_child: 79 | tallest_child = child.size.y 80 | 81 | next_position.x += child.size.x + horizontal_spacing 82 | new_line_count += 1 83 | 84 | if line_count == 0: 85 | line_count = new_line_count 86 | 87 | if get_parent() is ScrollContainer: 88 | if next_position.y + tallest_child > get_parent().size.y: 89 | custom_minimum_size.y = next_position.y + tallest_child + down_margin 90 | else: 91 | custom_minimum_size.y = start_min_size.y 92 | 93 | 94 | func update_vertical_direction() -> void: 95 | var new_line_count: int = 0 96 | line_count = 0 97 | 98 | var longest_child: int = 0 99 | for child: Node in get_children(): 100 | if !(child is Control): 101 | continue 102 | 103 | if next_position.y + down_margin + child.size.y > size.y: 104 | next_position.y = up_margin 105 | next_position.x += longest_child + horizontal_spacing 106 | longest_child = 0 107 | 108 | line_count = new_line_count 109 | new_line_count = 0 110 | 111 | if child.position != next_position: 112 | if tween == null or !tween.is_running(): 113 | restore_tween() 114 | tween.tween_property(child, "position", next_position, animation_speed) 115 | 116 | if child.size.x > longest_child: 117 | longest_child = child.size.x 118 | 119 | next_position.y += child.size.y + vertical_spacing 120 | new_line_count += 1 121 | 122 | if line_count == 0: 123 | line_count = new_line_count 124 | 125 | if get_parent() is ScrollContainer: 126 | if next_position.x + longest_child > get_parent().size.x: 127 | custom_minimum_size.x = next_position.x + longest_child + right_margin 128 | else: 129 | custom_minimum_size.x = start_min_size.x 130 | 131 | ## Creates a cooldown of x seconds rather than using the function every single frame. 132 | ## Plays the function again after poll rate ends to readjust positions. 133 | func cooldown_update() -> void: 134 | just_updated = true 135 | await get_tree().create_timer(poll_rate).timeout 136 | just_updated = false 137 | update_positions(false) 138 | 139 | func restore_tween() -> void: 140 | tween = create_tween() 141 | tween.set_parallel(true) 142 | tween.set_trans(Tween.TRANS_CUBIC) 143 | tween.set_ease(Tween.EASE_OUT) 144 | -------------------------------------------------------------------------------- /Scenes/Containers/smooth_container.gd.uid: -------------------------------------------------------------------------------- 1 | uid://b6biwpefgwr8s 2 | -------------------------------------------------------------------------------- /Scenes/Desktop/desktop_folder.gd.uid: -------------------------------------------------------------------------------- 1 | uid://j6auwoexib63 2 | -------------------------------------------------------------------------------- /Scenes/Desktop/folder.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=8 format=3 uid="uid://dci6t0fj42xpv"] 2 | 3 | [ext_resource type="Script" uid="uid://j6auwoexib63" path="res://Scenes/Desktop/desktop_folder.gd" id="1_44lov"] 4 | [ext_resource type="Texture2D" uid="uid://cjve37ywrq6qo" path="res://Art/Folder Icons/folder.png" id="2_8hyqf"] 5 | [ext_resource type="Script" uid="uid://csxjm2dry3dji" path="res://Scenes/Desktop/folder_title_edit.gd" id="2_aux0e"] 6 | 7 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fr400"] 8 | bg_color = Color(0, 0.521569, 0.627451, 0.784314) 9 | corner_radius_top_left = 10 10 | corner_radius_top_right = 10 11 | corner_radius_bottom_right = 10 12 | corner_radius_bottom_left = 10 13 | 14 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_3l4r3"] 15 | bg_color = Color(0, 0.568627, 0.682353, 0.941176) 16 | border_width_left = 2 17 | border_width_top = 2 18 | border_width_right = 2 19 | border_width_bottom = 2 20 | border_color = Color(0, 0.792157, 0.952941, 1) 21 | corner_radius_top_left = 10 22 | corner_radius_top_right = 10 23 | corner_radius_bottom_right = 10 24 | corner_radius_bottom_left = 10 25 | 26 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1hkig"] 27 | bg_color = Color(0, 0, 0, 0.784314) 28 | corner_radius_top_left = 10 29 | corner_radius_top_right = 10 30 | corner_radius_bottom_right = 10 31 | corner_radius_bottom_left = 10 32 | 33 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_r1fwe"] 34 | 35 | [node name="Folder" type="Control" groups=["folder", "right_click_enabled"]] 36 | custom_minimum_size = Vector2(80, 110) 37 | layout_mode = 3 38 | anchors_preset = 0 39 | size_flags_horizontal = 4 40 | mouse_filter = 1 41 | script = ExtResource("1_44lov") 42 | 43 | [node name="Hover Highlight" type="Panel" parent="."] 44 | layout_mode = 0 45 | offset_left = -10.0 46 | offset_right = 90.0 47 | offset_bottom = 114.0 48 | mouse_filter = 2 49 | theme_override_styles/panel = SubResource("StyleBoxFlat_fr400") 50 | 51 | [node name="Selected Highlight" type="Panel" parent="."] 52 | visible = false 53 | layout_mode = 0 54 | offset_left = -10.0 55 | offset_right = 90.0 56 | offset_bottom = 114.0 57 | mouse_filter = 2 58 | theme_override_styles/panel = SubResource("StyleBoxFlat_3l4r3") 59 | 60 | [node name="Folder" type="MarginContainer" parent="."] 61 | custom_minimum_size = Vector2(80, 100) 62 | layout_mode = 2 63 | offset_right = 80.0 64 | offset_bottom = 100.0 65 | size_flags_vertical = 4 66 | mouse_filter = 2 67 | theme_override_constants/margin_left = 5 68 | theme_override_constants/margin_top = 5 69 | theme_override_constants/margin_right = 5 70 | theme_override_constants/margin_bottom = 30 71 | 72 | [node name="TextureRect" type="TextureRect" parent="Folder"] 73 | modulate = Color(0.305882, 0.980392, 0.509804, 1) 74 | layout_mode = 2 75 | mouse_filter = 2 76 | texture = ExtResource("2_8hyqf") 77 | expand_mode = 4 78 | 79 | [node name="Double Click" type="Timer" parent="."] 80 | wait_time = 0.3 81 | one_shot = true 82 | 83 | [node name="Control" type="Control" parent="."] 84 | clip_contents = true 85 | custom_minimum_size = Vector2(100, 0) 86 | anchors_preset = 0 87 | offset_left = -10.0 88 | offset_top = 72.5 89 | offset_right = 90.0 90 | offset_bottom = 112.5 91 | mouse_filter = 2 92 | 93 | [node name="CenterContainer" type="CenterContainer" parent="Control"] 94 | layout_mode = 0 95 | offset_right = 100.0 96 | offset_bottom = 40.0 97 | mouse_filter = 2 98 | 99 | [node name="Folder Title" type="RichTextLabel" parent="Control/CenterContainer"] 100 | unique_name_in_owner = true 101 | custom_minimum_size = Vector2(95, 0) 102 | layout_mode = 2 103 | mouse_filter = 2 104 | theme_override_colors/font_shadow_color = Color(0, 0, 0, 1) 105 | theme_override_colors/font_outline_color = Color(0, 0, 0, 1) 106 | theme_override_constants/shadow_offset_x = 1 107 | theme_override_constants/shadow_offset_y = 1 108 | theme_override_font_sizes/normal_font_size = 14 109 | bbcode_enabled = true 110 | text = "[center]Hello World! 111 | Hello World." 112 | fit_content = true 113 | 114 | [node name="Title Edit Container" type="CenterContainer" parent="Control"] 115 | visible = false 116 | layout_mode = 0 117 | offset_right = 100.0 118 | offset_bottom = 40.0 119 | mouse_filter = 2 120 | 121 | [node name="Folder Title Edit" type="TextEdit" parent="Control/Title Edit Container"] 122 | unique_name_in_owner = true 123 | custom_minimum_size = Vector2(95, 40) 124 | layout_mode = 2 125 | theme_override_constants/line_spacing = 0 126 | theme_override_font_sizes/font_size = 14 127 | theme_override_styles/normal = SubResource("StyleBoxFlat_1hkig") 128 | theme_override_styles/focus = SubResource("StyleBoxEmpty_r1fwe") 129 | context_menu_enabled = false 130 | wrap_mode = 1 131 | autowrap_mode = 1 132 | scroll_fit_content_height = true 133 | script = ExtResource("2_aux0e") 134 | 135 | [connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"] 136 | [connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"] 137 | -------------------------------------------------------------------------------- /Scenes/Desktop/folder_title_edit.gd: -------------------------------------------------------------------------------- 1 | extends TextEdit 2 | 3 | ## Handles renaming of a folder. 4 | 5 | func _input(event: InputEvent) -> void: 6 | if event.is_action_pressed("rename") and $"../../../Selected Highlight".visible: 7 | show_rename() 8 | 9 | if !get_parent().visible: 10 | return 11 | 12 | if event.is_action_pressed("ui_accept"): 13 | accept_event() 14 | trigger_rename() 15 | 16 | if event.is_action_pressed("ui_cancel"): 17 | cancel_rename() 18 | 19 | if event is InputEventMouseButton and event.is_pressed(): 20 | var evLocal: InputEvent = make_input_local(event) 21 | if !Rect2(Vector2(0,0), size).has_point(evLocal.position): 22 | cancel_rename() 23 | 24 | func show_rename() -> void: 25 | get_parent().visible = true 26 | grab_focus() 27 | text = %"Folder Title".text.trim_prefix("[center]").split(".")[0] 28 | select_all() 29 | 30 | func trigger_rename() -> void: 31 | if text.contains('/') or text.contains('\\') or text.contains('¥') or text.contains('₩'): 32 | NotificationManager.spawn_notification("Error: File name can't include slashes!") 33 | return 34 | 35 | if text.is_empty(): 36 | NotificationManager.spawn_notification("Error: File name can't be empty!") 37 | return 38 | 39 | get_parent().visible = false 40 | var folder: FakeFolder = $"../../.." 41 | 42 | if folder.file_type != folder.file_type_enum.FOLDER: 43 | var old_folder_name: String = folder.folder_name 44 | var new_folder_name: String = "%s.%s" % [text, folder.folder_name.split('.')[-1]] 45 | if FileAccess.file_exists("user://files/%s/%s" % [folder.folder_path, new_folder_name]): 46 | cancel_rename() 47 | NotificationManager.spawn_notification("That file already exists!") 48 | return 49 | folder.folder_name = new_folder_name 50 | DirAccess.rename_absolute("user://files/%s/%s" % [folder.folder_path, old_folder_name], "user://files/%s/%s" % [folder.folder_path, folder.folder_name]) 51 | %"Folder Title".text = "[center]%s" % folder.folder_name 52 | 53 | if folder.get_parent() is DesktopFileManager: 54 | folder.get_parent().sort_folders() 55 | else: 56 | # Reloads open windows 57 | for file_manager: FileManagerWindow in get_tree().get_nodes_in_group("file_manager_window"): 58 | if file_manager.file_path == folder.folder_path: 59 | file_manager.sort_folders() 60 | for text_editor in get_tree().get_nodes_in_group("text_editor_window"): 61 | if text_editor.file_path == "%s/%s" % [folder.folder_path, old_folder_name]: 62 | text_editor.file_path = "%s/%s" % [folder.folder_path, folder.folder_name] 63 | elif text_editor.file_path == old_folder_name: # In desktop 64 | text_editor.file_path = folder.folder_name 65 | 66 | elif folder.file_type == folder.file_type_enum.FOLDER: 67 | var old_folder_name: String = folder.folder_name 68 | var old_folder_path: String = folder.folder_path 69 | 70 | if old_folder_path.contains("/"): 71 | var new_folder_path: String = "%s%s" % [folder.folder_path.trim_suffix(old_folder_name), text] 72 | if DirAccess.dir_exists_absolute("user://files/%s" % new_folder_path): 73 | cancel_rename() 74 | NotificationManager.spawn_notification("That folder already exists!") 75 | return 76 | folder.folder_path = new_folder_path 77 | else: 78 | if DirAccess.dir_exists_absolute("user://files/%s" % text): 79 | cancel_rename() 80 | NotificationManager.spawn_notification("That folder already exists!") 81 | return 82 | folder.folder_path = text 83 | folder.folder_name = text 84 | %"Folder Title".text = "[center]%s" % folder.folder_name 85 | DirAccess.rename_absolute("user://files/%s" % old_folder_path, "user://files/%s" % folder.folder_path) 86 | 87 | if folder.get_parent() is DesktopFileManager: 88 | folder.get_parent().sort_folders() 89 | for file_manager: FileManagerWindow in get_tree().get_nodes_in_group("file_manager_window"): 90 | if file_manager.file_path.begins_with(old_folder_path): 91 | file_manager.file_path = file_manager.file_path.replace(old_folder_path, folder.folder_path) 92 | file_manager.reload_window("") 93 | elif file_manager.file_path == folder.folder_path.trim_suffix("/%s" % folder.folder_name): 94 | file_manager.sort_folders() 95 | 96 | text = "" 97 | 98 | func cancel_rename() -> void: 99 | get_parent().visible = false 100 | text = "" 101 | -------------------------------------------------------------------------------- /Scenes/Desktop/folder_title_edit.gd.uid: -------------------------------------------------------------------------------- 1 | uid://csxjm2dry3dji 2 | -------------------------------------------------------------------------------- /Scenes/Main/BaseFileManager.gd.uid: -------------------------------------------------------------------------------- 1 | uid://d2ysc64ypkip5 2 | -------------------------------------------------------------------------------- /Scenes/Main/Boot Splash/boot_splash.gd: -------------------------------------------------------------------------------- 1 | extends CanvasLayer 2 | class_name BootSplash 3 | 4 | ## The boot splash animation that's shown when GodotOS is opened or powered off. 5 | ## It uses a CanvasGroup with 2D nodes for masking, hence why it adjusts scale manually. 6 | 7 | @export var quit_animation: bool 8 | 9 | func _ready() -> void: 10 | visible = true 11 | scale /= get_window().content_scale_factor 12 | if quit_animation: 13 | play_quit_animation() 14 | else: 15 | play_animation() 16 | 17 | func play_animation() -> void: 18 | var tween: Tween = create_tween() 19 | tween.set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_EXPO) 20 | tween.set_parallel(true) 21 | tween.tween_property($Logo, "scale", Vector2(10, 10), 2) 22 | tween.tween_property($CanvasGroup/Logo, "scale", Vector2(10, 10), 2) 23 | 24 | tween.tween_property($Logo, "self_modulate:a", 0, 1.5) 25 | 26 | await get_tree().create_timer(3).timeout 27 | queue_free() 28 | 29 | func play_quit_animation() -> void: 30 | $Logo.scale = Vector2(10, 10) 31 | $Logo.self_modulate.a = 0 32 | $CanvasGroup/Logo.scale = Vector2(10, 10) 33 | 34 | var tween: Tween = create_tween() 35 | tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_EXPO) 36 | tween.set_parallel(true) 37 | tween.tween_property($Logo, "scale", Vector2(1, 1), 2) 38 | tween.tween_property($CanvasGroup/Logo, "scale", Vector2(1, 1), 2) 39 | 40 | await get_tree().create_timer(1).timeout 41 | 42 | var tween2: Tween = create_tween() 43 | tween2.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC) 44 | tween2.tween_property($Logo, "self_modulate:a", 1, 1.5) 45 | 46 | await get_tree().create_timer(2).timeout 47 | get_tree().quit() 48 | 49 | func _physics_process(_delta: float) -> void: 50 | var window_size: Vector2 = DisplayServer.window_get_size() as Vector2 51 | $CanvasGroup/Background.scale = window_size 52 | $CanvasGroup/Background.global_position = window_size / 2 53 | $CanvasGroup/Logo.global_position = window_size / 2 54 | $Logo.global_position = window_size / 2 55 | -------------------------------------------------------------------------------- /Scenes/Main/Boot Splash/boot_splash.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cv20x048ht4ki 2 | -------------------------------------------------------------------------------- /Scenes/Main/Boot Splash/boot_splash.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://bwyybu5i3kid"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://b7m5up7nr6tko" path="res://Art/Godot Logo.png" id="1_h7qs8"] 4 | [ext_resource type="Script" uid="uid://cv20x048ht4ki" path="res://Scenes/Main/Boot Splash/boot_splash.gd" id="1_oyw0a"] 5 | 6 | [sub_resource type="Gradient" id="Gradient_w533j"] 7 | offsets = PackedFloat32Array(0) 8 | colors = PackedColorArray(0, 0, 0, 1) 9 | 10 | [sub_resource type="GradientTexture1D" id="GradientTexture1D_033me"] 11 | gradient = SubResource("Gradient_w533j") 12 | width = 1 13 | 14 | [sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_m3kw8"] 15 | blend_mode = 2 16 | 17 | [node name="Boot Splash" type="CanvasLayer"] 18 | script = ExtResource("1_oyw0a") 19 | 20 | [node name="CanvasGroup" type="CanvasGroup" parent="."] 21 | 22 | [node name="Background" type="Sprite2D" parent="CanvasGroup"] 23 | position = Vector2(576, 324) 24 | scale = Vector2(1152, 648) 25 | texture = SubResource("GradientTexture1D_033me") 26 | 27 | [node name="Logo" type="Sprite2D" parent="CanvasGroup"] 28 | texture_filter = 6 29 | material = SubResource("CanvasItemMaterial_m3kw8") 30 | position = Vector2(576, 324) 31 | texture = ExtResource("1_h7qs8") 32 | 33 | [node name="Logo" type="Sprite2D" parent="."] 34 | texture_filter = 6 35 | position = Vector2(576, 324) 36 | texture = ExtResource("1_h7qs8") 37 | -------------------------------------------------------------------------------- /Scenes/Main/MainScene.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=8 format=3 uid="uid://bmjyglrsf04uo"] 2 | 3 | [ext_resource type="Script" uid="uid://crccellk2oo41" path="res://Scenes/Main/desktop_file_manager.gd" id="1_c0q37"] 4 | [ext_resource type="Script" uid="uid://fgth35grbgyv" path="res://Scenes/Main/wallpaper.gd" id="1_xkkt2"] 5 | [ext_resource type="PackedScene" uid="uid://cfj5p5pgfnywp" path="res://Scenes/Taskbar/taskbar.tscn" id="2_35ao4"] 6 | [ext_resource type="PackedScene" uid="uid://bwyybu5i3kid" path="res://Scenes/Main/Boot Splash/boot_splash.tscn" id="3_ifoxq"] 7 | 8 | [sub_resource type="GDScript" id="GDScript_fyyaf"] 9 | resource_name = "MainScene" 10 | script/source = "extends Control 11 | 12 | func _ready() -> void: 13 | # Just shoves this back on ready so autoloads like the context menu can be in front 14 | get_parent().move_child.call_deferred(self, 0) 15 | " 16 | 17 | [sub_resource type="Gradient" id="Gradient_g3gwb"] 18 | offsets = PackedFloat32Array(0) 19 | colors = PackedColorArray(0, 0, 0, 1) 20 | 21 | [sub_resource type="GradientTexture1D" id="GradientTexture1D_agg5v"] 22 | gradient = SubResource("Gradient_g3gwb") 23 | width = 1 24 | 25 | [node name="Control" type="Control"] 26 | layout_mode = 3 27 | anchors_preset = 15 28 | anchor_right = 1.0 29 | anchor_bottom = 1.0 30 | grow_horizontal = 2 31 | grow_vertical = 2 32 | script = SubResource("GDScript_fyyaf") 33 | 34 | [node name="BackgroundColor" type="ColorRect" parent="."] 35 | layout_mode = 1 36 | anchors_preset = 15 37 | anchor_right = 1.0 38 | anchor_bottom = 1.0 39 | grow_horizontal = 2 40 | grow_vertical = 2 41 | mouse_filter = 2 42 | color = Color(0.301961, 0.301961, 0.301961, 1) 43 | 44 | [node name="Wallpaper" type="TextureRect" parent="."] 45 | texture_filter = 6 46 | layout_mode = 1 47 | anchors_preset = 15 48 | anchor_right = 1.0 49 | anchor_bottom = 1.0 50 | grow_horizontal = 2 51 | grow_vertical = 2 52 | mouse_filter = 2 53 | expand_mode = 3 54 | stretch_mode = 6 55 | script = ExtResource("1_xkkt2") 56 | 57 | [node name="Fade" type="TextureRect" parent="Wallpaper"] 58 | visible = false 59 | layout_mode = 1 60 | anchors_preset = 15 61 | anchor_right = 1.0 62 | anchor_bottom = 1.0 63 | grow_horizontal = 2 64 | grow_vertical = 2 65 | texture = SubResource("GradientTexture1D_agg5v") 66 | 67 | [node name="DesktopFileManager" type="Control" parent="." groups=["desktop_file_manager", "right_click_enabled"]] 68 | layout_mode = 1 69 | anchors_preset = 15 70 | anchor_right = 1.0 71 | anchor_bottom = 1.0 72 | offset_bottom = -40.0 73 | grow_horizontal = 2 74 | grow_vertical = 2 75 | script = ExtResource("1_c0q37") 76 | direction = "Vertical" 77 | horizontal_spacing = 20 78 | left_margin = 10 79 | up_margin = 10 80 | right_margin = 10 81 | 82 | [node name="Taskbar" parent="." instance=ExtResource("2_35ao4")] 83 | layout_mode = 1 84 | 85 | [node name="Boot Splash" parent="." instance=ExtResource("3_ifoxq")] 86 | visible = false 87 | -------------------------------------------------------------------------------- /Scenes/Main/desktop_file_manager.gd: -------------------------------------------------------------------------------- 1 | extends BaseFileManager 2 | class_name DesktopFileManager 3 | 4 | ## The desktop file manager. 5 | 6 | func _ready() -> void: 7 | var user_dir: DirAccess = DirAccess.open("user://") 8 | if !user_dir.dir_exists("files"): 9 | # Can't just use absolute paths due to https://github.com/godotengine/godot/issues/82550 10 | # Also DirAccess can't open on res:// at export, but FileAccess does... 11 | user_dir.make_dir_recursive("files/Welcome Folder") 12 | user_dir.make_dir_recursive("files/Wallpapers") 13 | copy_from_res("res://Default Files/Welcome.txt", "user://files/Welcome Folder/Welcome.txt") 14 | copy_from_res("res://Default Files/Credits.txt", "user://files/Welcome Folder/Credits.txt") 15 | copy_from_res("res://Default Files/GodotOS Handbook.txt", "user://files/Welcome Folder/GodotOS Handbook.txt") 16 | copy_from_res("res://Default Files/default wall.webp", "user://files/Wallpapers/default wall.webp") 17 | 18 | #Additional wallpapers 19 | copy_from_res("res://Default Files/wallpaper_chill.webp", "user://files/Wallpapers/chill.webp") 20 | copy_from_res("res://Default Files/wallpaper_minimalism.webp", "user://files/Wallpapers/minimalism.webp") 21 | 22 | var wallpaper: Wallpaper = $"/root/Control/Wallpaper" 23 | wallpaper.apply_wallpaper_from_path("files/Wallpapers/default wall.webp") 24 | 25 | copy_from_res("res://Default Files/default wall.webp", "user://default wall.webp") 26 | DefaultValues.wallpaper_name = "default wall.webp" 27 | DefaultValues.save_state() 28 | 29 | populate_file_manager() 30 | get_window().size_changed.connect(update_positions) 31 | get_window().focus_entered.connect(_on_window_focus) 32 | 33 | func copy_from_res(from: String, to: String) -> void: 34 | var file_from: FileAccess = FileAccess.open(from, FileAccess.READ) 35 | var file_to: FileAccess = FileAccess.open(to, FileAccess.WRITE) 36 | file_to.store_buffer(file_from.get_buffer(file_from.get_length())) 37 | 38 | file_from.close() 39 | file_to.close() 40 | 41 | ## Checks if any files were changed on the desktop, and populates the file manager again if so. 42 | func _on_window_focus() -> void: 43 | var current_file_names: Array[String] = [] 44 | for child in get_children(): 45 | if !(child is FakeFolder): 46 | continue 47 | 48 | current_file_names.append(child.folder_name) 49 | 50 | var new_file_names: Array[String] = [] 51 | for file_name in DirAccess.get_files_at("user://files/"): 52 | new_file_names.append(file_name) 53 | for folder_name in DirAccess.get_directories_at("user://files/"): 54 | new_file_names.append(folder_name) 55 | 56 | if current_file_names.size() != new_file_names.size(): 57 | populate_file_manager() 58 | return 59 | 60 | for file_name in new_file_names: 61 | if !current_file_names.has(file_name): 62 | populate_file_manager() 63 | return 64 | -------------------------------------------------------------------------------- /Scenes/Main/desktop_file_manager.gd.uid: -------------------------------------------------------------------------------- 1 | uid://crccellk2oo41 2 | -------------------------------------------------------------------------------- /Scenes/Main/wallpaper.gd: -------------------------------------------------------------------------------- 1 | extends TextureRect 2 | class_name Wallpaper 3 | 4 | ## The desktop wallpaper, has an empty texture when the wallpaper is removed. 5 | 6 | signal wallpaper_added() 7 | 8 | func _ready() -> void: 9 | # I use a node to fade because fading modulate doesn't work if there is no texture 10 | $Fade.modulate.a = 0 11 | $Fade.visible = true 12 | 13 | ## Applies wallpaper from path (called from default_values.gd on start) 14 | func apply_wallpaper_from_path(path: String) -> void: 15 | wallpaper_added.emit() 16 | 17 | var image: Image = Image.load_from_file("user://%s" % path) 18 | add_wallpaper(image) 19 | 20 | ## Applies wallpaper from an image file 21 | func apply_wallpaper_from_file(image_file: FakeFolder) -> void: 22 | wallpaper_added.emit() 23 | DefaultValues.save_wallpaper(image_file) 24 | 25 | var image: Image = Image.load_from_file("user://files/%s/%s" % [image_file.folder_path, image_file.folder_name]) 26 | add_wallpaper(image) 27 | 28 | func add_wallpaper(image: Image) -> void: 29 | image.generate_mipmaps() 30 | var texture_import: ImageTexture = ImageTexture.create_from_image(image) 31 | 32 | var tween: Tween = create_tween() 33 | tween.set_trans(Tween.TRANS_CUBIC) 34 | await tween.tween_property($Fade, "modulate:a", 1, 0.5).finished 35 | 36 | texture = texture_import 37 | 38 | var tween2: Tween = create_tween() 39 | tween2.set_trans(Tween.TRANS_CUBIC) 40 | tween2.tween_property($Fade, "modulate:a", 0, 0.5) 41 | 42 | func remove_wallpaper() -> void: 43 | DefaultValues.delete_wallpaper() 44 | var tween: Tween = create_tween() 45 | tween.set_trans(Tween.TRANS_CUBIC) 46 | await tween.tween_property($Fade, "modulate:a", 1, 0.5).finished 47 | 48 | texture = null 49 | 50 | var tween2: Tween = create_tween() 51 | tween2.set_trans(Tween.TRANS_CUBIC) 52 | tween2.tween_property($Fade, "modulate:a", 0, 0.5) 53 | 54 | func apply_wallpaper_stretch_mode(new_stretch_mode: TextureRect.StretchMode) -> void: 55 | stretch_mode = new_stretch_mode 56 | DefaultValues.wallpaper_stretch_mode = stretch_mode 57 | DefaultValues.save_state() 58 | -------------------------------------------------------------------------------- /Scenes/Main/wallpaper.gd.uid: -------------------------------------------------------------------------------- 1 | uid://fgth35grbgyv 2 | -------------------------------------------------------------------------------- /Scenes/Misc/Benchmark Tester/benchmark_test.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | ## Just a stupid benchmark to spam windows and see how it hurts FPS. 4 | ## Results: Starts lagging after 100 windows, starts chugging after ~200, barely runs at 1fps after 1500. 5 | 6 | var windows: int 7 | 8 | func _physics_process(_delta): 9 | if windows < 1500: 10 | window_spawner() 11 | $RichTextLabel.text = "Windows: %d\nFPS: %d" % [windows, Performance.get_monitor(Performance.TIME_FPS)] 12 | 13 | func window_spawner(): 14 | get_tree().get_first_node_in_group("folder").spawn_window() 15 | windows += 1 16 | -------------------------------------------------------------------------------- /Scenes/Misc/Benchmark Tester/benchmark_test.gd.uid: -------------------------------------------------------------------------------- 1 | uid://4bxqshfsr7cl 2 | -------------------------------------------------------------------------------- /Scenes/Misc/Benchmark Tester/benchmark_test.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://gmc12dsm1usj"] 2 | 3 | [ext_resource type="Script" uid="uid://4bxqshfsr7cl" path="res://Scenes/Misc/Benchmark Tester/benchmark_test.gd" id="1_vxxfi"] 4 | 5 | [node name="Benchmark Test" type="Node"] 6 | script = ExtResource("1_vxxfi") 7 | 8 | [node name="RichTextLabel" type="RichTextLabel" parent="."] 9 | modulate = Color(1, 0.156863, 0.235294, 1) 10 | offset_left = 131.0 11 | offset_right = 643.0 12 | offset_bottom = 171.0 13 | theme_override_font_sizes/normal_font_size = 48 14 | text = "Text" 15 | -------------------------------------------------------------------------------- /Scenes/Taskbar/power_button.gd: -------------------------------------------------------------------------------- 1 | extends Button 2 | 3 | ## The power button in the start menu. Does nothing if you're on the web version. 4 | 5 | var boot_splash_scene: PackedScene = preload("res://Scenes/Main/Boot Splash/boot_splash.tscn") 6 | 7 | func _on_pressed() -> void: 8 | if OS.has_feature("web"): 9 | NotificationManager.spawn_notification("You can't shut down the web version of GodotOS!") 10 | return 11 | var boot_splash: BootSplash = boot_splash_scene.instantiate() 12 | boot_splash.quit_animation = true 13 | get_tree().root.add_child(boot_splash) 14 | -------------------------------------------------------------------------------- /Scenes/Taskbar/power_button.gd.uid: -------------------------------------------------------------------------------- 1 | uid://ovt5fnqwt48p 2 | -------------------------------------------------------------------------------- /Scenes/Taskbar/settings_button.gd: -------------------------------------------------------------------------------- 1 | extends Button 2 | 3 | ## The settings menu in the start menu. Just spawns the settings menu. 4 | 5 | func _on_pressed() -> void: 6 | var window: FakeWindow 7 | window = load("res://Scenes/Window/Settings Window/settings_window.tscn").instantiate() 8 | 9 | window.title_text = "[center]Settings Menu" 10 | get_tree().current_scene.add_child(window) 11 | 12 | var taskbar_button: Control = load("res://Scenes/Taskbar/taskbar_button.tscn").instantiate() 13 | taskbar_button.target_window = window 14 | taskbar_button.active_color = Color.WHITE 15 | taskbar_button.get_node("TextureMargin/TextureRect").texture = icon 16 | get_tree().get_first_node_in_group("taskbar_buttons").add_child(taskbar_button) 17 | -------------------------------------------------------------------------------- /Scenes/Taskbar/settings_button.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bcvlao324av3w 2 | -------------------------------------------------------------------------------- /Scenes/Taskbar/start_button.gd: -------------------------------------------------------------------------------- 1 | extends MarginContainer 2 | 3 | ## The start menu in the taskbar. Handles showing and hiding the start menu. 4 | 5 | @onready var start_menu: Panel = $"../../StartMenuAnchor/Start Menu" 6 | 7 | var is_mouse_over_menu: bool 8 | var is_mouse_over: bool 9 | 10 | func _input(event: InputEvent) -> void: 11 | if event is InputEventMouseButton and event.button_index == 1 and event.is_pressed(): 12 | handle_mouse_click() 13 | 14 | func _on_mouse_entered() -> void: 15 | add_theme_constant_override("margin_bottom", 5) 16 | add_theme_constant_override("margin_left", 5) 17 | add_theme_constant_override("margin_right", 5) 18 | add_theme_constant_override("margin_top", 5) 19 | is_mouse_over = true 20 | 21 | func _on_mouse_exited() -> void: 22 | add_theme_constant_override("margin_bottom", 3) 23 | add_theme_constant_override("margin_left", 3) 24 | add_theme_constant_override("margin_right", 3) 25 | add_theme_constant_override("margin_top", 3) 26 | is_mouse_over = false 27 | 28 | func handle_mouse_click() -> void: 29 | if is_mouse_over_menu: # Mouse clicked on empty space in menu, do nothing 30 | return 31 | 32 | if is_mouse_over: 33 | if start_menu.position.y > 0: 34 | show_start_menu() 35 | else: 36 | hide_start_menu() 37 | else: 38 | hide_start_menu() 39 | 40 | func show_start_menu() -> void: 41 | var tween: Tween = create_tween() 42 | tween.set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) 43 | tween.tween_property(start_menu, "position:y", -405, 0.3).from(-50) 44 | 45 | func hide_start_menu() -> void: 46 | # Called from clicking on desktop 47 | var tween: Tween = create_tween() 48 | tween.set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) 49 | tween.tween_property(start_menu, "position:y", 50, 0.3) 50 | 51 | func _on_start_menu_mouse_entered() -> void: 52 | is_mouse_over_menu = true 53 | 54 | func _on_start_menu_mouse_exited() -> void: 55 | is_mouse_over_menu = false 56 | -------------------------------------------------------------------------------- /Scenes/Taskbar/start_button.gd.uid: -------------------------------------------------------------------------------- 1 | uid://clkes7h7romou 2 | -------------------------------------------------------------------------------- /Scenes/Taskbar/start_menu_option.gd: -------------------------------------------------------------------------------- 1 | extends Panel 2 | 3 | ## A start menu option. Currently only used to spawn game windows and nothing else. 4 | 5 | ## Path to the game scene 6 | @export var game_scene: String 7 | 8 | ## Title shown in start menu option (added at runtime). 9 | @export var title_text: String 10 | 11 | ## Description shown in start menu option (added at runtime). 12 | @export var description_text: String 13 | 14 | ## Whether or not the scene should be instantiated inside a game window or outside one. 15 | ## (You probably want this on, but it's great if you want to make your own custom window or behavior) 16 | @export var spawn_inside_window: bool = true 17 | 18 | ## Whether to use a simple pause menu or not (spawned by pressing ESC or P) 19 | @export var use_generic_pause_menu: bool 20 | 21 | var is_mouse_over: bool 22 | 23 | func _ready() -> void: 24 | $"Background Panel".visible = false 25 | %"Menu Title".text = "[center]%s" % title_text 26 | %"Menu Description".text = "[center]%s" % description_text 27 | 28 | func _gui_input(event: InputEvent) -> void: 29 | if event is InputEventMouseButton and event.button_index == 1 and event.is_pressed(): 30 | if spawn_inside_window: 31 | spawn_window() 32 | else: 33 | spawn_outside_window() 34 | 35 | func _on_mouse_entered() -> void: 36 | is_mouse_over = true 37 | $"Background Panel".visible = true 38 | var tween: Tween = create_tween() 39 | tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC) 40 | tween.tween_property($"Background Panel", "modulate:a", 1, 0.2) 41 | 42 | func _on_mouse_exited() -> void: 43 | is_mouse_over = false 44 | var tween: Tween = create_tween() 45 | tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC) 46 | await tween.tween_property($"Background Panel", "modulate:a", 0, 0.2).finished 47 | if !is_mouse_over: 48 | $"Background Panel".visible = false 49 | 50 | # TODO find a better way than copying this from desktop_folder.gd 51 | func spawn_window() -> void: 52 | var window: FakeWindow 53 | window = load("res://Scenes/Window/Game Window/game_window.tscn").instantiate() 54 | window.get_node("%Game Window").add_child(load(game_scene).instantiate()) 55 | 56 | if use_generic_pause_menu: 57 | window.get_node("%GamePauseManager").process_mode = Node.PROCESS_MODE_INHERIT 58 | 59 | window.title_text = %"Menu Title".text 60 | get_tree().current_scene.add_child(window) 61 | 62 | var taskbar_button: Control = load("res://Scenes/Taskbar/taskbar_button.tscn").instantiate() 63 | taskbar_button.target_window = window 64 | taskbar_button.get_node("TextureMargin/TextureRect").texture = $"HBoxContainer/MarginContainer/TextureRect".texture 65 | taskbar_button.active_color = $"HBoxContainer/MarginContainer/TextureRect".modulate 66 | get_tree().get_first_node_in_group("taskbar_buttons").add_child(taskbar_button) 67 | 68 | func spawn_outside_window() -> void: 69 | $/root/Control.add_child(load(game_scene).instantiate()) 70 | -------------------------------------------------------------------------------- /Scenes/Taskbar/start_menu_option.gd.uid: -------------------------------------------------------------------------------- 1 | uid://b4pjauo2jicy2 2 | -------------------------------------------------------------------------------- /Scenes/Taskbar/start_menu_option.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://da4oly47yx3ja"] 2 | 3 | [ext_resource type="Script" uid="uid://b4pjauo2jicy2" path="res://Scenes/Taskbar/start_menu_option.gd" id="1_2fneu"] 4 | [ext_resource type="Texture2D" uid="uid://2sqrvihn1cjq" path="res://Art/Folder Icons/game.png" id="2_4g113"] 5 | 6 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0gkon"] 7 | bg_color = Color(0, 0.792157, 0.952941, 0.72549) 8 | border_width_left = 2 9 | border_width_top = 2 10 | border_width_right = 2 11 | border_width_bottom = 2 12 | border_color = Color(0, 1, 0.952941, 1) 13 | 14 | [node name="Start Menu Option" type="Panel"] 15 | clip_contents = true 16 | custom_minimum_size = Vector2(0, 50) 17 | script = ExtResource("1_2fneu") 18 | game_scene = "res://Games/Cube Scene/cube_scene.tscn" 19 | use_generic_pause_menu = true 20 | 21 | [node name="Background Panel" type="Panel" parent="."] 22 | visible = false 23 | layout_mode = 1 24 | anchors_preset = 15 25 | anchor_right = 1.0 26 | anchor_bottom = 1.0 27 | grow_horizontal = 2 28 | grow_vertical = 2 29 | mouse_filter = 2 30 | theme_override_styles/panel = SubResource("StyleBoxFlat_0gkon") 31 | 32 | [node name="HBoxContainer" type="HBoxContainer" parent="."] 33 | layout_mode = 1 34 | anchors_preset = 15 35 | anchor_right = 1.0 36 | anchor_bottom = 1.0 37 | grow_horizontal = 2 38 | grow_vertical = 2 39 | mouse_filter = 2 40 | 41 | [node name="MarginContainer" type="MarginContainer" parent="HBoxContainer"] 42 | custom_minimum_size = Vector2(50, 0) 43 | layout_mode = 2 44 | mouse_filter = 2 45 | theme_override_constants/margin_left = 5 46 | theme_override_constants/margin_top = 5 47 | theme_override_constants/margin_right = 5 48 | theme_override_constants/margin_bottom = 5 49 | 50 | [node name="TextureRect" type="TextureRect" parent="HBoxContainer/MarginContainer"] 51 | modulate = Color(0.811765, 0.329412, 0.960784, 1) 52 | layout_mode = 2 53 | mouse_filter = 2 54 | texture = ExtResource("2_4g113") 55 | expand_mode = 2 56 | 57 | [node name="Control" type="Control" parent="HBoxContainer"] 58 | layout_mode = 2 59 | size_flags_horizontal = 3 60 | mouse_filter = 2 61 | 62 | [node name="Menu Title" type="RichTextLabel" parent="HBoxContainer/Control"] 63 | unique_name_in_owner = true 64 | layout_mode = 1 65 | anchors_preset = 10 66 | anchor_right = 1.0 67 | offset_bottom = 30.0 68 | grow_horizontal = 2 69 | size_flags_horizontal = 3 70 | mouse_filter = 2 71 | bbcode_enabled = true 72 | text = "[center]Game Title" 73 | 74 | [node name="Menu Description" type="RichTextLabel" parent="HBoxContainer/Control"] 75 | unique_name_in_owner = true 76 | layout_mode = 1 77 | anchors_preset = 12 78 | anchor_top = 1.0 79 | anchor_right = 1.0 80 | anchor_bottom = 1.0 81 | offset_top = -25.0 82 | offset_bottom = 5.0 83 | grow_horizontal = 2 84 | grow_vertical = 0 85 | size_flags_horizontal = 3 86 | mouse_filter = 2 87 | theme_override_font_sizes/normal_font_size = 14 88 | bbcode_enabled = true 89 | text = "[center]Your very cool game description" 90 | 91 | [connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"] 92 | [connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"] 93 | -------------------------------------------------------------------------------- /Scenes/Taskbar/taskbar_button.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | ## A window's taskbar button. Used to minimize/restore a window. 4 | ## Also shows which window is selected or minimized via colors. 5 | 6 | @onready var texture_margin: MarginContainer = $TextureMargin 7 | @onready var texture_rect: TextureRect = $"TextureMargin/TextureRect" 8 | @onready var selected_background: TextureRect = $SelectedBackground 9 | 10 | var target_window: FakeWindow 11 | 12 | var active_color: Color = Color("6de700") 13 | var disabled_color: Color = Color("908a8c") 14 | 15 | func _ready() -> void: 16 | target_window.minimized.connect(_on_window_minimized) 17 | target_window.deleted.connect(_on_window_deleted) 18 | target_window.selected.connect(_on_window_selected) 19 | texture_rect.self_modulate = active_color 20 | 21 | func _gui_input(event: InputEvent) -> void: 22 | if event is InputEventMouseButton and event.button_index == 1 and event.is_pressed(): 23 | if target_window.is_minimized: 24 | target_window.show_window() 25 | else: 26 | target_window.hide_window() 27 | 28 | func _on_mouse_entered() -> void: 29 | texture_margin.add_theme_constant_override("margin_bottom", 7) 30 | texture_margin.add_theme_constant_override("margin_left", 7) 31 | texture_margin.add_theme_constant_override("margin_right", 7) 32 | texture_margin.add_theme_constant_override("margin_top", 7) 33 | 34 | func _on_mouse_exited() -> void: 35 | texture_margin.add_theme_constant_override("margin_bottom", 5) 36 | texture_margin.add_theme_constant_override("margin_left", 5) 37 | texture_margin.add_theme_constant_override("margin_right", 5) 38 | texture_margin.add_theme_constant_override("margin_top", 5) 39 | 40 | func _on_window_minimized(is_minimized: bool) -> void: 41 | var tween: Tween = create_tween() 42 | tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC) 43 | if is_minimized: 44 | tween.tween_property(texture_rect, "self_modulate", disabled_color, 0.25) 45 | else: 46 | tween.tween_property(texture_rect, "self_modulate", active_color, 0.25) 47 | 48 | func _on_window_deleted() -> void: 49 | queue_free() 50 | 51 | func _on_window_selected(selected: bool) -> void: 52 | var tween: Tween = create_tween() 53 | tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC) 54 | 55 | if selected: 56 | tween.tween_property(selected_background, "self_modulate:a", 1, 0.25) 57 | else: 58 | tween.tween_property(selected_background, "self_modulate:a", 0, 0.25) 59 | -------------------------------------------------------------------------------- /Scenes/Taskbar/taskbar_button.gd.uid: -------------------------------------------------------------------------------- 1 | uid://2grdmbycx712 2 | -------------------------------------------------------------------------------- /Scenes/Taskbar/taskbar_button.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://b7mejsbueubva"] 2 | 3 | [ext_resource type="Script" uid="uid://2grdmbycx712" path="res://Scenes/Taskbar/taskbar_button.gd" id="1_j5fdb"] 4 | 5 | [sub_resource type="Gradient" id="Gradient_l7111"] 6 | offsets = PackedFloat32Array(0) 7 | colors = PackedColorArray(1, 1, 1, 1) 8 | 9 | [sub_resource type="GradientTexture1D" id="GradientTexture1D_mftby"] 10 | gradient = SubResource("Gradient_l7111") 11 | width = 1 12 | 13 | [sub_resource type="CanvasTexture" id="CanvasTexture_s4q16"] 14 | 15 | [node name="TaskbarButton" type="Control"] 16 | custom_minimum_size = Vector2(40, 0) 17 | layout_mode = 3 18 | anchors_preset = 0 19 | offset_left = 5.0 20 | offset_top = 5.0 21 | offset_right = 35.0 22 | offset_bottom = 6.0 23 | mouse_filter = 1 24 | script = ExtResource("1_j5fdb") 25 | 26 | [node name="SelectedBackground" type="TextureRect" parent="."] 27 | modulate = Color(0, 0.498039, 1, 0.470588) 28 | layout_mode = 0 29 | offset_right = 40.0 30 | offset_bottom = 40.0 31 | texture = SubResource("GradientTexture1D_mftby") 32 | expand_mode = 2 33 | 34 | [node name="TextureMargin" type="MarginContainer" parent="."] 35 | custom_minimum_size = Vector2(40, 0) 36 | layout_mode = 1 37 | anchors_preset = 15 38 | anchor_right = 1.0 39 | anchor_bottom = 1.0 40 | grow_horizontal = 2 41 | grow_vertical = 2 42 | mouse_filter = 2 43 | theme_override_constants/margin_left = 5 44 | theme_override_constants/margin_top = 5 45 | theme_override_constants/margin_right = 5 46 | theme_override_constants/margin_bottom = 5 47 | 48 | [node name="TextureRect" type="TextureRect" parent="TextureMargin"] 49 | self_modulate = Color(0.427451, 0.905882, 0, 1) 50 | texture_filter = 4 51 | layout_mode = 2 52 | mouse_filter = 2 53 | texture = SubResource("CanvasTexture_s4q16") 54 | expand_mode = 2 55 | 56 | [connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"] 57 | [connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"] 58 | -------------------------------------------------------------------------------- /Scenes/Taskbar/taskbar_time.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | ## The time and date in the taskbar. 4 | ## Updates once every 10 seconds since string replacements can be a waste of resources. 5 | 6 | func _ready() -> void: 7 | update_time() 8 | 9 | func update_time() -> void: 10 | var date_dict: Dictionary = Time.get_datetime_dict_from_system() 11 | var suffix: String 12 | if date_dict.hour >= 12: 13 | date_dict.hour -= 12 14 | suffix = "PM" 15 | else: 16 | suffix = "AM" 17 | if date_dict.hour == 0: 18 | date_dict.hour = 12 19 | 20 | $TimeText.text = "[center]%02d:%02d %s" % [date_dict.hour, date_dict.minute, suffix] 21 | $DateText.text = "[center]%02d/%02d/%d" % [date_dict.day, date_dict.month, date_dict.year] 22 | 23 | func _on_timer_timeout() -> void: 24 | update_time() 25 | -------------------------------------------------------------------------------- /Scenes/Taskbar/taskbar_time.gd.uid: -------------------------------------------------------------------------------- 1 | uid://33k2ree3e2yt 2 | -------------------------------------------------------------------------------- /Scenes/Window/File Manager/file_manager_window.gd: -------------------------------------------------------------------------------- 1 | extends BaseFileManager 2 | class_name FileManagerWindow 3 | 4 | ## The file manager window. 5 | 6 | func _ready() -> void: 7 | populate_file_manager() 8 | sort_folders() 9 | 10 | $"../../Resize Drag Spot".window_resized.connect(update_positions) 11 | 12 | func reload_window(folder_path: String) -> void: 13 | # Reload the same path if not given folder_path 14 | if !folder_path.is_empty(): 15 | file_path = folder_path 16 | 17 | for child in get_children(): 18 | if child is FakeFolder: 19 | child.queue_free() 20 | 21 | populate_file_manager() 22 | 23 | #TODO make this less dumb 24 | $"../../Top Bar/Title Text".text = "[center]%s" % file_path 25 | 26 | func close_window() -> void: 27 | $"../.."._on_close_button_pressed() 28 | 29 | ## Goes to the folder above the currently shown one. Can't go higher than user://files/ 30 | func _on_back_button_pressed() -> void: 31 | #TODO move it to a position that's less stupid 32 | var split_path: PackedStringArray = file_path.split("/") 33 | if split_path.size() <= 1: 34 | return 35 | 36 | split_path.remove_at(split_path.size() - 1) 37 | file_path = "/".join(split_path) 38 | 39 | reload_window(file_path) 40 | -------------------------------------------------------------------------------- /Scenes/Window/File Manager/file_manager_window.gd.uid: -------------------------------------------------------------------------------- 1 | uid://0e08uudim1di 2 | -------------------------------------------------------------------------------- /Scenes/Window/File Manager/file_manager_window.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=3 uid="uid://i03dt4l5msgl"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://cojrqff5vocjv" path="res://Scenes/Window/Window.tscn" id="1_xona8"] 4 | [ext_resource type="Script" uid="uid://0e08uudim1di" path="res://Scenes/Window/File Manager/file_manager_window.gd" id="2_prcfs"] 5 | 6 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_8j66m"] 7 | content_margin_left = 0.0 8 | content_margin_top = 0.0 9 | content_margin_right = 0.0 10 | content_margin_bottom = 0.0 11 | bg_color = Color(0.196078, 0.333333, 0.196078, 0.784314) 12 | corner_radius_top_left = 5 13 | corner_radius_top_right = 5 14 | corner_radius_bottom_right = 5 15 | corner_radius_bottom_left = 5 16 | corner_detail = 5 17 | shadow_color = Color(0, 0, 0, 0.0784314) 18 | 19 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_xgbvp"] 20 | bg_color = Color(0, 0, 0, 0.392157) 21 | corner_radius_top_left = 5 22 | 23 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_lrke7"] 24 | bg_color = Color(0.501961, 0.501961, 0.501961, 0.392157) 25 | corner_radius_top_left = 5 26 | 27 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ogij0"] 28 | bg_color = Color(0.4, 0.4, 0.4, 0.392157) 29 | corner_radius_top_left = 5 30 | 31 | [node name="Window" instance=ExtResource("1_xona8")] 32 | offset_left = -267.5 33 | offset_right = 267.5 34 | theme_override_styles/panel = SubResource("StyleBoxFlat_8j66m") 35 | 36 | [node name="ScrollContainer" type="ScrollContainer" parent="." index="0"] 37 | layout_mode = 1 38 | anchors_preset = -1 39 | anchor_right = 1.0 40 | anchor_bottom = 1.0 41 | offset_top = 30.0 42 | grow_horizontal = 2 43 | grow_vertical = 2 44 | 45 | [node name="File Manager Window" type="Control" parent="ScrollContainer" index="0" groups=["file_manager_window", "right_click_enabled"]] 46 | unique_name_in_owner = true 47 | layout_mode = 2 48 | size_flags_horizontal = 3 49 | size_flags_vertical = 3 50 | mouse_filter = 1 51 | script = ExtResource("2_prcfs") 52 | horizontal_spacing = 20 53 | vertical_spacing = 15 54 | left_margin = 20 55 | up_margin = 10 56 | right_margin = 20 57 | down_margin = 10 58 | 59 | [node name="Back Button" type="Button" parent="Top Bar" index="2"] 60 | custom_minimum_size = Vector2(40, 0) 61 | layout_mode = 1 62 | anchors_preset = 9 63 | anchor_bottom = 1.0 64 | offset_right = 8.0 65 | grow_vertical = 2 66 | focus_mode = 0 67 | mouse_filter = 1 68 | theme_override_styles/normal = SubResource("StyleBoxFlat_xgbvp") 69 | theme_override_styles/hover = SubResource("StyleBoxFlat_lrke7") 70 | theme_override_styles/pressed = SubResource("StyleBoxFlat_ogij0") 71 | text = "^" 72 | 73 | [connection signal="pressed" from="Top Bar/Back Button" to="ScrollContainer/File Manager Window" method="_on_back_button_pressed"] 74 | -------------------------------------------------------------------------------- /Scenes/Window/Game Window/game_pause_manager.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | class_name GamePauseManager 3 | 4 | ## A generic pause manager for games in GodotOS. 5 | ## When you press ui_cancel, it pauses or unpauses. 6 | 7 | ## NOTE: This node disabled by default but gets enabled by start menu option 8 | ## if the generic pause menu bool is enabled there. 9 | 10 | @export var pause_packed_scene: PackedScene 11 | 12 | @onready var window: FakeWindow = $".." 13 | 14 | var is_paused: bool 15 | var current_pause_screen: CanvasLayer 16 | 17 | func _input(event: InputEvent) -> void: 18 | if !window.is_selected: 19 | return 20 | 21 | if event.is_action_pressed("pause_game"): 22 | toggle_pause() 23 | 24 | ## Pauses and adds the pause screen as a child to the game scene. 25 | ## The reason for this is so the pause screen scales with the viewport. 26 | func toggle_pause() -> void: 27 | if %"Game Window".get_child_count() == 0: 28 | NotificationManager.spawn_notification("Error: No game scene to pause???") 29 | return 30 | 31 | var game_scene: Node = %"Game Window".get_child(0) 32 | 33 | if is_paused: 34 | game_scene.process_mode = Node.PROCESS_MODE_INHERIT 35 | if current_pause_screen != null: 36 | current_pause_screen.queue_free() 37 | else: 38 | game_scene.process_mode = Node.PROCESS_MODE_DISABLED 39 | var pause_screen: CanvasLayer = pause_packed_scene.instantiate() 40 | game_scene.add_child(pause_screen) 41 | current_pause_screen = pause_screen 42 | 43 | is_paused = !is_paused 44 | -------------------------------------------------------------------------------- /Scenes/Window/Game Window/game_pause_manager.gd.uid: -------------------------------------------------------------------------------- 1 | uid://8a1f31mrih3n 2 | -------------------------------------------------------------------------------- /Scenes/Window/Game Window/game_window.gd: -------------------------------------------------------------------------------- 1 | extends SubViewport 2 | 3 | ## The game window, used to show games. 4 | 5 | @onready var window: FakeWindow = $"../../.." 6 | @onready var game_pause_manager: GamePauseManager = %"GamePauseManager" 7 | 8 | func _ready() -> void: 9 | window.minimized.connect(_handle_window_minimized) 10 | window.selected.connect(_handle_window_selected) 11 | 12 | # WIP: Making game scene resolution not tied to screen scale 13 | #await get_tree().process_frame 14 | #$"../..".scale /= get_window().content_scale_factor 15 | #$"../..".size *= get_window().content_scale_factor 16 | 17 | func _handle_window_minimized(is_minimized: bool) -> void: 18 | if game_pause_manager.is_paused: 19 | return 20 | 21 | if is_minimized: 22 | get_child(0).process_mode = Node.PROCESS_MODE_DISABLED 23 | else: 24 | get_child(0).process_mode = Node.PROCESS_MODE_INHERIT 25 | 26 | ## Disables input if the window isn't selected. 27 | func _handle_window_selected(is_selected: bool) -> void: 28 | # TODO check if this wrecks performance 29 | #handle_input_locally = false 30 | set_input(self, is_selected) 31 | 32 | # WARNING recursively loops on every node in the game. Probably a bad idea. 33 | func set_input(node: Node, can_input: bool) -> void: 34 | node.set_process_input(can_input) 35 | for n in node.get_children(): 36 | set_input(n, can_input) 37 | -------------------------------------------------------------------------------- /Scenes/Window/Game Window/game_window.gd.uid: -------------------------------------------------------------------------------- 1 | uid://ba6ciics63ond 2 | -------------------------------------------------------------------------------- /Scenes/Window/Game Window/game_window.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://c73tsgfxmn37a"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://cojrqff5vocjv" path="res://Scenes/Window/Window.tscn" id="1_r6cfa"] 4 | [ext_resource type="Script" uid="uid://ba6ciics63ond" path="res://Scenes/Window/Game Window/game_window.gd" id="2_83d0v"] 5 | [ext_resource type="Script" uid="uid://8a1f31mrih3n" path="res://Scenes/Window/Game Window/game_pause_manager.gd" id="2_sh1be"] 6 | [ext_resource type="PackedScene" uid="uid://eprwl55n45fe" path="res://Scenes/Window/Game Window/pause_screen.tscn" id="3_uu1vi"] 7 | 8 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5cq01"] 9 | bg_color = Color(0.188235, 0.105882, 0.243137, 0.6) 10 | corner_radius_top_left = 5 11 | corner_radius_top_right = 5 12 | shadow_color = Color(0, 0, 0, 0.0784314) 13 | 14 | [node name="Window" instance=ExtResource("1_r6cfa")] 15 | offset_left = -288.0 16 | offset_top = -177.0 17 | offset_right = 288.0 18 | offset_bottom = 177.0 19 | theme_override_styles/panel = SubResource("StyleBoxFlat_5cq01") 20 | 21 | [node name="Title Text" parent="Top Bar" index="0"] 22 | texture_filter = 2 23 | 24 | [node name="GamePauseManager" type="Node" parent="." index="1"] 25 | unique_name_in_owner = true 26 | process_mode = 4 27 | editor_description = "Disabled by default, gets enabled by start_menu_option at runtime." 28 | script = ExtResource("2_sh1be") 29 | pause_packed_scene = ExtResource("3_uu1vi") 30 | 31 | [node name="AspectRatioContainer" type="AspectRatioContainer" parent="." index="2"] 32 | layout_mode = 1 33 | anchors_preset = 15 34 | anchor_right = 1.0 35 | anchor_bottom = 1.0 36 | offset_top = 29.0 37 | grow_horizontal = 2 38 | grow_vertical = 2 39 | mouse_filter = 2 40 | ratio = 1.7778 41 | 42 | [node name="SubViewportContainer" type="SubViewportContainer" parent="AspectRatioContainer" index="0"] 43 | layout_mode = 2 44 | stretch = true 45 | 46 | [node name="Game Window" type="SubViewport" parent="AspectRatioContainer/SubViewportContainer" index="0"] 47 | unique_name_in_owner = true 48 | own_world_3d = true 49 | handle_input_locally = false 50 | size = Vector2i(576, 323) 51 | size_2d_override = Vector2i(1152, 648) 52 | size_2d_override_stretch = true 53 | render_target_update_mode = 4 54 | script = ExtResource("2_83d0v") 55 | -------------------------------------------------------------------------------- /Scenes/Window/Game Window/pause_screen.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene format=3 uid="uid://eprwl55n45fe"] 2 | 3 | [node name="CanvasLayer" type="CanvasLayer"] 4 | 5 | [node name="ColorRect" type="ColorRect" parent="."] 6 | anchors_preset = 15 7 | anchor_right = 1.0 8 | anchor_bottom = 1.0 9 | grow_horizontal = 2 10 | grow_vertical = 2 11 | mouse_filter = 1 12 | color = Color(0, 0, 0, 0.784314) 13 | 14 | [node name="RichTextLabel" type="RichTextLabel" parent="ColorRect"] 15 | layout_mode = 1 16 | anchors_preset = 8 17 | anchor_left = 0.5 18 | anchor_top = 0.5 19 | anchor_right = 0.5 20 | anchor_bottom = 0.5 21 | offset_left = -200.0 22 | offset_top = -45.0 23 | offset_right = 200.0 24 | offset_bottom = 45.0 25 | grow_horizontal = 2 26 | grow_vertical = 2 27 | mouse_filter = 2 28 | theme_override_font_sizes/normal_font_size = 64 29 | bbcode_enabled = true 30 | text = "[center]- PAUSED -" 31 | -------------------------------------------------------------------------------- /Scenes/Window/Image Viewer/image_viewer.gd: -------------------------------------------------------------------------------- 1 | extends TextureRect 2 | 3 | ## The image viewer window. 4 | 5 | func import_image(file_path: String) -> void: 6 | if !FileAccess.file_exists("user://files/%s" % file_path): 7 | NotificationManager.spawn_notification("Error: Cannot find file (was it moved or deleted?)") 8 | return 9 | var image: Image = Image.load_from_file("user://files/%s" % file_path) 10 | image.generate_mipmaps() 11 | var texture_import: ImageTexture = ImageTexture.create_from_image(image) 12 | texture = texture_import 13 | -------------------------------------------------------------------------------- /Scenes/Window/Image Viewer/image_viewer.gd.uid: -------------------------------------------------------------------------------- 1 | uid://dy8ijrxds68k6 2 | -------------------------------------------------------------------------------- /Scenes/Window/Image Viewer/image_viewer.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://bw213qcym41ma"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://cojrqff5vocjv" path="res://Scenes/Window/Window.tscn" id="1_bisfo"] 4 | [ext_resource type="Script" uid="uid://dy8ijrxds68k6" path="res://Scenes/Window/Image Viewer/image_viewer.gd" id="2_3oyj5"] 5 | 6 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_8a368"] 7 | bg_color = Color(0.337151, 0.3052, 0.145422, 0.784314) 8 | corner_radius_top_left = 5 9 | corner_radius_top_right = 5 10 | corner_radius_bottom_right = 5 11 | corner_radius_bottom_left = 5 12 | shadow_color = Color(0, 0, 0, 0.0784314) 13 | 14 | [node name="Window" instance=ExtResource("1_bisfo")] 15 | theme_override_styles/panel = SubResource("StyleBoxFlat_8a368") 16 | 17 | [node name="Control" type="Control" parent="." index="1"] 18 | clip_contents = true 19 | layout_mode = 1 20 | anchors_preset = 15 21 | anchor_right = 1.0 22 | anchor_bottom = 1.0 23 | grow_horizontal = 2 24 | grow_vertical = 2 25 | mouse_filter = 2 26 | 27 | [node name="Image Viewer" type="TextureRect" parent="Control" index="0"] 28 | unique_name_in_owner = true 29 | texture_filter = 6 30 | layout_mode = 1 31 | anchors_preset = 15 32 | anchor_right = 1.0 33 | anchor_bottom = 1.0 34 | offset_top = 30.0 35 | grow_horizontal = 2 36 | grow_vertical = 2 37 | mouse_filter = 2 38 | expand_mode = 2 39 | stretch_mode = 5 40 | script = ExtResource("2_3oyj5") 41 | -------------------------------------------------------------------------------- /Scenes/Window/Settings Window/background_color_picker.gd: -------------------------------------------------------------------------------- 1 | extends ColorPickerButton 2 | 3 | ## The background color picker used in the settings menu. 4 | 5 | @onready var background_color: ColorRect = $"/root/Control/BackgroundColor" 6 | 7 | func _ready() -> void: 8 | if !background_color: 9 | printerr("background_color_picker.gd: Couldn't find background color (are you debugging the settings menu?)") 10 | return 11 | 12 | get_picker().presets_visible = false 13 | get_picker().deferred_mode = true 14 | get_picker().sliders_visible = true 15 | color = background_color.color 16 | 17 | func _on_color_changed(new_color: Color) -> void: 18 | var tween: Tween = create_tween() 19 | tween.set_trans(Tween.TRANS_CUBIC) 20 | tween.tween_property(background_color, "color", new_color, 0.5) 21 | DefaultValues.save_state() 22 | -------------------------------------------------------------------------------- /Scenes/Window/Settings Window/background_color_picker.gd.uid: -------------------------------------------------------------------------------- 1 | uid://n3mn2lwk6v46 2 | -------------------------------------------------------------------------------- /Scenes/Window/Settings Window/max_fps_options.gd: -------------------------------------------------------------------------------- 1 | extends OptionButton 2 | 3 | ## The max FPS options in the settings menu. 4 | 5 | func _ready() -> void: 6 | var index: int 7 | match Engine.max_fps: 8 | 30: index = 0 9 | 60: index = 1 10 | 90: index = 2 11 | 120: index = 3 12 | 144: index = 4 13 | 165: index = 5 14 | 240: index = 6 15 | 360: index = 7 16 | 17 | selected = index 18 | 19 | func _on_item_selected(index: int) -> void: 20 | var new_fps: int 21 | match index: 22 | 0: new_fps = 30 23 | 1: new_fps = 60 24 | 2: new_fps = 90 25 | 3: new_fps = 120 26 | 4: new_fps = 144 27 | 5: new_fps = 165 28 | 6: new_fps = 240 29 | 7: new_fps = 360 30 | 31 | Engine.max_fps = new_fps 32 | -------------------------------------------------------------------------------- /Scenes/Window/Settings Window/max_fps_options.gd.uid: -------------------------------------------------------------------------------- 1 | uid://c84pgsmltldk4 2 | -------------------------------------------------------------------------------- /Scenes/Window/Settings Window/remove_wallpaper.gd: -------------------------------------------------------------------------------- 1 | extends Button 2 | 3 | ## The remove wallpaper button in the settings menu. 4 | 5 | @onready var wallpaper: Wallpaper = $"/root/Control/Wallpaper" 6 | 7 | func _ready() -> void: 8 | if !wallpaper: 9 | printerr("remove_wallpaper.gd: Couldn't find wallpaper (are you debugging the settings menu?)") 10 | return 11 | 12 | if wallpaper.texture == null: 13 | disabled = true 14 | wallpaper.wallpaper_added.connect(_on_wallpaper_added) 15 | 16 | func _on_wallpaper_added() -> void: 17 | disabled = false 18 | 19 | func _on_pressed() -> void: 20 | wallpaper.remove_wallpaper() 21 | disabled = true 22 | -------------------------------------------------------------------------------- /Scenes/Window/Settings Window/remove_wallpaper.gd.uid: -------------------------------------------------------------------------------- 1 | uid://kmfv0m283o0l 2 | -------------------------------------------------------------------------------- /Scenes/Window/Settings Window/scaling_spinbox.gd: -------------------------------------------------------------------------------- 1 | extends SpinBox 2 | 3 | ## The scaling spinbox in the settings menu. 4 | ## Also handles the + and - buttons next to it. 5 | 6 | var is_mouse_over: bool 7 | 8 | func _ready() -> void: 9 | value = get_window().content_scale_factor 10 | 11 | func _input(event: InputEvent) -> void: 12 | if event is InputEventMouseButton and event.button_index == 1 and event.is_pressed() and !is_mouse_over: 13 | get_line_edit().release_focus() 14 | 15 | if event.is_action_pressed("zoom_in") or event.is_action_pressed("zoom_out"): 16 | await get_tree().process_frame 17 | value = get_window().content_scale_factor 18 | 19 | func _on_mouse_entered() -> void: 20 | is_mouse_over = true 21 | 22 | func _on_mouse_exited() -> void: 23 | is_mouse_over = false 24 | 25 | func _on_value_changed(new_value: float) -> void: 26 | get_window().content_scale_factor = new_value 27 | DefaultValues.save_state() 28 | 29 | func _on_increment_scaling_pressed() -> void: 30 | if value + 0.125 > max_value: 31 | get_window().content_scale_factor = max_value 32 | else: 33 | get_window().content_scale_factor += 0.125 34 | value = get_window().content_scale_factor 35 | 36 | func _on_decrement_scaling_pressed() -> void: 37 | if value - 0.125 < min_value: 38 | get_window().content_scale_factor = min_value 39 | else: 40 | get_window().content_scale_factor -= 0.125 41 | value = get_window().content_scale_factor 42 | -------------------------------------------------------------------------------- /Scenes/Window/Settings Window/scaling_spinbox.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cthe8oglu2808 2 | -------------------------------------------------------------------------------- /Scenes/Window/Settings Window/stretch_wallpaper.gd: -------------------------------------------------------------------------------- 1 | extends OptionButton 2 | 3 | ## The wallpaper stretch options in the settings menu. 4 | 5 | @onready var wallpaper: Wallpaper = $"/root/Control/Wallpaper" 6 | 7 | func _ready() -> void: 8 | if !wallpaper: 9 | printerr("stretch_wallpaper.gd: Couldn't find wallpaper.") 10 | return 11 | 12 | if wallpaper.texture == null: 13 | disabled = true 14 | wallpaper.wallpaper_added.connect(_on_wallpaper_added) 15 | match DefaultValues.wallpaper_stretch_mode: 16 | 0: selected = 0 17 | 1: selected = 1 18 | 5: selected = 2 19 | 6: selected = 3 20 | 21 | func _on_wallpaper_added() -> void: 22 | disabled = false 23 | 24 | func _on_item_selected(index: int) -> void: 25 | if index == 0: 26 | # Scale mode 27 | wallpaper.apply_wallpaper_stretch_mode(TextureRect.STRETCH_SCALE) 28 | elif index == 1: 29 | #Tile 30 | wallpaper.apply_wallpaper_stretch_mode(TextureRect.STRETCH_TILE) 31 | elif index == 2: 32 | #Center 33 | wallpaper.apply_wallpaper_stretch_mode(TextureRect.STRETCH_KEEP_ASPECT_CENTERED) 34 | elif index == 3: 35 | #Covered 36 | wallpaper.apply_wallpaper_stretch_mode(TextureRect.STRETCH_KEEP_ASPECT_COVERED) 37 | -------------------------------------------------------------------------------- /Scenes/Window/Settings Window/stretch_wallpaper.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bofup4ya34voc 2 | -------------------------------------------------------------------------------- /Scenes/Window/Settings Window/window_options.gd: -------------------------------------------------------------------------------- 1 | extends OptionButton 2 | 3 | ## The window fullscreen options in the settings menu. 4 | 5 | func _ready() -> void: 6 | set_selected_window_mode() 7 | 8 | func _input(event: InputEvent) -> void: 9 | if event.is_action_pressed("fullscreen"): 10 | await get_tree().process_frame 11 | set_selected_window_mode() 12 | 13 | func _on_item_selected(index: int) -> void: 14 | if index == 0: 15 | DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) 16 | elif index == 1: 17 | DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN) 18 | elif index == 2: 19 | DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN) 20 | 21 | func set_selected_window_mode() -> void: 22 | if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_WINDOWED: 23 | selected = 0 24 | elif DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN: 25 | selected = 1 26 | elif DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN: 27 | selected = 2 28 | -------------------------------------------------------------------------------- /Scenes/Window/Settings Window/window_options.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bmylb2xf7e5ih 2 | -------------------------------------------------------------------------------- /Scenes/Window/Text Editor/saved_notification.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://dypxkfx8bfb0d"] 2 | 3 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_oxmgl"] 4 | bg_color = Color(0, 0.8343, 0.819662, 0.490196) 5 | corner_radius_top_left = 5 6 | corner_radius_top_right = 5 7 | corner_radius_bottom_right = 5 8 | corner_radius_bottom_left = 5 9 | expand_margin_left = 2.0 10 | expand_margin_top = 2.0 11 | expand_margin_right = 2.0 12 | expand_margin_bottom = 2.0 13 | 14 | [sub_resource type="GDScript" id="GDScript_kaig5"] 15 | resource_name = "Saved_Notification" 16 | script/source = "extends Panel 17 | 18 | func _ready() -> void: 19 | var tween: Tween = create_tween() 20 | tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_SINE) 21 | tween.tween_property(self, \"position:y\", position.y - 75, 2) 22 | 23 | await get_tree().create_timer(1).timeout 24 | var fade: Tween = create_tween() 25 | fade.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_SINE) 26 | await fade.tween_property(self, \"modulate:a\", 0, 1.5).finished 27 | queue_free() 28 | " 29 | 30 | [node name="Panel" type="Panel"] 31 | offset_right = 96.0 32 | offset_bottom = 43.0 33 | mouse_filter = 2 34 | theme_override_styles/panel = SubResource("StyleBoxFlat_oxmgl") 35 | script = SubResource("GDScript_kaig5") 36 | 37 | [node name="RichTextLabel" type="RichTextLabel" parent="."] 38 | layout_mode = 1 39 | anchors_preset = 15 40 | anchor_right = 1.0 41 | anchor_bottom = 1.0 42 | offset_top = 2.0 43 | grow_horizontal = 2 44 | grow_vertical = 2 45 | mouse_filter = 2 46 | theme_override_font_sizes/normal_font_size = 28 47 | bbcode_enabled = true 48 | text = "[wave amp=30.0 freq=6.0 connected=1][center]Saved!" 49 | -------------------------------------------------------------------------------- /Scenes/Window/Text Editor/text_editor.gd: -------------------------------------------------------------------------------- 1 | extends CodeEdit 2 | 3 | ## The text editor window. Is actually a CodeEdit to support line numbers for each row. 4 | 5 | @onready var window: FakeWindow = $"../.." 6 | 7 | var text_edited: bool 8 | var file_path: String : 9 | set(value): 10 | file_path = value 11 | if text_edited: 12 | $"../../Top Bar/Title Text".text = "[center]%s*" % file_path.split('/')[-1] 13 | else: 14 | $"../../Top Bar/Title Text".text = "[center]%s" % file_path.split('/')[-1] 15 | 16 | func _ready() -> void: 17 | window.selected.connect(_on_window_selected) 18 | 19 | adjust_menu_options() 20 | 21 | func _input(event: InputEvent) -> void: 22 | if !$"../..".is_selected: 23 | return 24 | 25 | if event.is_action_pressed("save"): 26 | accept_event() 27 | save_file() 28 | 29 | func populate_text(path: String) -> void: 30 | file_path = path 31 | var file: FileAccess = FileAccess.open("user://files/%s" % file_path, FileAccess.READ) 32 | text = file.get_as_text() 33 | 34 | func _on_text_changed() -> void: 35 | if text_edited: 36 | return 37 | 38 | text_edited = true 39 | $"../../Top Bar/Title Text".text += '*' 40 | 41 | func save_file() -> void: 42 | if !text_edited: 43 | return 44 | 45 | if !FileAccess.file_exists("user://files/%s" % file_path): 46 | NotificationManager.spawn_notification("[color=fc6c64]Couldn't save text file: File no longer exists") 47 | return 48 | 49 | var file: FileAccess = FileAccess.open("user://files/%s" % file_path, FileAccess.WRITE) 50 | file.store_string(text) 51 | 52 | $"../../Top Bar/Title Text".text = $"../../Top Bar/Title Text".text.trim_suffix('*') 53 | text_edited = false 54 | 55 | var saved_notification: Panel = load("res://Scenes/Window/Text Editor/saved_notification.tscn").instantiate() 56 | saved_notification.position.y = $"../..".size.y - saved_notification.size.y - 15 57 | saved_notification.position.x = $"../..".size.x - saved_notification.size.x - 15 58 | $"../..".add_child(saved_notification) 59 | 60 | #TODO add warning when someone exits without saving 61 | 62 | func _on_window_selected(selected: bool) -> void: 63 | if selected: 64 | grab_focus() 65 | else: 66 | release_focus() 67 | 68 | ## Adjusts right click options for this TextEdit. 69 | ## Removes unnecessary options and adds one for word wrap. 70 | func adjust_menu_options() -> void: 71 | var menu: PopupMenu = get_menu() 72 | 73 | menu.remove_item(5) 74 | menu.remove_item(10) 75 | menu.remove_item(10) 76 | menu.remove_item(10) 77 | 78 | menu.add_check_item("Word Wrap") 79 | menu.set_item_checked(-1, true) 80 | 81 | menu.id_pressed.connect(_set_word_wrap) 82 | 83 | func _set_word_wrap(id: int) -> void: 84 | if id == 10: 85 | var menu: PopupMenu = get_menu() 86 | if wrap_mode == TextEdit.LINE_WRAPPING_NONE: 87 | wrap_mode = TextEdit.LINE_WRAPPING_BOUNDARY 88 | menu.set_item_checked(-1, true) 89 | else: 90 | wrap_mode = TextEdit.LINE_WRAPPING_NONE 91 | menu.set_item_checked(-1, false) 92 | -------------------------------------------------------------------------------- /Scenes/Window/Text Editor/text_editor.gd.uid: -------------------------------------------------------------------------------- 1 | uid://btrd7whll061f 2 | -------------------------------------------------------------------------------- /Scenes/Window/Text Editor/text_editor.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://t8c17cefd8nc"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://cojrqff5vocjv" path="res://Scenes/Window/Window.tscn" id="1_sycuj"] 4 | [ext_resource type="Script" uid="uid://btrd7whll061f" path="res://Scenes/Window/Text Editor/text_editor.gd" id="2_4wajo"] 5 | 6 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_22tla"] 7 | bg_color = Color(0, 0.270588, 0.270588, 0.862745) 8 | corner_radius_top_left = 5 9 | corner_radius_top_right = 5 10 | corner_radius_bottom_right = 5 11 | corner_radius_bottom_left = 5 12 | shadow_color = Color(0, 0, 0, 0.0784314) 13 | 14 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_uonls"] 15 | 16 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_jhtvb"] 17 | 18 | [node name="Window" instance=ExtResource("1_sycuj")] 19 | theme_override_styles/panel = SubResource("StyleBoxFlat_22tla") 20 | 21 | [node name="MarginContainer" type="MarginContainer" parent="." index="1"] 22 | layout_mode = 1 23 | anchors_preset = 15 24 | anchor_right = 1.0 25 | anchor_bottom = 1.0 26 | offset_top = 30.0 27 | grow_horizontal = 2 28 | grow_vertical = 2 29 | theme_override_constants/margin_left = 10 30 | theme_override_constants/margin_top = 5 31 | theme_override_constants/margin_right = 10 32 | theme_override_constants/margin_bottom = 10 33 | 34 | [node name="Text Editor" type="CodeEdit" parent="MarginContainer" index="0" groups=["text_editor_window"]] 35 | unique_name_in_owner = true 36 | layout_mode = 2 37 | focus_mode = 1 38 | mouse_filter = 1 39 | theme_override_colors/font_color = Color(1, 1, 1, 1) 40 | theme_override_styles/normal = SubResource("StyleBoxEmpty_uonls") 41 | theme_override_styles/focus = SubResource("StyleBoxEmpty_jhtvb") 42 | placeholder_text = "Start writing!" 43 | wrap_mode = 1 44 | caret_blink = true 45 | highlight_all_occurrences = true 46 | draw_tabs = true 47 | gutters_draw_line_numbers = true 48 | script = ExtResource("2_4wajo") 49 | 50 | [connection signal="text_changed" from="MarginContainer/Text Editor" to="MarginContainer/Text Editor" method="_on_text_changed"] 51 | -------------------------------------------------------------------------------- /Scenes/Window/Window.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=13 format=3 uid="uid://cojrqff5vocjv"] 2 | 3 | [ext_resource type="Script" uid="uid://cgo0a8abexc23" path="res://Scenes/Window/window.gd" id="1_c3iwi"] 4 | [ext_resource type="Texture2D" uid="uid://1ockgc20p033" path="res://Art/Icons/expand.png" id="2_bcfhp"] 5 | [ext_resource type="Script" uid="uid://chdl3m2p86twh" path="res://Scenes/Window/resize_drag_spot.gd" id="2_xymxc"] 6 | [ext_resource type="Texture2D" uid="uid://detscivjcbnpi" path="res://Art/Icons/corner-handle.png" id="4_qn6o7"] 7 | 8 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_gwhiu"] 9 | bg_color = Color(0.2, 0.2, 0.2, 0.666667) 10 | corner_radius_top_left = 5 11 | corner_radius_top_right = 5 12 | corner_radius_bottom_right = 5 13 | corner_radius_bottom_left = 5 14 | corner_detail = 10 15 | shadow_color = Color(0, 0, 0, 0.0784314) 16 | 17 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_4otup"] 18 | bg_color = Color(0.1, 0.1, 0.1, 0.6) 19 | corner_radius_top_left = 5 20 | corner_radius_top_right = 5 21 | 22 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_es3h4"] 23 | bg_color = Color(0, 0, 0, 0.392157) 24 | 25 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_iro1c"] 26 | bg_color = Color(0.501961, 0.501961, 0.501961, 0.392157) 27 | 28 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_epasn"] 29 | bg_color = Color(0.4, 0.4, 0.4, 0.392157) 30 | 31 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_i3xsn"] 32 | bg_color = Color(0, 0, 0, 0.392157) 33 | corner_radius_top_right = 5 34 | 35 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_g3pwt"] 36 | bg_color = Color(0.666667, 0, 0, 0.392157) 37 | corner_radius_top_right = 5 38 | 39 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jljmq"] 40 | bg_color = Color(1, 0.247059, 0.188235, 0.588235) 41 | corner_radius_top_right = 5 42 | 43 | [node name="Window" type="Panel" groups=["window"]] 44 | custom_minimum_size = Vector2(250, 150) 45 | anchors_preset = 8 46 | anchor_left = 0.5 47 | anchor_top = 0.5 48 | anchor_right = 0.5 49 | anchor_bottom = 0.5 50 | offset_left = -250.0 51 | offset_top = -150.0 52 | offset_right = 250.0 53 | offset_bottom = 150.0 54 | grow_horizontal = 2 55 | grow_vertical = 2 56 | theme_override_styles/panel = SubResource("StyleBoxFlat_gwhiu") 57 | script = ExtResource("1_c3iwi") 58 | 59 | [node name="Top Bar" type="Panel" parent="."] 60 | custom_minimum_size = Vector2(0, 30) 61 | layout_mode = 1 62 | anchors_preset = 10 63 | anchor_right = 1.0 64 | grow_horizontal = 2 65 | mouse_filter = 1 66 | theme_override_styles/panel = SubResource("StyleBoxFlat_4otup") 67 | 68 | [node name="Title Text" type="RichTextLabel" parent="Top Bar"] 69 | custom_minimum_size = Vector2(0, 22) 70 | layout_mode = 1 71 | anchors_preset = 14 72 | anchor_top = 0.5 73 | anchor_right = 1.0 74 | anchor_bottom = 0.5 75 | offset_top = -11.0 76 | offset_bottom = 11.0 77 | grow_horizontal = 2 78 | grow_vertical = 2 79 | mouse_filter = 2 80 | bbcode_enabled = true 81 | text = "[center]Hello World!" 82 | scroll_active = false 83 | 84 | [node name="HBoxContainer" type="HBoxContainer" parent="Top Bar"] 85 | layout_mode = 1 86 | anchors_preset = 6 87 | anchor_left = 1.0 88 | anchor_top = 0.5 89 | anchor_right = 1.0 90 | anchor_bottom = 0.5 91 | offset_left = -40.0 92 | offset_top = -15.0 93 | offset_bottom = 15.0 94 | grow_horizontal = 0 95 | grow_vertical = 2 96 | 97 | [node name="Minimize Button" type="Button" parent="Top Bar/HBoxContainer"] 98 | texture_filter = 6 99 | custom_minimum_size = Vector2(40, 0) 100 | layout_mode = 2 101 | focus_mode = 0 102 | theme_override_styles/normal = SubResource("StyleBoxFlat_es3h4") 103 | theme_override_styles/hover = SubResource("StyleBoxFlat_iro1c") 104 | theme_override_styles/pressed = SubResource("StyleBoxFlat_epasn") 105 | text = "-" 106 | 107 | [node name="Maximize Button" type="Button" parent="Top Bar/HBoxContainer"] 108 | texture_filter = 6 109 | custom_minimum_size = Vector2(40, 0) 110 | layout_mode = 2 111 | focus_mode = 0 112 | theme_override_constants/icon_max_width = 22 113 | theme_override_styles/normal = SubResource("StyleBoxFlat_es3h4") 114 | theme_override_styles/hover = SubResource("StyleBoxFlat_iro1c") 115 | theme_override_styles/pressed = SubResource("StyleBoxFlat_epasn") 116 | icon = ExtResource("2_bcfhp") 117 | icon_alignment = 1 118 | 119 | [node name="Close Button" type="Button" parent="Top Bar/HBoxContainer"] 120 | texture_filter = 6 121 | custom_minimum_size = Vector2(40, 0) 122 | layout_mode = 2 123 | focus_mode = 0 124 | theme_override_styles/normal = SubResource("StyleBoxFlat_i3xsn") 125 | theme_override_styles/hover = SubResource("StyleBoxFlat_g3pwt") 126 | theme_override_styles/pressed = SubResource("StyleBoxFlat_jljmq") 127 | text = "X" 128 | 129 | [node name="Resize Drag Spot" type="Control" parent="."] 130 | layout_mode = 1 131 | anchors_preset = 3 132 | anchor_left = 1.0 133 | anchor_top = 1.0 134 | anchor_right = 1.0 135 | anchor_bottom = 1.0 136 | offset_left = -17.0 137 | offset_top = -17.0 138 | offset_right = 6.0 139 | offset_bottom = 6.0 140 | grow_horizontal = 0 141 | grow_vertical = 0 142 | mouse_default_cursor_shape = 12 143 | script = ExtResource("2_xymxc") 144 | 145 | [node name="CornerHandle" type="TextureRect" parent="."] 146 | modulate = Color(1, 1, 1, 0.25) 147 | layout_mode = 1 148 | anchors_preset = 3 149 | anchor_left = 1.0 150 | anchor_top = 1.0 151 | anchor_right = 1.0 152 | anchor_bottom = 1.0 153 | offset_left = -16.0 154 | offset_top = -16.0 155 | grow_horizontal = 0 156 | grow_vertical = 0 157 | mouse_filter = 2 158 | texture = ExtResource("4_qn6o7") 159 | expand_mode = 1 160 | stretch_mode = 4 161 | 162 | [connection signal="gui_input" from="Top Bar" to="." method="_on_top_bar_gui_input"] 163 | [connection signal="pressed" from="Top Bar/HBoxContainer/Minimize Button" to="." method="_on_minimize_button_pressed"] 164 | [connection signal="pressed" from="Top Bar/HBoxContainer/Maximize Button" to="." method="_on_maximize_button_pressed"] 165 | [connection signal="pressed" from="Top Bar/HBoxContainer/Close Button" to="." method="_on_close_button_pressed"] 166 | -------------------------------------------------------------------------------- /Scenes/Window/resize_drag_spot.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | ## The resize drag spot in the bottom right of each window. 4 | 5 | var window: FakeWindow 6 | var is_dragging: bool 7 | 8 | var start_size: Vector2 9 | var mouse_start_drag_position: Vector2 10 | 11 | signal window_resized() 12 | 13 | func _ready() -> void: 14 | window = get_parent() 15 | 16 | func _gui_input(event: InputEvent) -> void: 17 | if event is InputEventMouseButton and event.button_index == 1: 18 | if event.is_pressed(): 19 | is_dragging = true 20 | mouse_start_drag_position = get_global_mouse_position() 21 | start_size = get_parent().size 22 | else: 23 | is_dragging = false 24 | 25 | func _physics_process(_delta: float) -> void: 26 | if is_dragging: 27 | # TODO optimize this a bit? 28 | window_resized.emit() 29 | if Input.is_key_pressed(KEY_SHIFT): 30 | var aspect_ratio: float = start_size.x / (start_size.y - 30) 31 | window.size.x = start_size.x + (get_global_mouse_position().x - mouse_start_drag_position.x) * aspect_ratio 32 | window.size.y = start_size.y + get_global_mouse_position().x - mouse_start_drag_position.x 33 | else: 34 | window.size = start_size + get_global_mouse_position() - mouse_start_drag_position 35 | window.clamp_window_inside_viewport() 36 | -------------------------------------------------------------------------------- /Scenes/Window/resize_drag_spot.gd.uid: -------------------------------------------------------------------------------- 1 | uid://chdl3m2p86twh 2 | -------------------------------------------------------------------------------- /Scenes/Window/window.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cgo0a8abexc23 2 | -------------------------------------------------------------------------------- /export_presets.cfg: -------------------------------------------------------------------------------- 1 | [preset.0] 2 | 3 | name="Windows Desktop" 4 | platform="Windows Desktop" 5 | runnable=true 6 | advanced_options=true 7 | dedicated_server=false 8 | custom_features="" 9 | export_filter="all_resources" 10 | include_filter="*.txt" 11 | exclude_filter="" 12 | export_path="../Releases_GodotOS/GodotOS.exe" 13 | patches=PackedStringArray() 14 | encryption_include_filters="" 15 | encryption_exclude_filters="" 16 | seed=0 17 | encrypt_pck=false 18 | encrypt_directory=false 19 | script_export_mode=2 20 | 21 | [preset.0.options] 22 | 23 | custom_template/debug="" 24 | custom_template/release="C:/godot-4.4-stable/bin/godot.windows.template_release.x86_64.llvm.exe" 25 | debug/export_console_wrapper=1 26 | binary_format/embed_pck=false 27 | texture_format/s3tc_bptc=true 28 | texture_format/etc2_astc=false 29 | binary_format/architecture="x86_64" 30 | codesign/enable=false 31 | codesign/timestamp=true 32 | codesign/timestamp_server_url="" 33 | codesign/digest_algorithm=1 34 | codesign/description="" 35 | codesign/custom_options=PackedStringArray() 36 | application/modify_resources=false 37 | application/icon="" 38 | application/console_wrapper_icon="" 39 | application/icon_interpolation=4 40 | application/file_version="" 41 | application/product_version="" 42 | application/company_name="" 43 | application/product_name="" 44 | application/file_description="" 45 | application/copyright="" 46 | application/trademarks="" 47 | application/export_angle=0 48 | application/export_d3d12=0 49 | application/d3d12_agility_sdk_multiarch=true 50 | ssh_remote_deploy/enabled=false 51 | ssh_remote_deploy/host="user@host_ip" 52 | ssh_remote_deploy/port="22" 53 | ssh_remote_deploy/extra_args_ssh="" 54 | ssh_remote_deploy/extra_args_scp="" 55 | ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}' 56 | $action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}' 57 | $trigger = New-ScheduledTaskTrigger -Once -At 00:00 58 | $settings = New-ScheduledTaskSettingsSet 59 | $task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings 60 | Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true 61 | Start-ScheduledTask -TaskName godot_remote_debug 62 | while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 } 63 | Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue" 64 | ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue 65 | Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue 66 | Remove-Item -Recurse -Force '{temp_dir}'" 67 | texture_format/bptc=true 68 | texture_format/s3tc=true 69 | texture_format/etc=false 70 | texture_format/etc2=false 71 | 72 | [preset.1] 73 | 74 | name="Linux/X11" 75 | platform="Linux" 76 | runnable=true 77 | advanced_options=false 78 | dedicated_server=false 79 | custom_features="" 80 | export_filter="all_resources" 81 | include_filter="*.txt" 82 | exclude_filter="" 83 | export_path="../Releases_GodotOS/GodotOS_v1.1_Linux/GodotOS_v1.1.x86_64" 84 | patches=PackedStringArray() 85 | encryption_include_filters="" 86 | encryption_exclude_filters="" 87 | seed=0 88 | encrypt_pck=false 89 | encrypt_directory=false 90 | script_export_mode=2 91 | 92 | [preset.1.options] 93 | 94 | custom_template/debug="" 95 | custom_template/release="" 96 | debug/export_console_wrapper=1 97 | binary_format/embed_pck=false 98 | texture_format/s3tc_bptc=true 99 | texture_format/etc2_astc=false 100 | binary_format/architecture="x86_64" 101 | ssh_remote_deploy/enabled=false 102 | ssh_remote_deploy/host="user@host_ip" 103 | ssh_remote_deploy/port="22" 104 | ssh_remote_deploy/extra_args_ssh="" 105 | ssh_remote_deploy/extra_args_scp="" 106 | ssh_remote_deploy/run_script="#!/usr/bin/env bash 107 | export DISPLAY=:0 108 | unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\" 109 | \"{temp_dir}/{exe_name}\" {cmd_args}" 110 | ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash 111 | kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\") 112 | rm -rf \"{temp_dir}\"" 113 | texture_format/bptc=true 114 | texture_format/s3tc=true 115 | texture_format/etc=false 116 | texture_format/etc2=false 117 | 118 | [preset.2] 119 | 120 | name="Web" 121 | platform="Web" 122 | runnable=true 123 | advanced_options=true 124 | dedicated_server=false 125 | custom_features="" 126 | export_filter="all_resources" 127 | include_filter="*.txt" 128 | exclude_filter="" 129 | export_path="../Releases_GodotOS/GodOS_v1.1_web/index.html" 130 | patches=PackedStringArray() 131 | encryption_include_filters="" 132 | encryption_exclude_filters="" 133 | seed=0 134 | encrypt_pck=false 135 | encrypt_directory=false 136 | script_export_mode=2 137 | 138 | [preset.2.options] 139 | 140 | custom_template/debug="" 141 | custom_template/release="C:/godot-4.4-stable/bin/godot.web.template_release.wasm32.nothreads.zip" 142 | variant/extensions_support=false 143 | variant/thread_support=false 144 | vram_texture_compression/for_desktop=true 145 | vram_texture_compression/for_mobile=false 146 | html/export_icon=true 147 | html/custom_html_shell="" 148 | html/head_include="" 149 | html/canvas_resize_policy=2 150 | html/focus_canvas_on_start=true 151 | html/experimental_virtual_keyboard=false 152 | progressive_web_app/enabled=false 153 | progressive_web_app/ensure_cross_origin_isolation_headers=true 154 | progressive_web_app/offline_page="" 155 | progressive_web_app/display=1 156 | progressive_web_app/orientation=0 157 | progressive_web_app/icon_144x144="" 158 | progressive_web_app/icon_180x180="" 159 | progressive_web_app/icon_512x512="" 160 | progressive_web_app/background_color=Color(0, 0, 0, 1) 161 | -------------------------------------------------------------------------------- /icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bvvdctur6sisw" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | --------------------------------------------------------------------------------