Skip to content

Commit aa62f42

Browse files
version 0.4 & create new project feature is added
1 parent 122389f commit aa62f42

File tree

8 files changed

+335
-105
lines changed

8 files changed

+335
-105
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ It launches many times faster, uses far less memory and CPU, and is a fraction o
1515
- Update projects to a Unity version of your choosing
1616
- Modern Fluent2 theme, including support for dark and light mode and Mica blur for Windows
1717
- Add an existing project to the list using the Add Existing button*
18+
- Create new unity projects with templates, for any modern Unity version you have installed, with the Create New button
1819
- *[TBA] Manage Unity licenses*
19-
- *[TBA] Create new unity projects with templates, for any modern Unity version you have installed, with the Create New button*
2020

2121
UnityHubNative.Net does not have every feature that the official hub has, but it has most of them. UnityHubNative.Net serves as a shortcut to get into your projects faster.
2222

UnityHubNative.Net/AboutDialogue.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,17 @@ public AboutDialogue()
1414
{
1515
Content = CreateContent();
1616
_btn!.Focus();
17-
TransparencyLevelHint =
18-
[
19-
WindowTransparencyLevel.AcrylicBlur,
20-
WindowTransparencyLevel.Blur,
21-
];
22-
CanResize = false;
23-
SizeToContent = SizeToContent.WidthAndHeight;
17+
18+
if (UnityHubNativeNetApp.Config.transparent)
19+
{
20+
TransparencyLevelHint = [WindowTransparencyLevel.AcrylicBlur, WindowTransparencyLevel.Blur];
2421
#if Windows
25-
Background = Brushes.Transparent;
22+
Background = new SolidColorBrush(Colors.Transparent, UnityHubNativeNetApp.Config.blurIntensity);
2623
#endif
24+
}
25+
26+
CanResize = false;
27+
SizeToContent = SizeToContent.WidthAndHeight;
2728
WindowStartupLocation = WindowStartupLocation.CenterOwner;
2829
Focusable = true;
2930
}

UnityHubNative.Net/ControlsExtensions.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,13 @@ public static Button OnClick(this Button button, params Action[] callbacks)
6464
return button;
6565
}
6666

67-
public static Button OnClick(this Button button, Action callback)
67+
public static T OnClick<T>(this T button, Action callback) where T : Button
68+
{
69+
button.Click += (obj, args) => callback();
70+
return button;
71+
}
72+
73+
public static NativeMenuItem OnClick(this NativeMenuItem button, Action callback)
6874
{
6975
button.Click += (obj, args) => callback();
7076
return button;
@@ -124,6 +130,13 @@ public static MenuItem AddItems(this MenuItem menu, params MenuItem[] menuItems)
124130
return menu;
125131
}
126132

