Add elements

Attempt to block line of sight with walls
This commit is contained in:
2024-09-06 22:04:00 -07:00
parent 8eeeb0890c
commit dc035eb1fe
35 changed files with 102 additions and 2219 deletions

View File

@@ -1,53 +0,0 @@
using System;
using System.Diagnostics;
using Godot;
namespace Laura.DeployToSteamOS;
public class GodotExportManager
{
public static void ExportProject(
string projectPath,
string outputPath,
bool isReleaseBuild,
Callable logCallable,
Action OnProcessExited = null)
{
logCallable.CallDeferred("Starting project export, this may take a while.");
logCallable.CallDeferred($"Output path: {outputPath}");
logCallable.CallDeferred($"Is Release Build: {(isReleaseBuild ? "Yes" : "No")}");
Process exportProcess = new Process();
exportProcess.StartInfo.FileName = OS.GetExecutablePath();
var arguments = $"--headless --path \"{projectPath}\" ";
arguments += isReleaseBuild ? "--export-release " : "--export-debug ";
arguments += "\"Steamdeck\" ";
arguments += $"\"{outputPath}\"";
exportProcess.StartInfo.Arguments = arguments;
exportProcess.StartInfo.UseShellExecute = false;
exportProcess.StartInfo.RedirectStandardOutput = true;
exportProcess.EnableRaisingEvents = true;
exportProcess.ErrorDataReceived += (sender, args) =>
{
throw new Exception("Error while building project: " + args.Data);
};
exportProcess.OutputDataReceived += (sender, args) =>
{
logCallable.CallDeferred(args.Data);
};
exportProcess.Exited += (sender, args) =>
{
OnProcessExited?.Invoke();
exportProcess.WaitForExit();
};
exportProcess.Start();
exportProcess.BeginOutputReadLine();
}
}

View File

@@ -1,33 +0,0 @@
#if TOOLS
using Godot;
namespace Laura.DeployToSteamOS;
[Tool]
public partial class Plugin : EditorPlugin
{
private Control _dock;
private Control _settingsPanel;
public override void _EnterTree()
{
AddAutoloadSingleton("SettingsManager", "res://addons/deploy_to_steamos/SettingsManager.cs");
_dock = GD.Load<PackedScene>("res://addons/deploy_to_steamos/deploy_dock/deploy_dock.tscn").Instantiate<Control>();
_settingsPanel = GD.Load<PackedScene>("res://addons/deploy_to_steamos/settings_panel/settings_panel.tscn").Instantiate<Control>();
AddControlToContainer(CustomControlContainer.Toolbar, _dock);
AddControlToContainer(CustomControlContainer.ProjectSettingTabRight, _settingsPanel);
}
public override void _ExitTree()
{
RemoveControlFromContainer(CustomControlContainer.Toolbar, _dock);
RemoveControlFromContainer(CustomControlContainer.ProjectSettingTabRight, _settingsPanel);
RemoveAutoloadSingleton("SettingsManager");
_dock.Free();
}
}
#endif

View File

@@ -1,13 +0,0 @@
public class SettingsFile
{
public enum UploadMethods
{
Differential,
Incremental,
CleanReplace
}
public string BuildPath { get; set; } = "";
public string StartParameters { get; set; } = "";
public UploadMethods UploadMethod { get; set; } = UploadMethods.Differential;
}

View File

@@ -1,101 +0,0 @@
using System.Collections.Generic;
using System.Text.Json;
using Godot;
namespace Laura.DeployToSteamOS;
[Tool]
public partial class SettingsManager : Node
{
public static SettingsManager Instance;
private const string FolderPath = "res://.deploy_to_steamos";
private const string SettingsPath = FolderPath + "/settings.json";
private const string DevicesPath = FolderPath + "/devices.json";
public bool IsDirty = false;
public SettingsFile Settings = new();
public List<SteamOSDevkitManager.Device> Devices = new();
public override void _EnterTree()
{
Instance = this;
Load();
}
public void Load()
{
if (!FileAccess.FileExists(SettingsPath))
{
Settings = new SettingsFile();
IsDirty = true;
}
else
{
using var settingsFile = FileAccess.Open(SettingsPath, FileAccess.ModeFlags.Read);
var settingsFileContent = settingsFile.GetAsText();
Settings = JsonSerializer.Deserialize<SettingsFile>(settingsFileContent, DefaultSerializerOptions);
// Failsafe if settings file is corrupt
if (Settings == null)
{
Settings = new SettingsFile();
IsDirty = true;
}
}
if (!FileAccess.FileExists(SettingsPath))
{
Devices = new List<SteamOSDevkitManager.Device>();
IsDirty = true;
}
else
{
using var devicesFile = FileAccess.Open(DevicesPath, FileAccess.ModeFlags.Read);
var devicesFileContent = devicesFile.GetAsText();
Devices = JsonSerializer.Deserialize<List<SteamOSDevkitManager.Device>>(devicesFileContent, DefaultSerializerOptions);
// Failsafe if device file is corrupt
if (Devices == null)
{
Devices = new List<SteamOSDevkitManager.Device>();
IsDirty = true;
}
}
if (IsDirty)
{
Save();
}
}
public void Save()
{
// Check if directory exists and create if it doesn't
var dirAccess = DirAccess.Open(FolderPath);
if (dirAccess == null)
{
DirAccess.MakeDirRecursiveAbsolute(FolderPath);
}
// Save Settings
var jsonSettings = JsonSerializer.Serialize(Settings);
using var settingsFile = FileAccess.Open(SettingsPath, FileAccess.ModeFlags.Write);
settingsFile.StoreString(jsonSettings);
// Save Devices
var jsonDevices = JsonSerializer.Serialize(Devices);
using var devicesFile = FileAccess.Open(DevicesPath, FileAccess.ModeFlags.Write);
devicesFile.StoreString(jsonDevices);
IsDirty = false;
}
public static readonly JsonSerializerOptions DefaultSerializerOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
};
}

View File

@@ -1,251 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Godot;
using Renci.SshNet;
using Zeroconf;
namespace Laura.DeployToSteamOS;
/// <summary>
/// Scans the network for SteamOS Devkit devices via the ZeroConf / Bonjour protocol
/// </summary>
public class SteamOSDevkitManager
{
public const string SteamOSProtocol = "_steamos-devkit._tcp.local.";
public const string CompatibleTextVersion = "1";
/// <summary>
/// Scans the network for valid SteamOS devkit devices
/// </summary>
/// <returns>A list of valid SteamOS devkit devices</returns>
public static async Task<List<Device>> ScanDevices()
{
var networkDevices = await ZeroconfResolver.ResolveAsync(SteamOSProtocol);
List<Device> devices = new();
// Iterate through all network devices and request further connection info from the service
foreach (var networkDevice in networkDevices)
{
var device = new Device
{
DisplayName = networkDevice.DisplayName,
IPAdress = networkDevice.IPAddress,
ServiceName = networkDevice.DisplayName + "." + SteamOSProtocol,
};
var hasServiceData = networkDevice.Services.TryGetValue(device.ServiceName, out var serviceData);
// This device is not a proper SteamOS device
if(!hasServiceData) continue;
var properties = serviceData.Properties.FirstOrDefault();
if (properties == null) continue;
// Device is not compatible (version mismatch)
// String"1" is for some reason not equal to String"1"
//if (properties["txtvers"] != CompatibleTextVersion) continue;
device.Settings = properties["settings"];
device.Login = properties["login"];
device.Devkit1 = properties["devkit1"];
devices.Add(device);
}
return devices;
}
/// <summary>
/// Creates an SSH connection and runs a command
/// </summary>
/// <param name="device">A SteamOS devkit device</param>
/// <param name="command">The SSH command to run</param>
/// <param name="logCallable">A callable for logging</param>
/// <returns>The SSH CLI output</returns>
public static async Task<string> RunSSHCommand(Device device, string command, Callable logCallable)
{
logCallable.CallDeferred($"Connecting to {device.Login}@{device.IPAdress}");
using var client = new SshClient(GetSSHConnectionInfo(device));
await client.ConnectAsync(CancellationToken.None);
logCallable.CallDeferred($"Command: '{command}'");
var sshCommand = client.CreateCommand(command);
var result = await Task.Factory.FromAsync(sshCommand.BeginExecute(), sshCommand.EndExecute);
client.Disconnect();
return result;
}
/// <summary>
/// Creates a new SCP connection and copies all local files to a remote path
/// </summary>
/// <param name="device">A SteamOS devkit device</param>
/// <param name="localPath">The path on the host</param>
/// <param name="remotePath">The path on the device</param>
/// <param name="logCallable">A callable for logging</param>
public static async Task CopyFiles(Device device, string localPath, string remotePath, Callable logCallable)
{
logCallable.CallDeferred($"Connecting to {device.Login}@{device.IPAdress}");
using var client = new ScpClient(GetSSHConnectionInfo(device));
await client.ConnectAsync(CancellationToken.None);
logCallable.CallDeferred($"Uploading files");
// Run async method until upload is done
// TODO: Set Progress based on files
var lastUploadedFilename = "";
var uploadProgress = 0;
var taskCompletion = new TaskCompletionSource<bool>();
client.Uploading += (sender, e) =>
{
if (e.Filename != lastUploadedFilename)
{
lastUploadedFilename = e.Filename;
uploadProgress = 0;
}
var progressPercentage = Mathf.CeilToInt((double)e.Uploaded / e.Size * 100);
if (progressPercentage != uploadProgress)
{
uploadProgress = progressPercentage;
logCallable.CallDeferred($"Uploading {lastUploadedFilename} ({progressPercentage}%)");
}
if (e.Uploaded == e.Size)
{
taskCompletion.TrySetResult(true);
}
};
client.ErrorOccurred += (sender, args) => throw new Exception("Error while uploading build.");
await Task.Run(() => client.Upload(new DirectoryInfo(localPath), remotePath));
await taskCompletion.Task;
client.Disconnect();
logCallable.CallDeferred($"Fixing file permissions");
await RunSSHCommand(device, $"chmod +x -R {remotePath}", logCallable);
}
/// <summary>
/// Runs an SSH command on the device that runs the steamos-prepare-upload script
/// </summary>
/// <param name="device">A SteamOS devkit device</param>
/// <param name="gameId">An ID for the game</param>
/// <param name="logCallable">A callable for logging</param>
/// <returns>The CLI result</returns>
public static async Task<PrepareUploadResult> PrepareUpload(Device device, string gameId, Callable logCallable)
{
logCallable.CallDeferred("Preparing upload");
var resultRaw = await RunSSHCommand(device, "python3 ~/devkit-utils/steamos-prepare-upload --gameid " + gameId, logCallable);
var result = JsonSerializer.Deserialize<PrepareUploadResult>(resultRaw, DefaultSerializerOptions);
return result;
}
/// <summary>
/// Runs an SSH command on the device that runs the steamos-create-shortcut script
/// </summary>
/// <param name="device">A SteamOS devkit device</param>
/// <param name="parameters">Parameters for the shortcut</param>
/// <param name="logCallable">A callable for logging</param>
/// <returns>The CLI result</returns>
public static async Task<CreateShortcutResult> CreateShortcut(Device device, CreateShortcutParameters parameters, Callable logCallable)
{
var parametersJson = JsonSerializer.Serialize(parameters);
var command = $"python3 ~/devkit-utils/steam-client-create-shortcut --parms '{parametersJson}'";
var resultRaw = await RunSSHCommand(device, command, logCallable);
var result = JsonSerializer.Deserialize<CreateShortcutResult>(resultRaw, DefaultSerializerOptions);
return result;
}
/// <summary>
/// A SteamOS devkit device
/// </summary>
public class Device
{
public string DisplayName { get; set; }
public string IPAdress { get; set; }
public int Port { get; set; }
public string ServiceName { get; set; }
public string Settings { get; set; }
public string Login { get; set; }
public string Devkit1 { get; set; }
}
public class PrepareUploadResult
{
public string User { get; set; }
public string Directory { get; set; }
}
public class CreateShortcutResult
{
public string Error { get; set; }
public string Success { get; set; }
}
/// <summary>
/// Parameters for the CreateShortcut method
/// </summary>
public struct CreateShortcutParameters
{
public string gameid { get; set; }
public string directory { get; set; }
public string[] argv { get; set; }
public Dictionary<string, string> settings { get; set; }
}
/// <summary>
/// Returns the path to the devkit_rsa key generated by the official SteamOS devkit client
/// </summary>
/// <returns>The path to the "devkit_rsa" key</returns>
public static string GetPrivateKeyPath()
{
string applicationDataPath;
switch (System.Environment.OSVersion.Platform)
{
// TODO: Linux Support
case PlatformID.Win32NT:
applicationDataPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), "steamos-devkit");
break;
case PlatformID.Unix:
applicationDataPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "Library", "Application Support");
break;
default:
applicationDataPath = "";
break;
}
var keyFolder = Path.Combine(applicationDataPath, "steamos-devkit");
return Path.Combine(keyFolder, "devkit_rsa");
}
/// <summary>
/// Creates a SSH Connection Info for a SteamOS devkit device
/// </summary>
/// <param name="device">A SteamOS devkit device</param>
/// <returns>An SSH ConnectionInfo</returns>
/// <exception cref="Exception">Throws if there is no private key present</exception>
public static ConnectionInfo GetSSHConnectionInfo(Device device)
{
var privateKeyPath = GetPrivateKeyPath();
if (!File.Exists(privateKeyPath)) throw new Exception("devkit_rsa key is missing. Have you connected to your device via the official devkit UI yet?");
var privateKeyFile = new PrivateKeyFile(privateKeyPath);
return new ConnectionInfo(device.IPAdress, device.Login, new PrivateKeyAuthenticationMethod(device.Login, privateKeyFile));
}
public static readonly JsonSerializerOptions DefaultSerializerOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
};
}

