Skip to content

Commit dc8a1bd

Browse files
committed
Adding template loading into NewProject panel #147
Fix ForceDX11 checkbox (was always enabled by default)
1 parent fffa97e commit dc8a1bd

File tree

6 files changed

+251
-45
lines changed

6 files changed

+251
-45
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
namespace UnityLauncherPro.Data
2+
{
3+
public class TemplateGraphQLResponse
4+
{
5+
public TemplateData data { get; set; }
6+
}
7+
8+
public class TemplateData
9+
{
10+
public GetTemplates getTemplates { get; set; }
11+
}
12+
13+
public class GetTemplates
14+
{
15+
public TemplateEdge[] edges { get; set; }
16+
}
17+
18+
public class TemplateEdge
19+
{
20+
public TemplateNode node { get; set; }
21+
}
22+
23+
public class TemplateNode
24+
{
25+
public string name { get; set; }
26+
public string packageName { get; set; }
27+
public string description { get; set; }
28+
public string type { get; set; }
29+
public string renderPipeline { get; set; }
30+
public PreviewImage previewImage { get; set; }
31+
public TemplateVersion[] versions { get; set; }
32+
}
33+
34+
public class PreviewImage
35+
{
36+
public string url { get; set; }
37+
}
38+
39+
public class TemplateVersion
40+
{
41+
public string name { get; set; }
42+
public Tarball tarball { get; set; }
43+
}
44+
45+
public class Tarball
46+
{
47+
public string url { get; set; }
48+
}
49+
}

UnityLauncherPro/NewProject.xaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
<Label x:Name="lblNewProjectNameLabel" Grid.Column="0" Content="Project Name:" Foreground="{DynamicResource ThemeButtonForeground}" Margin="0" Padding="0,5,5,0" />
3535
<Label Grid.Column="1" Content="Platform:" Foreground="{DynamicResource ThemeButtonForeground}" Margin="0" Padding="0,5,0,0" />
3636
<Label x:Name="lblTemplateTitleAndCount" Grid.Column="2" Content="Templates:" Foreground="{DynamicResource ThemeButtonForeground}" Margin="0" Padding="5,5,5,0" />
37-
<Label Content="Override" Grid.Column="3" Foreground="{DynamicResource ThemeButtonForeground}" Margin="0" Padding="0,5,0,0"/>
37+
<Label Content="Override" x:Name="lblOverride" Grid.Column="3" Foreground="{DynamicResource ThemeButtonForeground}" Margin="0" Padding="0,5,0,0"/>
3838
</Grid>
3939

4040
<Grid HorizontalAlignment="Stretch" Margin="0,3,0,0">
@@ -47,7 +47,7 @@
4747
<TextBox Grid.Column="0" x:Name="txtNewProjectName" VerticalAlignment="Center" IsUndoEnabled="True" TextChanged="TxtNewProjectName_TextChanged" PreviewKeyDown="TxtNewProjectName_PreviewKeyDown" TabIndex="0" Margin="0,2,6,2" />
4848
<ComboBox Grid.Column="1" x:Name="cmbNewProjectPlatform" SelectedIndex="0" Margin="0,0,0,0" TabIndex="2" DropDownOpened="CmbNewProjectPlatform_DropDownOpened" />
4949
<ComboBox Grid.Column="2" x:Name="cmbNewProjectTemplate" DisplayMemberPath="Key" SelectedIndex="0" Margin="6,0,0,0" TabIndex="2" DropDownOpened="CmbNewProjectTemplate_DropDownOpened" />
50-
<CheckBox Grid.Column="3" x:Name="chkForceDX11" Content="DX11" ToolTip="Use DX11 instead of DX12" Margin="6,0,0,0" IsChecked="True" Checked="chkForceDX11_Checked" Unchecked="chkForceDX11_Checked"/>
50+
<CheckBox Grid.Column="3" x:Name="chkForceDX11" Content="DX11" ToolTip="Use DX11 instead of DX12" Margin="6,0,0,0" IsChecked="False" Checked="chkForceDX11_Checked" Unchecked="chkForceDX11_Checked"/>
5151
</Grid>
5252

5353
<Label x:Name="lblNewProjectFolderLabel" Grid.Column="0" Content="Project Root Folder:" Foreground="{DynamicResource ThemeButtonForeground}" Margin="0" Padding="0,5,5,0" />

UnityLauncherPro/NewProject.xaml.cs