133+
public static T1 AddItems<T1, T2>(this T1 menu, T2[] items) where T1 : NativeMenu where T2 : NativeMenuItemBase
134+
{
135+
for (int i = 0; i < items.Length; i++)
136+
menu.Items.Add(items[i]);
137+
return menu;
138+
}
139+
127140
public static TabControl AddItems(this TabControl tabControl, TabItem[] items)
128141
{
129142
for (int i = 0; i < items.Length; i++)
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
using System.Diagnostics;
2+
using Avalonia;
3+
using Avalonia.Controls;
4+
using Avalonia.Input;
5+
using Avalonia.Interactivity;
6+
using Avalonia.Layout;
7+
using Avalonia.Media;
8+
using Avalonia.Platform.Storage;
9+
using MsBox.Avalonia;
10+
using MsBox.Avalonia.Enums;
11+
12+
namespace UnityHubNative.Net;
13+
14+
sealed class CreateNewProjectDialogue : Window
15+
{
16+
TextBox _pathTextBox;
17+
TextBox _nameTextBox;
18+
ComboBox _versionSelector;
19+
ListBox _templatesParent;
20+
private Button _createButton;
21+
22+
public CreateNewProjectDialogue()
23+
{
24+
Title = "Create a New Unity Project";
25+
Content = CreateContent();
26+
UpdateVersionSelectionViews();
27+
UpdateTemplateViews();
28+
SizeToContent = SizeToContent.WidthAndHeight;
29+
WindowStartupLocation = WindowStartupLocation.CenterOwner;
30+
CanResize = false;
31+
SystemDecorations = SystemDecorations.BorderOnly;
32+
33+
if (UnityHubNativeNetApp.Config.transparent)
34+
{
35+
TransparencyLevelHint = [WindowTransparencyLevel.AcrylicBlur, WindowTransparencyLevel.Blur];
36+
#if Windows
37+
Background = new SolidColorBrush(Colors.Transparent, UnityHubNativeNetApp.Config.blurIntensity);
38+
#endif
39+
ExtendClientAreaToDecorationsHint = true;
40+
}
41+
}
42+
43+
protected override async void OnOpened(EventArgs e)
44+
{
45+
base.OnOpened(e);
46+
47+
if (UnityHubUtils.UnityInstallations.Count == 0)
48+
{
49+
await MessageBoxManager.GetMessageBoxStandard("Can't create new projects", "No Unity Installations found").ShowAsPopupAsync(this);
50+
Close();
51+
return;
52+
}
53+
_nameTextBox.Focus();
54+
}
55+
56+
object? CreateContent()
57+
{
58+
return new DockPanel
59+
{
60+
Margin = WindowDecorationMargin + new Thickness(5)
61+
}.AddChildren
62+
([
63+
new DockPanel
64+
{
65+
Margin = new(2)
66+
}.AddChildren
67+
([
68+
new TextBlock
69+
{
70+
Text = "Project Name",
71+
VerticalAlignment = VerticalAlignment.Center,
72+
Width = 100,
73+
}.SetDock(Dock.Left),
74+
_nameTextBox = new TextBox
75+
{
76+
MaxLines = 1,
77+
VerticalAlignment = VerticalAlignment.Center,
78+
Watermark = "New Unity Project"
79+
},
80+
]).SetDock(Dock.Top),
81+
new DockPanel
82+
{
83+
Margin = new(2)
84+
}.AddChildren
85+
([
86+
new TextBlock
87+
{
88+
Text = "Location",
89+
Width = 100,
90+
VerticalAlignment = VerticalAlignment.Center,
91+
}.SetDock(Dock.Left),
92+
new Button
93+
{
94+
Content = "Choose",
95+
}.OnClick(OnChooseLocationClicked).SetDock(Dock.Right),
96+
_pathTextBox = new TextBox
97+
{
98+
MaxLines = 1,
99+
VerticalAlignment = VerticalAlignment.Center,
100+
Watermark = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)
101+
},
102+
]).SetDock(Dock.Top),
103+
new Separator
104+
{
105+
Margin = new(5)
106+
}.SetDock(Dock.Top),
107+
new DockPanel
108+
{
109+
Margin = new(2),
110+
LastChildFill = false
111+
}.AddChildren
112+
([
113+
new TextBlock
114+
{
115+
Text = "Select Template For Version",
116+
VerticalAlignment = VerticalAlignment.Center,
117+
Margin = new(0, 0, 5, 0),
118+
}.SetDock(Dock.Left),
119+
_versionSelector = new ComboBox
120+
{
121+
SelectedIndex = 0,
122+
}.OnSelectionChanged(OnVersionSelectionChanged).SetDock(Dock.Right),
123+
]).SetDock(Dock.Top),
124+
new DockPanel
125+
{
126+
Margin = new(2),
127+
LastChildFill = false,
128+
}.AddChildren
129+
([
130+
_createButton = new Button
131+
{
132+
Content = "Create",
133+
IsEnabled = false,
134+
VerticalAlignment = VerticalAlignment.Center,
135+
}.OnClick(OnCreateClicked).SetTooltip("Create the Unity Project with the specified attributes").SetDock(Dock.Right),
136+
new Button
137+
{
138+
Content = "Cancel",
139+
HotKey = new(Key.Escape),
140+
VerticalAlignment = VerticalAlignment.Center,
141+
}.OnClick(OnCancelClicked).SetTooltip("Cancel the creation of a new Unity Project").SetDock(Dock.Right),
142+
]).SetDock(Dock.Bottom),
143+
_templatesParent = new ListBox
144+
{
145+
SelectionMode = SelectionMode.Single | SelectionMode.AlwaysSelected,
146+
SelectedIndex = 0,
147+
IsTextSearchEnabled = true
148+
},
149+
]);
150+
}
151+
152+
void OnCreateClicked()
153+
{
154+
if (TryGetSelectedUnityInstallation(out var installation))
155+
{
156+
try
157+
{
158+
Task.Run(() => Process.Start(new ProcessStartInfo
159+
{
160+
FileName = installation.path,
161+
Arguments = $"-createProject \"{_pathTextBox}\" -cloneFromTemplate \"{UnityHubUtils.UnityInstallations[_templatesParent.SelectedIndex].path}\"",
162+
UseShellExecute = false,
163+
RedirectStandardOutput = true,
164+
RedirectStandardError = true,
165+
CreateNoWindow = true
166+
}));
167+
Close();
168+
}
169+
catch (Exception ex)
170+
{
171+
MessageBoxManager.GetMessageBoxStandard("Cannot Create Project", $"Cannot create project at {_pathTextBox} because an error occurred: {ex.Message}", ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error).ShowAsync();
172+
}
173+
}
174+
}
175+
176+
void OnCancelClicked() => Close();
177+
178+
void OnVersionSelectionChanged() => UpdateTemplateViews();
179+
180+
void UpdateVersionSelectionViews()
181+
{
182+
_versionSelector.Items.Clear();
183+
for (int i = 0; i < UnityHubUtils.UnityInstallations.Count; i++)
184+
_versionSelector.Items.Add(UnityHubUtils.UnityInstallations[i].version);
185+
if (_versionSelector.ItemCount > 0)
186+
_versionSelector.SelectedIndex = 0;
187+
}
188+
189+
void UpdateTemplateViews()
190+
{
191+
_templatesParent.Items.Clear();
192+
if (TryGetSelectedUnityInstallation(out var installation))
193+
foreach (var path in installation.GetTemplatePaths())
194+
_templatesParent.Items.Add(Path.GetFileName(path));
195+
UpdateCreateButtonView();
196+
}
197+
198+
void UpdateCreateButtonView() => _createButton.IsEnabled = _templatesParent.Items.Count > 0 && Directory.Exists(_pathTextBox.Text) && _nameTextBox.Text?.Length > 0;
199+
200+
bool TryGetSelectedUnityInstallation(out UnityInstallation installation)
201+
{
202+
if (_versionSelector.SelectedIndex < 0 || _versionSelector.SelectedIndex >= UnityHubUtils.UnityInstallations.Count)
203+
{
204+
installation = default;
205+
return false;
206+
}
207+
installation = UnityHubUtils.UnityInstallations[_versionSelector.SelectedIndex];
208+
return true;
209+
}
210+
211+
async void OnChooseLocationClicked(Button button, RoutedEventArgs args)
212+
{
213+
var path = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
214+
{
215+
AllowMultiple = false,
216+
Title = "Select where to write the Unity project"
217+
});
218+
if (path is null || path.Count == 0 || path[0] is null)
219+
return;
220+
var dir = path[0].TryGetLocalPath();
221+
if (Directory.Exists(dir))
222+
_pathTextBox.Text = dir;
223+
}
224+
}

0 commit comments

Comments
 (0)