├── icon.ico
├── assets
├── sprites
│ ├── star.png
│ ├── folder.png
│ ├── download_btn.png
│ ├── settings_icon.png
│ ├── arrows
│ │ ├── arrow_up.png
│ │ ├── arrow_down.png
│ │ ├── arrow_left.png
│ │ ├── arrow_right.png
│ │ ├── option_btn.png
│ │ ├── arrow_up.png.import
│ │ ├── arrow_left.png.import
│ │ ├── arrow_down.png.import
│ │ ├── arrow_right.png.import
│ │ └── option_btn.png.import
│ ├── crosses
│ │ ├── cross_hover.png
│ │ ├── cross_white.png
│ │ ├── cross_default.png
│ │ ├── cross_hover.png.import
│ │ ├── cross_white.png.import
│ │ └── cross_default.png.import
│ ├── folder_compressed.png
│ ├── check_boxes
│ │ ├── box_checked.png
│ │ ├── box_unchecked.png
│ │ ├── box_checked_disabled.png
│ │ ├── box_unchecked_disabled.png
│ │ ├── box_checked.png.import
│ │ ├── box_unchecked.png.import
│ │ ├── box_checked_disabled.png.import
│ │ └── box_unchecked_disabled.png.import
│ ├── check_buttons
│ │ ├── btn_checked.png
│ │ ├── btn_unchecked.png
│ │ ├── btn_checked_disabled.png
│ │ ├── btn_checked_mirrored.png
│ │ ├── btn_unchecked_disabled.png
│ │ ├── btn_unchecked_mirrored.png
│ │ ├── btn_check_disabled_mirrored.png
│ │ ├── btn_checked_disabled_mirrored.png
│ │ ├── btn_unchecked_disabled_mirrored.png
│ │ ├── btn_checked.png.import
│ │ ├── btn_unchecked.png.import
│ │ ├── btn_checked_disabled.png.import
│ │ ├── btn_checked_mirrored.png.import
│ │ ├── btn_unchecked_disabled.png.import
│ │ ├── btn_unchecked_mirrored.png.import
│ │ ├── btn_check_disabled_mirrored.png.import
│ │ ├── btn_checked_disabled_mirrored.png.import
│ │ └── btn_unchecked_disabled_mirrored.png.import
│ ├── star.png.import
│ ├── folder.png.import
│ ├── download_btn.png.import
│ ├── settings_icon.png.import
│ └── folder_compressed.png.import
├── gdh_splash-screen.png
├── fonts
│ ├── JetBrainsMono-Bold.ttf
│ ├── JetBrainsMono-Italic.ttf
│ ├── JetBrainsMono-Medium.ttf
│ ├── JetBrainsMono-Regular.ttf
│ ├── JetBrainsMono-ExtraBold.ttf
│ ├── JetBrainsMono-Bold-Italic.ttf
│ ├── JetBrainsMono-Medium-Italic.ttf
│ ├── JetBrainsMono-ExtraBold-Italic.ttf
│ ├── JetBrainsMono-Bold.ttf.import
│ ├── JetBrainsMono-Italic.ttf.import
│ ├── JetBrainsMono-Medium.ttf.import
│ ├── JetBrainsMono-Regular.ttf.import
│ ├── JetBrainsMono-ExtraBold.ttf.import
│ ├── JetBrainsMono-Bold-Italic.ttf.import
│ ├── JetBrainsMono-Medium-Italic.ttf.import
│ └── JetBrainsMono-ExtraBold-Italic.ttf.import
├── gdh_splash-screen.png.import
├── default_icon.svg.import
└── default_icon.svg
├── .gitattributes
├── resources
├── themes
│ ├── main.theme
│ ├── blue_btn.theme
│ ├── close_btn.theme
│ ├── settings.theme
│ ├── sort_btn.theme
│ ├── star_btn.theme
│ ├── half_red_btn.theme
│ └── half_blue_btn.theme
├── button_groups
│ ├── tab_btn_group.tres
│ └── install_btn_group.tres
└── style_boxes
│ ├── hseparator.stylebox
│ ├── progress_bg.stylebox
│ ├── vseparator.stylebox
│ ├── progress_fill.stylebox
│ ├── tabs
│ ├── tab_disabled.stylebox
│ ├── tab_selected.stylebox
│ └── tab_unselected.stylebox
│ ├── panels
│ ├── dark_window.stylebox
│ ├── dark_window_bg.stylebox
│ ├── hard_dark_panel.stylebox
│ ├── mid_dark_panel.stylebox
│ ├── soft_dark_panel.stylebox
│ └── light_dark_panel.stylebox
│ ├── buttons
│ ├── red
│ │ ├── red_hover.stylebox
│ │ └── red_pressed.stylebox
│ ├── blue
│ │ ├── blue_hover.stylebox
│ │ ├── blue_normal.stylebox
│ │ ├── blue_disabled.stylebox
│ │ └── blue_pressed.stylebox
│ ├── transparent_btn.stylebox
│ ├── default
│ │ ├── default_hover.stylebox
│ │ ├── default_disabled.stylebox
│ │ ├── default_normal.stylebox
│ │ └── default_pressed.stylebox
│ ├── star
│ │ ├── star_normal.tres
│ │ ├── star_hover.tres
│ │ ├── star_disabled.tres
│ │ └── star_pressed.tres
│ ├── close
│ │ ├── close_disabled.tres
│ │ ├── close_hover.tres
│ │ ├── close_normal.tres
│ │ └── close_pressed.tres
│ └── download
│ │ ├── download_disabled.tres
│ │ ├── download_hover.tres
│ │ ├── download_normal.tres
│ │ └── download_pressed.tres
│ └── scrolls
│ ├── scroll_scroll.stylebox
│ ├── scroll_grabber_normal.stylebox
│ └── scroll_grabber_highlight.stylebox
├── scripts
├── core
│ ├── data
│ │ ├── Architecture.cs
│ │ ├── OS.cs
│ │ ├── GDFile.cs
│ │ ├── FullParameterContractResolver.cs
│ │ ├── Source.cs
│ │ ├── Version.cs
│ │ └── ProjectsData.cs
│ ├── tabs
│ │ ├── projects
│ │ │ ├── VersioningMode.cs
│ │ │ ├── RenderMode.cs
│ │ │ └── ProjectsTabs.cs
│ │ ├── SortedPanel.cs
│ │ ├── documentation
│ │ │ └── DocumentationTab.cs
│ │ ├── Tab.cs
│ │ ├── UpdateRepoButton.cs
│ │ ├── SortToggle.cs
│ │ ├── versions
│ │ │ ├── VersionsTab.cs
│ │ │ ├── ReleasePanel.cs
│ │ │ ├── DownloadPanel.cs
│ │ │ ├── EnginesPanel.cs
│ │ │ └── EngineItem.cs
│ │ └── TabManager.cs
│ ├── settings
│ │ ├── buttons
│ │ │ ├── ISettingButton.cs
│ │ │ ├── ResetButton.cs
│ │ │ ├── toggles
│ │ │ │ ├── SettingToggle.cs
│ │ │ │ ├── AutoDeleteToggle.cs
│ │ │ │ ├── AutoCloseDLToggle.cs
│ │ │ │ ├── AutoShortcutToggle.cs
│ │ │ │ ├── AutoUpdateToggle.cs
│ │ │ │ ├── DebugToggle.cs
│ │ │ │ └── SameDirToggle.cs
│ │ │ ├── directory
│ │ │ │ ├── ProjectDirButton.cs
│ │ │ │ ├── InstallDirButton.cs
│ │ │ │ ├── DownloadDirButton.cs
│ │ │ │ └── DirButton.cs
│ │ │ └── SettingButton.cs
│ │ └── SettingsPanel.cs
│ ├── utils
│ │ ├── comparisons
│ │ │ ├── INamedItem.cs
│ │ │ ├── IMonoItem.cs
│ │ │ ├── IValidItem.cs
│ │ │ ├── IFavoriteItem.cs
│ │ │ ├── ITimedItem.cs
│ │ │ ├── IVersionItem.cs
│ │ │ └── Comparer.cs
│ │ ├── BBCodeT.cs
│ │ ├── Error.cs
│ │ ├── Colors.cs
│ │ ├── TimeFormater.cs
│ │ └── PathT.cs
│ ├── SplashScreen.cs
│ ├── debug
│ │ ├── ExceptionHandler.cs
│ │ └── Debugger.cs
│ └── Main.cs
├── installer
│ ├── JumpInstruction.cs
│ ├── InstallerConstants.cs
│ ├── InstallProgram.cs
│ └── AdminInstaller.cs
├── uninstaller
│ └── UninstallProgram.cs
└── updater
│ └── UpdateProgram.cs
├── scenes
├── utils
│ └── colors.tscn
├── message_dialog.tscn
├── confirmation_dialog.tscn
├── settings
│ └── folder_dialog.tscn
├── sort_button.tscn
├── versions
│ ├── subbutton.tscn
│ ├── installer.tscn
│ ├── release_item.tscn
│ └── engine_item.tscn
└── projects
│ ├── project_item.tscn
│ └── new_project_dialog.tscn
├── project.godot
├── icon.svg.import
├── README.md
├── Godot Hub.csproj
├── GodotHubUpdater.csproj
├── GodotUninstaller.csproj
├── GodotInstaller.csproj
├── CHANGELOG.md
├── godot_installer.manifest
├── godot_uninstaller.manifest
├── export_presets.cfg
└── icon.svg
/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/icon.ico
--------------------------------------------------------------------------------
/assets/sprites/star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/star.png
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Normalize EOL for all files that Git considers text files.
2 | * text=auto eol=crlf
3 |
--------------------------------------------------------------------------------
/assets/sprites/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/folder.png
--------------------------------------------------------------------------------
/assets/gdh_splash-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/gdh_splash-screen.png
--------------------------------------------------------------------------------
/resources/themes/main.theme:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/themes/main.theme
--------------------------------------------------------------------------------
/assets/sprites/download_btn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/download_btn.png
--------------------------------------------------------------------------------
/assets/sprites/settings_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/settings_icon.png
--------------------------------------------------------------------------------
/resources/themes/blue_btn.theme:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/themes/blue_btn.theme
--------------------------------------------------------------------------------
/resources/themes/close_btn.theme:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/themes/close_btn.theme
--------------------------------------------------------------------------------
/resources/themes/settings.theme:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/themes/settings.theme
--------------------------------------------------------------------------------
/resources/themes/sort_btn.theme:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/themes/sort_btn.theme
--------------------------------------------------------------------------------
/resources/themes/star_btn.theme:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/themes/star_btn.theme
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/fonts/JetBrainsMono-Bold.ttf
--------------------------------------------------------------------------------
/assets/sprites/arrows/arrow_up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/arrows/arrow_up.png
--------------------------------------------------------------------------------
/resources/themes/half_red_btn.theme:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/themes/half_red_btn.theme
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/fonts/JetBrainsMono-Italic.ttf
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/fonts/JetBrainsMono-Medium.ttf
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/fonts/JetBrainsMono-Regular.ttf
--------------------------------------------------------------------------------
/assets/sprites/arrows/arrow_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/arrows/arrow_down.png
--------------------------------------------------------------------------------
/assets/sprites/arrows/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/arrows/arrow_left.png
--------------------------------------------------------------------------------
/assets/sprites/arrows/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/arrows/arrow_right.png
--------------------------------------------------------------------------------
/assets/sprites/arrows/option_btn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/arrows/option_btn.png
--------------------------------------------------------------------------------
/assets/sprites/crosses/cross_hover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/crosses/cross_hover.png
--------------------------------------------------------------------------------
/assets/sprites/crosses/cross_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/crosses/cross_white.png
--------------------------------------------------------------------------------
/assets/sprites/folder_compressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/folder_compressed.png
--------------------------------------------------------------------------------
/resources/themes/half_blue_btn.theme:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/themes/half_blue_btn.theme
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-ExtraBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/fonts/JetBrainsMono-ExtraBold.ttf
--------------------------------------------------------------------------------
/assets/sprites/crosses/cross_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/crosses/cross_default.png
--------------------------------------------------------------------------------
/resources/button_groups/tab_btn_group.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="ButtonGroup" format=3 uid="uid://degxsui0oeqmj"]
2 |
3 | [resource]
4 |
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-Bold-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/fonts/JetBrainsMono-Bold-Italic.ttf
--------------------------------------------------------------------------------
/assets/sprites/check_boxes/box_checked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/check_boxes/box_checked.png
--------------------------------------------------------------------------------
/resources/style_boxes/hseparator.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/hseparator.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/progress_bg.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/progress_bg.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/vseparator.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/vseparator.stylebox
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-Medium-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/fonts/JetBrainsMono-Medium-Italic.ttf
--------------------------------------------------------------------------------
/assets/sprites/check_boxes/box_unchecked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/check_boxes/box_unchecked.png
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_checked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/check_buttons/btn_checked.png
--------------------------------------------------------------------------------
/resources/style_boxes/progress_fill.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/progress_fill.stylebox
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-ExtraBold-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/fonts/JetBrainsMono-ExtraBold-Italic.ttf
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_unchecked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/check_buttons/btn_unchecked.png
--------------------------------------------------------------------------------
/resources/style_boxes/tabs/tab_disabled.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/tabs/tab_disabled.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/tabs/tab_selected.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/tabs/tab_selected.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/panels/dark_window.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/panels/dark_window.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/tabs/tab_unselected.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/tabs/tab_unselected.stylebox
--------------------------------------------------------------------------------
/assets/sprites/check_boxes/box_checked_disabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/check_boxes/box_checked_disabled.png
--------------------------------------------------------------------------------
/assets/sprites/check_boxes/box_unchecked_disabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/check_boxes/box_unchecked_disabled.png
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_checked_disabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/check_buttons/btn_checked_disabled.png
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_checked_mirrored.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/check_buttons/btn_checked_mirrored.png
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/red/red_hover.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/buttons/red/red_hover.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/panels/dark_window_bg.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/panels/dark_window_bg.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/panels/hard_dark_panel.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/panels/hard_dark_panel.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/panels/mid_dark_panel.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/panels/mid_dark_panel.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/panels/soft_dark_panel.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/panels/soft_dark_panel.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/scrolls/scroll_scroll.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/scrolls/scroll_scroll.stylebox
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_unchecked_disabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/check_buttons/btn_unchecked_disabled.png
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_unchecked_mirrored.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/check_buttons/btn_unchecked_mirrored.png
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/blue/blue_hover.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/buttons/blue/blue_hover.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/blue/blue_normal.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/buttons/blue/blue_normal.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/red/red_pressed.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/buttons/red/red_pressed.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/transparent_btn.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/buttons/transparent_btn.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/panels/light_dark_panel.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/panels/light_dark_panel.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/blue/blue_disabled.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/buttons/blue/blue_disabled.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/blue/blue_pressed.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/buttons/blue/blue_pressed.stylebox
--------------------------------------------------------------------------------
/scripts/core/data/Architecture.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Core.Data
2 | {
3 | public enum Architecture
4 | {
5 | x32 = 0,
6 | x64 = 1,
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_check_disabled_mirrored.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/check_buttons/btn_check_disabled_mirrored.png
--------------------------------------------------------------------------------
/resources/button_groups/install_btn_group.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="ButtonGroup" format=3 uid="uid://c2ypx5qbtttva"]
2 |
3 | [resource]
4 | resource_local_to_scene = false
5 |
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/default/default_hover.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/buttons/default/default_hover.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/scrolls/scroll_grabber_normal.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/scrolls/scroll_grabber_normal.stylebox
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_checked_disabled_mirrored.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/check_buttons/btn_checked_disabled_mirrored.png
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/default/default_disabled.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/buttons/default/default_disabled.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/default/default_normal.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/buttons/default/default_normal.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/default/default_pressed.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/buttons/default/default_pressed.stylebox
--------------------------------------------------------------------------------
/resources/style_boxes/scrolls/scroll_grabber_highlight.stylebox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/resources/style_boxes/scrolls/scroll_grabber_highlight.stylebox
--------------------------------------------------------------------------------
/scripts/core/tabs/projects/VersioningMode.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Core.Tabs.Projects
2 | {
3 | public enum VersioningMode
4 | {
5 | None,
6 | Git,
7 | }
8 | }
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_unchecked_disabled_mirrored.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Astral-Sheep/GodotHub/HEAD/assets/sprites/check_buttons/btn_unchecked_disabled_mirrored.png
--------------------------------------------------------------------------------
/scripts/core/data/OS.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Core.Data
2 | {
3 | public enum OS
4 | {
5 | Windows = 0,
6 | Linux = 1,
7 | MacOS = 2,
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/scripts/installer/JumpInstruction.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Installer
2 | {
3 | public enum JumpInstruction : byte
4 | {
5 | None = 0,
6 | Delete = 1,
7 | Cancel = 2,
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/ISettingButton.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Core.Settings.Buttons
2 | {
3 | public interface ISettingButton
4 | {
5 | void Connect();
6 | void Disconnect();
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/scripts/core/tabs/SortedPanel.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace Com.Astral.GodotHub.Core.Tabs
4 | {
5 | public abstract partial class SortedPanel : Control
6 | {
7 | [Export] protected Control itemContainer;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/scenes/utils/colors.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://cd5aapghu6aef"]
2 |
3 | [ext_resource type="Script" path="res://scripts/core/utils/Colors.cs" id="1_rs3ov"]
4 |
5 | [node name="Colors" type="Node"]
6 | script = ExtResource("1_rs3ov")
7 |
--------------------------------------------------------------------------------
/scripts/core/tabs/documentation/DocumentationTab.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Core.Tabs.Documentation
2 | {
3 | public partial class DocumentationTab : Tab
4 | {
5 | protected override void Connect() { }
6 | protected override void Disconnect() { }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/scripts/core/utils/comparisons/INamedItem.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Core.Utils.Comparisons
2 | {
3 | public interface INamedItem
4 | {
5 | ///
6 | /// Name of this item
7 | ///
8 | string ItemName { get; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/scripts/core/utils/comparisons/IMonoItem.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Core.Utils.Comparisons
2 | {
3 | public interface IMonoItem
4 | {
5 | ///
6 | /// Whether or not this item supports C#
7 | ///
8 | bool IsMono { get; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/scripts/core/utils/comparisons/IValidItem.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Core.Utils.Comparisons
2 | {
3 | public interface IValidItem
4 | {
5 | ///
6 | /// Whether or not this item has valid data
7 | ///
8 | bool IsValid { get; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/scripts/core/utils/comparisons/IFavoriteItem.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Core.Utils.Comparisons
2 | {
3 | public interface IFavoriteItem
4 | {
5 | ///
6 | /// Whether or not the user marked this as favorite
7 | ///
8 | bool IsFavorite { get; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/scripts/core/utils/comparisons/ITimedItem.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Core.Utils.Comparisons
2 | {
3 | public interface ITimedItem
4 | {
5 | ///
6 | /// Time since the last time this item's files were opened
7 | ///
8 | double TimeSinceLastOpening { get; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/scripts/core/utils/comparisons/IVersionItem.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 |
3 | namespace Com.Astral.GodotHub.Core.Utils.Comparisons
4 | {
5 | public interface IVersionItem
6 | {
7 | ///
8 | /// of the item
9 | ///
10 | Version Version { get; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/star/star_normal.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://b8t8n87drtecc"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://n0ngwfu5xhvd" path="res://assets/sprites/star.png" id="1_h2w4n"]
4 |
5 | [resource]
6 | texture = ExtResource("1_h2w4n")
7 | modulate_color = Color(0.2, 0.2, 0.2, 1)
8 |
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/star/star_hover.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://pgwj67bkuk6y"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://n0ngwfu5xhvd" path="res://assets/sprites/star.png" id="1_wov08"]
4 |
5 | [resource]
6 | texture = ExtResource("1_wov08")
7 | modulate_color = Color(0.564706, 0.564706, 0.564706, 1)
8 |
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/star/star_disabled.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://b0rpaplouipyq"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://n0ngwfu5xhvd" path="res://assets/sprites/star.png" id="1_5ycx7"]
4 |
5 | [resource]
6 | texture = ExtResource("1_5ycx7")
7 | modulate_color = Color(0.117647, 0.117647, 0.117647, 1)
8 |
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/star/star_pressed.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://bwyc8ejlx13my"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://n0ngwfu5xhvd" path="res://assets/sprites/star.png" id="1_660vt"]
4 |
5 | [resource]
6 | texture = ExtResource("1_660vt")
7 | modulate_color = Color(0.721569, 0.721569, 0.721569, 1)
8 |
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/close/close_disabled.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://c1mypphbuba7b"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://crtj2ch3o166n" path="res://assets/sprites/crosses/cross_white.png" id="1_cdmas"]
4 |
5 | [resource]
6 | texture = ExtResource("1_cdmas")
7 | modulate_color = Color(0.2, 0.2, 0.2, 1)
8 |
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/download/download_disabled.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://cmj13fvlu7cfh"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://b6m2numrdnkgc" path="res://assets/sprites/download_btn.png" id="1_ydfhs"]
4 |
5 | [resource]
6 | texture = ExtResource("1_ydfhs")
7 | modulate_color = Color(0.2, 0.2, 0.2, 1)
8 |
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/close/close_hover.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://sog30gklctc4"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://crtj2ch3o166n" path="res://assets/sprites/crosses/cross_white.png" id="1_nnru4"]
4 |
5 | [resource]
6 | texture = ExtResource("1_nnru4")
7 | modulate_color = Color(0.831373, 0.313726, 0.309804, 1)
8 |
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/close/close_normal.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://be7jhdr22wtea"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://crtj2ch3o166n" path="res://assets/sprites/crosses/cross_white.png" id="1_pp1ot"]
4 |
5 | [resource]
6 | texture = ExtResource("1_pp1ot")
7 | modulate_color = Color(0.564706, 0.564706, 0.564706, 1)
8 |
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/download/download_hover.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://cm15h4syelk5n"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://b6m2numrdnkgc" path="res://assets/sprites/download_btn.png" id="1_a8s4b"]
4 |
5 | [resource]
6 | texture = ExtResource("1_a8s4b")
7 | modulate_color = Color(0.215686, 0.615686, 0.65098, 1)
8 |
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/download/download_normal.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://cx2kkw3gpsr06"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://b6m2numrdnkgc" path="res://assets/sprites/download_btn.png" id="1_48ssx"]
4 |
5 | [resource]
6 | texture = ExtResource("1_48ssx")
7 | modulate_color = Color(0.564706, 0.564706, 0.564706, 1)
8 |
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/download/download_pressed.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://dupfk7wsjifh8"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://b6m2numrdnkgc" path="res://assets/sprites/download_btn.png" id="1_lixio"]
4 |
5 | [resource]
6 | texture = ExtResource("1_lixio")
7 | modulate_color = Color(0.14902, 0.423529, 0.45098, 1)
8 |
--------------------------------------------------------------------------------
/resources/style_boxes/buttons/close/close_pressed.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://cdmqwnpe0kc12"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://crtj2ch3o166n" path="res://assets/sprites/crosses/cross_white.png" id="1_ybsvh"]
4 |
5 | [resource]
6 | texture = ExtResource("1_ybsvh")
7 | modulate_color = Color(0.427451, 0.156863, 0.156863, 1)
8 |
--------------------------------------------------------------------------------
/scripts/core/tabs/projects/RenderMode.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Core.Tabs.Projects
2 | {
3 | public enum RenderMode : int
4 | {
5 | OpenGL2 = 0b000,
6 | OpenGL3 = 0b001,
7 | Forward = 0b100,
8 | Mobile = 0b101,
9 | Compatibility = 0b110,
10 | ///
11 | /// This is not a render mode but a way to separate older modes from newer ones
12 | ///
13 | Config5 = 0b100,
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/ResetButton.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 | using Godot;
3 |
4 | namespace Com.Astral.GodotHub.Core.Settings.Buttons
5 | {
6 | public partial class ResetButton : Button, ISettingButton
7 | {
8 | public void Connect()
9 | {
10 | Pressed += AppConfig.ResetAll;
11 | }
12 |
13 | public void Disconnect()
14 | {
15 | Pressed -= AppConfig.ResetAll;
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/toggles/SettingToggle.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Core.Settings.Buttons.Toggles
2 | {
3 | public abstract partial class SettingToggle : SettingButton
4 | {
5 | public override void Connect()
6 | {
7 | button.Toggled += OnToggled;
8 | }
9 |
10 | public override void Disconnect()
11 | {
12 | button.Toggled -= OnToggled;
13 | }
14 |
15 | protected abstract void OnToggled(bool pToggled);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/toggles/AutoDeleteToggle.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 |
3 | namespace Com.Astral.GodotHub.Core.Settings.Buttons.Toggles
4 | {
5 | public partial class AutoDeleteToggle : SettingToggle
6 | {
7 | protected override void OnToggled(bool pToggled)
8 | {
9 | AppConfig.AutoDeleteZip = pToggled;
10 | }
11 |
12 | protected override void Reset()
13 | {
14 | button.ButtonPressed = AppConfig.AutoDeleteZip;
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/toggles/AutoCloseDLToggle.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 |
3 | namespace Com.Astral.GodotHub.Core.Settings.Buttons.Toggles
4 | {
5 | public partial class AutoCloseDLToggle : SettingToggle
6 | {
7 | protected override void OnToggled(bool pToggled)
8 | {
9 | AppConfig.AutoCloseDownload = pToggled;
10 | }
11 |
12 | protected override void Reset()
13 | {
14 | button.ButtonPressed = AppConfig.AutoCloseDownload;
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/toggles/AutoShortcutToggle.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 |
3 | namespace Com.Astral.GodotHub.Core.Settings.Buttons.Toggles
4 | {
5 | public partial class AutoShortcutToggle : SettingToggle
6 | {
7 | protected override void OnToggled(bool pToggled)
8 | {
9 | AppConfig.AutoCreateShortcut = pToggled;
10 | }
11 |
12 | protected override void Reset()
13 | {
14 | button.ButtonPressed = AppConfig.AutoCreateShortcut;
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/toggles/AutoUpdateToggle.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 |
3 | namespace Com.Astral.GodotHub.Core.Settings.Buttons.Toggles
4 | {
5 | public partial class AutoUpdateToggle : SettingToggle
6 | {
7 | protected override void OnToggled(bool pToggled)
8 | {
9 | AppConfig.AutoUpdateRepository = pToggled;
10 | }
11 |
12 | protected override void Reset()
13 | {
14 | button.ButtonPressed = AppConfig.AutoUpdateRepository;
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/directory/ProjectDirButton.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 |
3 | namespace Com.Astral.GodotHub.Core.Settings.Buttons.Directory
4 | {
5 | public partial class ProjectDirButton : DirButton
6 | {
7 | protected override void OnDirSelected(string pDir)
8 | {
9 | AppConfig.ProjectDir = pDir;
10 | base.OnDirSelected(pDir);
11 | }
12 |
13 | protected override void Reset()
14 | {
15 | button.Text = $" {AppConfig.ProjectDir}";
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/toggles/DebugToggle.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 | using Com.Astral.GodotHub.Core.Debug;
3 |
4 | namespace Com.Astral.GodotHub.Core.Settings.Buttons.Toggles
5 | {
6 | public partial class DebugToggle : SettingToggle
7 | {
8 | protected override void OnToggled(bool pToggled)
9 | {
10 | AppConfig.Debug = pToggled;
11 | Debugger.Enabled = pToggled;
12 | }
13 |
14 | protected override void Reset()
15 | {
16 | button.ButtonPressed = AppConfig.Debug;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/scripts/core/tabs/Tab.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace Com.Astral.GodotHub.Core.Tabs
4 | {
5 | public abstract partial class Tab : Control
6 | {
7 | public virtual void Toggle(bool pToggled)
8 | {
9 | if (Visible == pToggled)
10 | return;
11 |
12 | if (pToggled)
13 | {
14 | Visible = true;
15 | Connect();
16 | }
17 | else
18 | {
19 | Disconnect();
20 | Visible = false;
21 | }
22 | }
23 |
24 | protected abstract void Connect();
25 | protected abstract void Disconnect();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/scenes/message_dialog.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://cjui7vv5c4tpk"]
2 |
3 | [ext_resource type="Theme" uid="uid://ce3m7fxsw8f6t" path="res://resources/themes/main.theme" id="1_w1lgf"]
4 |
5 | [node name="MessageDialog" type="AcceptDialog"]
6 | transparent_bg = true
7 | title = "Error"
8 | position = Vector2i(300, 150)
9 | size = Vector2i(650, 350)
10 | visible = true
11 | transient = false
12 | unresizable = true
13 | always_on_top = true
14 | popup_window = true
15 | theme = ExtResource("1_w1lgf")
16 | dialog_text = "This is an error"
17 | dialog_autowrap = true
18 |
--------------------------------------------------------------------------------
/scenes/confirmation_dialog.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://bilwvy6kxj1nk"]
2 |
3 | [ext_resource type="Theme" uid="uid://ce3m7fxsw8f6t" path="res://resources/themes/main.theme" id="1_kav0p"]
4 |
5 | [node name="ConfirmationDialog" type="ConfirmationDialog"]
6 | transparent_bg = true
7 | title = "Remove version?"
8 | size = Vector2i(400, 200)
9 | visible = true
10 | exclusive = false
11 | unresizable = true
12 | popup_window = true
13 | theme = ExtResource("1_kav0p")
14 | dialog_text = "Are you confirming you want to do the action you clicked on?"
15 | dialog_autowrap = true
16 |
--------------------------------------------------------------------------------
/scenes/settings/folder_dialog.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=3 uid="uid://c54ctd2k2mbg0"]
2 |
3 | [ext_resource type="Theme" uid="uid://ce3m7fxsw8f6t" path="res://resources/themes/main.theme" id="1_madp0"]
4 |
5 | [node name="FileDialog" type="FileDialog"]
6 | transparent_bg = true
7 | title = "Open a Directory"
8 | position = Vector2i(125, 100)
9 | size = Vector2i(1000, 550)
10 | visible = true
11 | always_on_top = true
12 | popup_window = true
13 | min_size = Vector2i(600, 300)
14 | theme = ExtResource("1_madp0")
15 | ok_button_text = "Select This Folder"
16 | file_mode = 2
17 | access = 2
18 |
--------------------------------------------------------------------------------
/scripts/core/tabs/UpdateRepoButton.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 | using Com.Astral.GodotHub.Core.Debug;
3 | using Godot;
4 |
5 | using Error = Com.Astral.GodotHub.Core.Utils.Error;
6 |
7 | namespace Com.Astral.GodotHub.Core.Tabs
8 | {
9 | public partial class UpdateRepoButton : Button
10 | {
11 | public override void _Ready()
12 | {
13 | Pressed += OnPressed;
14 | }
15 |
16 | protected async void OnPressed()
17 | {
18 | Error lError = await GDRepository.UpdateReleases();
19 |
20 | if (!lError.Ok)
21 | {
22 | Debugger.LogException(lError.Exception);
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/toggles/SameDirToggle.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 | using Com.Astral.GodotHub.Core.Settings.Buttons.Directory;
3 | using Godot;
4 |
5 | namespace Com.Astral.GodotHub.Core.Settings.Buttons.Toggles
6 | {
7 | public partial class SameDirToggle : SettingToggle
8 | {
9 | [Export] protected DownloadDirButton downloadDirButton;
10 |
11 | protected override void OnToggled(bool pToggled)
12 | {
13 | AppConfig.UseInstallDirForDownload = pToggled;
14 | downloadDirButton.Enabled = !pToggled;
15 | }
16 |
17 | protected override void Reset()
18 | {
19 | button.ButtonPressed = AppConfig.UseInstallDirForDownload;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/SettingButton.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 | using Godot;
3 |
4 | namespace Com.Astral.GodotHub.Core.Settings.Buttons
5 | {
6 | public abstract partial class SettingButton : Control, ISettingButton
7 | {
8 | [Export] protected Button button;
9 |
10 | public override void _Ready()
11 | {
12 | Reset();
13 | AppConfig.Reset += Reset;
14 | }
15 |
16 | protected override void Dispose(bool pDisposing)
17 | {
18 | if (!pDisposing)
19 | return;
20 |
21 | AppConfig.Reset -= Reset;
22 | }
23 |
24 | public abstract void Connect();
25 | public abstract void Disconnect();
26 | protected abstract void Reset();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/directory/InstallDirButton.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 | using Godot;
3 |
4 | namespace Com.Astral.GodotHub.Core.Settings.Buttons.Directory
5 | {
6 | public partial class InstallDirButton : DirButton
7 | {
8 | [Export] protected DownloadDirButton downloadDirButton;
9 |
10 | protected override void OnDirSelected(string pDir)
11 | {
12 | AppConfig.InstallDir = pDir;
13 |
14 | if (AppConfig.UseInstallDirForDownload)
15 | {
16 | AppConfig.DownloadDir = pDir;
17 | downloadDirButton.Text = $" {pDir}";
18 | }
19 |
20 | base.OnDirSelected(pDir);
21 | }
22 |
23 | protected override void Reset()
24 | {
25 | button.Text = $" {AppConfig.InstallDir}";
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/scripts/core/SplashScreen.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace Com.Astral.GodotHub.Core
4 | {
5 | public partial class SplashScreen : ColorRect
6 | {
7 | [Export] protected float fadeDuration = 0.2f;
8 |
9 | public override void _Ready()
10 | {
11 | #if DEBUG
12 | Visible = true;
13 | #endif //DEBUG
14 |
15 | Main.Instance.Initialized += FadeOut;
16 | }
17 |
18 | protected void FadeOut()
19 | {
20 | Main.Instance.Initialized -= FadeOut;
21 | CreateTween()
22 | .SetTrans(Tween.TransitionType.Linear)
23 | .SetEase(Tween.EaseType.InOut)
24 | .TweenProperty(this, "self_modulate:a", 0f, fadeDuration)
25 | .Finished += OnFadeOutFinished;
26 | }
27 |
28 | protected void OnFadeOutFinished()
29 | {
30 | Visible = false;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/scripts/uninstaller/UninstallProgram.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Uninstaller
2 | {
3 | internal class UninstallProgram
4 | {
5 | public static void Main(string[] pArgs)
6 | {
7 | if (pArgs == null || pArgs.Length == 0)
8 | return;
9 |
10 | try
11 | {
12 | for (int i = 0; i < pArgs.Length; i++)
13 | {
14 | DeletePath(pArgs[i]);
15 | }
16 | }
17 | catch (Exception lException)
18 | {
19 | Console.WriteLine(lException);
20 | Console.ReadKey();
21 | }
22 | }
23 |
24 | private static void DeletePath(string pPath)
25 | {
26 | if (File.Exists(pPath))
27 | {
28 | File.Delete(pPath);
29 | }
30 | else if (Directory.Exists(pPath))
31 | {
32 | Directory.Delete(pPath, true);
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/directory/DownloadDirButton.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 |
3 | namespace Com.Astral.GodotHub.Core.Settings.Buttons.Directory
4 | {
5 | public partial class DownloadDirButton : DirButton
6 | {
7 | public bool Enabled
8 | {
9 | get => _enabled;
10 | set
11 | {
12 | if (Enabled == value)
13 | return;
14 |
15 | Visible = value;
16 | _enabled = value;
17 | }
18 | }
19 | protected bool _enabled = true;
20 |
21 | protected override void OnDirSelected(string pDir)
22 | {
23 | AppConfig.DownloadDir = pDir;
24 | base.OnDirSelected(pDir);
25 | }
26 |
27 | protected override void Reset()
28 | {
29 | button.Text = $" {AppConfig.DownloadDir}";
30 | Enabled = !AppConfig.UseInstallDirForDownload;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/scripts/core/data/GDFile.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Core.Data
2 | {
3 | ///
4 | /// Struct corresponding to an engine executable or a Godot project
5 | ///
6 | public struct GDFile
7 | {
8 | ///
9 | /// Absolute path to the file
10 | ///
11 | public string Path { get; private set; }
12 | ///
13 | /// Whether or not this file is marked as favorite by the user
14 | ///
15 | public bool IsFavorite { get; private set; }
16 | ///
17 | /// of the engine or the project
18 | ///
19 | public Version Version { get; private set; }
20 |
21 | public GDFile(string pPath, bool pIsFavorite, Version pVersion)
22 | {
23 | Path = pPath;
24 | IsFavorite = pIsFavorite;
25 | Version = pVersion;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-Bold.ttf.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="font_data_dynamic"
4 | type="FontFile"
5 | uid="uid://ykab4b3ximf0"
6 | path="res://.godot/imported/JetBrainsMono-Bold.ttf-f31f88c88fdce3c3d6a7829dad9ca238.fontdata"
7 |
8 | [deps]
9 |
10 | source_file="res://assets/fonts/JetBrainsMono-Bold.ttf"
11 | dest_files=["res://.godot/imported/JetBrainsMono-Bold.ttf-f31f88c88fdce3c3d6a7829dad9ca238.fontdata"]
12 |
13 | [params]
14 |
15 | Rendering=null
16 | antialiasing=1
17 | generate_mipmaps=false
18 | multichannel_signed_distance_field=false
19 | msdf_pixel_range=8
20 | msdf_size=48
21 | allow_system_fallback=true
22 | force_autohinter=false
23 | hinting=1
24 | subpixel_positioning=1
25 | oversampling=0.0
26 | Fallbacks=null
27 | fallbacks=[]
28 | Compress=null
29 | compress=true
30 | preload=[]
31 | language_support={}
32 | script_support={}
33 | opentype_features={}
34 |
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-Italic.ttf.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="font_data_dynamic"
4 | type="FontFile"
5 | uid="uid://bwv0di287lde3"
6 | path="res://.godot/imported/JetBrainsMono-Italic.ttf-826933456e09d4ab84cb3226492f017f.fontdata"
7 |
8 | [deps]
9 |
10 | source_file="res://assets/fonts/JetBrainsMono-Italic.ttf"
11 | dest_files=["res://.godot/imported/JetBrainsMono-Italic.ttf-826933456e09d4ab84cb3226492f017f.fontdata"]
12 |
13 | [params]
14 |
15 | Rendering=null
16 | antialiasing=1
17 | generate_mipmaps=false
18 | multichannel_signed_distance_field=false
19 | msdf_pixel_range=8
20 | msdf_size=48
21 | allow_system_fallback=true
22 | force_autohinter=false
23 | hinting=1
24 | subpixel_positioning=1
25 | oversampling=0.0
26 | Fallbacks=null
27 | fallbacks=[]
28 | Compress=null
29 | compress=true
30 | preload=[]
31 | language_support={}
32 | script_support={}
33 | opentype_features={}
34 |
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-Medium.ttf.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="font_data_dynamic"
4 | type="FontFile"
5 | uid="uid://deriya3c1o017"
6 | path="res://.godot/imported/JetBrainsMono-Medium.ttf-06044950c8d4b6cfb6cde21dbc11f060.fontdata"
7 |
8 | [deps]
9 |
10 | source_file="res://assets/fonts/JetBrainsMono-Medium.ttf"
11 | dest_files=["res://.godot/imported/JetBrainsMono-Medium.ttf-06044950c8d4b6cfb6cde21dbc11f060.fontdata"]
12 |
13 | [params]
14 |
15 | Rendering=null
16 | antialiasing=1
17 | generate_mipmaps=false
18 | multichannel_signed_distance_field=false
19 | msdf_pixel_range=8
20 | msdf_size=48
21 | allow_system_fallback=true
22 | force_autohinter=false
23 | hinting=1
24 | subpixel_positioning=1
25 | oversampling=0.0
26 | Fallbacks=null
27 | fallbacks=[]
28 | Compress=null
29 | compress=true
30 | preload=[]
31 | language_support={}
32 | script_support={}
33 | opentype_features={}
34 |
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-Regular.ttf.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="font_data_dynamic"
4 | type="FontFile"
5 | uid="uid://20nkj2oqpwl4"
6 | path="res://.godot/imported/JetBrainsMono-Regular.ttf-4207f0122299d0c43a34895264f1b346.fontdata"
7 |
8 | [deps]
9 |
10 | source_file="res://assets/fonts/JetBrainsMono-Regular.ttf"
11 | dest_files=["res://.godot/imported/JetBrainsMono-Regular.ttf-4207f0122299d0c43a34895264f1b346.fontdata"]
12 |
13 | [params]
14 |
15 | Rendering=null
16 | antialiasing=1
17 | generate_mipmaps=false
18 | multichannel_signed_distance_field=false
19 | msdf_pixel_range=8
20 | msdf_size=48
21 | allow_system_fallback=true
22 | force_autohinter=false
23 | hinting=1
24 | subpixel_positioning=1
25 | oversampling=0.0
26 | Fallbacks=null
27 | fallbacks=[]
28 | Compress=null
29 | compress=true
30 | preload=[]
31 | language_support={}
32 | script_support={}
33 | opentype_features={}
34 |
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-ExtraBold.ttf.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="font_data_dynamic"
4 | type="FontFile"
5 | uid="uid://b2dha2ictl01s"
6 | path="res://.godot/imported/JetBrainsMono-ExtraBold.ttf-ff94f9e44a98cadab98702a1a9f8d738.fontdata"
7 |
8 | [deps]
9 |
10 | source_file="res://assets/fonts/JetBrainsMono-ExtraBold.ttf"
11 | dest_files=["res://.godot/imported/JetBrainsMono-ExtraBold.ttf-ff94f9e44a98cadab98702a1a9f8d738.fontdata"]
12 |
13 | [params]
14 |
15 | Rendering=null
16 | antialiasing=1
17 | generate_mipmaps=false
18 | multichannel_signed_distance_field=false
19 | msdf_pixel_range=8
20 | msdf_size=48
21 | allow_system_fallback=true
22 | force_autohinter=false
23 | hinting=1
24 | subpixel_positioning=1
25 | oversampling=0.0
26 | Fallbacks=null
27 | fallbacks=[]
28 | Compress=null
29 | compress=true
30 | preload=[]
31 | language_support={}
32 | script_support={}
33 | opentype_features={}
34 |
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-Bold-Italic.ttf.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="font_data_dynamic"
4 | type="FontFile"
5 | uid="uid://u11pwpfdqleg"
6 | path="res://.godot/imported/JetBrainsMono-Bold-Italic.ttf-bbd6d59f11a5a87ded8f47223085fd53.fontdata"
7 |
8 | [deps]
9 |
10 | source_file="res://assets/fonts/JetBrainsMono-Bold-Italic.ttf"
11 | dest_files=["res://.godot/imported/JetBrainsMono-Bold-Italic.ttf-bbd6d59f11a5a87ded8f47223085fd53.fontdata"]
12 |
13 | [params]
14 |
15 | Rendering=null
16 | antialiasing=1
17 | generate_mipmaps=false
18 | multichannel_signed_distance_field=false
19 | msdf_pixel_range=8
20 | msdf_size=48
21 | allow_system_fallback=true
22 | force_autohinter=false
23 | hinting=1
24 | subpixel_positioning=1
25 | oversampling=0.0
26 | Fallbacks=null
27 | fallbacks=[]
28 | Compress=null
29 | compress=true
30 | preload=[]
31 | language_support={}
32 | script_support={}
33 | opentype_features={}
34 |
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-Medium-Italic.ttf.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="font_data_dynamic"
4 | type="FontFile"
5 | uid="uid://drc4cb0obved2"
6 | path="res://.godot/imported/JetBrainsMono-Medium-Italic.ttf-31da2408e034706a3d6e2311723282bb.fontdata"
7 |
8 | [deps]
9 |
10 | source_file="res://assets/fonts/JetBrainsMono-Medium-Italic.ttf"
11 | dest_files=["res://.godot/imported/JetBrainsMono-Medium-Italic.ttf-31da2408e034706a3d6e2311723282bb.fontdata"]
12 |
13 | [params]
14 |
15 | Rendering=null
16 | antialiasing=1
17 | generate_mipmaps=false
18 | multichannel_signed_distance_field=false
19 | msdf_pixel_range=8
20 | msdf_size=48
21 | allow_system_fallback=true
22 | force_autohinter=false
23 | hinting=1
24 | subpixel_positioning=1
25 | oversampling=0.0
26 | Fallbacks=null
27 | fallbacks=[]
28 | Compress=null
29 | compress=true
30 | preload=[]
31 | language_support={}
32 | script_support={}
33 | opentype_features={}
34 |
--------------------------------------------------------------------------------
/assets/fonts/JetBrainsMono-ExtraBold-Italic.ttf.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="font_data_dynamic"
4 | type="FontFile"
5 | uid="uid://cjyj30pvj70c3"
6 | path="res://.godot/imported/JetBrainsMono-ExtraBold-Italic.ttf-0f48647bc6a20054160164675a934b31.fontdata"
7 |
8 | [deps]
9 |
10 | source_file="res://assets/fonts/JetBrainsMono-ExtraBold-Italic.ttf"
11 | dest_files=["res://.godot/imported/JetBrainsMono-ExtraBold-Italic.ttf-0f48647bc6a20054160164675a934b31.fontdata"]
12 |
13 | [params]
14 |
15 | Rendering=null
16 | antialiasing=1
17 | generate_mipmaps=false
18 | multichannel_signed_distance_field=false
19 | msdf_pixel_range=8
20 | msdf_size=48
21 | allow_system_fallback=true
22 | force_autohinter=false
23 | hinting=1
24 | subpixel_positioning=1
25 | oversampling=0.0
26 | Fallbacks=null
27 | fallbacks=[]
28 | Compress=null
29 | compress=true
30 | preload=[]
31 | language_support={}
32 | script_support={}
33 | opentype_features={}
34 |
--------------------------------------------------------------------------------
/assets/sprites/star.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://n0ngwfu5xhvd"
6 | path="res://.godot/imported/star.png-3ab12433f97fcbd385d38b1404557e14.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/star.png"
14 | dest_files=["res://.godot/imported/star.png-3ab12433f97fcbd385d38b1404557e14.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 |
--------------------------------------------------------------------------------
/scripts/core/utils/BBCodeT.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace Com.Astral.GodotHub.Core.Utils
4 | {
5 | public static class BBCodeT
6 | {
7 | public static string GetColoredText(string pText, Color pColor)
8 | {
9 | return $"[color=#{Colors.ToHexa(pColor)}]{pText}[/color]";
10 | }
11 |
12 | public static string GetBoldText(string pText)
13 | {
14 | return $"[b]{pText}[/b]";
15 | }
16 |
17 | public static string GetItalicText(string pText)
18 | {
19 | return $"[i]{pText}[/i]";
20 | }
21 |
22 | public static string GetTaggedText(string pText, params string[] pTags)
23 | {
24 | string lRet = "";
25 |
26 | for (int i = 0; i < pTags.Length; i++)
27 | {
28 | lRet += "[" + pTags[i] + "]";
29 | }
30 |
31 | lRet += pText;
32 |
33 | for (int i = pTags.Length - 1; i >= 0; i--)
34 | {
35 | lRet += "[/" + pTags[i] + "]";
36 | }
37 |
38 | return lRet;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/assets/sprites/folder.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://ck0fei3vii0gs"
6 | path="res://.godot/imported/folder.png-829cf927d0a48d4f049a0065b70db740.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/folder.png"
14 | dest_files=["res://.godot/imported/folder.png-829cf927d0a48d4f049a0065b70db740.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 |
--------------------------------------------------------------------------------
/assets/sprites/arrows/arrow_up.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://buy4vfi18sdga"
6 | path="res://.godot/imported/arrow_up.png-b589b15a8fe6b3ade68f2301877f8175.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/arrows/arrow_up.png"
14 | dest_files=["res://.godot/imported/arrow_up.png-b589b15a8fe6b3ade68f2301877f8175.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 |
--------------------------------------------------------------------------------
/assets/sprites/download_btn.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://b6m2numrdnkgc"
6 | path="res://.godot/imported/download_btn.png-03e8306191a71276e7b0c19d1c821d62.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/download_btn.png"
14 | dest_files=["res://.godot/imported/download_btn.png-03e8306191a71276e7b0c19d1c821d62.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 |
--------------------------------------------------------------------------------
/assets/gdh_splash-screen.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://nl42yg4oevc5"
6 | path="res://.godot/imported/gdh_splash-screen.png-4e34233a7513afe045c9ca70e07f4b53.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/gdh_splash-screen.png"
14 | dest_files=["res://.godot/imported/gdh_splash-screen.png-4e34233a7513afe045c9ca70e07f4b53.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 |
--------------------------------------------------------------------------------
/assets/sprites/arrows/arrow_left.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://p3bmkkhysbnv"
6 | path="res://.godot/imported/arrow_left.png-5d4dd23636f1aa4b65fbe4304c04c362.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/arrows/arrow_left.png"
14 | dest_files=["res://.godot/imported/arrow_left.png-5d4dd23636f1aa4b65fbe4304c04c362.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 |
--------------------------------------------------------------------------------
/assets/sprites/settings_icon.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://b56ynjybl3xm3"
6 | path="res://.godot/imported/settings_icon.png-57802a87571912e0dc8029db181701e9.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/settings_icon.png"
14 | dest_files=["res://.godot/imported/settings_icon.png-57802a87571912e0dc8029db181701e9.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 |
--------------------------------------------------------------------------------
/assets/sprites/arrows/arrow_down.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://be2gnv6tr4e73"
6 | path="res://.godot/imported/arrow_down.png-03ba2e3a36a34345e1d37c177ddd62f3.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/arrows/arrow_down.png"
14 | dest_files=["res://.godot/imported/arrow_down.png-03ba2e3a36a34345e1d37c177ddd62f3.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 |
--------------------------------------------------------------------------------
/assets/sprites/arrows/arrow_right.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://jvyrvv8bmy4u"
6 | path="res://.godot/imported/arrow_right.png-8a166a9fcca6ecefe76397f8567adf53.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/arrows/arrow_right.png"
14 | dest_files=["res://.godot/imported/arrow_right.png-8a166a9fcca6ecefe76397f8567adf53.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 |
--------------------------------------------------------------------------------
/assets/sprites/arrows/option_btn.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dklahbv7sporm"
6 | path="res://.godot/imported/option_btn.png-67c2d353f69841bef12fa861a15c99b0.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/arrows/option_btn.png"
14 | dest_files=["res://.godot/imported/option_btn.png-67c2d353f69841bef12fa861a15c99b0.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 |
--------------------------------------------------------------------------------
/scripts/core/utils/Error.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Com.Astral.GodotHub.Core.Utils
4 | {
5 | ///
6 | /// Structure used to approximate a Rust enum: Error(string)
7 | ///
8 | public struct Error
9 | {
10 | ///
11 | /// If true, everything went well
12 | ///
13 | public bool Ok => _exception == null;
14 | ///
15 | /// The that happened. null if everything went well
16 | ///
17 | public Exception Exception => _exception;
18 | ///
19 | /// Message that describes the current exception. Empty if there's no
20 | ///
21 | public string Message => _exception.Message;
22 |
23 | private readonly Exception _exception;
24 |
25 | public Error()
26 | {
27 | _exception = null;
28 | }
29 |
30 | public Error(Exception pException)
31 | {
32 | _exception = pException;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/assets/sprites/crosses/cross_hover.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://y0dvw21vgsyb"
6 | path="res://.godot/imported/cross_hover.png-3a8dabdb0ddde2e365ac12bf00096d72.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/crosses/cross_hover.png"
14 | dest_files=["res://.godot/imported/cross_hover.png-3a8dabdb0ddde2e365ac12bf00096d72.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 |
--------------------------------------------------------------------------------
/assets/sprites/crosses/cross_white.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://crtj2ch3o166n"
6 | path="res://.godot/imported/cross_white.png-ddfe8f6addb29cf1ae60b65b9f616ec2.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/crosses/cross_white.png"
14 | dest_files=["res://.godot/imported/cross_white.png-ddfe8f6addb29cf1ae60b65b9f616ec2.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 |
--------------------------------------------------------------------------------
/assets/sprites/check_boxes/box_checked.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://4v0f3326dtvv"
6 | path="res://.godot/imported/box_checked.png-79e23c933897f27818e2c329bcc93a7a.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/check_boxes/box_checked.png"
14 | dest_files=["res://.godot/imported/box_checked.png-79e23c933897f27818e2c329bcc93a7a.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 |
--------------------------------------------------------------------------------
/assets/sprites/crosses/cross_default.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bq2mnb0nva1gp"
6 | path="res://.godot/imported/cross_default.png-daf0d358465aa1087bbf479b327a5c58.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/crosses/cross_default.png"
14 | dest_files=["res://.godot/imported/cross_default.png-daf0d358465aa1087bbf479b327a5c58.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 |
--------------------------------------------------------------------------------
/assets/sprites/folder_compressed.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dohlskxd3lklq"
6 | path="res://.godot/imported/folder_compressed.png-2c1c2ab6f20a44ffee9665d45887f435.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/folder_compressed.png"
14 | dest_files=["res://.godot/imported/folder_compressed.png-2c1c2ab6f20a44ffee9665d45887f435.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 |
--------------------------------------------------------------------------------
/assets/sprites/check_boxes/box_unchecked.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://qoq1yljgu7"
6 | path="res://.godot/imported/box_unchecked.png-0c915cc974d352116442923221fce1ab.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/check_boxes/box_unchecked.png"
14 | dest_files=["res://.godot/imported/box_unchecked.png-0c915cc974d352116442923221fce1ab.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 |
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_checked.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cbkbi55l2es62"
6 | path="res://.godot/imported/btn_checked.png-bcddafa2be736af435af086d09375cda.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/check_buttons/btn_checked.png"
14 | dest_files=["res://.godot/imported/btn_checked.png-bcddafa2be736af435af086d09375cda.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 |
--------------------------------------------------------------------------------
/project.godot:
--------------------------------------------------------------------------------
1 | ; Engine configuration file.
2 | ; It's best edited using the editor UI and not directly,
3 | ; since the parameters that go here are not all obvious.
4 | ;
5 | ; Format:
6 | ; [section] ; section goes between []
7 | ; param=value ; assign values to parameters
8 |
9 | config_version=5
10 |
11 | [application]
12 |
13 | config/name="Godot Hub"
14 | run/main_scene="res://scenes/main.tscn"
15 | config/features=PackedStringArray("4.0", "C#", "Mobile")
16 | config/icon="res://icon.svg"
17 | config/windows_native_icon="res://icon.ico"
18 |
19 | [autoload]
20 |
21 | ExceptionHandler="*res://scenes/debug/exception_handler.tscn"
22 | Colors="*res://scenes/utils/colors.tscn"
23 |
24 | [display]
25 |
26 | window/size/viewport_width=1280
27 | window/size/viewport_height=720
28 | window/stretch/mode="canvas_items"
29 | window/stretch/aspect="expand"
30 |
31 | [dotnet]
32 |
33 | project/assembly_name="Godot Hub"
34 |
35 | [rendering]
36 |
37 | renderer/rendering_method="mobile"
38 |
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_unchecked.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cyqq5wt7y5ri8"
6 | path="res://.godot/imported/btn_unchecked.png-f4ad166b5aeae3bc9397d8214bac88dc.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/check_buttons/btn_unchecked.png"
14 | dest_files=["res://.godot/imported/btn_unchecked.png-f4ad166b5aeae3bc9397d8214bac88dc.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 |
--------------------------------------------------------------------------------
/scripts/installer/InstallerConstants.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Installer
2 | {
3 | public static class InstallerConstants
4 | {
5 | #if DEBUG
6 | public const string MUTEX_NAME = "GodotHub-AdminMutex-Debug";
7 |
8 | public const string DOWNLOAD_MAP_NAME = "GodotHub-DownloadContentMap-Debug";
9 | public const string ZIP_MAP_NAME = "GodotHub-ZipPathMap-Debug";
10 | public const string EXTRACT_MAP_NAME = "GodotHub-ExtractDirMap-Debug";
11 | public const string JUMP_MAP_NAME = "GodotHub-JumpMap-Debug";
12 | #else
13 | public const string MUTEX_NAME = "GodotHub-AdminMutex";
14 |
15 | public const string DOWNLOAD_MAP_NAME = "GodotHub-DownloadContentMap";
16 | public const string ZIP_MAP_NAME = "GodotHub-ZipPathMap";
17 | public const string EXTRACT_MAP_NAME = "GodotHub-ExtractDirMap";
18 | public const string JUMP_MAP_NAME = "GodotHub-JumpMap";
19 | #endif //DEBUG
20 |
21 | public const string WRITE_ARGUMENT = "--write-zip";
22 | public const string EXTRACT_ARGUMENT = "--unzip";
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/icon.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cvbiw0kj5o88y"
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 |
--------------------------------------------------------------------------------
/assets/sprites/check_boxes/box_checked_disabled.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cmrbnnr3hcyq2"
6 | path="res://.godot/imported/box_checked_disabled.png-17e0744206c3f93fc44653b613f42220.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/check_boxes/box_checked_disabled.png"
14 | dest_files=["res://.godot/imported/box_checked_disabled.png-17e0744206c3f93fc44653b613f42220.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 |
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_checked_disabled.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://e5s3gekp2tfn"
6 | path="res://.godot/imported/btn_checked_disabled.png-ffc20e03046a8024825db0efd03735c8.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/check_buttons/btn_checked_disabled.png"
14 | dest_files=["res://.godot/imported/btn_checked_disabled.png-ffc20e03046a8024825db0efd03735c8.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 |
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_checked_mirrored.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bjyjla6t1lot7"
6 | path="res://.godot/imported/btn_checked_mirrored.png-1fc948935607ba22dd7c71f0ab1effd2.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/check_buttons/btn_checked_mirrored.png"
14 | dest_files=["res://.godot/imported/btn_checked_mirrored.png-1fc948935607ba22dd7c71f0ab1effd2.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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Quick info: I haven't abandonned this project. It's just that I don't have the time and the energy to work on it. I still want to finish it and make it a good tool for Godot users.
2 |
3 | # GodotHub
4 | Like Unity hub but for Godot.
5 |
6 | It's supposed to be a project and version manager, but I plan to add more features in the future.
7 |
8 | ## Getting Godot Hub
9 |
10 | You can either get the executable, or get the source code and export it with Godot 4.0. Since I can't export on Mac, you'll have to go for the second option if you want it on this platform.
11 |
12 | ## Screenshots
13 |
14 | ### Project List:
15 | 
16 |
17 | ### Installed Versions List:
18 | 
19 |
20 | ### Releases List:
21 | 
22 |
--------------------------------------------------------------------------------
/assets/sprites/check_boxes/box_unchecked_disabled.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://do74hj6aewgif"
6 | path="res://.godot/imported/box_unchecked_disabled.png-1772e9cc2d632b02e756c852d0374894.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/check_boxes/box_unchecked_disabled.png"
14 | dest_files=["res://.godot/imported/box_unchecked_disabled.png-1772e9cc2d632b02e756c852d0374894.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 |
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_unchecked_disabled.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://by1q0nrfe4s6w"
6 | path="res://.godot/imported/btn_unchecked_disabled.png-155ccf176e20559c74bbc5dbff4e5219.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/check_buttons/btn_unchecked_disabled.png"
14 | dest_files=["res://.godot/imported/btn_unchecked_disabled.png-155ccf176e20559c74bbc5dbff4e5219.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 |
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_unchecked_mirrored.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bcadjo1extons"
6 | path="res://.godot/imported/btn_unchecked_mirrored.png-da679aa1223739c8099ebf63de801857.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/check_buttons/btn_unchecked_mirrored.png"
14 | dest_files=["res://.godot/imported/btn_unchecked_mirrored.png-da679aa1223739c8099ebf63de801857.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 |
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_check_disabled_mirrored.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cs727hgthptx"
6 | path="res://.godot/imported/btn_check_disabled_mirrored.png-e79de934ca3eb99dd3f9867ac5e507c2.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/check_buttons/btn_check_disabled_mirrored.png"
14 | dest_files=["res://.godot/imported/btn_check_disabled_mirrored.png-e79de934ca3eb99dd3f9867ac5e507c2.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 |
--------------------------------------------------------------------------------
/assets/default_icon.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://4wgos1q8t8tv"
6 | path="res://.godot/imported/default_icon.svg-89937e2172e005a1330a2139d4b6965d.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/default_icon.svg"
14 | dest_files=["res://.godot/imported/default_icon.svg-89937e2172e005a1330a2139d4b6965d.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 |
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_checked_disabled_mirrored.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bv4yc4m6wi3tk"
6 | path="res://.godot/imported/btn_checked_disabled_mirrored.png-69ab4ab8d22f405838b5d15acc7b9bf1.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/check_buttons/btn_checked_disabled_mirrored.png"
14 | dest_files=["res://.godot/imported/btn_checked_disabled_mirrored.png-69ab4ab8d22f405838b5d15acc7b9bf1.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 |
--------------------------------------------------------------------------------
/scenes/sort_button.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://dcyk3xxppgacf"]
2 |
3 | [ext_resource type="Theme" uid="uid://dpsfmlg5cj4ka" path="res://resources/themes/sort_btn.theme" id="1_0gx4y"]
4 | [ext_resource type="Script" path="res://scripts/core/tabs/SortToggle.cs" id="2_hv8wg"]
5 | [ext_resource type="Texture2D" uid="uid://be2gnv6tr4e73" path="res://assets/sprites/arrows/arrow_down.png" id="3_0pcu5"]
6 |
7 | [node name="NameButton" type="Button" node_paths=PackedStringArray("arrowRect")]
8 | anchors_preset = -1
9 | anchor_left = 0.075
10 | anchor_top = 0.25
11 | anchor_right = 0.35
12 | anchor_bottom = 0.75
13 | focus_mode = 0
14 | theme = ExtResource("1_0gx4y")
15 | toggle_mode = true
16 | text = "Name"
17 | alignment = 0
18 | script = ExtResource("2_hv8wg")
19 | arrowRect = NodePath("Arrow")
20 |
21 | [node name="Arrow" type="TextureRect" parent="."]
22 | layout_mode = 1
23 | anchors_preset = 9
24 | anchor_bottom = 1.0
25 | offset_left = 55.0
26 | offset_right = 70.0
27 | grow_vertical = 2
28 | texture = ExtResource("3_0pcu5")
29 | stretch_mode = 5
30 |
--------------------------------------------------------------------------------
/assets/sprites/check_buttons/btn_unchecked_disabled_mirrored.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://4e1jphqiexep"
6 | path="res://.godot/imported/btn_unchecked_disabled_mirrored.png-6d595d74a6c4b7bfaa00c01f8925ca95.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://assets/sprites/check_buttons/btn_unchecked_disabled_mirrored.png"
14 | dest_files=["res://.godot/imported/btn_unchecked_disabled_mirrored.png-6d595d74a6c4b7bfaa00c01f8925ca95.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 |
--------------------------------------------------------------------------------
/scripts/core/utils/Colors.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace Com.Astral.GodotHub.Core.Utils
4 | {
5 | public partial class Colors : Node
6 | {
7 | public static Colors Singleton { get; private set; }
8 |
9 | public Color White => _white;
10 | public Color Blue => _blue;
11 | public Color Green => _green;
12 | public Color Yellow => _yellow;
13 | public Color Red => _red;
14 |
15 | [Export] protected Color _white = new Color(0xB8B8B8FF);
16 | [Export] protected Color _blue = new Color(0x379DA6FF);
17 | [Export] protected Color _green = new Color(0x769656FF);
18 | [Export] protected Color _yellow = new Color(0xE7B44FFF);
19 | [Export] protected Color _red = new Color(0xD4504FFF);
20 |
21 | public override void _EnterTree()
22 | {
23 | Singleton = this;
24 | }
25 |
26 | public override void _ExitTree()
27 | {
28 | Singleton = null;
29 | }
30 |
31 | ///
32 | /// Return a string of the color converted to hexadecimal
33 | ///
34 | public static string ToHexa(Color pColor)
35 | {
36 | return $"{pColor.R8:x2}{pColor.G8:x2}{pColor.B8:x2}";
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/scripts/core/tabs/SortToggle.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using System;
3 |
4 | namespace Com.Astral.GodotHub.Core.Tabs
5 | {
6 | public partial class SortToggle : Button
7 | {
8 | public event Action CustomToggled;
9 |
10 | [Export] protected TextureRect arrowRect;
11 |
12 | protected bool toggled = false;
13 |
14 | public override void _Ready()
15 | {
16 | arrowRect.Visible = false;
17 | arrowRect.PivotOffset = arrowRect.Size / 2f;
18 | Toggled += OnToggled;
19 | }
20 |
21 | public void Enable()
22 | {
23 | if (ButtonPressed)
24 | return;
25 |
26 | SetPressedNoSignal(true);
27 | arrowRect.Visible = true;
28 | toggled = true;
29 | arrowRect.Rotation = 0f;
30 | }
31 |
32 | public void Disable()
33 | {
34 | if (!ButtonPressed)
35 | return;
36 |
37 | SetPressedNoSignal(false);
38 | arrowRect.Visible = false;
39 | toggled = false;
40 | }
41 |
42 | protected void OnToggled(bool pToggled)
43 | {
44 | SetPressedNoSignal(true);
45 | toggled = !toggled;
46 | arrowRect.Visible = true;
47 | arrowRect.Rotation = toggled ? 0f : Mathf.Pi;
48 | CustomToggled?.Invoke(toggled);
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/scripts/core/settings/buttons/directory/DirButton.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace Com.Astral.GodotHub.Core.Settings.Buttons.Directory
4 | {
5 | public abstract partial class DirButton : SettingButton
6 | {
7 | public string Text
8 | {
9 | get => button.Text;
10 | set
11 | {
12 | button.Text = value;
13 | }
14 | }
15 |
16 | [Export] protected PackedScene folderDialogScene;
17 |
18 | public override void Connect()
19 | {
20 | button.Pressed += OnPressed;
21 | }
22 |
23 | public override void Disconnect()
24 | {
25 | button.Pressed -= OnPressed;
26 | }
27 |
28 | protected virtual void OnPressed()
29 | {
30 | button.Pressed -= OnPressed;
31 | FileDialog lDialog = folderDialogScene.Instantiate();
32 | Main.Instance.AddChild(lDialog);
33 | lDialog.PopupCentered();
34 | lDialog.RootSubfolder = "";
35 | lDialog.CurrentDir = button.Text[1..];
36 | lDialog.DirSelected += OnDirSelected;
37 | lDialog.Canceled += OnCanceled;
38 | }
39 |
40 | protected virtual void OnDirSelected(string pDir)
41 | {
42 | button.Text = $" {pDir}";
43 | button.Pressed += OnPressed;
44 | }
45 |
46 | protected void OnCanceled()
47 | {
48 | button.Pressed += OnPressed;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/scripts/core/data/FullParameterContractResolver.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Serialization;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 |
7 | namespace Com.Astral.GodotHub.Core.Data
8 | {
9 | ///
10 | /// used to select the most complete constructor when deserializing a .json file
11 | ///
12 | internal class FullParameterContractResolver : DefaultContractResolver
13 | {
14 | protected override JsonObjectContract CreateObjectContract(Type pObjectType)
15 | {
16 | JsonObjectContract lContract = base.CreateObjectContract(pObjectType);
17 | ConstructorInfo lConstructor = pObjectType
18 | .GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
19 | .OrderBy(constructor => constructor.GetParameters().Length)
20 | .LastOrDefault();
21 |
22 | if (lConstructor == null)
23 | {
24 | return lContract;
25 | }
26 |
27 | lContract.OverrideCreator = (@params) => lConstructor.Invoke(@params);
28 | IList lProperties = CreateConstructorParameters(lConstructor, lContract.Properties);
29 |
30 | for (int i = 0; i < lProperties.Count; i++)
31 | {
32 | lContract.CreatorParameters.Add(lProperties[i]);
33 | }
34 |
35 | return lContract;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/scripts/core/tabs/versions/VersionsTab.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace Com.Astral.GodotHub.Core.Tabs.Versions
4 | {
5 | public partial class VersionsTab : Tab
6 | {
7 | [ExportGroup("Panels")]
8 | [Export] protected EnginesPanel enginesPanel;
9 | [Export] protected ReleasePanel releasesPanel;
10 | [Export] protected Button enginesButton;
11 | [Export] protected Button releasesButton;
12 |
13 | public override void _Ready()
14 | {
15 | enginesButton.ButtonPressed = true;
16 | releasesButton.ButtonPressed = false;
17 | enginesPanel.Visible = true;
18 | releasesPanel.Visible = false;
19 | }
20 |
21 | protected override void Connect()
22 | {
23 | enginesButton.Toggled += OnInstallsToggled;
24 | releasesButton.Toggled += OnReleasesToggled;
25 | }
26 |
27 | protected override void Disconnect()
28 | {
29 | releasesButton.Toggled -= OnReleasesToggled;
30 | enginesButton.Toggled -= OnInstallsToggled;
31 | }
32 |
33 | protected void OnInstallsToggled(bool pToggled)
34 | {
35 | if (!pToggled || enginesPanel.Visible)
36 | return;
37 |
38 | enginesPanel.Visible = true;
39 | releasesPanel.Visible = false;
40 | }
41 |
42 | protected void OnReleasesToggled(bool pToggled)
43 | {
44 | if (!pToggled || releasesPanel.Visible)
45 | return;
46 |
47 | releasesPanel.Visible = true;
48 | enginesPanel.Visible = false;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Godot Hub.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net6.0
4 | true
5 | Com.Astral.GodotHub.Core
6 | False
7 |
8 |
9 | 1701;1702;IDE0090;IDE0063;CA1822
10 |
11 |
12 | 1701;1702;IDE0090;IDE0063;CA1822
13 |
14 |
15 | 1701;1702;IDE0090;IDE0063;CA1822
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/scenes/versions/subbutton.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=7 format=3 uid="uid://dpptd81s7nml2"]
2 |
3 | [ext_resource type="Theme" uid="uid://ce3m7fxsw8f6t" path="res://resources/themes/main.theme" id="1_pl5se"]
4 | [ext_resource type="StyleBox" uid="uid://bwbtmxumfpuux" path="res://resources/style_boxes/buttons/default/default_pressed.stylebox" id="2_gb8s2"]
5 | [ext_resource type="StyleBox" uid="uid://cy18s2lgnjx5u" path="res://resources/style_boxes/buttons/default/default_hover.stylebox" id="3_nyalc"]
6 | [ext_resource type="StyleBox" uid="uid://c7pi54b60wghh" path="res://resources/style_boxes/buttons/default/default_normal.stylebox" id="4_7okq5"]
7 | [ext_resource type="StyleBox" uid="uid://donklkuk8tnlx" path="res://resources/style_boxes/buttons/default/default_disabled.stylebox" id="5_be4ah"]
8 | [ext_resource type="ButtonGroup" uid="uid://c2ypx5qbtttva" path="res://resources/button_groups/install_btn_group.tres" id="6_dgadc"]
9 |
10 | [node name="SubButton" type="Button"]
11 | custom_minimum_size = Vector2(0, 45)
12 | offset_left = 25.0
13 | offset_top = 15.0
14 | offset_right = 140.0
15 | offset_bottom = 60.0
16 | focus_mode = 0
17 | theme = ExtResource("1_pl5se")
18 | theme_override_colors/font_color = Color(0.721569, 0.721569, 0.721569, 1)
19 | theme_override_colors/font_pressed_color = Color(0.721569, 0.721569, 0.721569, 1)
20 | theme_override_colors/font_hover_color = Color(0.933333, 0.933333, 0.933333, 1)
21 | theme_override_colors/font_focus_color = Color(0.933333, 0.933333, 0.933333, 1)
22 | theme_override_colors/font_hover_pressed_color = Color(0.933333, 0.933333, 0.933333, 1)
23 | theme_override_styles/normal = ExtResource("2_gb8s2")
24 | theme_override_styles/hover = ExtResource("3_nyalc")
25 | theme_override_styles/pressed = ExtResource("4_7okq5")
26 | theme_override_styles/disabled = ExtResource("5_be4ah")
27 | toggle_mode = true
28 | button_group = ExtResource("6_dgadc")
29 | text = "Installs"
30 |
--------------------------------------------------------------------------------
/scripts/core/tabs/TabManager.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace Com.Astral.GodotHub.Core.Tabs
4 | {
5 | public partial class TabManager : Control
6 | {
7 | [ExportGroup("Tabs")]
8 | [Export] protected Tab projectsTab;
9 | [Export] protected Tab versionsTab;
10 | [Export] protected Tab documentationTab;
11 |
12 | [ExportGroup("Buttons")]
13 | [Export] protected Button projectsButton;
14 | [Export] protected Button versionsButton;
15 | [Export] protected Button documentationButton;
16 |
17 | public override void _Ready()
18 | {
19 | projectsButton.Toggled += OnProjectsToggled;
20 | versionsButton.Toggled += OnVersionsToggled;
21 | #if DEBUG
22 | documentationButton.Toggled += OnDocumentationToggled;
23 | #endif //DEBUG
24 |
25 | projectsTab.Toggle(projectsButton.ButtonPressed);
26 | versionsTab.Toggle(versionsButton.ButtonPressed);
27 | #if DEBUG
28 | documentationTab.Toggle(documentationButton.ButtonPressed);
29 | #else
30 | documentationButton.Visible = false;
31 | documentationTab.Visible = false;
32 | #endif //DEBUG
33 | }
34 |
35 | protected void OnProjectsToggled(bool pToggle)
36 | {
37 | if (projectsTab.Visible || !pToggle)
38 | return;
39 |
40 | projectsTab.Toggle(true);
41 | versionsTab.Toggle(false);
42 | #if DEBUG
43 | documentationTab.Toggle(false);
44 | #endif //DEBUG
45 | }
46 |
47 | protected void OnVersionsToggled(bool pToggle)
48 | {
49 | if (versionsTab.Visible || !pToggle)
50 | return;
51 |
52 | versionsTab.Toggle(true);
53 | projectsTab.Toggle(false);
54 | #if DEBUG
55 | documentationTab.Toggle(false);
56 | #endif //DEBUG
57 | }
58 |
59 | #if DEBUG
60 | protected void OnDocumentationToggled(bool pToggle)
61 | {
62 | if (documentationTab.Visible || !pToggle)
63 | return;
64 |
65 | documentationTab.Toggle(true);
66 | projectsTab.Toggle(false);
67 | versionsTab.Toggle(false);
68 | }
69 | #endif //DEBUG
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/scripts/core/utils/TimeFormater.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Com.Astral.GodotHub.Core.Utils
4 | {
5 | public static class TimeFormater
6 | {
7 | private const string YEAR = "year";
8 | private const string MONTH = "month";
9 | private const string DAY = "day";
10 | private const string HOUR = "hour";
11 | private const string MINUTE = "minute";
12 | private const string SECOND = "second";
13 | private const string NOW = "Now";
14 |
15 | public static string Format(DateTime pTime)
16 | {
17 | DateTime lCurrentTime = DateTime.UtcNow;
18 | TimeSpan lDifferenceSpan = lCurrentTime - pTime;
19 |
20 | // Basic comparisons
21 | if (lDifferenceSpan.TotalSeconds < 1d)
22 | {
23 | return NOW;
24 | }
25 |
26 | if (lDifferenceSpan.TotalMinutes < 1d)
27 | {
28 | return FormatInternal((int)Math.Floor(lDifferenceSpan.TotalSeconds), SECOND);
29 | }
30 |
31 | if (lDifferenceSpan.TotalHours < 1d)
32 | {
33 | return FormatInternal((int)Math.Floor(lDifferenceSpan.TotalMinutes), MINUTE);
34 | }
35 |
36 | if (lDifferenceSpan.TotalDays < 1d)
37 | {
38 | return FormatInternal((int)Math.Floor(lDifferenceSpan.TotalHours), HOUR);
39 | }
40 |
41 | // Comparisons that need more information on the date of the year
42 | int lYearDiff = (int)Math.Floor(lDifferenceSpan.TotalDays / 365.2425);
43 |
44 | if (lYearDiff > 0)
45 | {
46 | return FormatInternal(lYearDiff, YEAR);
47 | }
48 |
49 | if (lCurrentTime.Month == pTime.Month)
50 | {
51 | return FormatInternal((int)Math.Floor(lDifferenceSpan.TotalDays), DAY);
52 | }
53 |
54 | int lMonthDiff = lCurrentTime.Month - pTime.Month;
55 |
56 | if (lMonthDiff < 0)
57 | {
58 | lMonthDiff += 12;
59 | }
60 |
61 | if (lMonthDiff == 1 && lCurrentTime.Day < pTime.Day)
62 | {
63 | return FormatInternal((int)Math.Floor(lDifferenceSpan.TotalDays), DAY);
64 | }
65 |
66 | return FormatInternal(lMonthDiff, MONTH);
67 | }
68 |
69 | private static string FormatInternal(int pValue, string pSuffix)
70 | {
71 | // Will need refactoring if localisation is added
72 | return $"{pValue} {pSuffix}{(pValue > 1 ? "s" : "")} ago";
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/GodotHubUpdater.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 | Com.Astral.GodotHub.Updater
9 | bin\GodotHubUpdater\
10 | obj\GodotHubUpdater\
11 | Com.Astral.GodotHub.Updater.UpdateProgram
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/GodotUninstaller.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net6.0
6 | enable
7 | enable
8 | Com.Astral.GodotHub.Uninstaller.UninstallProgram
9 | Com.Astral.GodotHub.Uninstaller
10 | godot_uninstaller.manifest
11 | bin\GodotUninstaller
12 | obj\GodotUninstaller
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/scripts/core/utils/comparisons/Comparer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Com.Astral.GodotHub.Core.Utils.Comparisons
4 | {
5 | public static class Comparer
6 | {
7 | public static int CompareFavorites(T pLhs, T pRhs) where T : IFavoriteItem, IValidItem
8 | {
9 | return CompareItems(pLhs, pRhs, (lhs, rhs) => rhs.IsFavorite.CompareTo(lhs.IsFavorite));
10 | }
11 |
12 | public static int CompareMonos(T pLhs, T pRhs) where T : IMonoItem, IValidItem
13 | {
14 | return CompareItems(pLhs, pRhs, (lhs, rhs) => rhs.IsMono.CompareTo(lhs.IsMono));
15 | }
16 |
17 | public static int CompareNames(T pLhs, T pRhs) where T : INamedItem, IValidItem
18 | {
19 | return CompareItems(pLhs, pRhs, (lhs, rhs) => lhs.ItemName.CompareTo(rhs.ItemName));
20 | }
21 |
22 | public static int CompareTimes(T pLhs, T pRhs) where T : ITimedItem, IValidItem
23 | {
24 | return CompareItems(pLhs, pRhs, (lhs, rhs) => lhs.TimeSinceLastOpening.CompareTo(rhs.TimeSinceLastOpening));
25 | }
26 |
27 | public static int CompareVersions(T pLhs, T pRhs) where T : IVersionItem, IValidItem
28 | {
29 | return CompareItems(pLhs, pRhs, (lhs, rhs) => rhs.Version.CompareTo(lhs.Version));
30 | }
31 |
32 | public static int ReversedCompareFavorites(T pLhs, T pRhs) where T : IFavoriteItem, IValidItem
33 | {
34 | return CompareFavorites(pRhs, pLhs);
35 | }
36 |
37 | public static int ReversedCompareMonos(T pLhs, T pRhs) where T : IMonoItem, IValidItem
38 | {
39 | return CompareMonos(pRhs, pLhs);
40 | }
41 |
42 | public static int ReversedCompareNames(T pLhs, T pRhs) where T : INamedItem, IValidItem
43 | {
44 | return CompareNames(pRhs, pLhs);
45 | }
46 |
47 | public static int ReversedCompareTimes(T pLhs, T pRhs) where T : ITimedItem, IValidItem
48 | {
49 | return CompareTimes(pRhs, pLhs);
50 | }
51 |
52 | public static int ReversedCompareVersions(T pLhs, T pRhs) where T : IVersionItem, IValidItem
53 | {
54 | return CompareVersions(pRhs, pLhs);
55 | }
56 |
57 | private static int CompareItems(T pLhs, T pRhs, Func pComparison) where T : IValidItem
58 | {
59 | if (pLhs.IsValid ^ pRhs.IsValid)
60 | {
61 | return pLhs.IsValid ? -1 : 1;
62 | }
63 |
64 | return pComparison(pLhs, pRhs);
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/scripts/core/debug/ExceptionHandler.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using System;
3 |
4 | using Colors = Com.Astral.GodotHub.Core.Utils.Colors;
5 |
6 | namespace Com.Astral.GodotHub.Core.Debug
7 | {
8 | public partial class ExceptionHandler : Node
9 | {
10 | public enum ExceptionGravity
11 | {
12 | Message,
13 | Warning,
14 | Error,
15 | }
16 |
17 | public static ExceptionHandler Singleton { get; private set; }
18 |
19 | [Export] protected PackedScene popupScene;
20 | [ExportGroup("Colors")]
21 | [Export] protected Color warningColor = new Color(1f, 1f, 0f);
22 | [Export] protected Color errorColor = new Color(1f, 0f, 0f);
23 |
24 | public override void _EnterTree()
25 | {
26 | Singleton = this;
27 | }
28 |
29 | public override void _ExitTree()
30 | {
31 | Singleton = null;
32 | }
33 |
34 | public void LogException(Exception pException, bool pLogOnConsole = true)
35 | {
36 | if (pLogOnConsole)
37 | {
38 | Debugger.LogException(pException);
39 | }
40 |
41 | LogMessage(pException.Message, pException.GetType().ToString(), ExceptionGravity.Error);
42 | }
43 |
44 | public void LogMessage(string pMessage, string pTitle = null, ExceptionGravity pGravity = ExceptionGravity.Message)
45 | {
46 | Color? lColor = pGravity switch {
47 | ExceptionGravity.Error => errorColor,
48 | ExceptionGravity.Warning => warningColor,
49 | _ => null
50 | };
51 |
52 | CreatePopup(pMessage, pTitle ?? pGravity.ToString(), lColor);
53 | }
54 |
55 | private void CreatePopup(string pMessage, string pTitle, Color? pColor = null)
56 | {
57 | AcceptDialog lPopup = popupScene.Instantiate();
58 | AddChild(lPopup);
59 |
60 | if (pColor != null)
61 | {
62 | StyleBoxFlat lStyleBox = lPopup.GetThemeStylebox("panel").Duplicate() as StyleBoxFlat;
63 | lStyleBox.BorderColor = (Color)pColor;
64 | lPopup.AddThemeStyleboxOverride("panel", lStyleBox);
65 | lStyleBox = lPopup.GetThemeStylebox("embedded_border").Duplicate() as StyleBoxFlat;
66 | lStyleBox.BgColor = (Color)pColor;
67 | lPopup.AddThemeStyleboxOverride("embedded_border", lStyleBox);
68 | }
69 |
70 | lPopup.GetOkButton().FocusMode = Control.FocusModeEnum.None;
71 | lPopup.PopupCentered();
72 | lPopup.Title = pTitle;
73 | lPopup.DialogText = pMessage;
74 | lPopup.CloseRequested += () => lPopup.QueueFree();
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/GodotInstaller.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net6.0
6 | enable
7 | enable
8 | Com.Astral.GodotHub.Installer.InstallProgram
9 | godot_installer.manifest
10 | Com.Astral.GodotHub.Installer
11 | True
12 | False
13 | bin\GodotInstaller
14 | obj\GodotInstaller
15 |
16 |
17 |
18 | 1701;1702;IDE0090;IDE0063
19 | bin\Debug\
20 |
21 |
22 |
23 | 1701;1702;IDE0090;IDE0063
24 | bin\Release\
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/scripts/core/data/Source.cs:
--------------------------------------------------------------------------------
1 | using Octokit;
2 |
3 | namespace Com.Astral.GodotHub.Core.Data
4 | {
5 | ///
6 | /// Struct representing a with additional data
7 | ///
8 | public class Source
9 | {
10 | ///
11 | /// Specific asset from a github release
12 | ///
13 | public ReleaseAsset asset;
14 | ///
15 | /// of the release
16 | ///
17 | public Version version;
18 | ///
19 | /// Whether or not it has C# support
20 | ///
21 | public bool mono;
22 | ///
23 | /// Target of the release
24 | ///
25 | public OS os;
26 | ///
27 | /// Target of the release
28 | ///
29 | public Architecture? architecture;
30 |
31 | public Source() { }
32 |
33 | public Source(ReleaseAsset pAsset, Version pVersion, bool pMono, OS pOS, Architecture? pArchitecture = null)
34 | {
35 | asset = pAsset;
36 | version = pVersion;
37 | mono = pMono;
38 | os = pOS;
39 | architecture = pArchitecture;
40 | }
41 |
42 | ///
43 | /// Return the of the release
44 | ///
45 | public static Version GetVersion(Release pRelease)
46 | {
47 | return (Version)pRelease.TagName;
48 | }
49 |
50 | ///
51 | /// Whether or not the has C# support
52 | ///
53 | public static bool IsMono(ReleaseAsset pAsset)
54 | {
55 | return pAsset.Name.Contains("mono");
56 | }
57 |
58 | ///
59 | /// Return the target of the
60 | ///
61 | public static OS GetOS(ReleaseAsset pAsset)
62 | {
63 | if (pAsset.Name.Contains("win"))
64 | {
65 | return OS.Windows;
66 | }
67 | else if (pAsset.Name.Contains("linux"))
68 | {
69 | return OS.Linux;
70 | }
71 | else
72 | {
73 | return OS.MacOS;
74 | }
75 | }
76 |
77 | ///
78 | /// Return the target of the
79 | ///
80 | public static Architecture GetArchitecture(ReleaseAsset pAsset)
81 | {
82 | if (pAsset.Name.Contains("64"))
83 | {
84 | return Architecture.x64;
85 | }
86 | else
87 | {
88 | return Architecture.x32;
89 | }
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/scripts/updater/UpdateProgram.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Updater
2 | {
3 | internal static class UpdateProgram
4 | {
5 | private static readonly string Appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).Replace('\\', '/') + "/Godot Hub";
6 |
7 | private static readonly string NewProjectsPath = Appdata + "/projects.cfg";
8 | private static readonly string NewEnginesPath = Appdata + "/engines.cfg";
9 |
10 | private static readonly string[] OldProjectsPaths = new string[] {
11 | Appdata + "/project.cfg",
12 | };
13 | private static readonly string[] OldEnginesPaths = new string[] {
14 | Appdata + "/installs.cfg",
15 | };
16 |
17 | public static void Main(string[] pArgs)
18 | {
19 | bool lAutoDeleteSource = pArgs.Length > 0 && (pArgs[0].ToLower() == "-d" || pArgs[0].ToLower() == "--delete");
20 |
21 | if (UpdatePath(OldProjectsPaths, NewProjectsPath, lAutoDeleteSource))
22 | {
23 | Console.WriteLine("Projects data updated.");
24 | }
25 | else
26 | {
27 | Console.WriteLine("Projects data can't be updated.");
28 | }
29 |
30 | if (UpdatePath(OldEnginesPaths, NewEnginesPath, lAutoDeleteSource))
31 | {
32 | Console.WriteLine("Engines data updated.");
33 | }
34 | else
35 | {
36 | Console.WriteLine("Engines data can't be updated.");
37 | }
38 |
39 | Console.WriteLine("\nPress any key to close the window");
40 | Console.ReadKey();
41 | }
42 |
43 | private static bool UpdatePath(string[] pOldPaths, string pNewPath, bool pDeleteSource = false)
44 | {
45 | for (int i = 0; i < pOldPaths.Length; i++)
46 | {
47 | if (CopyFile(pOldPaths[i], pNewPath, pDeleteSource))
48 | return true;
49 | }
50 |
51 | return false;
52 | }
53 |
54 | private static bool CopyFile(string pSource, string pDestination, bool pDeleteSource)
55 | {
56 | if (!File.Exists(pSource))
57 | return false;
58 |
59 | try
60 | {
61 | using (
62 | FileStream lSourceFStream = new FileStream(pSource, FileMode.Open),
63 | lDestFStream = new FileStream(pDestination, FileMode.OpenOrCreate)
64 | )
65 | {
66 | lSourceFStream.CopyTo(lDestFStream);
67 | lDestFStream.Close();
68 | lSourceFStream.Close();
69 | }
70 | }
71 | catch (Exception lException)
72 | {
73 | Console.WriteLine(lException);
74 | return false;
75 | }
76 |
77 | if (pDeleteSource)
78 | {
79 | File.Delete(pSource);
80 | }
81 |
82 | return true;
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/scripts/installer/InstallProgram.cs:
--------------------------------------------------------------------------------
1 | namespace Com.Astral.GodotHub.Installer
2 | {
3 | internal class InstallProgram
4 | {
5 | //arg[0] = --mode (--write_zip | --unzip)
6 | public static void Main(string[] pArgs)
7 | {
8 | using (Mutex lMutex = Mutex.OpenExisting(InstallerConstants.MUTEX_NAME))
9 | {
10 | if (pArgs.Length == 0)
11 | {
12 | Console.WriteLine("No argument given");
13 | Console.ReadKey();
14 | throw new ArgumentException("No argument given");
15 | }
16 |
17 | switch (pArgs[0])
18 | {
19 | case InstallerConstants.WRITE_ARGUMENT:
20 | goto WRITE;
21 | case InstallerConstants.EXTRACT_ARGUMENT:
22 | goto EXTRACT;
23 | default:
24 | throw new ArgumentException($"Invalid mode given: {pArgs[0]}");
25 | }
26 |
27 | #region WRITE
28 |
29 | WRITE:
30 | lMutex.WaitOne();
31 |
32 | try
33 | {
34 | AdminInstaller.WriteZip();
35 | }
36 | catch (Exception e)
37 | {
38 | Console.WriteLine($"Writing exception:\n{e}");
39 | Console.ReadKey();
40 | lMutex.ReleaseMutex();
41 | throw;
42 | }
43 |
44 | lMutex.ReleaseMutex();
45 |
46 | #endregion //WRITE
47 |
48 | #region EXTRACT
49 |
50 | EXTRACT:
51 | lMutex.WaitOne();
52 |
53 | switch (AdminInstaller.Jump())
54 | {
55 | case (byte)JumpInstruction.Delete:
56 | goto DELETE;
57 | case (byte)JumpInstruction.Cancel:
58 | AdminInstaller.CancelInstall(true, false);
59 | goto END;
60 | default:
61 | break;
62 | }
63 |
64 | try
65 | {
66 | AdminInstaller.Extract();
67 | }
68 | catch (Exception e)
69 | {
70 | Console.WriteLine($"Extraction exception:\n{e}");
71 | Console.ReadKey();
72 | lMutex.ReleaseMutex();
73 | throw;
74 | }
75 |
76 | lMutex.ReleaseMutex();
77 |
78 | #endregion //EXTRACT
79 |
80 | #region DELETE
81 |
82 | lMutex.WaitOne();
83 |
84 | if (AdminInstaller.Jump() == (byte)JumpInstruction.Cancel)
85 | {
86 | AdminInstaller.CancelInstall(true, true);
87 | goto END;
88 | }
89 |
90 | DELETE:
91 | try
92 | {
93 | AdminInstaller.DeleteZip();
94 | }
95 | catch (Exception e)
96 | {
97 | Console.WriteLine($"Deletion exception:\n{e}");
98 | Console.ReadKey();
99 | lMutex.ReleaseMutex();
100 | throw;
101 | }
102 |
103 | #endregion //DELETE
104 |
105 | END:
106 | lMutex.ReleaseMutex();
107 | }
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/scenes/versions/installer.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=5 format=3 uid="uid://3ek1c5uks77u"]
2 |
3 | [ext_resource type="Theme" uid="uid://ce3m7fxsw8f6t" path="res://resources/themes/main.theme" id="1_6dfu7"]
4 | [ext_resource type="Script" path="res://scripts/core/tabs/versions/Installer.cs" id="1_ke4qi"]
5 | [ext_resource type="Theme" uid="uid://c2cgnbja48m7i" path="res://resources/themes/close_btn.theme" id="3_gl0mp"]
6 |
7 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_i8jxo"]
8 | bg_color = Color(0.117647, 0.117647, 0.117647, 1)
9 |
10 | [node name="Installer" type="Panel" node_paths=PackedStringArray("versionLabel", "statusLabel", "loadingBar", "cancelButton")]
11 | clip_contents = true
12 | custom_minimum_size = Vector2(0, 100)
13 | offset_right = 320.0
14 | offset_bottom = 100.0
15 | theme = ExtResource("1_6dfu7")
16 | theme_override_styles/panel = SubResource("StyleBoxFlat_i8jxo")
17 | script = ExtResource("1_ke4qi")
18 | closeDuration = 0.2
19 | versionLabel = NodePath("VersionLabel")
20 | statusLabel = NodePath("StatusLabel")
21 | loadingBar = NodePath("ProgressBar")
22 | cancelButton = NodePath("CancelButton")
23 |
24 | [node name="VersionLabel" type="Label" parent="."]
25 | layout_mode = 1
26 | anchors_preset = -1
27 | anchor_right = 1.0
28 | offset_left = 10.0
29 | offset_top = 5.0
30 | offset_right = -10.0
31 | grow_horizontal = 2
32 | theme_override_colors/font_color = Color(0.588235, 0.588235, 0.588235, 1)
33 | theme_override_font_sizes/font_size = 14
34 | text = "Godot 4.0.4 Mono Windows x64"
35 | horizontal_alignment = 1
36 | vertical_alignment = 1
37 |
38 | [node name="StatusLabel" type="Label" parent="."]
39 | layout_mode = 1
40 | anchors_preset = -1
41 | anchor_top = 0.5
42 | anchor_right = 1.0
43 | anchor_bottom = 0.5
44 | offset_left = 25.0
45 | offset_top = -10.0
46 | offset_right = -25.0
47 | offset_bottom = 20.0
48 | grow_horizontal = 2
49 | grow_vertical = 2
50 | text = "Downloading"
51 | horizontal_alignment = 1
52 | vertical_alignment = 1
53 |
54 | [node name="ProgressBar" type="ProgressBar" parent="."]
55 | layout_mode = 1
56 | anchors_preset = -1
57 | anchor_top = 1.0
58 | anchor_right = 1.0
59 | anchor_bottom = 1.0
60 | offset_left = 20.0
61 | offset_top = -15.0
62 | offset_right = -20.0
63 | offset_bottom = -11.0
64 | grow_horizontal = 2
65 | grow_vertical = 0
66 |
67 | [node name="CancelButton" type="Button" parent="."]
68 | custom_minimum_size = Vector2(15, 15)
69 | layout_mode = 1
70 | anchors_preset = -1
71 | anchor_left = 1.0
72 | anchor_right = 1.0
73 | offset_left = -25.0
74 | offset_top = 7.5
75 | offset_right = -10.0
76 | offset_bottom = 22.5
77 | grow_horizontal = 0
78 | focus_mode = 0
79 | theme = ExtResource("3_gl0mp")
80 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6 |
7 | ## [Unreleased]
8 |
9 | ### Added
10 | - GodotHub updater to update config files
11 | - Option to delete old data when updating data to new version with GodotHubUpdater
12 |
13 | ### Changed
14 | - Release item text alignement
15 | - Rename installs as versions and install items as engine items
16 | - Rename config files
17 |
18 | ### Fixed
19 | - Application version not shown on build
20 | - Bad C# solution initialization on mono project creation
21 |
22 | ### Removed
23 |
24 |
25 | ## [0.1.3] - 2024-02-08
26 |
27 | ### Added
28 | - Tooltip on project path and version path
29 | - Process elevation for engine installation and deletion on windows
30 | - "Update Repo" button to check for new releases without restarting the application
31 | - Icon creation when creating a new project
32 | - Changelog
33 |
34 | ### Changed
35 | - Tab buttons always have the same space between them
36 |
37 | ### Fixed
38 | - Focus on "Add" button in installs tab removed
39 | - Install items auto sort when adding a new item
40 | - Check installs config file when checking if an engine is installed
41 | - Date going crazy after new year
42 |
43 | ## [0.1.2] - 2023-11-05
44 |
45 | ### Added
46 | - Error popups
47 |
48 | ### Changed
49 | - Use only alpha for splash screen animation
50 |
51 | ### Fixed
52 | - Repository first initialization
53 |
54 | ## [0.1.1] - 2023-09-24
55 |
56 | ### Added
57 | - Install item instantiation only if the downloaded engine is put in the config file
58 | - Project creation for supported versions
59 |
60 | ### Changed
61 | - Increased sorting button size in installs tab
62 |
63 | ### Fixed
64 | - Project items auto sort when adding a new item
65 | - Syntax error in linux and macos builds
66 |
67 | ## [0.1] - 2023-09-18
68 |
69 | ### Added
70 | - Releases download from Github
71 | - Projects tab
72 | - Installs tab
73 | - Releases tab
74 | - Settings panel
75 | - Config files
76 | * Store settings, projects and engine versions
77 | - Release item
78 | * Release configuration before download
79 | * OS selection
80 | * Architecture selection
81 | * C# support selection
82 | * Check for installed versions
83 | - Items sorting
84 | - Download status
85 | - Releases storage on disk
86 | - Project item
87 | * Project opening
88 | * Project deletion (only in config file)
89 | * Engine version selection
90 | * Favorite tag
91 | * Project item sorting
92 | - Project addition in project tab ("Add" button in project tab)
93 | - Check for project in default folder
94 | - Support for releases greater or equal to 3.1.1
95 | - UI theme
96 | - License
97 | - Readme
98 |
99 | [unreleased]: https://github.com/Astral-Sheep/GodotHub/compare/0.1.3...HEAD
100 | [0.1.3]: https://github.com/Astral-Sheep/GodotHub/compare/0.1.2...0.1.3
101 | [0.1.2]: https://github.com/Astral-Sheep/GodotHub/compare/0.1.1...0.1.2
102 | [0.1.1]: https://github.com/Astral-Sheep/GodotHub/compare/0.1...0.1.1
103 | [0.1]: https://github.com/Astral-Sheep/GodotHub/releases/tag/0.1
104 |
--------------------------------------------------------------------------------
/scripts/installer/AdminInstaller.cs:
--------------------------------------------------------------------------------
1 | using System.IO.Compression;
2 | using System.IO.MemoryMappedFiles;
3 | using System.Text;
4 |
5 | namespace Com.Astral.GodotHub.Installer
6 | {
7 | internal static class AdminInstaller
8 | {
9 | internal static void WriteZip()
10 | {
11 | byte[] lContent;
12 |
13 | using (MemoryMappedFile lMMFile = MemoryMappedFile.OpenExisting(InstallerConstants.DOWNLOAD_MAP_NAME))
14 | {
15 | using (MemoryMappedViewStream lMMVStream = lMMFile.CreateViewStream())
16 | {
17 | lContent = new byte[lMMVStream.Length];
18 | lMMVStream.Read(lContent, 0, lContent.Length);
19 | lMMVStream.Close();
20 | }
21 | }
22 |
23 | using (FileStream lFStream = new FileStream(GetZipPath(), FileMode.Create))
24 | {
25 | lFStream.Write(lContent, 0, lContent.Length);
26 | lFStream.Close();
27 | }
28 | }
29 |
30 | internal static void Extract()
31 | {
32 | ZipFile.ExtractToDirectory(
33 | GetZipPath(),
34 | GetExtractPath()
35 | );
36 | }
37 |
38 | internal static void DeleteZip()
39 | {
40 | File.Delete(GetZipPath());
41 | }
42 |
43 | internal static void CancelInstall(bool pDeleteZip, bool pDeleteExecutable)
44 | {
45 | if (pDeleteZip)
46 | {
47 | string lZip = GetZipPath();
48 |
49 | if (File.Exists(lZip))
50 | {
51 | File.Delete(lZip);
52 | }
53 | }
54 |
55 | if (pDeleteExecutable)
56 | {
57 | string lExecutable = GetExtractPath();
58 |
59 | if (File.Exists(lExecutable))
60 | {
61 | File.Delete(lExecutable);
62 | }
63 | else if (Directory.Exists(lExecutable))
64 | {
65 | Directory.Delete(lExecutable);
66 | }
67 | }
68 | }
69 |
70 | internal static byte Jump()
71 | {
72 | using (MemoryMappedFile lMMFile = MemoryMappedFile.OpenExisting(InstallerConstants.JUMP_MAP_NAME))
73 | {
74 | using (MemoryMappedViewStream lMMVStream = lMMFile.CreateViewStream())
75 | {
76 | byte[] lBytes = new byte[1];
77 | lMMVStream.Read(lBytes, 0, 1);
78 | return lBytes[0];
79 | }
80 | }
81 | }
82 |
83 | private static string GetZipPath()
84 | {
85 | return GetStringFromMap(InstallerConstants.ZIP_MAP_NAME);
86 | }
87 |
88 | private static string GetExtractPath()
89 | {
90 | return GetStringFromMap(InstallerConstants.EXTRACT_MAP_NAME);
91 | }
92 |
93 | private static string GetStringFromMap(string pMapName)
94 | {
95 | using (MemoryMappedFile lMMFile = MemoryMappedFile.OpenExisting(pMapName))
96 | {
97 | using (MemoryMappedViewStream lMMVStream = lMMFile.CreateViewStream())
98 | {
99 | byte[] lStringBytes = new byte[lMMVStream.Length];
100 | lMMVStream.Read(lStringBytes, 0, lStringBytes.Length);
101 | lMMVStream.Close();
102 | string lString = Encoding.UTF8.GetString(lStringBytes);
103 |
104 | // Since the stream has a static size, the string can be shorter than the allocated space.
105 | // The remaining bytes are set to 0, and we don't want to recover that part,
106 | // thus the lString[..lString.IndexOf('\0')]
107 | return lString[..lString.IndexOf('\0')];
108 | }
109 | }
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/scenes/versions/release_item.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=5 format=3 uid="uid://c75ty2plb2sys"]
2 |
3 | [ext_resource type="Theme" uid="uid://ce3m7fxsw8f6t" path="res://resources/themes/main.theme" id="1_0r2wn"]
4 | [ext_resource type="Script" path="res://scripts/core/tabs/versions/ReleaseItem.cs" id="1_ukbs0"]
5 | [ext_resource type="Theme" uid="uid://m20yduadk25m" path="res://resources/themes/half_blue_btn.theme" id="3_78hul"]
6 |
7 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_d0sgs"]
8 | bg_color = Color(0.117647, 0.117647, 0.117647, 1)
9 |
10 | [node name="ReleaseItem" type="Panel" node_paths=PackedStringArray("versionLabel", "dateLabel", "monoCheck", "osButton", "architectureButton", "installButton")]
11 | clip_contents = true
12 | custom_minimum_size = Vector2(0, 75)
13 | offset_right = 850.0
14 | offset_bottom = 75.0
15 | theme = ExtResource("1_0r2wn")
16 | theme_override_styles/panel = SubResource("StyleBoxFlat_d0sgs")
17 | script = ExtResource("1_ukbs0")
18 | versionLabel = NodePath("Version")
19 | dateLabel = NodePath("Date")
20 | monoCheck = NodePath("MonoCheck")
21 | osButton = NodePath("OSOption")
22 | architectureButton = NodePath("ArchitectureOption")
23 | installButton = NodePath("InstallButton")
24 |
25 | [node name="Version" type="RichTextLabel" parent="."]
26 | layout_mode = 1
27 | anchors_preset = -1
28 | anchor_right = 0.2
29 | anchor_bottom = 1.0
30 | offset_left = 25.0
31 | offset_top = 15.0
32 | offset_bottom = -35.0
33 | grow_horizontal = 2
34 | grow_vertical = 2
35 | bbcode_enabled = true
36 | text = "[b]Godot 1.0.0[/b]"
37 |
38 | [node name="Date" type="Label" parent="."]
39 | layout_mode = 1
40 | anchors_preset = -1
41 | anchor_top = 1.0
42 | anchor_right = 0.2
43 | anchor_bottom = 1.0
44 | offset_left = 25.0
45 | offset_top = -35.0
46 | offset_bottom = -20.0
47 | grow_vertical = 0
48 | theme_override_colors/font_color = Color(0.588235, 0.588235, 0.588235, 1)
49 | theme_override_font_sizes/font_size = 10
50 | text = "jj/mm/yyyy"
51 | vertical_alignment = 1
52 |
53 | [node name="MonoCheck" type="CheckBox" parent="."]
54 | layout_mode = 1
55 | anchors_preset = -1
56 | anchor_left = 0.25
57 | anchor_right = 0.25
58 | anchor_bottom = 1.0
59 | offset_top = 10.0
60 | offset_bottom = -10.0
61 | focus_mode = 0
62 | button_pressed = true
63 | text = "Mono"
64 |
65 | [node name="OSOption" type="OptionButton" parent="."]
66 | layout_mode = 1
67 | anchors_preset = -1
68 | anchor_left = 0.4
69 | anchor_right = 0.55
70 | anchor_bottom = 1.0
71 | offset_top = 10.0
72 | offset_bottom = -10.0
73 | focus_mode = 0
74 | text_overrun_behavior = 3
75 |
76 | [node name="ArchitectureOption" type="OptionButton" parent="."]
77 | layout_mode = 1
78 | anchors_preset = -1
79 | anchor_left = 0.6
80 | anchor_right = 0.7
81 | anchor_bottom = 1.0
82 | offset_top = 10.0
83 | offset_bottom = -10.0
84 | focus_mode = 0
85 | text_overrun_behavior = 3
86 |
87 | [node name="InstallButton" type="Button" parent="."]
88 | layout_mode = 1
89 | anchors_preset = -1
90 | anchor_left = 1.0
91 | anchor_right = 1.0
92 | anchor_bottom = 1.0
93 | offset_top = 15.0
94 | offset_right = -25.0
95 | offset_bottom = -15.0
96 | grow_horizontal = 0
97 | focus_mode = 0
98 | theme = ExtResource("3_78hul")
99 | text = "Install"
100 |
--------------------------------------------------------------------------------
/scripts/core/debug/Debugger.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 | using Godot;
3 | using System;
4 | using Com.Astral.GodotHub.Core.Utils;
5 | using Colors = Com.Astral.GodotHub.Core.Utils.Colors;
6 |
7 | namespace Com.Astral.GodotHub.Core.Debug
8 | {
9 | ///
10 | /// In-app console
11 | ///
12 | public sealed partial class Debugger : Control
13 | {
14 | ///
15 | /// Whether or not the console is visible
16 | ///
17 | public static bool Enabled
18 | {
19 | get => instance.Visible;
20 | set
21 | {
22 | if (instance.Visible == value)
23 | return;
24 |
25 | instance.Visible = value;
26 | }
27 | }
28 |
29 | private static Debugger instance;
30 |
31 | [ExportGroup("Parameters")]
32 | [Export] private RichTextLabel label;
33 |
34 | private Debugger() : base()
35 | {
36 | if (instance != null)
37 | {
38 | GD.PushWarning($"{nameof(Debugger)} instance already exists, destroying the last added.");
39 | Free();
40 | return;
41 | }
42 |
43 | instance = this;
44 | }
45 |
46 | public override void _Ready()
47 | {
48 | if (!label.BbcodeEnabled)
49 | {
50 | label.BbcodeEnabled = true;
51 | }
52 |
53 | Enabled = AppConfig.Debug;
54 | }
55 |
56 | protected override void Dispose(bool pDisposing)
57 | {
58 | if (!pDisposing)
59 | return;
60 |
61 | if (instance == this)
62 | {
63 | instance = null;
64 | }
65 | }
66 |
67 | ///
68 | /// Print an in
69 | ///
70 | public static void LogObject(object pObject)
71 | {
72 | LogMessage(pObject.ToString());
73 | }
74 |
75 | ///
76 | /// Print a message in
77 | ///
78 | public static void LogMessage(string pMessage)
79 | {
80 | instance.label.Text += FormatMessage(pMessage, Colors.Singleton.White);
81 | }
82 |
83 | ///
84 | /// Print a message in
85 | ///
86 | public static void LogValidation(string pMessage)
87 | {
88 | instance.label.Text += FormatMessage(pMessage, Colors.Singleton.Green);
89 | }
90 |
91 | ///
92 | /// Print a message in
93 | ///
94 | public static void LogWarning(string pMessage)
95 | {
96 | instance.label.Text += FormatMessage(pMessage, Colors.Singleton.Yellow);
97 | }
98 |
99 | ///
100 | /// Print a message in bold
101 | ///
102 | public static void LogError(string pMessage)
103 | {
104 | instance.label.Text += FormatMessage($"[b]{pMessage}[/b]", Colors.Singleton.Red);
105 | }
106 |
107 | ///
108 | /// Print an in bold
109 | ///
110 | public static void LogException(Exception pException)
111 | {
112 | LogError($"{pException.GetType()}: {pException.Message}");
113 | #if DEBUG
114 | GD.PrintErr(pException);
115 | #endif //DEBUG
116 | }
117 |
118 | private static string FormatMessage(string pMessage, Color pColor)
119 | {
120 | return BBCodeT.GetColoredText(pMessage, pColor) + '\n';
121 | }
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/scripts/core/Main.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 | using Com.Astral.GodotHub.Core.Debug;
3 | using Godot;
4 | using System;
5 |
6 | using Error = Com.Astral.GodotHub.Core.Utils.Error;
7 | using GError = Godot.Error;
8 |
9 | namespace Com.Astral.GodotHub.Core
10 | {
11 | public partial class Main : Node
12 | {
13 | private const string CURRENT_VERSION = "0.1.4";
14 | private static readonly Vector2I DefaultWindowSize = new Vector2I(1100, 600);
15 |
16 | public static Main Instance { get; private set; }
17 |
18 | public event Action Initialized;
19 |
20 | [Export] protected PackedScene fileDialogScene;
21 |
22 | private Main() : base()
23 | {
24 | if (Instance != null)
25 | {
26 | GD.PushWarning($"{nameof(Main)} instance already exists, destroying the last added");
27 | Free();
28 | return;
29 | }
30 |
31 | Instance = this;
32 | }
33 |
34 | public override void _EnterTree()
35 | {
36 | DisplayServer.WindowSetMinSize(DefaultWindowSize);
37 |
38 | // ConfigFile lExportPresets = new ConfigFile();
39 | // lExportPresets.Load("res://export_presets.cfg");
40 | // string lAppVersion = (string)lExportPresets.GetValue("preset.0.options", "application/product_version", "0.0.0.0");
41 | // lAppVersion = lAppVersion[..lAppVersion.RFind(".")];
42 |
43 | DisplayServer.WindowSetTitle(
44 | $"{ProjectSettings.GetSetting("application/config/name", "Godot Hub")}" +
45 | " " +
46 | $"{GetProductVersion()}"
47 | );
48 | }
49 |
50 | public override void _Ready()
51 | {
52 | Init();
53 | }
54 |
55 | protected override void Dispose(bool pDisposing)
56 | {
57 | if (!pDisposing)
58 | return;
59 |
60 | if (Instance == this)
61 | {
62 | Instance = null;
63 | }
64 | }
65 |
66 | protected async void Init()
67 | {
68 | Error lError = await GDRepository.Init();
69 |
70 | if (!lError.Ok)
71 | {
72 | ExceptionHandler.Singleton.LogException(lError.Exception);
73 | }
74 |
75 | Initialized?.Invoke();
76 | }
77 |
78 | protected string GetProductVersion()
79 | {
80 | ConfigFile lExportPresets = new ConfigFile();
81 | GError lError = lExportPresets.Load("res://export_presets.cfg");
82 |
83 | if (lError != GError.Ok)
84 | {
85 | return "0.0.0";
86 | }
87 |
88 | #if GODOT_WINDOWS
89 | int lPreset = 0;
90 | #elif GODOT_LINUXBSD
91 | int lPreset = 1;
92 | #else
93 | int lPreset = 2;
94 | #endif
95 |
96 | string lVersion = (string)lExportPresets.GetValue($"preset.{lPreset}.options", "application/product_version", "0.0.0.0");
97 | return lVersion[..lVersion.RFind(".")];
98 | }
99 |
100 | public FileDialog InstantiateFileDialog(Node pParent = null, bool pAutoFree = true)
101 | {
102 | FileDialog lDialog = fileDialogScene.Instantiate();
103 |
104 | if (pParent == null)
105 | {
106 | AddChild(lDialog);
107 | }
108 | else
109 | {
110 | pParent.AddChild(lDialog);
111 | }
112 |
113 | lDialog.GetCancelButton().FocusMode = Control.FocusModeEnum.None;
114 | lDialog.GetOkButton().FocusMode = Control.FocusModeEnum.None;
115 | lDialog.PopupCentered();
116 |
117 | if (pAutoFree)
118 | {
119 | lDialog.CloseRequested += () => lDialog.QueueFree();
120 | }
121 |
122 | return lDialog;
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/scripts/core/tabs/versions/ReleasePanel.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 | using Com.Astral.GodotHub.Core.Utils.Comparisons;
3 | using Godot;
4 | using Octokit;
5 | using System;
6 | using System.Collections.Generic;
7 |
8 | using Version = Com.Astral.GodotHub.Core.Data.Version;
9 |
10 | namespace Com.Astral.GodotHub.Core.Tabs.Versions
11 | {
12 | public partial class ReleasePanel : SortedPanel
13 | {
14 | [Export] protected PackedScene releaseItemScene;
15 |
16 | [ExportGroup("Sorting")]
17 | [Export] protected SortToggle versionButton;
18 | [Export] protected SortToggle dateButton;
19 |
20 | protected List items = new List();
21 | protected Comparison currentComparison = CompareIndices;
22 |
23 | public override void _Ready()
24 | {
25 | GDRepository.Loaded += OnRepoLoaded;
26 | }
27 |
28 | protected override void Dispose(bool pDisposing)
29 | {
30 | base.Dispose(pDisposing);
31 |
32 | if (!pDisposing)
33 | return;
34 |
35 | GDRepository.Loaded -= OnRepoLoaded;
36 | GDRepository.Updated -= OnRepoUpdated;
37 | }
38 |
39 | protected void OnRepoLoaded()
40 | {
41 | GDRepository.Loaded -= OnRepoLoaded;
42 | List lReleases = GDRepository.Releases;
43 | Release lRelease;
44 |
45 | for (int i = 0; i < lReleases.Count; i++)
46 | {
47 | lRelease = lReleases[i];
48 |
49 | if ((Version)lRelease.TagName < Version.minimumSupportedVersion)
50 | continue;
51 |
52 | items.Add(CreateItem(lReleases[i], i));
53 | }
54 |
55 | Sort();
56 |
57 | versionButton.CustomToggled += OnVersionToggled;
58 | dateButton.CustomToggled += OnDateToggled;
59 | dateButton.ButtonPressed = true;
60 |
61 | GDRepository.Updated += OnRepoUpdated;
62 | }
63 |
64 | protected void OnRepoUpdated(List pReleases)
65 | {
66 | if (pReleases.Count <= 0)
67 | return;
68 |
69 | for (int i = 0; i < pReleases.Count; i++)
70 | {
71 | if ((Version)pReleases[i].TagName < Version.minimumSupportedVersion)
72 | continue;
73 |
74 | items.Add(CreateItem(pReleases[i], i));
75 | }
76 |
77 | Sort();
78 | }
79 |
80 | protected ReleaseItem CreateItem(Release pRelease, int pIndex)
81 | {
82 | ReleaseItem lItem = releaseItemScene.Instantiate();
83 | itemContainer.AddChild(lItem);
84 | lItem.Init(pRelease, pIndex);
85 | return lItem;
86 | }
87 |
88 | protected void OnVersionToggled(bool pToggled)
89 | {
90 | dateButton.Disable();
91 | currentComparison = pToggled ? Comparer.CompareVersions : Comparer.ReversedCompareVersions;
92 | Sort();
93 | }
94 |
95 | protected void OnDateToggled(bool pToggled)
96 | {
97 | versionButton.Disable();
98 | currentComparison = pToggled ? CompareIndices : ReversedCompareIndices;
99 | Sort();
100 | }
101 |
102 | protected void Sort()
103 | {
104 | items.Sort(currentComparison);
105 |
106 | for (int i = 0; i < items.Count; i++)
107 | {
108 | itemContainer.MoveChild(items[i], i);
109 | }
110 | }
111 |
112 | protected static int CompareIndices(ReleaseItem pLhs, ReleaseItem pRhs)
113 | {
114 | return pLhs.Index - pRhs.Index;
115 | }
116 |
117 | protected static int ReversedCompareIndices(ReleaseItem pLhs, ReleaseItem pRhs)
118 | {
119 | return CompareIndices(pRhs, pLhs);
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/scripts/core/settings/SettingsPanel.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 | using Com.Astral.GodotHub.Core.Settings.Buttons;
3 | using Godot;
4 | using Godot.Collections;
5 | using System.Collections.Generic;
6 |
7 | namespace Com.Astral.GodotHub.Core.Settings
8 | {
9 | public partial class SettingsPanel : Control
10 | {
11 | [Export] protected Control content;
12 | [Export] protected float openDuration = 0.2f;
13 |
14 | [ExportGroup("Buttons")]
15 | [Export] protected Button openButton;
16 | [Export] protected Button closeButton;
17 | [Export] protected Button backgroundButton;
18 | [ExportSubgroup("Settings buttons")]
19 | [Export] protected Array buttonsPath;
20 |
21 | protected List buttons;
22 | protected (float top, float bottom) anchor;
23 |
24 | public override void _Ready()
25 | {
26 | #if DEBUG
27 | Visible = true;
28 | #endif //DEBUG
29 |
30 | buttons = new List();
31 |
32 | for (int i = 0; i < buttonsPath.Count; i++)
33 | {
34 | buttons.Add(GetNode(buttonsPath[i]));
35 | }
36 |
37 | anchor = (content.AnchorTop, content.AnchorBottom);
38 | CloseInstant();
39 | openButton.Pressed += OnOpenPressed;
40 | }
41 |
42 | protected override void Dispose(bool pDisposing)
43 | {
44 | if (!pDisposing)
45 | return;
46 |
47 | if (openButton != null)
48 | {
49 | openButton.Pressed -= OnOpenPressed;
50 | }
51 | }
52 |
53 | protected void EnableButtons()
54 | {
55 | for (int i = 0; i < buttons.Count; i++)
56 | {
57 | buttons[i].Connect();
58 | }
59 | }
60 |
61 | protected void DisableButtons()
62 | {
63 | for (int i = 0; i < buttons.Count; i++)
64 | {
65 | buttons[i].Disconnect();
66 | }
67 | }
68 |
69 | protected void OnOpenPressed()
70 | {
71 | Tween lTween = CreateTween()
72 | .SetParallel()
73 | .SetTrans(Tween.TransitionType.Cubic)
74 | .SetEase(Tween.EaseType.Out);
75 | lTween.TweenProperty(content, "anchor_top", anchor.top,openDuration);
76 | lTween.TweenProperty(content, "anchor_bottom", anchor.bottom, openDuration);
77 | lTween.TweenProperty(backgroundButton, "self_modulate", new Color(backgroundButton.SelfModulate, 1f), openDuration);
78 |
79 | EnableButtons();
80 | openButton.Pressed -= OnOpenPressed;
81 | closeButton.Pressed += OnClosePressed;
82 | backgroundButton.Pressed += OnClosePressed;
83 | backgroundButton.MouseFilter = MouseFilterEnum.Stop;
84 | }
85 |
86 | protected void OnClosePressed()
87 | {
88 | AppConfig.Save();
89 |
90 | backgroundButton.MouseFilter = MouseFilterEnum.Ignore;
91 | backgroundButton.Pressed -= OnClosePressed;
92 | closeButton.Pressed -= OnClosePressed;
93 | openButton.Pressed += OnOpenPressed;
94 | DisableButtons();
95 |
96 | Tween lTween = CreateTween()
97 | .SetParallel()
98 | .SetTrans(Tween.TransitionType.Cubic)
99 | .SetEase(Tween.EaseType.In);
100 | lTween.TweenProperty(content, "anchor_top", -anchor.bottom, openDuration);
101 | lTween.TweenProperty(content, "anchor_bottom", anchor.top, openDuration);
102 | lTween.TweenProperty(backgroundButton, "self_modulate", new Color(backgroundButton.SelfModulate, 0f), openDuration);
103 | }
104 |
105 | protected void CloseInstant()
106 | {
107 | content.AnchorTop = -anchor.bottom;
108 | content.AnchorBottom = anchor.top;
109 | backgroundButton.SelfModulate = new Color(backgroundButton.SelfModulate, 0f);
110 | backgroundButton.MouseFilter = MouseFilterEnum.Ignore;
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/scripts/core/utils/PathT.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Debug;
2 | using Godot;
3 | using System;
4 | using System.IO;
5 |
6 | using Environment = System.Environment;
7 | using OS = Com.Astral.GodotHub.Core.Data.OS;
8 | using Version = Com.Astral.GodotHub.Core.Data.Version;
9 |
10 | namespace Com.Astral.GodotHub.Core.Utils
11 | {
12 | public static class PathT
13 | {
14 | #if GODOT_WINDOWS
15 | public const string EOL = "\r\n";
16 | #elif GODOT_MACOS
17 | public const string EOL = "\r";
18 | #else
19 | public const string EOL = "\n";
20 | #endif
21 |
22 | private const string MAC_EXE_PATH = "/Contents/MacOS/Godot";
23 | private const string DEFAULT_EXE_PATH = "/";
24 |
25 | ///
26 | /// The roaming appdata path
27 | ///
28 | public static readonly string appdata = GetEnvironmentPath(Environment.SpecialFolder.ApplicationData) + "/Godot Hub";
29 | private static readonly string exePath;
30 |
31 | static PathT()
32 | {
33 | if (!Directory.Exists(appdata))
34 | {
35 | Directory.CreateDirectory(appdata);
36 | }
37 |
38 | #if GODOT_MACOS
39 | exePath = MAC_EXE_PATH;
40 | #else
41 | exePath = DEFAULT_EXE_PATH;
42 | #endif
43 | }
44 |
45 | public static string FormatLinuxFolder(string pPath)
46 | {
47 | int lIndex = pPath.RFind("linux_x86");
48 |
49 | if (lIndex >= 0)
50 | {
51 | pPath = $"{pPath[..(lIndex + 5)]}.{pPath[(lIndex + 6)..]}";
52 | }
53 |
54 | return pPath;
55 | }
56 |
57 | public static string FormatMacOSFolder(string pPath, Version pVersion, bool pMono)
58 | {
59 | int lIndex = pPath.RFind($"Godot{(pMono ? "_mono" : "")}.app");
60 |
61 | if (lIndex >= 0)
62 | {
63 | string lVersion = $"_v{(string)pVersion}";
64 | pPath = pPath[..(lIndex + 5)] + lVersion + pPath[(lIndex + 5 + lVersion.Length)..];
65 | }
66 |
67 | return pPath;
68 | }
69 |
70 | public static string GetMacOSFolderFromZip(string pZip, bool pMono)
71 | {
72 | return pZip[..pZip.RFind("/")] + $"/Godot{(pMono ? "_mono" : "")}.app";
73 | }
74 |
75 | public static string GetExeFromFolder(string pPath)
76 | {
77 | #if GODOT_MACOS
78 | return pPath + exePath;
79 | #elif GODOT_LINUXBSD
80 | return pPath + pPath[pPath.RFind(exePath)..];
81 | #else
82 | return pPath + pPath[pPath.RFind(exePath)..] + ".exe";
83 | #endif
84 | }
85 |
86 | public static string GetExeFromFolder(string pPath, OS pOS)
87 | {
88 | if (pOS == OS.MacOS)
89 | {
90 | return pPath + MAC_EXE_PATH;
91 | }
92 |
93 | string lPath = pPath + pPath[pPath.RFind(DEFAULT_EXE_PATH)..];
94 |
95 | if (pOS == OS.Windows)
96 | {
97 | lPath += ".exe";
98 | }
99 |
100 | return lPath;
101 | }
102 |
103 | public static string GetFolderFromExe(string pPath)
104 | {
105 | return pPath[..pPath.RFind(exePath)];
106 | }
107 |
108 | public static string GetFolderFromExe(string pPath, OS pOS)
109 | {
110 | return pPath[..pPath.RFind(pOS == OS.MacOS ? MAC_EXE_PATH : DEFAULT_EXE_PATH)];
111 | }
112 |
113 | ///
114 | /// Rename the folder to
115 | ///
116 | public static bool RenameFolder(string pSource, string pTarget)
117 | {
118 | try
119 | {
120 | Directory.Move(pSource, pTarget);
121 | }
122 | catch (Exception lException)
123 | {
124 | Debugger.LogException(lException);
125 | return false;
126 | }
127 |
128 | return true;
129 | }
130 |
131 | ///
132 | /// Get a path with every \ replaced by a /
133 | ///
134 | public static string GetEnvironmentPath(Environment.SpecialFolder pFolder)
135 | {
136 | return Environment.GetFolderPath(pFolder).Replace('\\', '/');
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/godot_installer.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
54 |
62 |
63 |
64 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/godot_uninstaller.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
54 |
62 |
63 |
64 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/scripts/core/tabs/versions/DownloadPanel.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 | using Godot;
3 | using System.Collections.Generic;
4 |
5 | namespace Com.Astral.GodotHub.Core.Tabs.Versions
6 | {
7 | public partial class DownloadPanel : Control
8 | {
9 | [Export] protected float openDuration = 0.2f;
10 | [Export] protected Control panel;
11 | [Export] protected Button background;
12 |
13 | [ExportGroup("Installation")]
14 | [Export] protected PackedScene installerScene;
15 | [Export] protected Control installerContainer;
16 |
17 | [ExportGroup("Buttons")]
18 | [Export] protected Button openButton;
19 | [Export] protected Button closeButton;
20 |
21 | protected List installers = new List();
22 | protected Tween tween;
23 |
24 | public override void _Ready()
25 | {
26 | panel.Position = new Vector2(-panel.Size.X, panel.Position.Y);
27 | background.MouseFilter = MouseFilterEnum.Ignore;
28 | background.SelfModulate = new Color(background.SelfModulate, 0f);
29 |
30 | CreateCustomTween(Tween.EaseType.Out);
31 | ReleaseItem.InstallPressed += Install;
32 | openButton.Pressed += Open;
33 | Visible = true;
34 | }
35 |
36 | protected override void Dispose(bool pDisposing)
37 | {
38 | if (!pDisposing)
39 | return;
40 |
41 | ReleaseItem.InstallPressed -= Install;
42 | }
43 |
44 | ///
45 | /// Create a new to download and install the given
46 | ///
47 | public void Install(ReleaseItem pItem, Source pSource)
48 | {
49 | Installer lInstaller = installerScene.Instantiate();
50 | installerContainer.AddChild(lInstaller);
51 | installers.Add(lInstaller);
52 | pItem.Connect(lInstaller);
53 | lInstaller.Init(pSource);
54 | lInstaller.Completed += OnInstallerCompleted;
55 |
56 | if (installers.Count < 2)
57 | {
58 | lInstaller.Install();
59 | }
60 | }
61 |
62 | protected void OnInstallerCompleted(Installer pInstaller, InstallT.Result _)
63 | {
64 | pInstaller.Completed -= OnInstallerCompleted;
65 | installers.Remove(pInstaller);
66 |
67 | if (installers.Count > 0)
68 | {
69 | Installer lInstaller = installers[0];
70 | lInstaller.Install();
71 | }
72 | }
73 |
74 | protected void Open()
75 | {
76 | openButton.Pressed -= Open;
77 | openButton.Pressed += Close;
78 | closeButton.Pressed += Close;
79 | background.Pressed += Close;
80 |
81 | background.MouseFilter = MouseFilterEnum.Stop;
82 | ResetTween(Tween.EaseType.Out);
83 | tween.TweenProperty(background, "self_modulate:a", 1f, openDuration);
84 | tween
85 | .TweenProperty(panel, "position:x", 0, openDuration)
86 | .Finished += OnTweenFinished;
87 | tween.Play();
88 | }
89 |
90 | protected void Close()
91 | {
92 | background.Pressed -= Close;
93 | closeButton.Pressed -= Close;
94 | openButton.Pressed -= Close;
95 | openButton.Pressed += Open;
96 |
97 | background.MouseFilter = MouseFilterEnum.Ignore;
98 | ResetTween(Tween.EaseType.In);
99 | tween.TweenProperty(background, "self_modulate:a", 0f, openDuration);
100 | tween
101 | .TweenProperty(panel, "position:x", -panel.Size.X, openDuration)
102 | .Finished += OnTweenFinished;
103 | tween.Play();
104 | }
105 |
106 | protected void OnTweenFinished()
107 | {
108 | tween.Stop();
109 | }
110 |
111 | protected void ResetTween(Tween.EaseType pEase)
112 | {
113 | if (tween != null && tween.IsValid())
114 | {
115 | tween.Kill();
116 | }
117 |
118 | CreateCustomTween(pEase);
119 | }
120 |
121 | protected void CreateCustomTween(Tween.EaseType pEase)
122 | {
123 | tween = CreateTween()
124 | .SetTrans(Tween.TransitionType.Cubic)
125 | .SetEase(pEase);
126 | tween.Stop();
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/assets/default_icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/scripts/core/data/Version.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Debug;
2 | using System;
3 | using System.Text.RegularExpressions;
4 |
5 | namespace Com.Astral.GodotHub.Core.Data
6 | {
7 | ///
8 | /// Representation of a Godot version as major.minor.patch
9 | ///
10 | public struct Version : IComparable
11 | {
12 | ///
13 | /// s older than this one aren't supported by Godot Hub
14 | /// since it would be too much work for little to no use
15 | ///
16 | public static readonly Version minimumSupportedVersion = new Version(3, 1, 1);
17 | private static readonly Regex expression = new Regex(@"([0-9]+)([.]{1}?[0-9]+){1,2}");
18 |
19 | public int major;
20 | public int minor;
21 | public int patch;
22 |
23 | public Version(int pMajor, int pMinor, int pPatch)
24 | {
25 | major = pMajor;
26 | minor = pMinor;
27 | patch = pPatch;
28 | }
29 |
30 | ///
31 | /// For 4.x: whether or not each has the same and indices
32 | /// For 3.x: whether or not each has the same index
33 | ///
34 | public bool IsCompatible(Version pOther)
35 | {
36 | if (major >= 4)
37 | {
38 | return major == pOther.major && minor == pOther.minor;
39 | }
40 | else
41 | {
42 | return major == pOther.major;
43 | }
44 | }
45 |
46 | public int CompareTo(Version pOther)
47 | {
48 | if (major == pOther.major)
49 | {
50 | if (minor == pOther.minor)
51 | {
52 | return patch - pOther.patch;
53 | }
54 |
55 | return minor - pOther.minor;
56 | }
57 |
58 | return major - pOther.major;
59 | }
60 |
61 | public override bool Equals(object pObj)
62 | {
63 | if (pObj is Version version)
64 | {
65 | return this == version;
66 | }
67 |
68 | return false;
69 | }
70 |
71 | public override int GetHashCode()
72 | {
73 | return major ^ minor ^ patch;
74 | }
75 |
76 | public override string ToString()
77 | {
78 | return (string)this;
79 | }
80 |
81 | public static bool operator==(Version pLhs, Version pRhs)
82 | {
83 | return pLhs.major == pRhs.major && pLhs.minor == pRhs.minor && pLhs.patch == pRhs.patch;
84 | }
85 |
86 | public static bool operator!=(Version pLhs, Version pRhs)
87 | {
88 | return !(pLhs == pRhs);
89 | }
90 |
91 | public static bool operator <(Version pLhs, Version pRhs)
92 | {
93 | return pLhs.CompareTo(pRhs) < 0;
94 | }
95 |
96 | public static bool operator <=(Version pLhs, Version pRhs)
97 | {
98 | return pLhs.CompareTo(pRhs) <= 0;
99 | }
100 |
101 | public static bool operator >(Version pLhs, Version pRhs)
102 | {
103 | return pLhs.CompareTo(pRhs) > 0;
104 | }
105 |
106 | public static bool operator >=(Version pLhs, Version pRhs)
107 | {
108 | return pLhs.CompareTo(pRhs) >= 0;
109 | }
110 |
111 | public static explicit operator Version(string pValue)
112 | {
113 | Match lMatch = expression.Match(pValue);
114 |
115 | if (!lMatch.Success)
116 | {
117 | Debugger.LogError($"Invalid format: can't convert string \"{pValue}\" to {nameof(Version)}");
118 | return new Version(0, 0, 0);
119 | }
120 |
121 | CaptureCollection lMinorCapture = lMatch.Groups[2].Captures;
122 | return new Version(
123 | int.Parse(lMatch.Groups[1].Value),
124 | int.Parse(lMinorCapture[0].Value[1..]),
125 | lMinorCapture.Count > 1 ? int.Parse(lMinorCapture[1].Value[1..]) : 0
126 | );
127 | }
128 |
129 | public static explicit operator string(Version pValue)
130 | {
131 | string lResult = $"{pValue.major}.{pValue.minor}";
132 |
133 | if (pValue.patch != 0)
134 | {
135 | lResult += $".{pValue.patch}";
136 | }
137 |
138 | return lResult;
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/export_presets.cfg:
--------------------------------------------------------------------------------
1 | [preset.0]
2 |
3 | name="Windows Desktop"
4 | platform="Windows Desktop"
5 | runnable=true
6 | dedicated_server=false
7 | custom_features=""
8 | export_filter="all_resources"
9 | include_filter="export_presets.cfg"
10 | exclude_filter=""
11 | export_path="bin/GodotHub_v0.1.4/GodotHub_v0.1.4_win64/GodotHub_v0.1.4_win64.exe"
12 | encryption_include_filters=""
13 | encryption_exclude_filters=""
14 | encrypt_pck=false
15 | encrypt_directory=false
16 | script_encryption_key=""
17 |
18 | [preset.0.options]
19 |
20 | custom_template/debug=""
21 | custom_template/release=""
22 | debug/export_console_script=1
23 | binary_format/embed_pck=false
24 | texture_format/bptc=true
25 | texture_format/s3tc=true
26 | texture_format/etc=false
27 | texture_format/etc2=false
28 | binary_format/architecture="x86_64"
29 | codesign/enable=false
30 | codesign/identity_type=0
31 | codesign/identity=""
32 | codesign/password=""
33 | codesign/timestamp=true
34 | codesign/timestamp_server_url=""
35 | codesign/digest_algorithm=1
36 | codesign/description=""
37 | codesign/custom_options=PackedStringArray()
38 | application/modify_resources=true
39 | application/icon="res://icon.ico"
40 | application/console_wrapper_icon=""
41 | application/icon_interpolation=4
42 | application/file_version="0.1.4.0"
43 | application/product_version="0.1.4.0"
44 | application/company_name="Astral_Sheep"
45 | application/product_name="Godot Hub"
46 | application/file_description=""
47 | application/copyright=""
48 | application/trademarks=""
49 | ssh_remote_deploy/enabled=false
50 | ssh_remote_deploy/host="user@host_ip"
51 | ssh_remote_deploy/port="22"
52 | ssh_remote_deploy/extra_args_ssh=""
53 | ssh_remote_deploy/extra_args_scp=""
54 | ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}'
55 | $action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}'
56 | $trigger = New-ScheduledTaskTrigger -Once -At 00:00
57 | $settings = New-ScheduledTaskSettingsSet
58 | $task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings
59 | Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true
60 | Start-ScheduledTask -TaskName godot_remote_debug
61 | while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 }
62 | Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue"
63 | ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
64 | Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
65 | Remove-Item -Recurse -Force '{temp_dir}'"
66 |
67 | [preset.1]
68 |
69 | name="Linux/X11"
70 | platform="Linux/X11"
71 | runnable=true
72 | dedicated_server=false
73 | custom_features=""
74 | export_filter="all_resources"
75 | include_filter=""
76 | exclude_filter=""
77 | export_path="bin/GodotHub_v0.1.3/linux_x86_64/Godot Hub.x86_64"
78 | encryption_include_filters=""
79 | encryption_exclude_filters=""
80 | encrypt_pck=false
81 | encrypt_directory=false
82 | script_encryption_key=""
83 |
84 | [preset.1.options]
85 |
86 | custom_template/debug=""
87 | custom_template/release=""
88 | debug/export_console_script=1
89 | binary_format/embed_pck=false
90 | texture_format/bptc=true
91 | texture_format/s3tc=true
92 | texture_format/etc=false
93 | texture_format/etc2=false
94 | binary_format/architecture="x86_64"
95 | ssh_remote_deploy/enabled=false
96 | ssh_remote_deploy/host="user@host_ip"
97 | ssh_remote_deploy/port="22"
98 | ssh_remote_deploy/extra_args_ssh=""
99 | ssh_remote_deploy/extra_args_scp=""
100 | ssh_remote_deploy/run_script="#!/usr/bin/env bash
101 | export DISPLAY=:0
102 | unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
103 | \"{temp_dir}/{exe_name}\" {cmd_args}"
104 | ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
105 | kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")
106 | rm -rf \"{temp_dir}\""
107 |
--------------------------------------------------------------------------------
/scenes/projects/project_item.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=8 format=3 uid="uid://83qph142ha7s"]
2 |
3 | [ext_resource type="Theme" uid="uid://ce3m7fxsw8f6t" path="res://resources/themes/main.theme" id="1_hu2pw"]
4 | [ext_resource type="Script" path="res://scripts/core/tabs/projects/ProjectItem.cs" id="2_uxxbh"]
5 | [ext_resource type="PackedScene" uid="uid://bilwvy6kxj1nk" path="res://scenes/confirmation_dialog.tscn" id="3_58hgf"]
6 | [ext_resource type="Theme" uid="uid://bwmtny758y0se" path="res://resources/themes/half_red_btn.theme" id="4_efnx3"]
7 | [ext_resource type="Theme" uid="uid://brtddydnujip" path="res://resources/themes/blue_btn.theme" id="4_fp7tl"]
8 | [ext_resource type="Theme" uid="uid://owhv26bfo2cv" path="res://resources/themes/star_btn.theme" id="4_i21nj"]
9 |
10 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_gi7kc"]
11 | bg_color = Color(0.117647, 0.117647, 0.117647, 1)
12 |
13 | [node name="ProjectItem" type="Panel" node_paths=PackedStringArray("nameLabel", "pathLabel", "lastOpenedLabel", "favoriteToggle", "versionButton", "openButton", "removeButton")]
14 | clip_contents = true
15 | custom_minimum_size = Vector2(0, 75)
16 | offset_right = 1000.0
17 | offset_bottom = 75.0
18 | theme = ExtResource("1_hu2pw")
19 | theme_override_styles/panel = SubResource("StyleBoxFlat_gi7kc")
20 | script = ExtResource("2_uxxbh")
21 | nameLabel = NodePath("Name")
22 | pathLabel = NodePath("Path")
23 | lastOpenedLabel = NodePath("LastOpened")
24 | favoriteToggle = NodePath("FavoriteButton")
25 | versionButton = NodePath("VersionButton")
26 | openButton = NodePath("OpenButton")
27 | removeButton = NodePath("RemoveButton")
28 | confirmationPopupScene = ExtResource("3_58hgf")
29 |
30 | [node name="FavoriteButton" type="Button" parent="."]
31 | layout_mode = 1
32 | anchors_preset = -1
33 | anchor_left = 0.038
34 | anchor_top = 0.5
35 | anchor_right = 0.038
36 | anchor_bottom = 0.5
37 | offset_left = -16.0
38 | offset_top = -15.0
39 | offset_right = 16.0
40 | offset_bottom = 15.0
41 | focus_mode = 0
42 | theme = ExtResource("4_i21nj")
43 | toggle_mode = true
44 |
45 | [node name="Name" type="RichTextLabel" parent="."]
46 | layout_mode = 1
47 | anchors_preset = -1
48 | anchor_left = 0.05
49 | anchor_right = 0.35
50 | anchor_bottom = 1.0
51 | offset_left = 25.0
52 | offset_top = 15.0
53 | offset_bottom = -35.0
54 | bbcode_enabled = true
55 | text = "Godot Hub"
56 | scroll_active = false
57 | shortcut_keys_enabled = false
58 |
59 | [node name="Path" type="Label" parent="."]
60 | layout_mode = 1
61 | anchors_preset = -1
62 | anchor_left = 0.05
63 | anchor_top = 1.0
64 | anchor_right = 0.35
65 | anchor_bottom = 1.0
66 | offset_left = 25.0
67 | offset_top = -35.0
68 | offset_bottom = -20.0
69 | mouse_filter = 1
70 | theme_override_colors/font_color = Color(0.588235, 0.588235, 0.588235, 1)
71 | theme_override_font_sizes/font_size = 10
72 | text = "E:/Path/69/ProjectName"
73 | vertical_alignment = 1
74 | text_overrun_behavior = 3
75 |
76 | [node name="LastOpened" type="RichTextLabel" parent="."]
77 | layout_mode = 1
78 | anchors_preset = -1
79 | anchor_left = 0.375
80 | anchor_top = 0.3
81 | anchor_right = 0.55
82 | anchor_bottom = 0.7
83 | bbcode_enabled = true
84 | text = "69 months ago"
85 | scroll_active = false
86 |
87 | [node name="VersionButton" type="OptionButton" parent="."]
88 | layout_mode = 1
89 | anchors_preset = -1
90 | anchor_left = 0.575
91 | anchor_top = 0.2
92 | anchor_right = 0.725
93 | anchor_bottom = 0.8
94 | focus_mode = 0
95 |
96 | [node name="OpenButton" type="Button" parent="."]
97 | layout_mode = 1
98 | anchors_preset = -1
99 | anchor_left = 0.75
100 | anchor_top = 0.2
101 | anchor_right = 0.85
102 | anchor_bottom = 0.8
103 | grow_horizontal = 0
104 | grow_vertical = 2
105 | focus_mode = 0
106 | theme = ExtResource("4_fp7tl")
107 | text = "Open"
108 |
109 | [node name="RemoveButton" type="Button" parent="."]
110 | layout_mode = 1
111 | anchors_preset = -1
112 | anchor_left = 0.875
113 | anchor_top = 0.2
114 | anchor_right = 0.975
115 | anchor_bottom = 0.8
116 | grow_horizontal = 0
117 | grow_vertical = 2
118 | focus_mode = 0
119 | theme = ExtResource("4_efnx3")
120 | text = "Remove"
121 |
--------------------------------------------------------------------------------
/scenes/versions/engine_item.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=8 format=3 uid="uid://8wgykcf75ex1"]
2 |
3 | [ext_resource type="Theme" uid="uid://ce3m7fxsw8f6t" path="res://resources/themes/main.theme" id="1_wybn5"]
4 | [ext_resource type="Script" path="res://scripts/core/tabs/versions/EngineItem.cs" id="2_us1bx"]
5 | [ext_resource type="PackedScene" uid="uid://bilwvy6kxj1nk" path="res://scenes/confirmation_dialog.tscn" id="3_woeeq"]
6 | [ext_resource type="Theme" uid="uid://owhv26bfo2cv" path="res://resources/themes/star_btn.theme" id="4_36lft"]
7 | [ext_resource type="Theme" uid="uid://brtddydnujip" path="res://resources/themes/blue_btn.theme" id="4_oxtu8"]
8 | [ext_resource type="Theme" uid="uid://bwmtny758y0se" path="res://resources/themes/half_red_btn.theme" id="5_4lvaj"]
9 |
10 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_gi7kc"]
11 | bg_color = Color(0.117647, 0.117647, 0.117647, 1)
12 |
13 | [node name="EngineItem" type="Panel" node_paths=PackedStringArray("nameLabel", "pathLabel", "isMonoBox", "timeLabel", "favoriteToggle", "openButton", "uninstallButton")]
14 | clip_contents = true
15 | custom_minimum_size = Vector2(0, 75)
16 | offset_right = 1000.0
17 | offset_bottom = 75.0
18 | theme = ExtResource("1_wybn5")
19 | theme_override_styles/panel = SubResource("StyleBoxFlat_gi7kc")
20 | script = ExtResource("2_us1bx")
21 | confirmationPopup = ExtResource("3_woeeq")
22 | nameLabel = NodePath("VersionLabel")
23 | pathLabel = NodePath("Path")
24 | isMonoBox = NodePath("IsMono")
25 | timeLabel = NodePath("DateLabel")
26 | favoriteToggle = NodePath("FavoriteButton")
27 | openButton = NodePath("OpenButton")
28 | uninstallButton = NodePath("UninstallButton")
29 |
30 | [node name="FavoriteButton" type="Button" parent="."]
31 | layout_mode = 1
32 | anchors_preset = -1
33 | anchor_left = 0.038
34 | anchor_top = 0.5
35 | anchor_right = 0.038
36 | anchor_bottom = 0.5
37 | offset_left = -16.0
38 | offset_top = -15.0
39 | offset_right = 16.0
40 | offset_bottom = 15.0
41 | focus_mode = 0
42 | theme = ExtResource("4_36lft")
43 | toggle_mode = true
44 |
45 | [node name="VersionLabel" type="RichTextLabel" parent="."]
46 | layout_mode = 1
47 | anchors_preset = -1
48 | anchor_left = 0.05
49 | anchor_right = 0.3
50 | anchor_bottom = 1.0
51 | offset_left = 25.0
52 | offset_top = 15.0
53 | offset_bottom = -35.0
54 | bbcode_enabled = true
55 | text = "[b]Godot 4.0[/b]"
56 | scroll_active = false
57 |
58 | [node name="Path" type="Label" parent="."]
59 | layout_mode = 1
60 | anchors_preset = -1
61 | anchor_left = 0.05
62 | anchor_top = 1.0
63 | anchor_right = 0.3
64 | anchor_bottom = 1.0
65 | offset_left = 25.0
66 | offset_top = -35.0
67 | offset_bottom = -20.0
68 | mouse_filter = 1
69 | theme_override_colors/font_color = Color(0.588235, 0.588235, 0.588235, 1)
70 | theme_override_font_sizes/font_size = 10
71 | text = "E:/Path/69/ProjectName"
72 | vertical_alignment = 1
73 | text_overrun_behavior = 3
74 |
75 | [node name="IsMono" type="CheckBox" parent="."]
76 | layout_mode = 1
77 | anchors_preset = -1
78 | anchor_left = 0.325
79 | anchor_right = 0.425
80 | anchor_bottom = 1.0
81 | focus_mode = 0
82 | theme_override_colors/font_color = Color(0.721569, 0.721569, 0.721569, 1)
83 | theme_override_colors/font_pressed_color = Color(0.721569, 0.721569, 0.721569, 1)
84 | theme_override_colors/font_hover_color = Color(0.721569, 0.721569, 0.721569, 1)
85 | theme_override_colors/font_hover_pressed_color = Color(0.721569, 0.721569, 0.721569, 1)
86 | theme_override_colors/font_focus_color = Color(0.721569, 0.721569, 0.721569, 1)
87 | button_pressed = true
88 | button_mask = 0
89 | shortcut_feedback = false
90 | shortcut_in_tooltip = false
91 | text = "Mono"
92 |
93 | [node name="DateLabel" type="RichTextLabel" parent="."]
94 | layout_mode = 1
95 | anchors_preset = -1
96 | anchor_left = 0.45
97 | anchor_top = 0.3
98 | anchor_right = 0.65
99 | anchor_bottom = 0.7
100 | bbcode_enabled = true
101 | text = "69 months ago"
102 |
103 | [node name="OpenButton" type="Button" parent="."]
104 | layout_mode = 1
105 | anchors_preset = -1
106 | anchor_left = 0.725
107 | anchor_top = 0.2
108 | anchor_right = 0.825
109 | anchor_bottom = 0.8
110 | grow_horizontal = 0
111 | grow_vertical = 2
112 | focus_mode = 0
113 | theme = ExtResource("4_oxtu8")
114 | text = "Open"
115 |
116 | [node name="UninstallButton" type="Button" parent="."]
117 | layout_mode = 1
118 | anchors_preset = -1
119 | anchor_left = 0.85
120 | anchor_top = 0.2
121 | anchor_right = 0.975
122 | anchor_bottom = 0.8
123 | grow_horizontal = 0
124 | grow_vertical = 2
125 | focus_mode = 0
126 | theme = ExtResource("5_4lvaj")
127 | text = "Uninstall"
128 |
--------------------------------------------------------------------------------
/scripts/core/tabs/versions/EnginesPanel.cs:
--------------------------------------------------------------------------------
1 | using Com.Astral.GodotHub.Core.Data;
2 | using Com.Astral.GodotHub.Core.Utils.Comparisons;
3 | using Godot;
4 | using System;
5 | using System.Collections.Generic;
6 |
7 | namespace Com.Astral.GodotHub.Core.Tabs.Versions
8 | {
9 | public partial class EnginesPanel : SortedPanel
10 | {
11 | [Export] protected PackedScene engineItemScene;
12 |
13 | [ExportGroup("Engine addition")]
14 | [Export] protected Button addButton;
15 | [Export] protected PackedScene fileDialogScene;
16 |
17 | [ExportGroup("Sorting")]
18 | [Export] protected Button favoriteButton;
19 | [Export] protected SortToggle versionButton;
20 | [Export] protected SortToggle monoButton;
21 | [Export] protected SortToggle dateButton;
22 |
23 | protected List items = new List();
24 | protected Comparison currentComparison = Comparer.CompareTimes;
25 |
26 | public override void _Ready()
27 | {
28 | List lVersions = VersionsData.GetAllVersions();
29 |
30 | for (int i = 0; i < lVersions.Count; i++)
31 | {
32 | CreateItem(lVersions[i]);
33 | }
34 |
35 | Sort();
36 |
37 | VersionsData.VersionAdded += OnVersionAdded;
38 | EngineItem.Closed += OnItemClosed;
39 |
40 | favoriteButton.Toggled += OnFavoriteToggled;
41 | versionButton.CustomToggled += OnVersionToggled;
42 | monoButton.CustomToggled += OnMonoToggled;
43 | dateButton.CustomToggled += OnDateToggled;
44 | addButton.Pressed += OnAddPressed;
45 |
46 | dateButton.ButtonPressed = true;
47 | }
48 |
49 | protected override void Dispose(bool pDisposing)
50 | {
51 | if (pDisposing)
52 | {
53 | EngineItem.Closed -= OnItemClosed;
54 | VersionsData.VersionAdded -= OnVersionAdded;
55 | }
56 | }
57 |
58 | protected EngineItem CreateItem(GDFile pInstall)
59 | {
60 | EngineItem lItem = engineItemScene.Instantiate();
61 | itemContainer.AddChild(lItem);
62 | lItem.Init(pInstall);
63 | items.Add(lItem);
64 | return lItem;
65 | }
66 |
67 | #region EVENT_HANDLING
68 |
69 | protected void OnVersionAdded(GDFile pInstall)
70 | {
71 | CreateItem(pInstall);
72 | Sort();
73 | }
74 |
75 | protected void OnItemClosed(EngineItem pItem)
76 | {
77 | items.Remove(pItem);
78 | }
79 |
80 | protected void OnAddPressed()
81 | {
82 | FileDialog lDialog = fileDialogScene.Instantiate();
83 | Main.Instance.AddChild(lDialog);
84 | lDialog.PopupCentered();
85 | lDialog.FileMode = FileDialog.FileModeEnum.OpenFiles;
86 |
87 | #if GODOT_WINDOWS
88 | lDialog.Filters = new string[] { "*.exe" };
89 | #else
90 | lDialog.Filters = new string [] { "*" };
91 | #endif
92 |
93 | lDialog.CurrentDir = AppConfig.InstallDir;
94 | lDialog.FilesSelected += OnFilesSelected;
95 | }
96 |
97 | protected void OnFilesSelected(string[] pPaths)
98 | {
99 | string lPath;
100 |
101 | for (int i = 0; i < pPaths.Length; i++)
102 | {
103 | lPath = pPaths[i];
104 | VersionsData.AddVersion(lPath, true);
105 | }
106 | }
107 |
108 | protected void OnFavoriteToggled(bool pToggled)
109 | {
110 | versionButton.Disable();
111 | monoButton.Disable();
112 |
113 | if (pToggled)
114 | {
115 | dateButton.Disable();
116 | currentComparison = Comparer.CompareFavorites;
117 | Sort();
118 | }
119 | else
120 | {
121 | dateButton.Enable();
122 | currentComparison = Comparer.CompareTimes;
123 | Sort();
124 | }
125 | }
126 |
127 | protected void OnVersionToggled(bool pToggled)
128 | {
129 | favoriteButton.SetPressedNoSignal(false);
130 | monoButton.Disable();
131 | dateButton.Disable();
132 | currentComparison = pToggled ? Comparer.CompareVersions : Comparer.ReversedCompareVersions;
133 | Sort();
134 | }
135 |
136 | protected void OnMonoToggled(bool pToggled)
137 | {
138 | favoriteButton.SetPressedNoSignal(false);
139 | versionButton.Disable();
140 | dateButton.Disable();
141 | currentComparison = pToggled ? Comparer.CompareMonos : Comparer.ReversedCompareMonos;
142 | Sort();
143 | }
144 |
145 | protected void OnDateToggled(bool pToggled)
146 | {
147 | favoriteButton.SetPressedNoSignal(false);
148 | versionButton.Disable();
149 | monoButton.Disable();
150 | currentComparison = pToggled ? Comparer.CompareTimes : Comparer.ReversedCompareTimes;
151 | Sort();
152 | }
153 |
154 | #endregion //EVENT_HANDLING
155 |
156 | protected void Sort()
157 | {
158 | items.Sort(currentComparison);
159 |
160 | for (int i = 0; i < items.Count; i++)
161 | {
162 | itemContainer.MoveChild(items[i], i);
163 | }
164 | }
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/icon.svg:
--------------------------------------------------------------------------------
1 |
2 |