Lines changed: 184 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
using System;
22
using System.Collections.Generic;
33
using System.IO;
4+
using System.Net.Http;
5+
using System.Text;
46
using System.Windows;
57
using System.Windows.Controls;
68
using System.Windows.Input;
79
using System.Windows.Media;
810
using UnityLauncherPro.Data;
11+
using UnityLauncherPro.Properties;
912

1013
namespace UnityLauncherPro
1114
{
@@ -35,6 +38,8 @@ public NewProject(string unityVersion, string suggestedName, string targetFolder
3538
// TODO could optionally disable templates in settings
3639
_ = LoadOnlineTemplatesAsync();
3740

41+
LoadSettings();
42+
3843
// get version
3944
newVersion = unityVersion;
4045
newName = suggestedName;
@@ -83,6 +88,11 @@ public NewProject(string unityVersion, string suggestedName, string targetFolder
8388
isInitializing = false;
8489
} // NewProject
8590

91+
private void LoadSettings()
92+
{
93+
chkForceDX11.IsChecked = Settings.Default.forceDX11;
94+
}
95+
8696
void UpdateTemplatesDropDown(string unityPath)
8797
{
8898
// scan available templates, TODO could cache this at least per session?
@@ -296,7 +306,9 @@ private void GridAvailableVersions_SelectionChanged(object sender, SelectionChan
296306

297307
// hide forceDX11 checkbox if version is below 6000
298308
bool is6000 = k.Version.Contains("6000");
299-
chkForceDX11.Visibility = is6000 ? Visibility.Visible : Visibility.Collapsed;
309+
lblOverride.Visibility = chkForceDX11.Visibility = is6000 ? Visibility.Visible : Visibility.Collapsed;
310+
//chkForceDX11.IsChecked = chkForceDX11.Visibility == Visibility.Visible ? forceDX11 : false;
311+
forceDX11 = Settings.Default.forceDX11 && is6000;
300312
}
301313

302314
private void GridAvailableVersions_Loaded(object sender, RoutedEventArgs e)
@@ -334,7 +346,10 @@ private void gridAvailableVersions_PreviewMouseDoubleClick(object sender, MouseB
334346

335347
private void chkForceDX11_Checked(object sender, RoutedEventArgs e)
336348
{
337-
forceDX11 = chkForceDX11.IsChecked == true;
349+
if (isInitializing) return; // Don't save during initialization
350+
351+
Settings.Default.forceDX11 = forceDX11;
352+
Settings.Default.Save();
338353
}
339354

340355
private void btnBrowseForProjectFolder_Click(object sender, RoutedEventArgs e)
@@ -405,55 +420,181 @@ private void btnCreateMissingFolder_Click(object sender, RoutedEventArgs e)
405420

406421
private async System.Threading.Tasks.Task LoadOnlineTemplatesAsync()
407422
{
408-
// Simulate async loading (replace with actual async HTTP call later)
409-
await System.Threading.Tasks.Task.Run(() =>
423+
try
410424
{
411-
var templates = new List<OnlineTemplateItem>
412-
{
413-
new OnlineTemplateItem
425+
using (var client = new HttpClient())
426+
{
427+
client.DefaultRequestHeaders.Add("Accept", "application/json");
428+
429+
// Build JSON manually
430+
var graphqlJson = "{\"query\":\"fragment TemplateEntity on Template { __typename name packageName description type buildPlatforms renderPipeline previewImage { url } versions { name tarball { url } } } query HUB__getTemplates($limit: Int! $skip: Int! $orderBy: TemplateOrder! $supportedUnityEditorVersions: [String!]!) { getTemplates(limit: $limit skip: $skip orderBy: $orderBy supportedUnityEditorVersions: $supportedUnityEditorVersions) { edges { node { ...TemplateEntity } } } }\",\"variables\":{\"limit\":50,\"skip\":0,\"orderBy\":\"WEIGHTED_DESC\",\"supportedUnityEditorVersions\":[\"6000.0\"]}}";
431+
432+
var content = new StringContent(graphqlJson, Encoding.UTF8, "application/json");
433+
434+
var response = await client.PostAsync("https://live-platform-api.prd.ld.unity3d.com/graphql", content);
435+
436+
if (response.IsSuccessStatusCode)
437+
{
438+
var responseString = await response.Content.ReadAsStringAsync();
439+
var templates = ParseTemplatesFromJson(responseString);
440+
441+
// Update UI on dispatcher thread
442+
Dispatcher.Invoke(() =>
443+
{
444+
listOnlineTemplates.Items.Clear();
445+
listOnlineTemplates.ItemsSource = templates;
446+
});
447+
}
448+
else
449+
{
450+
Console.WriteLine($"GraphQL request failed: {response.StatusCode}");
451+
LoadFallbackTemplates();
452+
}
453+
}
454+
}
455+
catch (Exception ex)
414456
{
415-
Name = "3D Template",
416-
Description = "A great starting point for 3D projects using the Universal Render Pipeline (URP).",
417-
PreviewImageURL = "https://storage.googleapis.com/live-platform-resources-prd/templates/assets/AR_Mobile_Thumbnail_HUB_464008d11a/AR_Mobile_Thumbnail_HUB_464008d11a.png",
418-
Type = "CORE",
419-
RenderPipeline = "URP",
420-
TarBallURL = "https://download.packages.unity.com/com.unity.template.hdrp-blank/-/com.unity.template.hdrp-blank-17.0.2.tgz"
421-
},
422-
new OnlineTemplateItem
457+
Console.WriteLine($"Error loading online templates: {ex.Message}");
458+
LoadFallbackTemplates();
459+
}
460+
}
461+
462+
private List<OnlineTemplateItem> ParseTemplatesFromJson(string json)
463+
{
464+
var templates = new List<OnlineTemplateItem>();
465+
466+
try
423467
{
424-
Name = "2D Template",
425-
Description = "A great starting point for 2D projects using the Built-in Render Pipeline.",
426-
PreviewImageURL = "https://storage.googleapis.com/live-platform-resources-prd/templates/assets/Platformer_preview_887cd85a63/Platformer_preview_887cd85a63.png",
427-
Type = "CORE",
428-
RenderPipeline = "Built-in",
429-
TarBallURL = "https://download.packages.unity.com/com.unity.template.mr-multiplayer/-/com.unity.template.mr-multiplayer-1.0.3.tgz"
430-
},
431-
new OnlineTemplateItem
468+
// Find the edges array
469+
int edgesStart = json.IndexOf("\"edges\":");
470+
if (edgesStart == -1) return templates;
471+
472+
// Find all node objects
473+
int currentPos = edgesStart;
474+
while (true)
475+
{
476+
int nodeStart = json.IndexOf("{\"__typename\":\"Template\"", currentPos);
477+
if (nodeStart == -1) break;
478+
479+
// Find the end of this node object (simplified - find matching brace)
480+
int nodeEnd = FindMatchingBrace(json, nodeStart);
481+
if (nodeEnd == -1) break;
482+
483+
string nodeJson = json.Substring(nodeStart, nodeEnd - nodeStart + 1);
484+
485+
// Parse individual fields
486+
var template = new OnlineTemplateItem
487+
{
488+
Name = ExtractJsonString(nodeJson, "\"name\""),
489+
Description = ExtractJsonString(nodeJson, "\"description\""),
490+
Type = ExtractJsonString(nodeJson, "\"type\""),
491+
RenderPipeline = ExtractJsonString(nodeJson, "\"renderPipeline\""),
492+
PreviewImageURL = ExtractNestedJsonString(nodeJson, "\"previewImage\"", "\"url\"") ?? "pack://application:,,,/Images/icon.png",
493+
TarBallURL = ExtractNestedJsonString(nodeJson, "\"tarball\"", "\"url\"")
494+
};
495+
496+
templates.Add(template);
497+
currentPos = nodeEnd + 1;
498+
}
499+
}
500+
catch (Exception ex)
432501
{
433-
Name = "Wubba Template",
434-
Description = "A great asdfasdf projects using.",
435-
PreviewImageURL = "https://storage.googleapis.com/live-platform-resources-prd/templates/assets/2_4_1_Overview_627c09d1be/2_4_1_Overview_627c09d1be.png",
436-
Type = "SAMPLES",
437-
RenderPipeline = "URP",
438-
TarBallURL = "https://download.packages.unity.com/com.unity.template.vr/-/com.unity.template.vr-9.2.0.tgz"
439-
},
440-
new OnlineTemplateItem
502+
Console.WriteLine($"Error parsing templates: {ex.Message}");
503+
}
504+
505+
return templates;
506+
}
507+
508+
private string ExtractJsonString(string json, string key)
509+
{
510+
int keyIndex = json.IndexOf(key + ":");
511+
if (keyIndex == -1) return null;
512+
513+
int valueStart = json.IndexOf("\"", keyIndex + key.Length + 1);
514+
if (valueStart == -1) return null;
515+
516+
int valueEnd = json.IndexOf("\"", valueStart + 1);
517+
if (valueEnd == -1) return null;
518+
519+
return json.Substring(valueStart + 1, valueEnd - valueStart - 1);
520+
}
521+
522+
private string ExtractNestedJsonString(string json, string parentKey, string childKey)
523+
{
524+
int parentIndex = json.IndexOf(parentKey + ":");
525+
if (parentIndex == -1) return null;
526+
527+
// Find the object after parentKey
528+
int objectStart = json.IndexOf("{", parentIndex);
529+
if (objectStart == -1) return null;
530+
531+
int objectEnd = FindMatchingBrace(json, objectStart);
532+
if (objectEnd == -1) return null;
533+
534+
string nestedJson = json.Substring(objectStart, objectEnd - objectStart + 1);
535+
return ExtractJsonString(nestedJson, childKey);
536+
}
537+
538+
private int FindMatchingBrace(string json, int openBraceIndex)
539+
{
540+
int braceCount = 0;
541+
bool inString = false;
542+
bool escapeNext = false;
543+
544+
for (int i = openBraceIndex; i < json.Length; i++)
441545
{
442-
Name = "ASDF Template",
443-
Description = "A great asdfasdf projects using.",
444-
PreviewImageURL = "https://storage.googleapis.com/live-platform-resources-prd/templates/assets/HDRP_c27702ce66/HDRP_c27702ce66.jpg",
445-
Type = "LEARNING",
446-
RenderPipeline = "HDRP",
447-
TarBallURL = "https://download.packages.unity.com/com.unity.template.platformer/-/com.unity.template.platformer-5.0.5.tgz"
546+
char c = json[i];
547+
548+
if (escapeNext)
549+
{
550+
escapeNext = false;
551+
continue;
552+
}
553+
554+
if (c == '\\')
555+
{
556+
escapeNext = true;
557+
continue;
558+
}
559+
560+
if (c == '"')
561+
{
562+
inString = !inString;
563+
continue;
564+
}
565+
566+
if (!inString)
567+
{
568+
if (c == '{') braceCount++;
569+
else if (c == '}')
570+
{
571+
braceCount--;
572+
if (braceCount == 0) return i;
573+
}
574+
}
448575
}
449-
};
450576

451-
// Update UI on dispatcher thread
452-
Dispatcher.Invoke(() =>
577+
return -1;
578+
}
579+
580+
private void LoadFallbackTemplates()
581+
{
582+
var templates = new List<OnlineTemplateItem>
583+
{
584+
new OnlineTemplateItem
453585
{
454-
listOnlineTemplates.Items.Clear();
455-
listOnlineTemplates.ItemsSource = templates;
456-
});
586+
Name = "3D Template",
587+
Description = "A great starting point for 3D projects using the Universal Render Pipeline (URP).",
588+
PreviewImageURL = "pack://application:,,,/Images/icon.png",
589+
Type = "CORE",
590+
RenderPipeline = "URP"
591+
}
592+
};
593+
594+
Dispatcher.Invoke(() =>
595+
{
596+
listOnlineTemplates.Items.Clear();
597+
listOnlineTemplates.ItemsSource = templates;
457598
});
458599
}
459600
}

UnityLauncherPro/Properties/Settings.Designer.cs

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

UnityLauncherPro/Properties/Settings.settings

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,5 +160,8 @@
160160
<Setting Name="fetchAdditionalInfo" Type="System.Boolean" Scope="User">
161161
<Value Profile="(Default)">False</Value>
162162
</Setting>
163+
<Setting Name="forceDX11" Type="System.Boolean" Scope="User">
164+
<Value Profile="(Default)">False</Value>
165+
</Setting>
163166
</Settings>
164167
</SettingsFile>

UnityLauncherPro/UnityLauncherPro.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
<Compile Include="Data\OnlineTemplateItem.cs" />
9494
<Compile Include="Data\Platform.cs" />
9595
<Compile Include="Data\Tabs.cs" />
96+
<Compile Include="Data\TemplateGraphQLResponse.cs" />
9697
<Compile Include="Data\ThemeColor.cs" />
9798
<Compile Include="Data\UnityVersion.cs" />
9899
<Compile Include="Data\UnityVersionResponse.cs" />

0 commit comments

Comments
 (0)