Skip to content

Commit

Permalink
feat: install/uninstall modules from welcome window (#593)
Browse files Browse the repository at this point in the history
The welcome window can now install packages for Mirage
  • Loading branch information
paulpach committed Feb 21, 2021
2 parents dc5c921 + 381d001 commit 53ac404
Show file tree
Hide file tree
Showing 3 changed files with 239 additions and 14 deletions.
12 changes: 10 additions & 2 deletions Assets/Mirage/Editor/WelcomeWindow/Resources/WelcomeWindow.uss
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
-unity-text-align: upper-left;
padding-left: 10px;
padding-right: 10px;
padding-bottom: 10px;
padding-top: 5px;
padding-bottom: 15px;
padding-top: 0;
flex: 3;
white-space: normal;
}
Expand Down Expand Up @@ -99,6 +99,14 @@ Button {
justify-content: space-between;
}

#Module {
flex-basis: 20px;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 3px;
}

.dark-selected-tab {
background-color: rgba(53, 53, 53, 255);
border-left-color: rgba(36, 36, 36, 255);
Expand Down
21 changes: 21 additions & 0 deletions Assets/Mirage/Editor/WelcomeWindow/Resources/WelcomeWindow.uxml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<ui:VisualElement name="LeftColumnBox">
<ui:Button name="WelcomeButton" text="Welcome" class="light-selected-tab dark-selected-tab" />
<ui:Button name="QuickStartButton" text="Quick Start Guide" class="light-selected-tab dark-selected-tab" />
<ui:Button name="PackagesButton" text="Packages" class="light-selected-tab dark-selected-tab" />
<ui:Button name="FaqButton" text="FAQ" class="light-selected-tab dark-selected-tab" />
<ui:Button name="BestPracticesButton" text="Best Practices" class="light-selected-tab dark-selected-tab" />
<ui:Button name="ChangeLogButton" text="Change Log" class="light-selected-tab dark-selected-tab" />
Expand Down Expand Up @@ -59,6 +60,26 @@
<ui:VisualElement name="Spacer" />
<ui:Button name="Redirect" text="Join Discord" class="redirect" />
</ui:VisualElement>
<ui:ScrollView name="Packages" style="display: none;">
<ui:Label name="Header" text="Packages" />
<ui:Label name="Description" text="Mirage is a modular networking library. It ships with the foundation that you can build upon by installing packages." style="flex-basis: auto; flex-grow: 0; flex-shrink: 0;" />
<ui:Label text="Available Packages" display-tooltip-when-elided="True" style="padding-left: 10px; -unity-font-style: bold;" />
<ui:VisualElement name="ModulesList" style="flex-grow: 1; padding-left: 10px; padding-right: 10px;">
<ui:VisualElement name="Module" tooltip="Automatically find games within the same network.">
<ui:Label text="LAN Discovery" name="Name" />
<ui:Button text="Install" display-tooltip-when-elided="True" name="InstallButton" style="flex-shrink: 1; height: auto;" />
</ui:VisualElement>
<ui:VisualElement name="Module" tooltip="A transport that uses Facepunch&apos;s Steam SDK.">
<ui:Label text="Steam (Facepunch)" name="Name" />
<ui:Button text="Install" display-tooltip-when-elided="True" name="InstallButton" style="flex-shrink: 1; height: auto;" />
</ui:VisualElement>
<ui:VisualElement name="Module" tooltip="A transport that uses Steamworks.NET.">
<ui:Label text="Steam (Steamworks.NET)" name="Name" />
<ui:Button text="Install" display-tooltip-when-elided="True" name="InstallButton" style="flex-shrink: 1; height: auto;" />
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement name="Spacer" />
</ui:ScrollView>
</ui:VisualElement>
</ui:Box>
</ui:UXML>
220 changes: 208 additions & 12 deletions Assets/Mirage/Editor/WelcomeWindow/WelcomeWindow.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor.PackageManager;
using UnityEditor.PackageManager.Requests;
using System.Collections.Generic;

/**
* Docs used:
Expand All @@ -17,8 +20,7 @@ namespace Mirage
public class WelcomeWindow : EditorWindow
{
private Button lastClickedTab;
private StyleColor defaultButtonBackgroundColor;
private StyleColor defaultButtonBorderColor;
private readonly List<Button> installButtons = new List<Button>();

#region Setup

Expand All @@ -32,8 +34,22 @@ public class WelcomeWindow : EditorWindow
private const string SponsorUrl = "";
private const string DiscordInviteUrl = "https://discord.gg/DTBPBYvexy";

private readonly List<Package> Packages = new List<Package>()
{
new Package { displayName = "LAN Discovery", packageName = "com.miragenet.discovery", gitUrl = "https://github.com/MirageNet/Discovery.git?path=/Assets/Discovery"},
new Package { displayName = "Steam (Facepunch)", packageName = "com.miragenet.steamyface", gitUrl = "https://github.com/MirageNet/SteamyFaceNG.git?path=/Assets/Mirage/Runtime/Transport/SteamyFaceMirror" },
new Package { displayName = "Steam (Steamworks.NET)", packageName = "com.miragenet.steamy", gitUrl = "https://github.com/MirageNet/FizzySteamyMirror.git?path=/Assets/Mirage/Runtime/Transport/FizzySteamyMirror" },
};

#endregion

//request for the module install
private static AddRequest installRequest;
private static RemoveRequest uninstallRequest;
private static ListRequest listRequest;

private static WelcomeWindow currentWindow;

//window size of the welcome screen
private static Vector2 windowSize = new Vector2(500, 415);
private static string screenToOpenKey = "MirageScreenToOpen";
Expand Down Expand Up @@ -90,12 +106,12 @@ private static void ShowWindowOnFirstStart()
public static void OpenWindow()
{
//create the window
WelcomeWindow window = GetWindow<WelcomeWindow>("Mirage Welcome Page");
currentWindow = GetWindow<WelcomeWindow>("Mirage Welcome Page");
//set the position and size
window.position = new Rect(new Vector2(100, 100), windowSize);
currentWindow.position = new Rect(new Vector2(100, 100), windowSize);
//set min and max sizes so we cant readjust window size
window.maxSize = windowSize;
window.minSize = windowSize;
currentWindow.maxSize = windowSize;
currentWindow.minSize = windowSize;
}

#endregion
Expand All @@ -120,11 +136,6 @@ private void OnEnable()
Label versionText = root.Q<Label>("VersionText");
versionText.text = "v" + GetVersion();

//set button default colors (used in page nav)
IStyle sampleStyle = rootVisualElement.Q<Button>("WelcomeButton").style;
defaultButtonBackgroundColor = sampleStyle.backgroundColor;
defaultButtonBorderColor = sampleStyle.borderTopColor;

#region Page buttons

ConfigureTab("WelcomeButton", "Welcome", WelcomePageUrl);
Expand All @@ -134,6 +145,7 @@ private void OnEnable()
ConfigureTab("FaqButton", "Faq", FaqUrl);
ConfigureTab("SponsorButton", "Sponsor", SponsorUrl);
ConfigureTab("DiscordButton", "Discord", DiscordInviteUrl);
ConfigurePackagesTab();

ShowTab(EditorPrefs.GetString(screenToOpenKey, "Welcome"));

Expand All @@ -153,6 +165,7 @@ private void OnDisable()
EditorPrefs.SetBool(firstTimeMirageKey, true);
}

//menu button setup
private void ConfigureTab(string tabButtonName, string tab, string url)
{
Button tabButton = rootVisualElement.Q<Button>(tabButtonName);
Expand All @@ -165,6 +178,7 @@ private void ConfigureTab(string tabButtonName, string tab, string url)
ToggleMenuButtonColor(tabButton, true);
ToggleMenuButtonColor(lastClickedTab, false);
ShowTab(tab);
lastClickedTab = tabButton;
EditorPrefs.SetString(screenToOpenKey, tab);
};
Expand All @@ -173,6 +187,7 @@ private void ConfigureTab(string tabButtonName, string tab, string url)
redirectButton.clicked += () => Application.OpenURL(url);
}

//switch between content
private void ShowTab(string screen)
{
VisualElement rightColumn = rootVisualElement.Q<VisualElement>("RightColumnBox");
Expand All @@ -195,9 +210,12 @@ private void ShowTab(string screen)
}
}

//changes the background and border color of the button
//if toggle == true, keep the button tinted
//otherwise, return the button to the default, not active, colors
private void ToggleMenuButtonColor(Button button, bool toggle)
{
if(button == null) { return; }
if (button == null) { return; }

//dark mode
if (EditorGUIUtility.isProSkin)
Expand All @@ -211,7 +229,185 @@ private void ToggleMenuButtonColor(Button button, bool toggle)
}
}

#region Packages

//configure the package tab when the tab button is pressed
private void ConfigurePackagesTab()
{
Button tabButton = rootVisualElement.Q<Button>("PackagesButton");

tabButton.EnableInClassList("dark-selected-tab", false);
tabButton.EnableInClassList("light-selected-tab", false);

tabButton.clicked += () =>
{
ToggleMenuButtonColor(tabButton, true);
ToggleMenuButtonColor(lastClickedTab, false);
ShowTab("Packages");
lastClickedTab = tabButton;
EditorPrefs.SetString(screenToOpenKey, "Packages");
};

listRequest = UnityEditor.PackageManager.Client.List(true, false);

//subscribe to ListPackageProgress for updates
EditorApplication.update += ListPackageProgress;
}

//install the package
private void InstallPackage(string packageName)
{
installRequest = UnityEditor.PackageManager.Client.Add(Packages.Find((x) => x.displayName == packageName).gitUrl);

//subscribe to InstallPackageProgress for updates
EditorApplication.update += InstallPackageProgress;
}

//uninstall the package
private void UninstallPackage(string packageName)
{
uninstallRequest = UnityEditor.PackageManager.Client.Remove(Packages.Find((x) => x.displayName == packageName).packageName);

//subscribe to UninstallPackageProgress for updates
EditorApplication.update += UninstallPackageProgress;
}

//keeps track of the package install progress
private void InstallPackageProgress()
{
if (installRequest.IsCompleted)
{
//log results
if (installRequest.Status == StatusCode.Success)
{
Debug.Log("Package install successful.");
}
else if (installRequest.Status == StatusCode.Failure)
{
Debug.LogError("Package install was unsuccessful. \n Error Code: " + installRequest.Error.errorCode + "\n Error Message: " + installRequest.Error.message);
}

EditorApplication.update -= InstallPackageProgress;

//refresh the package tab
currentWindow?.Close();
OpenWindow();
}
}

private void UninstallPackageProgress()
{
if (uninstallRequest.IsCompleted)
{
//log results
EditorApplication.update -= UninstallPackageProgress;

if (uninstallRequest.Status == StatusCode.Success)
{
Debug.Log("Package uninstall successful.");
}
else if (uninstallRequest.Status == StatusCode.Failure)
{
Debug.LogError("Package uninstall was unsuccessful. \n Error Code: " + uninstallRequest.Error.errorCode + "\n Error Message: " + uninstallRequest.Error.message);
}

//refresh the package tab
currentWindow?.Close();
OpenWindow();
}
}

private void ListPackageProgress()
{
if (listRequest.IsCompleted)
{
EditorApplication.update -= ListPackageProgress;

if (listRequest.Status == StatusCode.Success)
{
List<string> installedPackages = new List<string>();

//populate installedPackages
foreach (var package in listRequest.Result)
{
Package? miragePackage = Packages.Find((x) => x.packageName == package.name);
if (miragePackage != null)
{
installedPackages.Add(miragePackage.Value.displayName);
}
}

ConfigureInstallButtons(installedPackages);
}
//log error
else if (listRequest.Status == StatusCode.Failure)
{
Debug.LogError("There was an issue finding packages. \n Error Code: " + listRequest.Error.errorCode + "\n Error Message: " + listRequest.Error.message);
}
}
}

//configures the install button
//changes text and functionality after button press
private void ConfigureInstallButtons(List<string> installedPackages)
{
//get all the packages
foreach (VisualElement package in rootVisualElement.Q<VisualElement>("ModulesList").Children())
{
//get the button and name of the package
Button installButton = package.Q<Button>("InstallButton");
string packageName = package.Q<Label>("Name").text;
bool foundInInstalledPackages = installedPackages.Contains(packageName);

//set text
installButton.text = !foundInInstalledPackages ? "Install" : "Uninstall";

//set functionality
if (!foundInInstalledPackages)
{
installButton.clicked += () =>
{
InstallPackage(packageName);
installButton.text = "Installing";
DisableInstallButtons();
};
}
else
{
installButton.clicked += () =>
{
UninstallPackage(packageName);
installButton.text = "Uninstalling";
DisableInstallButtons();
};
}

installButtons.Add(installButton);
}
}

//prevents user from spamming install button
//spamming the button while installing/uninstalling throws errors
//buttons enabled again after window refreshes
private void DisableInstallButtons()
{
foreach (Button button in installButtons)
{
button.SetEnabled(false);
}
}

#endregion

#endregion
}

//module data type
public struct Package
{
public string displayName;
public string packageName;
public string gitUrl;
}
}

0 comments on commit 53ac404

Please sign in to comment.