Skip to content

Commit 57d7a55

Browse files
authored
Merge pull request #4 from PawlygonStudio/feature/1.7.0
Release 1.7.0: review follow-ups and a UX pass across all tools
2 parents f3e12c1 + 5479279 commit 57d7a55

56 files changed

Lines changed: 14561 additions & 5148 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎Packages/net.pawlygon.unitytools/Editor/AvatarSetupWizard.FXCheck.cs‎

Lines changed: 747 additions & 0 deletions
Large diffs are not rendered by default.

‎Packages/net.pawlygon.unitytools/Editor/AvatarSetupWizard.FXCheck.cs.meta‎

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
using System;
2+
using System.Linq;
3+
using UnityEditor;
4+
using UnityEditor.SceneManagement;
5+
using UnityEngine;
6+
7+
namespace Pawlygon.UnityTools.Editor
8+
{
9+
/// <summary>
10+
/// Step 6: the real outcome of each avatar (replacements, patch files, FX controller, VRCFT), quick
11+
/// actions on the created files and the tools to use next.
12+
/// </summary>
13+
public partial class AvatarSetupWizard
14+
{
15+
private static readonly (string Name, string Description, Action Open)[] NextSteps =
16+
{
17+
("Getting Started", "Overview of every Pawlygon tool and when to use it.", GettingStarted.ShowWindow),
18+
("Eye Muscle Settings", "Set how far the eyes can look in each direction, with a live preview.", EyeMuscleSettings.ShowWindow),
19+
("Face Tracking Extras", "Ears, tail and pupils that react to your face.", FaceTrackingExtras.ShowWindow),
20+
("Patch Config Package Rules", "Add the packages (and minimum versions) your customers need to the patch configs.", PatchConfigRulesEditor.ShowWindow),
21+
};
22+
23+
private void DrawCompleteStep()
24+
{
25+
int attentionCount = avatarEntries.Count(EntryNeedsAttention);
26+
27+
using (new EditorGUILayout.VerticalScope(PawlygonEditorUI.SectionStyle))
28+
{
29+
using (new EditorGUILayout.HorizontalScope())
30+
{
31+
string icon = attentionCount == 0 ? "TestPassed" : "console.warnicon.sml";
32+
GUILayout.Label(EditorGUIUtility.IconContent(icon), GUILayout.Width(20f), GUILayout.Height(20f));
33+
EditorGUILayout.LabelField(
34+
attentionCount == 0 ? "Setup complete" : $"Setup finished: {Plural(attentionCount, "avatar needs", "avatars need")} attention",
35+
PawlygonEditorUI.SectionTitleStyle);
36+
}
37+
38+
EditorGUILayout.Space(2f);
39+
EditorGUILayout.LabelField(
40+
attentionCount == 0
41+
? "Test the avatar in the working scene, then continue with the next steps below."
42+
: "The badges below show what still needs a look. Every step stays open from the step bar.",
43+
PawlygonEditorUI.SubLabelStyle);
44+
}
45+
46+
EditorGUILayout.Space(SectionSpacing);
47+
48+
for (int i = 0; i < avatarEntries.Count; i++)
49+
{
50+
DrawFinishEntryCard(i, avatarEntries[i]);
51+
EditorGUILayout.Space(4f);
52+
}
53+
54+
if (cachedEntriesMissingPatchConfig.Count > 0)
55+
{
56+
using (new EditorGUILayout.VerticalScope(PawlygonEditorUI.SectionStyle))
57+
{
58+
DrawMissingPatchConfigsNotice();
59+
}
60+
61+
EditorGUILayout.Space(4f);
62+
}
63+
64+
EditorGUILayout.Space(SectionSpacing);
65+
DrawNextStepsCard();
66+
}
67+
68+
private void DrawFinishEntryCard(int index, AvatarEntry entry)
69+
{
70+
using (new EditorGUILayout.VerticalScope(PawlygonEditorUI.SectionStyle))
71+
{
72+
using (new EditorGUILayout.HorizontalScope())
73+
{
74+
EditorGUILayout.LabelField(GetEntryDisplayName(entry), PawlygonEditorUI.SectionTitleStyle);
75+
GUILayout.FlexibleSpace();
76+
77+
if (GUILayout.Button(new GUIContent("Ping Folder", entry.avatarRootPath), EditorStyles.miniButtonLeft, GUILayout.Width(80f)))
78+
{
79+
PingAssetPath(entry.avatarRootPath);
80+
}
81+
82+
using (new EditorGUI.DisabledScope(!AssetFileExists(entry.createdScenePath)))
83+
{
84+
if (GUILayout.Button(new GUIContent("Open Scene", entry.createdScenePath), EditorStyles.miniButtonRight, GUILayout.Width(80f)))
85+
{
86+
OpenWorkingScene(entry.createdScenePath);
87+
// May show the save-scene dialog and loads another scene.
88+
GUIUtility.ExitGUI();
89+
}
90+
}
91+
}
92+
93+
EditorGUILayout.Space(2f);
94+
95+
var review = GetReviewBadge(entry);
96+
DrawBadgeRow("Replacements", review.Text, review.Kind, review.Tooltip);
97+
98+
var patch = GetPatchBadge(entry);
99+
DrawBadgeRow("Patch files", patch.Text, patch.Kind, patch.Tooltip);
100+
101+
var fx = GetFxBadge(entry);
102+
DrawBadgeRow("FX controller", fx.Text, fx.Kind, fx.Tooltip);
103+
104+
if (cachedVrcftAvailable)
105+
{
106+
if (IsVrcftOnEntry(index))
107+
{
108+
DrawBadgeRow("VRCFT prefab", "Added", PawlygonEditorUI.BadgeKind.Ok, "The prefab has the Pawlygon VRCFT setup.");
109+
}
110+
else
111+
{
112+
DrawBadgeRow("VRCFT prefab", "Not added", PawlygonEditorUI.BadgeKind.Neutral, "Add it in the Prefabs step (optional).");
113+
}
114+
}
115+
116+
EditorGUILayout.Space(2f);
117+
118+
// Draw with this event's value so Layout and Repaint match; the change shows on the next event.
119+
bool showDetails = entry.showFinishDetails;
120+
bool newShowDetails = EditorGUILayout.Foldout(showDetails, "Details", true);
121+
if (showDetails)
122+
{
123+
DrawPathRow("Avatar folder", entry.avatarRootPath);
124+
DrawPathRow("Edited FBX", entry.copiedFbxPath);
125+
DrawPathRow("Prefab", entry.copiedPrefabPath);
126+
DrawPathRow("Working scene", entry.createdScenePath);
127+
DrawPathRow("Diff generator", entry.diffGeneratorAssetPath);
128+
DrawPathRow("FX controller", entry.copiedFxControllerPath);
129+
130+
if (entry.diffGenerationFailed)
131+
{
132+
EditorGUILayout.LabelField($"Patch error: {entry.diffGenerationError}", PawlygonEditorUI.RichMiniLabelStyle);
133+
}
134+
}
135+
136+
entry.showFinishDetails = newShowDetails;
137+
}
138+
}
139+
140+
private void DrawNextStepsCard()
141+
{
142+
using (new EditorGUILayout.VerticalScope(PawlygonEditorUI.SectionStyle))
143+
{
144+
PawlygonEditorUI.DrawSectionHeader("Next steps", "Tools that build on this setup.");
145+
146+
foreach ((string name, string description, Action open) in NextSteps)
147+
{
148+
using (new EditorGUILayout.HorizontalScope())
149+
{
150+
if (GUILayout.Button(name, GUILayout.Width(190f), GUILayout.Height(22f)))
151+
{
152+
open();
153+
GUIUtility.ExitGUI();
154+
}
155+
156+
GUILayout.Space(6f);
157+
EditorGUILayout.LabelField(description, PawlygonEditorUI.SubLabelStyle);
158+
}
159+
160+
EditorGUILayout.Space(2f);
161+
}
162+
}
163+
}
164+
165+
private void DrawCompleteActions()
166+
{
167+
DrawBackButton(WizardStep.FXCheck);
168+
169+
if (PawlygonEditorUI.DrawSecondaryButton(new GUIContent("Start Over…", "Start a new setup. Created files stay in the project."), ActionButtonHeight))
170+
{
171+
ConfirmStartOver();
172+
GUIUtility.ExitGUI();
173+
}
174+
175+
GUILayout.FlexibleSpace();
176+
177+
string[] scenes = avatarEntries
178+
.Select(entry => entry.createdScenePath)
179+
.Where(path => !string.IsNullOrEmpty(path))
180+
.Distinct(StringComparer.OrdinalIgnoreCase)
181+
.ToArray();
182+
183+
if (scenes.Length == 1 &&
184+
PawlygonEditorUI.DrawPrimaryButton(new GUIContent("Open Working Scene", scenes[0]), ActionButtonHeight, GUILayout.MinWidth(PrimaryButtonMinWidth)))
185+
{
186+
OpenWorkingScene(scenes[0]);
187+
GUIUtility.ExitGUI();
188+
}
189+
}
190+
191+
private bool EntryNeedsAttention(AvatarEntry entry)
192+
{
193+
return entry.diffGenerationFailed || entry.needsProcessing || !entry.isMeshReviewComplete || !IsFxComplete(entry);
194+
}
195+
196+
private (string Text, PawlygonEditorUI.BadgeKind Kind, string Tooltip) GetPatchBadge(AvatarEntry entry)
197+
{
198+
if (entry.diffGenerationFailed)
199+
{
200+
return ("Failed", PawlygonEditorUI.BadgeKind.Error, FirstLine(entry.diffGenerationError));
201+
}
202+
203+
if (entry.needsProcessing)
204+
{
205+
return ("Out of date", PawlygonEditorUI.BadgeKind.Warning, "The FBX changed after the patch was made. Update it from the banner.");
206+
}
207+
208+
if (cachedEntriesMissingPatchConfig.Contains(entry))
209+
{
210+
return ("No patch config", PawlygonEditorUI.BadgeKind.Warning, "The patch files exist but PatcherHub has no config for them yet. Generate it below.");
211+
}
212+
213+
return cachedPatcherHubAvailable
214+
? ("Ready", PawlygonEditorUI.BadgeKind.Ok, "The patch files and the PatcherHub config are up to date.")
215+
: ("Ready", PawlygonEditorUI.BadgeKind.Ok, "The patch files are up to date. Install PatcherHub (Prefabs step) to also get a patch config.");
216+
}
217+
218+
private void OpenWorkingScene(string scenePath)
219+
{
220+
if (!AssetFileExists(scenePath))
221+
{
222+
status.Error($"The working scene '{scenePath}' doesn't exist anymore.");
223+
return;
224+
}
225+
226+
if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
227+
{
228+
return;
229+
}
230+
231+
EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Single);
232+
}
233+
}
234+
}

‎Packages/net.pawlygon.unitytools/Editor/AvatarSetupWizard.Finish.cs.meta‎

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

0 commit comments

Comments
 (0)