Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sources/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,4 @@
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" PrivateAssets="all" />
</ItemGroup>
</Project>
</Project>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah those things where made automatically by vs I didn't touch that

Copy link
Member

@Kryptos-FR Kryptos-FR May 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't be done by VS unless you have some non-standard config that overrides the .editorconfig that we have at the root of the repo. It has this line which forces each file to have a blank line at the end:

stride/.editorconfig

Lines 6 to 8 in f99bde2

[*]
end_of_line = crlf
insert_final_newline = true

Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,14 @@
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>

<DrawingImage x:Key="ImageStart">
<DrawingImage.Drawing>
<GeometryDrawing Brush="#4CAF50">
<GeometryDrawing.Geometry>
<Geometry>F1 M 2,2 L 14,8 L 2,14 Z</Geometry>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
</ResourceDictionary>
1 change: 1 addition & 0 deletions sources/editor/Stride.GameStudio.Avalonia/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core.Plugins;
using Avalonia.Input;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't seem required.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah i forgot about that but should port the input checking function to this file

using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Styling;
Expand Down
130 changes: 130 additions & 0 deletions sources/editor/Stride.GameStudio.Avalonia/ViewModels/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public MainViewModel(IViewModelServiceProvider serviceProvider)
OpenDebugWindowCommand = new AnonymousTaskCommand(serviceProvider, OnOpenDebugWindow, () => DialogService.HasMainWindow);
OpenSettingsWindowCommand = new AnonymousTaskCommand(serviceProvider, OnOpenSettingsWindow, () => DialogService.HasMainWindow);
OpenWebPageCommand = new AnonymousTaskCommand<string>(serviceProvider, OnOpenWebPage);
RunCurrentProjectCommand = new AnonymousTaskCommand(serviceProvider, RunCurrentProject);

Status = new StatusViewModel(ServiceProvider);
Status.PushStatus("Ready");
Expand Down Expand Up @@ -80,6 +81,8 @@ public string Title

public ICommandBase OpenWebPageCommand { get; }

public ICommandBase RunCurrentProjectCommand { get; }

private EditorDialogService DialogService => ServiceProvider.Get<EditorDialogService>();

public async Task<bool?> OpenSession(UFile? filePath, CancellationToken token = default)
Expand Down Expand Up @@ -141,6 +144,128 @@ private void OnExit()
DialogService.Exit();
}

private static async Task<bool> BuildProject(string projectPath, string framework, string workingDirectory)
{
using var process = new Process();
process.StartInfo = new ProcessStartInfo
{
FileName = "dotnet",
Arguments = $"build \"{projectPath}\" --framework {framework}",
WorkingDirectory = workingDirectory,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
};

process.OutputDataReceived += (_, e) => { if (e.Data != null) Console.Out.WriteLine("[build] " + e.Data); };
process.ErrorDataReceived += (_, e) => { if (e.Data != null) Console.Error.WriteLine("[build-err] " + e.Data); };

try
{
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
await process.WaitForExitAsync();
return process.ExitCode == 0;
}
catch (Exception ex)
{
await Console.Error.WriteLineAsync("Build process failed: " + ex);
return false;
}
}

private async Task RunCurrentProject()
{
var mainProjectPath = Session?.CurrentProject?.RootDirectory;
if (mainProjectPath == null) return;

var projectDir = Path.GetDirectoryName(mainProjectPath.FullPath);
var projectBaseName = Path.GetFileNameWithoutExtension(mainProjectPath.FullPath);

string platformSuffix, framework, platformRuntime;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
platformSuffix = "Windows";
platformRuntime = "win-x64";
framework = "net8.0-windows";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
platformSuffix = "Linux";
platformRuntime = "linux-x64";
framework = "net8.0-linux";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
platformSuffix = "macOS";
platformRuntime = "osx-x64";
framework = "net8.0-macos";
}
else
{
await ShowError("Unsupported OS platform");
return;
}

var platformProjectName = $"{projectBaseName}.{platformSuffix}.csproj";
var platformProjectPath = Path.Combine(projectDir, $"{projectBaseName}.{platformSuffix}", platformProjectName);
var execPath = Path.Combine(projectDir, "Bin", platformSuffix, "Debug", platformRuntime);
var dllPath = Path.Combine(execPath, $"{projectBaseName}.{platformSuffix}.dll");


if (!File.Exists(platformProjectPath))
{
await ShowError($"Platform-specific project not found: {platformProjectPath}");
return;
}

Status.PushStatus("Building project...");
await Console.Out.WriteLineAsync("Building project...");
bool buildSuccess = await Task.Run(() => BuildProject(platformProjectPath, framework, projectDir));
if (!buildSuccess)
{
Status.PushStatus("Build failed.");
await Console.Out.WriteLineAsync("Build failed.");
await ShowError("Build failed. See output for details.");
return;
}

Status.PushStatus("Running project...");
await Console.Out.WriteLineAsync("Running project...");
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "dotnet",
Arguments = $"\"{dllPath}\"",
WorkingDirectory = projectDir,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = false,
}
};

process.OutputDataReceived += (_, e) => { if (e.Data != null) Console.Out.WriteLine("[run] " + e.Data); };
process.ErrorDataReceived += (_, e) => { if (e.Data != null) Console.Error.WriteLine("[run-err] " + e.Data); };

try
{
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
}
catch (Exception ex)
{
await Console.Error.WriteLineAsync("Run process failed: " + ex);
await ShowError("Failed to start the game process. See output for details.");
}

// FIXME: should we wait for process end?
}

private async Task OnOpen(UFile? initialPath)
{
await OpenSession(initialPath);
Expand Down Expand Up @@ -169,4 +294,9 @@ private async Task OnOpenWebPage(string url)
await ServiceProvider.Get<IDialogService>().MessageBoxAsync(message, MessageBoxButton.OK, MessageBoxImage.Error);
}
}

private async Task ShowError(string message)
{
await ServiceProvider.Get<IDialogService>().MessageBoxAsync(message, MessageBoxButton.OK, MessageBoxImage.Error);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,14 @@
<MenuItem Header="Simulate a crash"
Command="{Binding CrashCommand}"/>
</MenuItem>
<Button Width="32" Height="32"
Command="{Binding RunCurrentProjectCommand}"
HotKey="F5"
ToolTip.Tip="{sd:LocalizeString Start (F5)}">
<Image Source="{StaticResource ImageStart}" Width="16" Height="16"/>
</Button>
</Menu>

<Grid Grid.Row="1"
RowDefinitions="2*, 2, *">
<Grid Grid.Row="0"
Expand Down