View File

@@ -1,130 +0,0 @@
using System.Collections.Generic;
using Godot;
namespace Laura.DeployToSteamOS;
[Tool]
public partial class AddDeviceWindow : Window
{
private bool _isVisible;
private bool _isUpdatingDevices;
private float _scanCooldown;
private List<SteamOSDevkitManager.Device> _scannedDevices = new();
private List<SteamOSDevkitManager.Device> _pairedDevices = new();
public delegate void DevicesChangedDelegate(List<SteamOSDevkitManager.Device> devices);
public event DevicesChangedDelegate OnDevicesChanged;
[ExportGroup("References")]
[Export] private VBoxContainer _devicesContainer;
[Export] private PackedScene _deviceItemPrefab;
[Export] private Button _refreshButton;
public override void _Process(double delta)
{
if (!Visible) return;
_scanCooldown -= (float)delta;
if (_scanCooldown < 0f)
{
_scanCooldown = 10f;
UpdateDevices();
UpdateDeviceList();
}
_refreshButton.Disabled = _isUpdatingDevices;
}
private async void UpdateDevices()
{
if (!Visible || _isUpdatingDevices) return;
_isUpdatingDevices = true;
var devices = await SteamOSDevkitManager.ScanDevices();
if (devices != _scannedDevices)
{
foreach (var device in devices)
{
if (
_scannedDevices.Exists(x => x.IPAdress == device.IPAdress && x.Login == device.Login)
|| _pairedDevices.Exists(x => x.IPAdress == device.IPAdress && x.Login == device.Login)
) continue;
_scannedDevices.Add(device);
}
UpdateDeviceList();
}
_isUpdatingDevices = false;
}
public void UpdateDeviceList()
{
// Clear List
foreach (var childNode in _devicesContainer.GetChildren())
{
childNode.QueueFree();
}
var devices = new List<SteamOSDevkitManager.Device>();
devices.AddRange(_pairedDevices);
foreach (var scannedDevice in _scannedDevices)
{
if (devices.Exists(x => x.IPAdress == scannedDevice.IPAdress && x.Login == scannedDevice.Login))
{
continue;
}
devices.Add(scannedDevice);
}
foreach (var scannedDevice in devices)
{
var deviceItem = _deviceItemPrefab.Instantiate<DeviceItemPrefab>();
deviceItem.SetUI(scannedDevice);
deviceItem.OnDevicePair += device =>
{
// TODO: Connect to device and run a random ssh command to check communication
if (!_pairedDevices.Exists(x => x.IPAdress == device.IPAdress && x.Login == device.Login))
{
_pairedDevices.Add(device);
}
UpdateDeviceList();
};
deviceItem.OnDeviceUnpair += device =>
{
_pairedDevices.Remove(device);
UpdateDeviceList();
};
_devicesContainer.AddChild(deviceItem);
}
}
public void Close()
{
Hide();
if (_pairedDevices != SettingsManager.Instance.Devices)
{
OnDevicesChanged?.Invoke(_pairedDevices);
}
}
public void OnVisibilityChanged()
{
if (Visible)
{
_isVisible = true;
// Prepopulate device list with saved devices
_pairedDevices = new List<SteamOSDevkitManager.Device>(SettingsManager.Instance.Devices);
UpdateDeviceList();
}
else
{
_isVisible = false;
}
}
}

View File

@@ -1,42 +0,0 @@
using Godot;
namespace Laura.DeployToSteamOS;
[Tool]
public partial class DeviceItemPrefab : PanelContainer
{
private SteamOSDevkitManager.Device _device;
public delegate void DeviceDelegate(SteamOSDevkitManager.Device device);
public event DeviceDelegate OnDevicePair;
public event DeviceDelegate OnDeviceUnpair;
[ExportGroup("References")]
[Export] private Label _deviceNameLabel;
[Export] private Label _deviceConnectionLabel;
[Export] private Button _devicePairButton;
[Export] private Button _deviceUnpairButton;
public void SetUI(SteamOSDevkitManager.Device device)
{
_device = device;
_deviceNameLabel.Text = device.DisplayName;
_deviceConnectionLabel.Text = $"{device.Login}@{device.IPAdress}";
if (SettingsManager.Instance.Devices.Exists(x => x.IPAdress == device.IPAdress && x.Login == device.Login))
{
_devicePairButton.Visible = false;
_deviceUnpairButton.Visible = true;
}
}
public void Pair()
{
OnDevicePair?.Invoke(_device);
}
public void Unpair()
{
OnDeviceUnpair?.Invoke(_device);
}
}

View File

@@ -1,107 +0,0 @@
[gd_scene load_steps=7 format=3 uid="uid://6be5afncp3nr"]
[ext_resource type="Script" path="res://addons/deploy_to_steamos/add_device_window/AddDeviceWindow.cs" id="1_3tepc"]
[ext_resource type="PackedScene" uid="uid://p64nkj5ii2xt" path="res://addons/deploy_to_steamos/add_device_window/device_item_prefab.tscn" id="2_dka1k"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mam6h"]
content_margin_left = 0.0
content_margin_top = 0.0
content_margin_right = 0.0
content_margin_bottom = 0.0
bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_imdn0"]
content_margin_left = 30.0
content_margin_top = 10.0
content_margin_right = 30.0
content_margin_bottom = 10.0
bg_color = Color(0.2, 0.0823529, 0.121569, 1)
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_74135"]
content_margin_left = 15.0
content_margin_top = 15.0
content_margin_right = 15.0
content_margin_bottom = 15.0
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ne8al"]
content_margin_left = 30.0
content_margin_top = 10.0
content_margin_right = 30.0
content_margin_bottom = 10.0
bg_color = Color(0.133333, 0.133333, 0.133333, 1)
[node name="AddDeviceWindow" type="Window" node_paths=PackedStringArray("_devicesContainer", "_refreshButton")]
title = "Add devkit device"
initial_position = 1
size = Vector2i(650, 500)
transient = true
exclusive = true
min_size = Vector2i(650, 500)
script = ExtResource("1_3tepc")
_devicesContainer = NodePath("PanelContainer/VBoxContainer/ScrollContainer/ContentContainer/DevicesContainer")
_deviceItemPrefab = ExtResource("2_dka1k")
_refreshButton = NodePath("PanelContainer/VBoxContainer/ActionsContainer/HBoxContainer/RefreshButton")
[node name="PanelContainer" type="PanelContainer" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_mam6h")
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="InfoContainer" type="PanelContainer" parent="PanelContainer/VBoxContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_imdn0")
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/InfoContainer"]
custom_minimum_size = Vector2(0, 10)
layout_mode = 2
theme_override_colors/font_color = Color(1, 0.788235, 0.858824, 1)
theme_override_font_sizes/font_size = 11
text = "Please keep in mind that you need to connect to your devkit device at least once through the official SteamOS devkit client to install the devkit tools to your device and create the necessary authentication keys."
autowrap_mode = 3
[node name="ScrollContainer" type="ScrollContainer" parent="PanelContainer/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="ContentContainer" type="PanelContainer" parent="PanelContainer/VBoxContainer/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 0
theme_override_styles/panel = SubResource("StyleBoxEmpty_74135")
[node name="DevicesContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/ScrollContainer/ContentContainer"]
layout_mode = 2
theme_override_constants/separation = 10
[node name="ActionsContainer" type="PanelContainer" parent="PanelContainer/VBoxContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_ne8al")
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBoxContainer/ActionsContainer"]
layout_mode = 2
theme_override_constants/separation = 10
alignment = 2
[node name="RefreshButton" type="Button" parent="PanelContainer/VBoxContainer/ActionsContainer/HBoxContainer"]
layout_mode = 2
text = "Refresh"
[node name="CloseButton" type="Button" parent="PanelContainer/VBoxContainer/ActionsContainer/HBoxContainer"]
layout_mode = 2
text = "Close"
[connection signal="close_requested" from="." to="." method="Close"]
[connection signal="visibility_changed" from="." to="." method="OnVisibilityChanged"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/ActionsContainer/HBoxContainer/RefreshButton" to="." method="UpdateDevices"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/ActionsContainer/HBoxContainer/CloseButton" to="." method="Close"]

View File

@@ -1,63 +0,0 @@
[gd_scene load_steps=3 format=3 uid="uid://p64nkj5ii2xt"]
[ext_resource type="Script" path="res://addons/deploy_to_steamos/add_device_window/DeviceItemPrefab.cs" id="1_q77lw"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6g2hd"]
content_margin_left = 15.0
content_margin_top = 10.0
content_margin_right = 15.0
content_margin_bottom = 10.0
bg_color = Color(0.133333, 0.133333, 0.133333, 1)
corner_radius_top_left = 4
corner_radius_top_right = 4
corner_radius_bottom_right = 4
corner_radius_bottom_left = 4
[node name="DeviceItemPrefab" type="PanelContainer" node_paths=PackedStringArray("_deviceNameLabel", "_deviceConnectionLabel", "_devicePairButton", "_deviceUnpairButton")]
offset_right = 532.0
offset_bottom = 51.0
theme_override_styles/panel = SubResource("StyleBoxFlat_6g2hd")
script = ExtResource("1_q77lw")
_deviceNameLabel = NodePath("HBoxContainer/VBoxContainer/DeviceNameLabel")
_deviceConnectionLabel = NodePath("HBoxContainer/VBoxContainer/DeviceConnectionLabel")
_devicePairButton = NodePath("HBoxContainer/PairButton")
_deviceUnpairButton = NodePath("HBoxContainer/UnpairButton")
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = 5
alignment = 1
[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = -5
[node name="DeviceNameLabel" type="Label" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "steamdeck"
[node name="DeviceConnectionLabel" type="Label" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(1, 1, 1, 0.490196)
theme_override_font_sizes/font_size = 12
text = "deck@127.0.0.1"
[node name="PairButton" type="Button" parent="HBoxContainer"]
layout_mode = 2
size_flags_vertical = 4
theme_override_constants/icon_max_width = 20
text = "Pair"
[node name="UnpairButton" type="Button" parent="HBoxContainer"]
visible = false
layout_mode = 2
size_flags_vertical = 4
theme_override_constants/icon_max_width = 20
text = "Unpair"
[connection signal="pressed" from="HBoxContainer/PairButton" to="." method="Pair"]
[connection signal="pressed" from="HBoxContainer/UnpairButton" to="." method="Unpair"]

View File

@@ -1,108 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Godot;
namespace Laura.DeployToSteamOS;
[Tool]
public partial class DeployDock : PanelContainer
{
private int _selectedId = 10000;
[Export] private OptionButton _deployTargetButton;
[Export] private Button _deployButton;
[Export] private AddDeviceWindow _addDeviceWindow;
[Export] private DeployWindow _deployWindow;
public override void _EnterTree()
{
_addDeviceWindow.OnDevicesChanged += OnDevicesChanged;
}
public override void _ExitTree()
{
_addDeviceWindow.OnDevicesChanged -= OnDevicesChanged;
}
public override void _Ready()
{
UpdateDropdown();
}
public void OnDeployTargetItemSelected(int index)
{
var itemId = _deployTargetButton.GetItemId(index);
if (_selectedId == itemId) return;
if (itemId <= 10000)
{
_selectedId = itemId;
}
else if (itemId == 10001)
{
_addDeviceWindow.Show();
}
_deployTargetButton.Select(_deployTargetButton.GetItemIndex(_selectedId));
_deployButton.Disabled = _selectedId >= 10000;
}
public void Deploy()
{
var device = SettingsManager.Instance.Devices.ElementAtOrDefault(_selectedId);
if (device == null)
{
GD.PrintErr("[DeployToSteamOS] Unknown deploy target.");
return;
}
// TODO: Detect Export Presets and stop if no Linux preset named "Steamdeck" exists
_deployWindow.Deploy(device);
}
private void OnDevicesChanged(List<SteamOSDevkitManager.Device> devices)
{
// Adding Devices
var devicesToAdd = devices.Where(device => !SettingsManager.Instance.Devices.Exists(x => x.IPAdress == device.IPAdress && x.Login == device.Login)).ToList();
foreach (var device in devicesToAdd)
{
SettingsManager.Instance.Devices.Add(device);
}
// Removing Devices
var devicesToRemove = SettingsManager.Instance.Devices.Where(savedDevice => !devices.Exists(x => x.IPAdress == savedDevice.IPAdress && x.Login == savedDevice.Login)).ToList();
foreach (var savedDevice in devicesToRemove)
{
SettingsManager.Instance.Devices.Remove(savedDevice);
}
SettingsManager.Instance.Save();
UpdateDropdown();
}
private async void UpdateDropdown()
{
// Hack to prevent console error
// Godot apparently calls this before the settings are loaded
while (SettingsManager.Instance == null)
{
await Task.Delay(10);
}
_deployTargetButton.Clear();
_deployTargetButton.AddItem("None", 10000);
for (var index = 0; index < SettingsManager.Instance.Devices.Count; index++)
{
var savedDevice = SettingsManager.Instance.Devices.ElementAtOrDefault(index);
if(savedDevice == null) continue;
_deployTargetButton.AddItem($"{savedDevice.DisplayName} ({savedDevice.Login}@{savedDevice.IPAdress})", index);
}
_deployTargetButton.AddSeparator();
_deployTargetButton.AddItem("Add devkit device", 10001);
}
}

View File

@@ -1,54 +0,0 @@
[gd_scene load_steps=6 format=3 uid="uid://kdbpdei4v1ub"]
[ext_resource type="Script" path="res://addons/deploy_to_steamos/deploy_dock/DeployDock.cs" id="1_atc6e"]
[ext_resource type="Texture2D" uid="uid://s1tcpal4iir4" path="res://addons/deploy_to_steamos/icon.svg" id="2_rpj28"]
[ext_resource type="PackedScene" uid="uid://6be5afncp3nr" path="res://addons/deploy_to_steamos/add_device_window/add_device_window.tscn" id="3_qfyb3"]
[ext_resource type="PackedScene" uid="uid://ds2umdqybfls8" path="res://addons/deploy_to_steamos/deploy_window/deploy_window.tscn" id="4_8y8co"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ebqha"]
content_margin_left = 10.0
[node name="DeployDock" type="PanelContainer" node_paths=PackedStringArray("_deployTargetButton", "_deployButton", "_addDeviceWindow", "_deployWindow")]
offset_right = 337.0
offset_bottom = 32.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxEmpty_ebqha")
script = ExtResource("1_atc6e")
_deployTargetButton = NodePath("HBoxContainer/DeployTargetButton")
_deployButton = NodePath("HBoxContainer/DeployButton")
_addDeviceWindow = NodePath("AddDeviceWindow")
_deployWindow = NodePath("DeployWindow")
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 2
[node name="DeployTargetButton" type="OptionButton" parent="HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
item_count = 3
selected = 0
popup/item_0/text = "None"
popup/item_0/id = 10000
popup/item_1/text = ""
popup/item_1/id = -1
popup/item_1/separator = true
popup/item_2/text = "Add devkit device"
popup/item_2/id = 10001
[node name="DeployButton" type="Button" parent="HBoxContainer"]
custom_minimum_size = Vector2(32, 32)
layout_mode = 2
disabled = true
icon = ExtResource("2_rpj28")
icon_alignment = 1
expand_icon = true
[node name="AddDeviceWindow" parent="." instance=ExtResource("3_qfyb3")]
visible = false
[node name="DeployWindow" parent="." instance=ExtResource("4_8y8co")]
visible = false
[connection signal="item_selected" from="HBoxContainer/DeployTargetButton" to="." method="OnDeployTargetItemSelected"]
[connection signal="pressed" from="HBoxContainer/DeployButton" to="." method="Deploy"]

View File

@@ -1,38 +0,0 @@
using System.IO;
using System.Threading.Tasks;
using Godot;
namespace Laura.DeployToSteamOS;
public partial class DeployWindow
{
private async Task DeployBuild(Callable logCallable)
{
CurrentStep = DeployStep.Building;
CurrentProgress = StepProgress.Running;
UpdateUI();
// Adding a 2 second delay so the UI can update
await ToSignal(GetTree().CreateTimer(1), "timeout");
var buildTask = new TaskCompletionSource<bool>();
if (SettingsManager.Instance.Settings.UploadMethod == SettingsFile.UploadMethods.CleanReplace)
{
AddToConsole(DeployStep.Building, "Removing previous build as upload method is set to CleanReplace");
await SteamOSDevkitManager.RunSSHCommand(_device, "python3 ~/devkit-utils/steamos-delete --delete-title " + _gameId, logCallable);
}
GodotExportManager.ExportProject(
ProjectSettings.GlobalizePath("res://"),
Path.Join(_localPath, "game.x86_64"),
false,
logCallable,
() => { buildTask.SetResult(true); }
);
await buildTask.Task;
CurrentProgress = StepProgress.Succeeded;
UpdateUI();
}
}

View File

@@ -1,36 +0,0 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Godot;
namespace Laura.DeployToSteamOS;
public partial class DeployWindow
{
private async Task DeployCreateShortcut(Callable logCallable)
{
CurrentStep = DeployStep.CreateShortcut;
CurrentProgress = StepProgress.Running;
UpdateUI();
var createShortcutParameters = new SteamOSDevkitManager.CreateShortcutParameters
{
gameid = _gameId,
directory = _prepareUploadResult.Directory,
argv = new[] { "game.x86_64", SettingsManager.Instance.Settings.StartParameters },
settings = new Dictionary<string, string>
{
{ "steam_play", "0" }
},
};
// TODO: Fix Result, success/error are not filled in response but exist/dont
_createShortcutResult = await SteamOSDevkitManager.CreateShortcut(
_device,
createShortcutParameters,
logCallable
);
CurrentProgress = StepProgress.Succeeded;
UpdateUI();
}
}

View File

@@ -1,41 +0,0 @@
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Godot;
namespace Laura.DeployToSteamOS;
public partial class DeployWindow
{
private async Task DeployInit()
{
CurrentStep = DeployStep.Init;
CurrentProgress = StepProgress.Running;
UpdateUI();
await Task.Delay(0);
_gameId = ProjectSettings.GetSetting("application/config/name", "game").AsString();
_gameId = Regex.Replace(_gameId, @"[^a-zA-Z0-9]", string.Empty);
// Add current timestamp to gameid for incremental builds
if (SettingsManager.Instance.Settings.UploadMethod == SettingsFile.UploadMethods.Incremental)
{
_gameId += "_" + DateTimeOffset.Now.ToUnixTimeSeconds();
}
GD.Print($"[DeployToSteamOS] Deploying '{_gameId}' to '{_device.DisplayName} ({_device.Login}@{_device.IPAdress})'");
_localPath = SettingsManager.Instance.Settings.BuildPath;
if (DirAccess.Open(_localPath) == null)
{
GD.PrintErr($"[DeployToSteamOS] Build path '{_localPath}' does not exist.");
UpdateUIToFail();
return;
}
CurrentProgress = StepProgress.Succeeded;
UpdateUI();
}
}

View File

@@ -1,26 +0,0 @@
using System.Threading.Tasks;
using Godot;
namespace Laura.DeployToSteamOS;
public partial class DeployWindow
{
private async Task DeployPrepareUpload(Callable logCallable)
{
CurrentStep = DeployStep.PrepareUpload;
CurrentProgress = StepProgress.Running;
UpdateUI();
_prepareUploadResult = await SteamOSDevkitManager.PrepareUpload(
_device,
_gameId,
logCallable
);
AddToConsole(DeployStep.PrepareUpload, $"User: {_prepareUploadResult.User}");
AddToConsole(DeployStep.PrepareUpload, $"Directory: {_prepareUploadResult.Directory}");
CurrentProgress = StepProgress.Succeeded;
UpdateUI();
}
}

View File

@@ -1,33 +0,0 @@
using System;
using System.Threading.Tasks;
using Godot;
namespace Laura.DeployToSteamOS;
public partial class DeployWindow
{
private async Task DeployUpload(Callable logCallable)
{
CurrentStep = DeployStep.Uploading;
CurrentProgress = StepProgress.Running;
UpdateUI();
try
{
await SteamOSDevkitManager.CopyFiles(
_device,
_localPath,
_prepareUploadResult.Directory,
logCallable
);
}
catch (Exception e)
{
AddToConsole(DeployStep.Uploading, e.Message);
UpdateUIToFail();
}
CurrentProgress = StepProgress.Succeeded;
UpdateUI();
}
}

View File

@@ -1,304 +0,0 @@
using System.Collections.Generic;
using Godot;
namespace Laura.DeployToSteamOS;
[Tool]
public partial class DeployWindow : Window
{
public enum DeployStep
{
Init,
Building,
PrepareUpload,
Uploading,
CreateShortcut,
Done
}
public DeployStep CurrentStep = DeployStep.Init;
public enum StepProgress
{
Queued,
Running,
Succeeded,
Failed
}
public StepProgress CurrentProgress = StepProgress.Queued;
private string _localPath;
private string _gameId;
private SteamOSDevkitManager.Device _device;
private SteamOSDevkitManager.PrepareUploadResult _prepareUploadResult;
private SteamOSDevkitManager.CreateShortcutResult _createShortcutResult;
private Dictionary<StepProgress, Color> _colorsBright = new()
{
{ StepProgress.Queued, new Color("#6a6a6a") },
{ StepProgress.Running, new Color("#ffffff") },
{ StepProgress.Succeeded, new Color("#00f294") },
{ StepProgress.Failed, new Color("#ff4245") },
};
private Dictionary<StepProgress, Color> _colorsDim = new()
{
{ StepProgress.Queued, new Color("#1d1d1d") },
{ StepProgress.Running, new Color("#222222") },
{ StepProgress.Succeeded, new Color("#13241d") },
{ StepProgress.Failed, new Color("#241313") },
};
[ExportGroup("References")]
[Export] private VBoxContainer _buildingContainer;
[Export] private VBoxContainer _prepareUploadContainer;
[Export] private VBoxContainer _uploadingContainer;
[Export] private VBoxContainer _createShortcutContainer;
public override void _Process(double delta)
{
if (CurrentStep != DeployStep.Done)
{
var container = CurrentStep switch
{
DeployStep.Building => _buildingContainer,
DeployStep.PrepareUpload => _prepareUploadContainer,
DeployStep.Uploading => _uploadingContainer,
DeployStep.CreateShortcut => _createShortcutContainer,
_ => null
};
if (container != null)
{
var progressBar = container.GetNode<ProgressBar>("Progressbar");
if (progressBar.Value < 95f)
{
var shouldDoubleSpeed = CurrentStep is DeployStep.PrepareUpload or DeployStep.CreateShortcut;
progressBar.Value += (float)delta * (shouldDoubleSpeed ? 2f : 1f);
}
}
}
}
public async void Deploy(SteamOSDevkitManager.Device device)
{
if (device == null)
{
GD.PrintErr("[DeployToSteamOS] Device is not available.");
return;
}
_device = device;
_prepareUploadResult = null;
_createShortcutResult = null;
ResetUI();
Title = $"Deploying to {_device.DisplayName} ({_device.Login}@{_device.IPAdress})";
Show();
await DeployInit();
await DeployBuild(Callable.From((Variant log) => AddToConsole(DeployStep.Building, log.AsString())));
await DeployPrepareUpload(Callable.From((Variant log) => AddToConsole(DeployStep.PrepareUpload, log.AsString())));
await DeployUpload(Callable.From((Variant log) => AddToConsole(DeployStep.Uploading, log.AsString())));
await DeployCreateShortcut(Callable.From((Variant log) => AddToConsole(DeployStep.CreateShortcut, log.AsString())));
CurrentStep = DeployStep.Done;
CurrentProgress = StepProgress.Succeeded;
UpdateUI();
}
public void Close()
{
if (CurrentStep != DeployStep.Init && CurrentStep != DeployStep.Done) return;
Hide();
}
private void UpdateUI()
{
UpdateContainer(CurrentStep, CurrentProgress);
if (CurrentStep == DeployStep.Done)
{
SetConsoleVisibility(DeployStep.Building, false, false);
SetConsoleVisibility(DeployStep.PrepareUpload, false, false);
SetConsoleVisibility(DeployStep.Uploading, false, false);
SetConsoleVisibility(DeployStep.CreateShortcut, false, false);
}
}
private void ResetUI()
{
// Clear Consoles
List<Node> consoleNodes = new();
consoleNodes.AddRange(_buildingContainer.GetNode<VBoxContainer>("ConsoleContainer/ScrollContainer/VBoxContainer").GetChildren());
consoleNodes.AddRange(_prepareUploadContainer.GetNode<VBoxContainer>("ConsoleContainer/ScrollContainer/VBoxContainer").GetChildren());
consoleNodes.AddRange(_uploadingContainer.GetNode<VBoxContainer>("ConsoleContainer/ScrollContainer/VBoxContainer").GetChildren());
consoleNodes.AddRange(_createShortcutContainer.GetNode<VBoxContainer>("ConsoleContainer/ScrollContainer/VBoxContainer").GetChildren());
foreach (var consoleNode in consoleNodes)
{
consoleNode.QueueFree();
}
// Clear States
UpdateContainer(DeployStep.Building, StepProgress.Queued);
UpdateContainer(DeployStep.PrepareUpload, StepProgress.Queued);
UpdateContainer(DeployStep.Uploading, StepProgress.Queued);
UpdateContainer(DeployStep.CreateShortcut, StepProgress.Queued);
CurrentStep = DeployStep.Init;
CurrentProgress = StepProgress.Queued;
}
private void UpdateContainer(DeployStep step, StepProgress progress)
{
var container = step switch
{
DeployStep.Building => _buildingContainer,
DeployStep.PrepareUpload => _prepareUploadContainer,
DeployStep.Uploading => _uploadingContainer,
DeployStep.CreateShortcut => _createShortcutContainer,
_ => null
};
if (container == null) return;
var headerContainer = container.GetNode<PanelContainer>("HeaderContainer");
var label = headerContainer.GetNode<Label>("HBoxContainer/Label");
var toggleConsoleButton = headerContainer.GetNode<Button>("HBoxContainer/ToggleConsoleButton");
var progressBar = container.GetNode<ProgressBar>("Progressbar");
label.AddThemeColorOverride("font_color", _colorsBright[progress]);
headerContainer.AddThemeStyleboxOverride("panel", new StyleBoxFlat
{
BgColor = _colorsDim[progress],
ContentMarginTop = 10,
ContentMarginBottom = 10,
ContentMarginLeft = 10,
ContentMarginRight = 10,
});
progressBar.AddThemeStyleboxOverride("fill", new StyleBoxFlat
{
BgColor = _colorsBright[progress],
});
progressBar.Value = progress switch
{
StepProgress.Queued => 0,
StepProgress.Running => 0,
StepProgress.Succeeded => 100,
StepProgress.Failed => 100,
_ => progressBar.Value
};
SetConsoleVisibility(step, progress == StepProgress.Running, false);
toggleConsoleButton.Visible = progress is StepProgress.Succeeded or StepProgress.Failed;
toggleConsoleButton.Disabled = progress is not StepProgress.Succeeded and not StepProgress.Failed;
}
private void AddToConsole(DeployStep step, string text)
{
var consoleContainer = step switch
{
DeployStep.Building => _buildingContainer.GetNode<PanelContainer>("ConsoleContainer"),
DeployStep.PrepareUpload => _prepareUploadContainer.GetNode<PanelContainer>("ConsoleContainer"),
DeployStep.Uploading => _uploadingContainer.GetNode<PanelContainer>("ConsoleContainer"),
DeployStep.CreateShortcut => _createShortcutContainer.GetNode<PanelContainer>("ConsoleContainer"),
_ => null
};
if (consoleContainer == null) return;
var consoleScrollContainer = consoleContainer.GetNode<ScrollContainer>("ScrollContainer");
var consoleVBoxContainer = consoleScrollContainer.GetNode<VBoxContainer>("VBoxContainer");
// Create new Label
var newLabel = new Label { Text = text };
newLabel.AddThemeFontSizeOverride("font_size", 12);
newLabel.AutowrapMode = TextServer.AutowrapMode.Word;
newLabel.SizeFlagsHorizontal = Control.SizeFlags.ExpandFill;
consoleVBoxContainer.AddChild(newLabel);
consoleScrollContainer.ScrollVertical = (int)consoleScrollContainer.GetVScrollBar().MaxValue;
}
private void SetConsoleVisibility(DeployStep step, bool shouldOpen, bool closeOthers)
{
var consoleContainer = step switch
{
DeployStep.Building => _buildingContainer.GetNode<PanelContainer>("ConsoleContainer"),
DeployStep.PrepareUpload => _prepareUploadContainer.GetNode<PanelContainer>("ConsoleContainer"),
DeployStep.Uploading => _uploadingContainer.GetNode<PanelContainer>("ConsoleContainer"),
DeployStep.CreateShortcut => _createShortcutContainer.GetNode<PanelContainer>("ConsoleContainer"),
_ => null
};
if (consoleContainer == null) return;
// Open Container
if (shouldOpen)
{
// Close all other open containers if not running anymore
if (closeOthers)
{
var consoleContainers = new List<PanelContainer>
{
_buildingContainer.GetNode<PanelContainer>("ConsoleContainer"),
_prepareUploadContainer.GetNode<PanelContainer>("ConsoleContainer"),
_uploadingContainer.GetNode<PanelContainer>("ConsoleContainer"),
_createShortcutContainer.GetNode<PanelContainer>("ConsoleContainer")
};
foreach (var container in consoleContainers)
{
container.Visible = false;
container.GetParent<VBoxContainer>().SizeFlagsVertical = Control.SizeFlags.ShrinkBegin;
}
}
// Open container
consoleContainer.Visible = true;
consoleContainer.GetParent<VBoxContainer>().SizeFlagsVertical = Control.SizeFlags.ExpandFill;
}
else
{
consoleContainer.Visible = false;
consoleContainer.GetParent<VBoxContainer>().SizeFlagsVertical = Control.SizeFlags.ShrinkBegin;
}
}
private void ToggleConsoleVisiblity(DeployStep step)
{
var consoleContainer = step switch
{
DeployStep.Building => _buildingContainer.GetNode<PanelContainer>("ConsoleContainer"),
DeployStep.PrepareUpload => _prepareUploadContainer.GetNode<PanelContainer>("ConsoleContainer"),
DeployStep.Uploading => _uploadingContainer.GetNode<PanelContainer>("ConsoleContainer"),
DeployStep.CreateShortcut => _createShortcutContainer.GetNode<PanelContainer>("ConsoleContainer"),
_ => null
};
if (consoleContainer == null) return;
SetConsoleVisibility(step, !consoleContainer.Visible, CurrentStep == DeployStep.Done);
}
private void UpdateUIToFail()
{
CurrentProgress = StepProgress.Failed;
UpdateUI();
CurrentStep = DeployStep.Done;
CurrentProgress = StepProgress.Queued;
UpdateUI();
}
public void OnBuildingConsolePressed()
{
ToggleConsoleVisiblity(DeployStep.Building);
}
public void OnPrepareUploadConsolePressed()
{
ToggleConsoleVisiblity(DeployStep.PrepareUpload);
}
public void OnUploadingConsolePressed()
{
ToggleConsoleVisiblity(DeployStep.Uploading);
}
public void OnCreatingShortcutConsolePressed()
{
ToggleConsoleVisiblity(DeployStep.CreateShortcut);
}
}

View File

@@ -1,287 +0,0 @@
[gd_scene load_steps=17 format=3 uid="uid://ds2umdqybfls8"]
[ext_resource type="Script" path="res://addons/deploy_to_steamos/deploy_window/DeployWindow.cs" id="1_01184"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_4voio"]
content_margin_left = 10.0
content_margin_top = 10.0
content_margin_right = 10.0
content_margin_bottom = 10.0
bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1)
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_e8gqy"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_lhk4y"]
bg_color = Color(0.866667, 0.866667, 0.866667, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_asgva"]
content_margin_left = 10.0
content_margin_top = 10.0
content_margin_right = 10.0
content_margin_bottom = 10.0
bg_color = Color(0.113725, 0.113725, 0.113725, 1)
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_7uvru"]
content_margin_left = 5.0
content_margin_top = 5.0
content_margin_right = 5.0
content_margin_bottom = 5.0
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ojxav"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_e3114"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_gqti7"]
bg_color = Color(0.866667, 0.866667, 0.866667, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ok20f"]
content_margin_left = 10.0
content_margin_top = 10.0
content_margin_right = 10.0
content_margin_bottom = 10.0
bg_color = Color(0.113725, 0.113725, 0.113725, 1)
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_aj0up"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_td6y3"]
bg_color = Color(0.866667, 0.866667, 0.866667, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_017mf"]
content_margin_left = 10.0
content_margin_top = 10.0
content_margin_right = 10.0
content_margin_bottom = 10.0
bg_color = Color(0.113725, 0.113725, 0.113725, 1)
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_encuu"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_esvxa"]
bg_color = Color(0.866667, 0.866667, 0.866667, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dgegm"]
content_margin_left = 10.0
content_margin_top = 10.0
content_margin_right = 10.0
content_margin_bottom = 10.0
bg_color = Color(0.113725, 0.113725, 0.113725, 1)
[node name="DeployWindow" type="Window" node_paths=PackedStringArray("_buildingContainer", "_prepareUploadContainer", "_uploadingContainer", "_createShortcutContainer")]
title = "Deploying to steamdeck (deck@127.0.0.1)"
initial_position = 1
size = Vector2i(450, 600)
transient = true
min_size = Vector2i(450, 600)
script = ExtResource("1_01184")
_buildingContainer = NodePath("PanelContainer/VBoxContainer/BuildContainer")
_prepareUploadContainer = NodePath("PanelContainer/VBoxContainer/PrepareUploadContainer")
_uploadingContainer = NodePath("PanelContainer/VBoxContainer/UploadContainer")
_createShortcutContainer = NodePath("PanelContainer/VBoxContainer/CreateShortcutContainer")
[node name="PanelContainer" type="PanelContainer" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_4voio")
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 10
[node name="BuildContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 0
theme_override_constants/separation = 0
[node name="Progressbar" type="ProgressBar" parent="PanelContainer/VBoxContainer/BuildContainer"]
custom_minimum_size = Vector2(0, 2)
layout_mode = 2
theme_override_styles/background = SubResource("StyleBoxEmpty_e8gqy")
theme_override_styles/fill = SubResource("StyleBoxFlat_lhk4y")
show_percentage = false
[node name="HeaderContainer" type="PanelContainer" parent="PanelContainer/VBoxContainer/BuildContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_asgva")
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBoxContainer/BuildContainer/HeaderContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/BuildContainer/HeaderContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.415686, 0.415686, 0.415686, 1)
text = "Building Project"
[node name="ToggleConsoleButton" type="Button" parent="PanelContainer/VBoxContainer/BuildContainer/HeaderContainer/HBoxContainer"]
layout_mode = 2
disabled = true
text = "Output"
[node name="ConsoleContainer" type="PanelContainer" parent="PanelContainer/VBoxContainer/BuildContainer"]
visible = false
layout_mode = 2
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxEmpty_7uvru")
[node name="ScrollContainer" type="ScrollContainer" parent="PanelContainer/VBoxContainer/BuildContainer/ConsoleContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxEmpty_ojxav")
horizontal_scroll_mode = 0
vertical_scroll_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/BuildContainer/ConsoleContainer/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = 0
[node name="PrepareUploadContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 0
theme_override_constants/separation = 0
[node name="Progressbar" type="ProgressBar" parent="PanelContainer/VBoxContainer/PrepareUploadContainer"]
custom_minimum_size = Vector2(0, 2)
layout_mode = 2
theme_override_styles/background = SubResource("StyleBoxEmpty_e3114")
theme_override_styles/fill = SubResource("StyleBoxFlat_gqti7")
show_percentage = false
[node name="HeaderContainer" type="PanelContainer" parent="PanelContainer/VBoxContainer/PrepareUploadContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_ok20f")
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBoxContainer/PrepareUploadContainer/HeaderContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/PrepareUploadContainer/HeaderContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.415686, 0.415686, 0.415686, 1)
text = "Preparing Upload"
[node name="ToggleConsoleButton" type="Button" parent="PanelContainer/VBoxContainer/PrepareUploadContainer/HeaderContainer/HBoxContainer"]
layout_mode = 2
disabled = true
text = "Output"
[node name="ConsoleContainer" type="PanelContainer" parent="PanelContainer/VBoxContainer/PrepareUploadContainer"]
visible = false
layout_mode = 2
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxEmpty_7uvru")
[node name="ScrollContainer" type="ScrollContainer" parent="PanelContainer/VBoxContainer/PrepareUploadContainer/ConsoleContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxEmpty_ojxav")
horizontal_scroll_mode = 0
vertical_scroll_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/PrepareUploadContainer/ConsoleContainer/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 0
theme_override_constants/separation = 0
[node name="UploadContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 0
[node name="Progressbar" type="ProgressBar" parent="PanelContainer/VBoxContainer/UploadContainer"]
custom_minimum_size = Vector2(0, 2)
layout_mode = 2
theme_override_styles/background = SubResource("StyleBoxEmpty_aj0up")
theme_override_styles/fill = SubResource("StyleBoxFlat_td6y3")
show_percentage = false
[node name="HeaderContainer" type="PanelContainer" parent="PanelContainer/VBoxContainer/UploadContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_017mf")
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBoxContainer/UploadContainer/HeaderContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/UploadContainer/HeaderContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.415686, 0.415686, 0.415686, 1)
text = "Uploading Project"
[node name="ToggleConsoleButton" type="Button" parent="PanelContainer/VBoxContainer/UploadContainer/HeaderContainer/HBoxContainer"]
layout_mode = 2
disabled = true
text = "Output"
[node name="ConsoleContainer" type="PanelContainer" parent="PanelContainer/VBoxContainer/UploadContainer"]
visible = false
layout_mode = 2
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxEmpty_7uvru")
[node name="ScrollContainer" type="ScrollContainer" parent="PanelContainer/VBoxContainer/UploadContainer/ConsoleContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxEmpty_ojxav")
horizontal_scroll_mode = 0
vertical_scroll_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/UploadContainer/ConsoleContainer/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = 0
[node name="CreateShortcutContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 0
[node name="Progressbar" type="ProgressBar" parent="PanelContainer/VBoxContainer/CreateShortcutContainer"]
custom_minimum_size = Vector2(0, 2)
layout_mode = 2
theme_override_styles/background = SubResource("StyleBoxEmpty_encuu")
theme_override_styles/fill = SubResource("StyleBoxFlat_esvxa")
show_percentage = false
[node name="HeaderContainer" type="PanelContainer" parent="PanelContainer/VBoxContainer/CreateShortcutContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_dgegm")
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBoxContainer/CreateShortcutContainer/HeaderContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/CreateShortcutContainer/HeaderContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.415686, 0.415686, 0.415686, 1)
text = "Creating Shortcut"
[node name="ToggleConsoleButton" type="Button" parent="PanelContainer/VBoxContainer/CreateShortcutContainer/HeaderContainer/HBoxContainer"]
layout_mode = 2
disabled = true
text = "Output"
[node name="ConsoleContainer" type="PanelContainer" parent="PanelContainer/VBoxContainer/CreateShortcutContainer"]
visible = false
layout_mode = 2
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxEmpty_7uvru")
[node name="ScrollContainer" type="ScrollContainer" parent="PanelContainer/VBoxContainer/CreateShortcutContainer/ConsoleContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxEmpty_ojxav")
horizontal_scroll_mode = 0
vertical_scroll_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/CreateShortcutContainer/ConsoleContainer/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = 0
[connection signal="close_requested" from="." to="." method="Close"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/BuildContainer/HeaderContainer/HBoxContainer/ToggleConsoleButton" to="." method="OnBuildingConsolePressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/PrepareUploadContainer/HeaderContainer/HBoxContainer/ToggleConsoleButton" to="." method="OnPrepareUploadConsolePressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/UploadContainer/HeaderContainer/HBoxContainer/ToggleConsoleButton" to="." method="OnUploadingConsolePressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/CreateShortcutContainer/HeaderContainer/HBoxContainer/ToggleConsoleButton" to="." method="OnCreatingShortcutConsolePressed"]

View File

@@ -1 +0,0 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M2 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-4a1 1 0 0 1-1-1V3a1 1 0 0 0-1-1z" fill="#e0e0e0"/></svg>

Before

Width:  |  Height:  |  Size: 219 B

View File

@@ -1,37 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://du661vtsmqc7h"
path="res://.godot/imported/folder.svg-3209c1ff45131a205cbeb3923822ebc7.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/deploy_to_steamos/folder.svg"
dest_files=["res://.godot/imported/folder.svg-3209c1ff45131a205cbeb3923822ebc7.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Ebene_1" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 24 24">
<defs>
<style>
.cls-1 {
fill: #e0e0e0;
stroke-width: 0px;
}
</style>
</defs>
<path class="cls-1" d="M12,2C6.9,2,2.3,6.1,2,11.2c1.3.6,6.8,2.8,6.8,2.8l2.2-4.4-3.4-1.7c-.9-.5.2-1.8.5-2.4,0-.2.4-.4.6-.4h4.2l7.1,3.7c.3.2.5.6.3.9-2.4,4.5-1.1,4-5.6,1.8l-3.5,6.8c-1.1,2.2-4.6.8-3.9-1.5l-5-2.1c2.8,10,17.3,9.5,19.4-.7,1.4-6.1-3.5-12-9.7-12Z"/>
<rect class="cls-1" x="16.6" y="9.7" width="2.1" height="1.4" transform="translate(.3 21.3) rotate(-62.9)"/>
</svg>

Before

Width:  |  Height:  |  Size: 641 B

View File

@@ -1,37 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://s1tcpal4iir4"
path="res://.godot/imported/icon.svg-3fd3169593c3fd142e77475bb0bb8a61.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/deploy_to_steamos/icon.svg"
dest_files=["res://.godot/imported/icon.svg-3fd3169593c3fd142e77475bb0bb8a61.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@@ -1,7 +0,0 @@
[plugin]
name="Deploy to SteamOS"
description="A Godot plugin integrating a direct deployment workflow to SteamOS"
author="Laura Sofia Heimann"
version="1.1.0"
script="Plugin.cs"

View File

@@ -1,101 +0,0 @@
using Godot;
namespace Laura.DeployToSteamOS;
[Tool]
public partial class SettingsPanel : PanelContainer
{
[ExportGroup("References")]
[Export] private Label _versionLabel;
[Export] private AddDeviceWindow _addDeviceWindow;
[Export] private LineEdit _buildPathLineEdit;
[Export] private FileDialog _buildPathFileDialog;
[Export] private LineEdit _startParametersLineEdit;
[Export] private OptionButton _uploadMethodOptionButton;
[Export] private Label _uploadMethodDifferentialHintLabel;
[Export] private Label _uploadMethodIncrementalHintLabel;
[Export] private Label _uploadMethodCleanReplaceHintLabel;
private float _saveCooldown = 2f;
public override void _Process(double delta)
{
if (SettingsManager.Instance.IsDirty && _saveCooldown < 0f)
{
_saveCooldown = 2f;
SettingsManager.Instance.Save();
}
if (SettingsManager.Instance.IsDirty && Visible)
{
_saveCooldown -= (float)delta;
}
}
public void OnVisibilityChanged()
{
if (Visible)
{
ShowPanel();
}
else
{
HidePanel();
}
}
private void ShowPanel()
{
_buildPathLineEdit.Text = SettingsManager.Instance.Settings.BuildPath;
_startParametersLineEdit.Text = SettingsManager.Instance.Settings.StartParameters;
_uploadMethodOptionButton.Selected = (int)SettingsManager.Instance.Settings.UploadMethod;
_saveCooldown = 2f;
}
private void HidePanel()
{
}
public void BuildPathTextChanged(string newBuildPath)
{
SettingsManager.Instance.Settings.BuildPath = newBuildPath;
_buildPathLineEdit.Text = newBuildPath;
_saveCooldown = 2f;
SettingsManager.Instance.IsDirty = true;
}
public void BuildPathOpenFileDialog()
{
_buildPathFileDialog.Show();
}
public void StartParametersTextChanged(string newStartParameters)
{
SettingsManager.Instance.Settings.StartParameters = newStartParameters;
_startParametersLineEdit.Text = newStartParameters;
_saveCooldown = 2f;
SettingsManager.Instance.IsDirty = true;
}
public void UploadMethodItemSelected(int newItemIndex)
{
var newUploadMethod = (SettingsFile.UploadMethods)newItemIndex;
SettingsManager.Instance.Settings.UploadMethod = newUploadMethod;
_uploadMethodOptionButton.Selected = newItemIndex;
_saveCooldown = 2f;
SettingsManager.Instance.IsDirty = true;
_uploadMethodDifferentialHintLabel.Visible = newUploadMethod == SettingsFile.UploadMethods.Differential;
_uploadMethodIncrementalHintLabel.Visible = newUploadMethod == SettingsFile.UploadMethods.Incremental;
_uploadMethodCleanReplaceHintLabel.Visible = newUploadMethod == SettingsFile.UploadMethods.CleanReplace;
}
public void PairDevices()
{
_addDeviceWindow.Show();
}
}

View File

@@ -1,259 +0,0 @@
[gd_scene load_steps=12 format=3 uid="uid://c8k27e2fcl21j"]
[ext_resource type="Script" path="res://addons/deploy_to_steamos/settings_panel/SettingsPanel.cs" id="1_sde4n"]
[ext_resource type="Texture2D" uid="uid://s1tcpal4iir4" path="res://addons/deploy_to_steamos/icon.svg" id="2_uruwd"]
[ext_resource type="Texture2D" uid="uid://du661vtsmqc7h" path="res://addons/deploy_to_steamos/folder.svg" id="3_w3m1c"]
[ext_resource type="PackedScene" uid="uid://6be5afncp3nr" path="res://addons/deploy_to_steamos/add_device_window/add_device_window.tscn" id="4_yoa1a"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_txpoc"]
content_margin_left = 15.0
content_margin_top = 15.0
content_margin_right = 15.0
content_margin_bottom = 15.0
bg_color = Color(0.0666667, 0.0666667, 0.0666667, 1)
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_t6jug"]
content_margin_left = 15.0
content_margin_top = 15.0
content_margin_right = 15.0
content_margin_bottom = 15.0
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_twxhr"]
texture = ExtResource("2_uruwd")
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jrblc"]
content_margin_left = 15.0
content_margin_top = 15.0
content_margin_right = 15.0
content_margin_bottom = 15.0
bg_color = Color(0.133333, 0.133333, 0.133333, 1)
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_so52p"]
content_margin_left = 5.0
content_margin_top = 5.0
content_margin_right = 5.0
content_margin_bottom = 5.0
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_r6ghl"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_2gufl"]
content_margin_left = 10.0
content_margin_top = 10.0
content_margin_right = 10.0
content_margin_bottom = 10.0
bg_color = Color(0.2, 0.2, 0.2, 1)
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
[node name="Deploy to SteamOS" type="PanelContainer" node_paths=PackedStringArray("_versionLabel", "_addDeviceWindow", "_buildPathLineEdit", "_buildPathFileDialog", "_startParametersLineEdit", "_uploadMethodOptionButton", "_uploadMethodDifferentialHintLabel", "_uploadMethodIncrementalHintLabel", "_uploadMethodCleanReplaceHintLabel")]
offset_right = 600.0
offset_bottom = 500.0
theme_override_styles/panel = SubResource("StyleBoxFlat_txpoc")
script = ExtResource("1_sde4n")
_versionLabel = NodePath("VBoxContainer/LogoContainer/VBoxContainer/VersionLabel")
_addDeviceWindow = NodePath("AddDeviceWindow")
_buildPathLineEdit = NodePath("VBoxContainer/ScrollContainer/SettingsContainer/BuildPathContainer/HBoxContainer/HBoxContainer/BuildPathInput")
_buildPathFileDialog = NodePath("BuildPathFileDialog")
_startParametersLineEdit = NodePath("VBoxContainer/ScrollContainer/SettingsContainer/StartParametersContainer/HBoxContainer/StartParametersInput")
_uploadMethodOptionButton = NodePath("VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer/VBoxContainer/HBoxContainer/PanelContainer/UploadMethodOptionButton")
_uploadMethodDifferentialHintLabel = NodePath("VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer/VBoxContainer/UploadMethodHintContainer/DifferentialHintLabel")
_uploadMethodIncrementalHintLabel = NodePath("VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer/VBoxContainer/UploadMethodHintContainer/IncrementalHintLabel")
_uploadMethodCleanReplaceHintLabel = NodePath("VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer/VBoxContainer/UploadMethodHintContainer/CleanReplaceHintLabel")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 2
theme_override_constants/separation = 5
[node name="LogoContainer" type="PanelContainer" parent="VBoxContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxEmpty_t6jug")
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/LogoContainer"]
layout_mode = 2
theme_override_constants/separation = 0
alignment = 1
[node name="LogoContainer" type="HBoxContainer" parent="VBoxContainer/LogoContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 10
alignment = 1
[node name="Icon" type="Panel" parent="VBoxContainer/LogoContainer/VBoxContainer/LogoContainer"]
custom_minimum_size = Vector2(32, 32)
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxTexture_twxhr")
[node name="DevkitPathLabel" type="Label" parent="VBoxContainer/LogoContainer/VBoxContainer/LogoContainer"]
layout_mode = 2
size_flags_horizontal = 0
text = "Deploy to SteamOS"
[node name="VersionLabel" type="Label" parent="VBoxContainer/LogoContainer/VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 4
theme_override_colors/font_color = Color(1, 1, 1, 0.490196)
theme_override_font_sizes/font_size = 12
text = "Version 1.1.0"
horizontal_alignment = 1
[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_jrblc")
[node name="SettingsContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 0
[node name="BuildPathContainer" type="PanelContainer" parent="VBoxContainer/ScrollContainer/SettingsContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxEmpty_so52p")
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/ScrollContainer/SettingsContainer/BuildPathContainer"]
layout_mode = 2
theme_override_constants/separation = 5
[node name="BuildPathLabel" type="Label" parent="VBoxContainer/ScrollContainer/SettingsContainer/BuildPathContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Build Path"
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/ScrollContainer/SettingsContainer/BuildPathContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = 5
[node name="BuildPathInput" type="LineEdit" parent="VBoxContainer/ScrollContainer/SettingsContainer/BuildPathContainer/HBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "C:/Users/hello/Development/Godot4-DeployToSteamOS-Builds"
[node name="BrowseButton" type="Button" parent="VBoxContainer/ScrollContainer/SettingsContainer/BuildPathContainer/HBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/icon_max_width = 20
icon = ExtResource("3_w3m1c")
[node name="StartParametersContainer" type="PanelContainer" parent="VBoxContainer/ScrollContainer/SettingsContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxEmpty_so52p")
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/ScrollContainer/SettingsContainer/StartParametersContainer"]
layout_mode = 2
theme_override_constants/separation = 5
[node name="StartParametersLabel" type="Label" parent="VBoxContainer/ScrollContainer/SettingsContainer/StartParametersContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Start Parameters"
[node name="StartParametersInput" type="LineEdit" parent="VBoxContainer/ScrollContainer/SettingsContainer/StartParametersContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="UploadMethodContainer" type="PanelContainer" parent="VBoxContainer/ScrollContainer/SettingsContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxEmpty_so52p")
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer"]
layout_mode = 2
theme_override_constants/separation = 10
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 5
[node name="UploadMethodLabel" type="Label" parent="VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Upload Method"
[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_styles/panel = SubResource("StyleBoxEmpty_r6ghl")
[node name="UploadMethodOptionButton" type="OptionButton" parent="VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer/VBoxContainer/HBoxContainer/PanelContainer"]
layout_mode = 2
item_count = 3
selected = 0
popup/item_0/text = "Differential"
popup/item_0/id = 0
popup/item_1/text = "Incremental"
popup/item_1/id = 1
popup/item_2/text = "CleanReplace"
popup/item_2/id = 2
[node name="UploadMethodHintContainer" type="PanelContainer" parent="VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer/VBoxContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_2gufl")
[node name="DifferentialHintLabel" type="Label" parent="VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer/VBoxContainer/UploadMethodHintContainer"]
custom_minimum_size = Vector2(0, 15)
layout_mode = 2
theme_override_colors/font_color = Color(1, 1, 1, 0.588235)
theme_override_font_sizes/font_size = 12
text = "Only changed and new files of the build will be uploaded."
autowrap_mode = 3
[node name="IncrementalHintLabel" type="Label" parent="VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer/VBoxContainer/UploadMethodHintContainer"]
visible = false
custom_minimum_size = Vector2(0, 15)
layout_mode = 2
theme_override_colors/font_color = Color(1, 1, 1, 0.588235)
theme_override_font_sizes/font_size = 12
text = "A new build will be uploaded with the current timestamp. Existing builds will not be changed."
autowrap_mode = 3
[node name="CleanReplaceHintLabel" type="Label" parent="VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer/VBoxContainer/UploadMethodHintContainer"]
visible = false
custom_minimum_size = Vector2(0, 15)
layout_mode = 2
theme_override_colors/font_color = Color(1, 1, 1, 0.588235)
theme_override_font_sizes/font_size = 12
text = "Before the new build will be uploaded, the old one will be fully removed."
autowrap_mode = 3
[node name="DevicesContainer" type="PanelContainer" parent="VBoxContainer/ScrollContainer/SettingsContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxEmpty_so52p")
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/ScrollContainer/SettingsContainer/DevicesContainer"]
layout_mode = 2
theme_override_constants/separation = 5
[node name="DevicesLabel" type="Label" parent="VBoxContainer/ScrollContainer/SettingsContainer/DevicesContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Devices"
[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer/ScrollContainer/SettingsContainer/DevicesContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_styles/panel = SubResource("StyleBoxEmpty_r6ghl")
[node name="PairDevicesButton" type="Button" parent="VBoxContainer/ScrollContainer/SettingsContainer/DevicesContainer/HBoxContainer/PanelContainer"]
layout_mode = 2
size_flags_horizontal = 0
text = "Pair Devices"
[node name="BuildPathFileDialog" type="FileDialog" parent="."]
title = "Open a Directory"
initial_position = 2
size = Vector2i(700, 400)
ok_button_text = "Select Current Folder"
file_mode = 2
access = 2
[node name="AddDeviceWindow" parent="." instance=ExtResource("4_yoa1a")]
visible = false
[connection signal="visibility_changed" from="." to="." method="OnVisibilityChanged"]
[connection signal="text_changed" from="VBoxContainer/ScrollContainer/SettingsContainer/BuildPathContainer/HBoxContainer/HBoxContainer/BuildPathInput" to="." method="BuildPathTextChanged"]
[connection signal="pressed" from="VBoxContainer/ScrollContainer/SettingsContainer/BuildPathContainer/HBoxContainer/HBoxContainer/BrowseButton" to="." method="BuildPathOpenFileDialog"]
[connection signal="text_changed" from="VBoxContainer/ScrollContainer/SettingsContainer/StartParametersContainer/HBoxContainer/StartParametersInput" to="." method="StartParametersTextChanged"]
[connection signal="item_selected" from="VBoxContainer/ScrollContainer/SettingsContainer/UploadMethodContainer/VBoxContainer/HBoxContainer/PanelContainer/UploadMethodOptionButton" to="." method="UploadMethodItemSelected"]
[connection signal="pressed" from="VBoxContainer/ScrollContainer/SettingsContainer/DevicesContainer/HBoxContainer/PanelContainer/PairDevicesButton" to="." method="PairDevices"]
[connection signal="dir_selected" from="BuildPathFileDialog" to="." method="BuildPathTextChanged"]

View File

@@ -15,10 +15,6 @@ run/main_scene="res://src/Main.tscn"
config/features=PackedStringArray("4.4", "C#", "GL Compatibility")
boot_splash/show_image=false
[autoload]
SettingsManager="*res://addons/deploy_to_steamos/SettingsManager.cs"
[display]
window/size/viewport_width=1920
@@ -30,7 +26,7 @@ project/assembly_name="GameJamDungeon"
[editor_plugins]
enabled=PackedStringArray("res://addons/SimpleDungeons/plugin.cfg", "res://addons/deploy_to_steamos/plugin.cfg")
enabled=PackedStringArray("res://addons/SimpleDungeons/plugin.cfg")
[input]

View File

@@ -39,7 +39,7 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
[Dependency] IGameRepo GameRepo => this.DependOn<IGameRepo>();
[Export]
public EnemyStatInfo EnemyStatInfo { get; set; } = new();
public EnemyStatInfo EnemyStatInfo { get; set; } = default!;
public static PackedScene CollisionDetectorScene => GD.Load<PackedScene>("res://src/enemy/CollisionDetector.tscn");
@@ -57,6 +57,8 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
[Node] public AnimationPlayer AnimationPlayer { get; set; } = default!;
[Node] public RayCast3D Raycast { get; set; } = default!;
public void Setup()
{
EnemyLogic = new EnemyLogic();
@@ -99,7 +101,22 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
private void LineOfSight_BodyEntered(Node3D body)
{
EnemyLogic.Input(new EnemyLogic.Input.Alerted());
var overlappingBodies = LineOfSight.GetOverlappingBodies();
foreach (var overlap in overlappingBodies)
{
Raycast.LookAt(GameRepo.PlayerGlobalPosition.Value, Vector3.Up);
Raycast.ForceRaycastUpdate();
if (Raycast.IsColliding())
{
var collider = Raycast.GetCollider();
if (collider is IPlayer player)
{
Raycast.DebugShapeCustomColor = Color.FromString("Purple", Colors.Purple);
EnemyLogic.Input(new EnemyLogic.Input.Alerted());
}
}
}
}
public void OnResolved()

View File

@@ -15,21 +15,27 @@ namespace GameJamDungeon
public int BaseDefense { get; set; }
[Export]
public double ElementAResistance { get; set; }
public double TelluricResistance { get; set; }
[Export]
public double ElementBResistance { get; set; }
public double AeolicResistance { get; set; }
[Export]
public double ElementCResistance { get; set; }
public double HydricResistance { get; set; }
[Export]
public double BaseElementADamageBonus { get; set; }
public double IgneousResistance { get; set; }
[Export]
public double BaseElementBDamageBonus { get; set; }
public double TelluricDamageBonus { get; set; }
[Export]
public double BaseElementCDamageBonus { get; set; }
public double AeolicDamageBonus { get; set; }
[Export]
public double BaseHydricDamageBonus { get; set; }
[Export]
public double IgneousDamageBonus { get; set; }
}
}

View File

@@ -1,15 +1,17 @@
[gd_resource type="Resource" script_class="EnemyStatInfo" load_steps=2 format=3 uid="uid://c8h26ip4ly18r"]
[gd_resource type="Resource" script_class="EnemyStatInfo" load_steps=2 format=3 uid="uid://c08wbuumw6dk5"]
[ext_resource type="Script" path="res://src/enemy/EnemyStatInfo.cs" id="1_oabqi"]
[ext_resource type="Script" path="res://src/enemy/EnemyStatInfo.cs" id="1_2i74g"]
[resource]
script = ExtResource("1_oabqi")
script = ExtResource("1_2i74g")
MaximumHP = 50.0
BaseAttack = 10
BaseDefense = 1
ElementAResistance = 15.0
ElementBResistance = -20.0
ElementCResistance = 0.0
BaseElementADamageBonus = 0.0
BaseElementBDamageBonus = 0.0
BaseElementCDamageBonus = 0.0
BaseDefense = 2
TelluricResistance = 0.0
AeolicResistance = 0.0
HydricResistance = 0.0
IgneousResistance = 0.0
TelluricDamageBonus = 0.0
AeolicDamageBonus = 0.0
BaseHydricDamageBonus = 0.0
IgneousDamageBonus = 0.0

View File

@@ -1,7 +1,7 @@
[gd_scene load_steps=15 format=4 uid="uid://dcgj5i52i76gj"]
[ext_resource type="Script" path="res://src/enemy/Enemy.cs" id="1_jw471"]
[ext_resource type="Resource" uid="uid://c8h26ip4ly18r" path="res://src/enemy/enemy_types/floating_enemy/FloatingEnemy.tres" id="2_ewaf6"]
[ext_resource type="Resource" uid="uid://c08wbuumw6dk5" path="res://src/enemy/enemy_types/floating_enemy/FloatingEnemy.tres" id="2_b8sx5"]
[ext_resource type="Script" path="res://src/hitbox/Hitbox.cs" id="3_erpyl"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_5tio6"]
@@ -179,7 +179,7 @@ collision_layer = 10
collision_mask = 9
axis_lock_linear_y = true
script = ExtResource("1_jw471")
EnemyStatInfo = ExtResource("2_ewaf6")
EnemyStatInfo = ExtResource("2_b8sx5")
[node name="DISSAPPEARING ENEMY" type="Node3D" parent="."]
@@ -231,3 +231,8 @@ script = ExtResource("3_erpyl")
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.189337, 0.217529, -0.78415)
shape = SubResource("BoxShape3D_0yire")
disabled = true
[node name="Raycast" type="RayCast3D" parent="."]
unique_name_in_owner = true
target_position = Vector3(0, 0, -3)
collision_mask = 3

View File

@@ -29,6 +29,8 @@ environment = SubResource("Environment_fke5g")
[node name="Player" parent="." instance=ExtResource("3_kk6ly")]
process_mode = 1
transform = Transform3D(0.0871905, 0, -0.996192, 0, 1, 0, 0.996192, 0, 0.0871905, -71.4241, -4.70883, -0.527107)
MoveSpeed = 8.0
Acceleration = 4.0
[node name="RigidBody3D" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -69.9907, -4.96505, 0)

View File

@@ -127,6 +127,8 @@ axis_lock_angular_z = true
motion_mode = 1
script = ExtResource("1_xcol5")
RotationSpeed = 0.025
MoveSpeed = 3.0
Acceleration = 0.01
PlayerStatInfo = ExtResource("2_nuh2a")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]

View File

@@ -18,21 +18,27 @@ namespace GameJamDungeon
public int BaseDefense { get; set; }
[Export]
public double ElementAResistance { get; set; }
public double TelluricResistance { get; set; }
[Export]
public double ElementBResistance { get; set; }
public double AeolicResistance { get; set; }
[Export]
public double ElementCResistance { get; set; }
public double HydricResistance { get; set; }
[Export]
public double BaseElementADamageBonus { get; set; }
public double IgneousResistance { get; set; }
[Export]
public double BaseElementBDamageBonus { get; set; }
public double TelluricDamageBonus { get; set; }
[Export]
public double BaseElementCDamageBonus { get; set; }
public double AeolicDamageBonus { get; set; }
[Export]
public double BaseHydricDamageBonus { get; set; }
[Export]
public double IgneousDamageBonus { get; set; }
}
}

View File

@@ -7,10 +7,11 @@ namespace GameJamDungeon
public static double CalculatePlayerDamage(int attackDamage, PlayerStatInfo playerStatInfo, EnemyStatInfo enemyStatInfo)
{
var baseDamage = attackDamage + playerStatInfo.BaseAttack;
var elementADamage = (playerStatInfo.BaseElementADamageBonus > 0 ? playerStatInfo.BaseElementADamageBonus - enemyStatInfo.ElementAResistance : 0) / 100;
var elementBDamage = (playerStatInfo.BaseElementBDamageBonus > 0 ? playerStatInfo.BaseElementBDamageBonus - enemyStatInfo.ElementBResistance : 0) / 100;
var elementCDamage = (playerStatInfo.BaseElementCDamageBonus > 0 ? playerStatInfo.BaseElementCDamageBonus - enemyStatInfo.ElementCResistance : 0) / 100;
var elementalBonusDamage = baseDamage + (baseDamage * elementADamage) + (baseDamage * elementBDamage) + (baseDamage * elementCDamage);
var elementADamage = (playerStatInfo.BaseHydricDamageBonus > 0 ? playerStatInfo.BaseHydricDamageBonus - enemyStatInfo.HydricResistance : 0) / 100;
var elementBDamage = (playerStatInfo.IgneousDamageBonus > 0 ? playerStatInfo.IgneousDamageBonus - enemyStatInfo.IgneousResistance : 0) / 100;
var elementCDamage = (playerStatInfo.TelluricDamageBonus > 0 ? playerStatInfo.TelluricDamageBonus - enemyStatInfo.TelluricResistance : 0) / 100;
var elementDDamage = (playerStatInfo.AeolicDamageBonus > 0 ? playerStatInfo.AeolicDamageBonus - enemyStatInfo.AeolicResistance : 0) / 100;
var elementalBonusDamage = baseDamage + (baseDamage * elementADamage) + (baseDamage * elementBDamage) + (baseDamage * elementCDamage) + (baseDamage * elementDDamage);
var calculatedDamage = elementalBonusDamage - enemyStatInfo.BaseDefense;
return calculatedDamage;
}
@@ -18,11 +19,12 @@ namespace GameJamDungeon
public static double CalculateEnemyDamage(int attackDamage, PlayerStatInfo playerStatInfo, EnemyStatInfo enemyStatInfo)
{
var baseDamage = attackDamage + enemyStatInfo.BaseAttack;
var elementADamage = (enemyStatInfo.BaseElementADamageBonus > 0 ? enemyStatInfo.BaseElementADamageBonus - playerStatInfo.ElementAResistance : 0) / 100;
var elementBDamage = (enemyStatInfo.BaseElementBDamageBonus > 0 ? enemyStatInfo.BaseElementBDamageBonus - playerStatInfo.ElementBResistance : 0) / 100;
var elementCDamage = (enemyStatInfo.BaseElementCDamageBonus > 0 ? enemyStatInfo.BaseElementCDamageBonus - playerStatInfo.ElementCResistance : 0) / 100;
var elementalBonusDamage = baseDamage + (baseDamage * elementADamage) + (baseDamage * elementBDamage) + (baseDamage * elementCDamage);
var calculatedDamage = elementalBonusDamage - enemyStatInfo.BaseDefense;
var elementADamage = (enemyStatInfo.BaseHydricDamageBonus > 0 ? enemyStatInfo.BaseHydricDamageBonus - playerStatInfo.HydricResistance : 0) / 100;
var elementBDamage = (enemyStatInfo.IgneousDamageBonus > 0 ? enemyStatInfo.IgneousDamageBonus - playerStatInfo.IgneousResistance : 0) / 100;
var elementCDamage = (enemyStatInfo.TelluricDamageBonus > 0 ? enemyStatInfo.TelluricDamageBonus - playerStatInfo.TelluricResistance : 0) / 100;
var elementDDamage = (enemyStatInfo.AeolicDamageBonus > 0 ? enemyStatInfo.AeolicDamageBonus - playerStatInfo.AeolicResistance : 0) / 100;
var elementalBonusDamage = baseDamage + (baseDamage * elementADamage) + (baseDamage * elementBDamage) + (baseDamage * elementCDamage) + (baseDamage * elementDDamage);
var calculatedDamage = elementalBonusDamage - playerStatInfo.BaseDefense;
return calculatedDamage;
}
}

View File

@@ -1,4 +1,6 @@
namespace GameJamDungeon
using Godot;
namespace GameJamDungeon
{
public interface ICharacterStats
{
@@ -8,10 +10,28 @@
public int BaseDefense { get; }
public double ElementAResistance { get; }
[Export]
public double TelluricResistance { get; set; }
public double ElementBResistance { get; }
[Export]
public double AeolicResistance { get; set; }
public double ElementCResistance { get; }
[Export]
public double HydricResistance { get; set; }
[Export]
public double IgneousResistance { get; set; }
[Export]
public double TelluricDamageBonus { get; set; }
[Export]
public double AeolicDamageBonus { get; set; }
[Export]
public double BaseHydricDamageBonus { get; set; }
[Export]
public double IgneousDamageBonus { get; set; }
}
}