Library
parent
c8ee1b28b3
commit
e4824f4ff3
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/icondeletedlocaloverlay@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/icondeletedlocaloverlay@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/icondeletedremote.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/icondeletedremote.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/icondeletedremote@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/icondeletedremote@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/icondeletedremoteoverlay@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/icondeletedremoteoverlay@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconemptygravatar.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconemptygravatar.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconemptygravatar@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconemptygravatar@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconlockedlocaloverlay@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconlockedlocaloverlay@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconlockedremoteoverlay@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconlockedremoteoverlay@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconmergelink.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconmergelink.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconmoved.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconmoved.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconoutofsync.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconoutofsync.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconoutofsync@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconoutofsync@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconoutofsyncoverlay@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconoutofsyncoverlay@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplastic.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplastic.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplasticnotifyconflict.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplasticnotifyconflict.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplasticnotifyconflict@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplasticnotifyconflict@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplasticnotifyincoming.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplasticnotifyincoming.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplasticnotifyincoming@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplasticnotifyincoming@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplasticview.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplasticview.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplasticview@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconplasticview@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconpressedclosebutton.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconpressedclosebutton.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconprivateoverlay@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconprivateoverlay@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconrepository.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconrepository.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconundo.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconundo.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconundo@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/iconundo@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/ignored.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/ignored.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/ignoredoverlay@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/ignoredoverlay@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/loading.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/loading.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/loading@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/loading@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/notondisk.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/notondisk.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/ok.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/ok.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/refresh.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/refresh.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/refresh@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/refresh@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/secondarytabclose.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/secondarytabclose.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/secondarytabclosehover.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/secondarytabclosehover.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/step1.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/step1.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/step1@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/step1@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/step2.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/step2.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/step2@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/step2@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/step3.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/step3.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/step3@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/step3@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/stepok.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/stepok.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/stepok@2x.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/stepok@2x.png (Stored with Git LFS)
100644
Binary file not shown.
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/xlink.png (Stored with Git LFS)
100644
BIN
Library/PackageCache/com.unity.collab-proxy@2.0.3/Editor/PlasticSCM/Assets/Images/xlink.png (Stored with Git LFS)
100644
Binary file not shown.
|
@ -0,0 +1,11 @@
|
||||||
|
<UXML xmlns="UnityEngine.UIElements">
|
||||||
|
<VisualElement class="flex-container main">
|
||||||
|
<VisualElement class="form">
|
||||||
|
<Label name="createdTitle" class="title" />
|
||||||
|
<Label name="createdExplanation" />
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
<VisualElement class="footer">
|
||||||
|
<Button name="continue" />
|
||||||
|
</VisualElement>
|
||||||
|
</UXML>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<UXML xmlns="UnityEngine.UIElements">
|
||||||
|
<VisualElement name="container">
|
||||||
|
<Label name="title" />
|
||||||
|
<Label name="requireMessage" text="This feature requires a Unity Version Control installation." />
|
||||||
|
<Label name="message" />
|
||||||
|
<VisualElement name="progressControlsContainer" />
|
||||||
|
<VisualElement name="footer">
|
||||||
|
<VisualElement class="grow-max" />
|
||||||
|
<Button name="downloadCloudEdition" />
|
||||||
|
<Button name="downloadEnterpriseEdition" />
|
||||||
|
<Button name="cancel" />
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
</UXML>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<UXML xmlns="UnityEngine.UIElements">
|
||||||
|
<VisualElement class="flex-container column main">
|
||||||
|
<Label name="confirmationMessage" class="title" />
|
||||||
|
|
||||||
|
<VisualElement name="joinSingleOrganization" class="organization-section row collapse">
|
||||||
|
<Label name="joinSingleOrganizationLabel" class="organization-left" />
|
||||||
|
<VisualElement class="align-vertical-center">
|
||||||
|
<Button name="joinSingleOrganizationButton" class="organization-right" />`
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
|
||||||
|
<VisualElement name="joinMultipleOrganizations" class="organization-section collapse">
|
||||||
|
<Label name="joinMultipleOrganizationsLabel" />
|
||||||
|
<VisualElement class="row">
|
||||||
|
<VisualElement name="organizationDropdown" class="organization-left"/>
|
||||||
|
<Button name="joinMultipleOrganizationsButton" class="organization-right" />
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
|
||||||
|
<VisualElement name="noOrganization" class="organization-section column collapse">
|
||||||
|
<Label name="noOrganizationLabel" class="organization-left"/>
|
||||||
|
<Button name="openUnityDashboardButton" class="row">
|
||||||
|
<Image name="iconUnity" />
|
||||||
|
</Button>
|
||||||
|
</VisualElement>
|
||||||
|
|
||||||
|
<VisualElement name="progressContainer"/>
|
||||||
|
</VisualElement>
|
||||||
|
</UXML>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<UXML xmlns="UnityEngine.UIElements">
|
||||||
|
<VisualElement name="UpdateNotificationContainer" class="row">
|
||||||
|
<Image name="UpdateNotificationImage" />
|
||||||
|
<Label name="UpdateNotificationLabel" />
|
||||||
|
</VisualElement>
|
||||||
|
|
||||||
|
<Button name="UpdateButton" />
|
||||||
|
|
||||||
|
<Label name="BranchLabel" class="grow" />
|
||||||
|
</UXML>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<UXML xmlns="UnityEngine.UIElements">
|
||||||
|
<VisualElement class="flex-container row">
|
||||||
|
<VisualElement name="UndefinedProgress" class="collapse" />
|
||||||
|
<Label name="Progress" />
|
||||||
|
<Label name="Status" />
|
||||||
|
<Label name="Percentage" />
|
||||||
|
</VisualElement>
|
||||||
|
</UXML>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<UXML xmlns="UnityEngine.UIElements">
|
||||||
|
<VisualElement name="signInChoiceContainer" class="flex-container column main">
|
||||||
|
<VisualElement name="signUpContainer" class="row-reverse">
|
||||||
|
<Button name="signUpButton"/>
|
||||||
|
<Label name="signUpLabel"/>
|
||||||
|
</VisualElement>
|
||||||
|
<Button name="unityIDButton" class="sign-in-buttons">
|
||||||
|
<Image name="iconUnity" />
|
||||||
|
</Button>
|
||||||
|
<Button name="emailButton" class="sign-in-buttons">
|
||||||
|
<Image name="iconEmail" />
|
||||||
|
</Button>
|
||||||
|
</VisualElement>
|
||||||
|
<VisualElement class="footer">
|
||||||
|
<Label name="privacyStatementText" />
|
||||||
|
<Button name="privacyStatement" class="anchor" />
|
||||||
|
</VisualElement>
|
||||||
|
</UXML>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<UXML
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="UnityEngine.UIElements"
|
||||||
|
xsi:noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd"
|
||||||
|
xsi:schemaLocation="UnityEngine.UIElements ../UIElementsSchema/UnityEngine.UIElements.xsd">
|
||||||
|
<VisualElement name="loginContainer" class="flex-container main">
|
||||||
|
<Label name="signInLabel" class="title"/>
|
||||||
|
<TextField name="email"/>
|
||||||
|
<Label name="emailNotification" class="alert-label"/>
|
||||||
|
<TextField name="password" password="true"/>
|
||||||
|
<Label name="passwordNotification" class="alert-label"/>
|
||||||
|
|
||||||
|
<VisualElement class="row align-end">
|
||||||
|
<Button name="back" class="classic-button"/>
|
||||||
|
<Button name="signIn" class="classic-button"/>
|
||||||
|
</VisualElement>
|
||||||
|
|
||||||
|
<VisualElement name="progressContainer"/>
|
||||||
|
|
||||||
|
<VisualElement name="signUpNeededNotificationContainer" class="collapse row">
|
||||||
|
<Label name="signUpNeededNotificationLabel"/>
|
||||||
|
<Button name="signUpButton" class="anchor"/>
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
</UXML>
|
|
@ -0,0 +1,4 @@
|
||||||
|
<UXML xmlns="UnityEngine.UIElements">
|
||||||
|
<VisualElement name="TabArea" class="flex-container row" />
|
||||||
|
<VisualElement name="ContentArea" />
|
||||||
|
</UXML>
|
|
@ -0,0 +1,42 @@
|
||||||
|
<UXML xmlns="UnityEngine.UIElements">
|
||||||
|
<VisualElement class="container">
|
||||||
|
<Label name="plasticConfigurationTitle" />
|
||||||
|
<Label name="plasticConfigurationExplanation" class="sub-section" />
|
||||||
|
</VisualElement>
|
||||||
|
<VisualElement class="container">
|
||||||
|
<VisualElement class="sub-section">
|
||||||
|
<Label name="configurationServerInfo"></Label>
|
||||||
|
<VisualElement name="configurationServerInfoSection">
|
||||||
|
<VisualElement class="flex-container row">
|
||||||
|
<TextField name="serverTextField" class="grow" />
|
||||||
|
<Button name="connect" />
|
||||||
|
</VisualElement>
|
||||||
|
<VisualElement class="flex-container row">
|
||||||
|
<Toggle name="useSslToogle" />
|
||||||
|
<Label name="useSsl" />
|
||||||
|
</VisualElement>
|
||||||
|
<VisualElement>
|
||||||
|
<Label name="connectedLabel" class="hide" />
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
<Label name="configurationUserNameInfo" />
|
||||||
|
<Label name="configurationCredentialsInfo" class="collapse" />
|
||||||
|
<VisualElement class="flex-container row">
|
||||||
|
<TextField name="userTextField" class="credentials" />
|
||||||
|
<TextField name="passwordTextField" class="credentials collapse" />
|
||||||
|
<Button name="check" />
|
||||||
|
<VisualElement name="credentialsPadding" class="grow" />
|
||||||
|
</VisualElement>
|
||||||
|
<Label name="credentialsOk" class="hide" />
|
||||||
|
<VisualElement class="flex-container row">
|
||||||
|
<VisualElement name="spinnerContainer" class="hide"/>
|
||||||
|
<Label name="spinnerLabel" class="hide"/>
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
<VisualElement class="container flex-container row last">
|
||||||
|
<VisualElement class="grow"></VisualElement>"
|
||||||
|
<Button name="okButton" />
|
||||||
|
<Button name="cancelButton" />
|
||||||
|
</VisualElement>
|
||||||
|
</UXML>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<UXML xmlns="UnityEngine.UIElements">
|
||||||
|
<VisualElement class="flex-container main">
|
||||||
|
<Label name="signInToPlasticSCM" class="title" />
|
||||||
|
<Label name="completeSignInOnBrowser" />
|
||||||
|
<VisualElement name="wait" class="flex-container row">
|
||||||
|
<VisualElement name="progressContainer" class="row" />
|
||||||
|
<Button name="cancelButton"></Button>
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
</UXML>
|
|
@ -0,0 +1,140 @@
|
||||||
|
.collapse {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-reverse {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grow {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grow-max {
|
||||||
|
flex-grow: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parent-vertical-center{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.elements-vertical-center{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontally-centered {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-end {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-center{
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-vertical-center{
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-start {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding-left: 25px;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 10px 0px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: #FF0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
cursor: link;
|
||||||
|
}
|
||||||
|
|
||||||
|
.anchor {
|
||||||
|
color: #2196F3;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
background-color: transparent;
|
||||||
|
border-width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.classic-button {
|
||||||
|
padding: 7px;
|
||||||
|
margin-top: 10px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-label {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
position: absolute;
|
||||||
|
margin: 20px 10px 0px 10px;
|
||||||
|
bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
padding: 10px;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
border-bottom-color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container.last {
|
||||||
|
border-bottom-width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-section {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
margin-left: 0px;
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toggle {
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
@import "Base.uss";
|
||||||
|
|
||||||
|
#container {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title {
|
||||||
|
-unity-font-style: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progressControlsContainer {
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
white-space: normal;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
width: 180px;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
@import "Base.uss";
|
||||||
|
|
||||||
|
.organization-section {
|
||||||
|
margin: 10px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.organization-right {
|
||||||
|
width: auto;
|
||||||
|
min-width: 70px;
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.organization-left{
|
||||||
|
flex: auto;
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#openUnityDashboardButton {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
height: 30px;
|
||||||
|
color: white;
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#joinSingleOrganizationButton{
|
||||||
|
height: 19px;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ContentArea {
|
||||||
|
background-color: rgba(48, 48, 48, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
#StatusBar {
|
||||||
|
background-color: rgba(25, 25, 25, 255);
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ContentArea {
|
||||||
|
background-color: rgba(184, 184, 184, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
#StatusBar {
|
||||||
|
background-color: rgba(138, 138, 138, 255);
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
@import "../Base.uss";
|
||||||
|
|
||||||
|
/* Plastic Window Tabview */
|
||||||
|
#TabView {
|
||||||
|
height: auto;
|
||||||
|
min-height: 235px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#TabArea {
|
||||||
|
margin: 0px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-button {
|
||||||
|
width: 130px;
|
||||||
|
|
||||||
|
margin: 0px;
|
||||||
|
margin-top: 1px;
|
||||||
|
padding: 1px 16px 2px 16px;
|
||||||
|
|
||||||
|
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notifications, buttons, and settings */
|
||||||
|
#ControlsContainer {
|
||||||
|
flex-grow: 1;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#StatusBar {
|
||||||
|
flex-grow: 1;
|
||||||
|
justify-content: flex-end;
|
||||||
|
height: 22px;
|
||||||
|
max-height: 22px;
|
||||||
|
padding: 2px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#UpdateNotificationContainer {
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#UpdateNotificationImage {
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#RefreshButton,
|
||||||
|
#SettingsButton {
|
||||||
|
background-color: rgba(1, 1, 1, 0);
|
||||||
|
border-width: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#BranchLabel {
|
||||||
|
-unity-text-align: middle-right;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
@import "Base.uss";
|
||||||
|
|
||||||
|
#Status {
|
||||||
|
color: red;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
@import "Base.uss";
|
||||||
|
|
||||||
|
.sign-in-buttons {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#iconUnity, #iconEmail {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px
|
||||||
|
}
|
||||||
|
|
||||||
|
#unityIDButton {
|
||||||
|
color: white;
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#signUpLabel{
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#privacyStatement {
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
@import "Base.uss";
|
||||||
|
|
||||||
|
#windowContainer {
|
||||||
|
height: 100%;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loginContainer TextField {
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#emailNotification, #passwordNotification {
|
||||||
|
height: 15px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progressContainer {
|
||||||
|
height: 15px;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#signIn,
|
||||||
|
#back {
|
||||||
|
width: 125px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#signUpNeededNotificationLabel{
|
||||||
|
color: red;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
@import "Base.uss";
|
||||||
|
|
||||||
|
#TabView,
|
||||||
|
#ContentArea {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#TabArea {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-button {
|
||||||
|
padding-bottom: 2px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
border-width: 0px;
|
||||||
|
border-radius: 0px;
|
||||||
|
|
||||||
|
font-size: 15px;
|
||||||
|
background-color: rgba(1, 1, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#TabArea .tab-button:hover {
|
||||||
|
border-bottom-color: #2196F3;
|
||||||
|
border-bottom-width: 0.25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#TabArea .tab-button.active {
|
||||||
|
border-bottom-color: #2196F3;
|
||||||
|
border-bottom-width: 1.5px;
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
@import "Base.uss";
|
||||||
|
|
||||||
|
#configurationServerInfoSection {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spinnerLabel {
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#connectedLabel {
|
||||||
|
-unity-text-align: middle-right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#credentialsOk {
|
||||||
|
-unity-text-align: middle-right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#plasticConfigurationTitle {
|
||||||
|
font-size: 18px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credentials {
|
||||||
|
width: 265px;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#wait {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progressContainer {
|
||||||
|
padding-top: 3px;
|
||||||
|
margin-right: 50%;
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
using Codice.Client.Common;
|
||||||
|
using Codice.Utils;
|
||||||
|
using PlasticGui;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.AssetUtils
|
||||||
|
{
|
||||||
|
internal static class AssetsPath
|
||||||
|
{
|
||||||
|
internal static class GetFullPath
|
||||||
|
{
|
||||||
|
internal static string ForObject(Object obj)
|
||||||
|
{
|
||||||
|
string relativePath = AssetDatabase.GetAssetPath(obj);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(relativePath))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return Path.GetFullPath(relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string ForGuid(string guid)
|
||||||
|
{
|
||||||
|
string relativePath = GetAssetPath(guid);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(relativePath))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return Path.GetFullPath(relativePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class GetFullPathUnderWorkspace
|
||||||
|
{
|
||||||
|
internal static string ForAsset(
|
||||||
|
string wkPath,
|
||||||
|
string assetPath)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(assetPath))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
string fullPath = Path.GetFullPath(assetPath);
|
||||||
|
|
||||||
|
if (!PathHelper.IsContainedOn(fullPath, wkPath))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return fullPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string ForGuid(
|
||||||
|
string wkPath,
|
||||||
|
string guid)
|
||||||
|
{
|
||||||
|
return ForAsset(wkPath, GetAssetPath(guid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetLayoutsFolderRelativePath()
|
||||||
|
{
|
||||||
|
return string.Concat(mAssetsFolderLocation, "/Layouts");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetStylesFolderRelativePath()
|
||||||
|
{
|
||||||
|
return string.Concat(mAssetsFolderLocation, "/Styles");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetImagesFolderRelativePath()
|
||||||
|
{
|
||||||
|
return string.Concat(mAssetsFolderLocation, "/Images");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetRelativePath(string fullPath)
|
||||||
|
{
|
||||||
|
return PathHelper.GetRelativePath(
|
||||||
|
mProjectFullPath, fullPath).Substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool IsRunningAsUPMPackage()
|
||||||
|
{
|
||||||
|
string unityPlasticDllPath = Path.GetFullPath(
|
||||||
|
AssemblyLocation.GetAssemblyDirectory(
|
||||||
|
Assembly.GetAssembly(typeof(PlasticLocalization))));
|
||||||
|
|
||||||
|
return Directory.Exists(
|
||||||
|
Path.GetFullPath(Path.Combine(
|
||||||
|
unityPlasticDllPath,
|
||||||
|
// assets relative path when running as a UPM package
|
||||||
|
"../../../Editor/PlasticSCM/Assets")));
|
||||||
|
}
|
||||||
|
|
||||||
|
static string GetAssetPath(string guid)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(guid))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return AssetDatabase.GUIDToAssetPath(guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static AssetsPath()
|
||||||
|
{
|
||||||
|
mAssetsFolderLocation = (IsRunningAsUPMPackage()) ?
|
||||||
|
"Packages/com.unity.collab-proxy/Editor/PlasticSCM/Assets" :
|
||||||
|
"Assets/Plugins/PlasticSCM/Editor/Assets";
|
||||||
|
}
|
||||||
|
|
||||||
|
static string mProjectFullPath = ProjectPath.
|
||||||
|
FromApplicationDataPath(ApplicationDataPath.Get());
|
||||||
|
|
||||||
|
static string mAssetsFolderLocation;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
using Unity.PlasticSCM.Editor.AssetMenu;
|
||||||
|
using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
|
||||||
|
using UnityEditor.VersionControl;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.AssetUtils
|
||||||
|
{
|
||||||
|
internal static class GetSelectedPaths
|
||||||
|
{
|
||||||
|
internal static List<string> ForOperation(
|
||||||
|
string wkPath,
|
||||||
|
AssetList assetList,
|
||||||
|
IAssetStatusCache assetStatusCache,
|
||||||
|
AssetMenuOperations operation)
|
||||||
|
{
|
||||||
|
List<string> selectedPaths = AssetsSelection.
|
||||||
|
GetSelectedPaths(wkPath, assetList);
|
||||||
|
|
||||||
|
List<string> result = new List<string>(selectedPaths);
|
||||||
|
|
||||||
|
foreach (string path in selectedPaths)
|
||||||
|
{
|
||||||
|
if (MetaPath.IsMetaPath(path))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string metaPath = MetaPath.GetMetaPath(path);
|
||||||
|
|
||||||
|
if (!File.Exists(metaPath))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (result.Contains(metaPath))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!IsApplicableForOperation(
|
||||||
|
metaPath, false, operation, assetStatusCache))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result.Add(metaPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsApplicableForOperation(
|
||||||
|
string path,
|
||||||
|
bool isDirectory,
|
||||||
|
AssetMenuOperations operation,
|
||||||
|
IAssetStatusCache assetStatusCache)
|
||||||
|
{
|
||||||
|
SelectedAssetGroupInfo info = SelectedAssetGroupInfo.BuildFromSingleFile(
|
||||||
|
path, isDirectory, assetStatusCache);
|
||||||
|
|
||||||
|
return AssetMenuUpdater.GetAvailableMenuOperations(info).HasFlag(operation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
using Codice.Client.BaseCommands;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.AssetUtils
|
||||||
|
{
|
||||||
|
internal static class LoadAsset
|
||||||
|
{
|
||||||
|
internal static UnityEngine.Object FromChangeInfo(ChangeInfo changeInfo)
|
||||||
|
{
|
||||||
|
string changeFullPath = changeInfo.GetFullPath();
|
||||||
|
|
||||||
|
if (MetaPath.IsMetaPath(changeFullPath))
|
||||||
|
changeFullPath = MetaPath.GetPathFromMetaPath(changeFullPath);
|
||||||
|
|
||||||
|
return FromFullPath(changeFullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
static UnityEngine.Object FromFullPath(string fullPath)
|
||||||
|
{
|
||||||
|
if (!IsPathUnderProject(fullPath))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return AssetDatabase.LoadMainAssetAtPath(
|
||||||
|
AssetsPath.GetRelativePath(fullPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsPathUnderProject(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var fullPath = Path.GetFullPath(path).Replace('\\', '/');
|
||||||
|
|
||||||
|
return fullPath.StartsWith(
|
||||||
|
mProjectRelativePath,
|
||||||
|
StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
static string mProjectRelativePath =
|
||||||
|
Directory.GetCurrentDirectory().Replace('\\', '/') + '/';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
using AssetOverlays = Unity.PlasticSCM.Editor.AssetsOverlays;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.AssetUtils.Processor
|
||||||
|
{
|
||||||
|
class AssetModificationProcessor : UnityEditor.AssetModificationProcessor
|
||||||
|
{
|
||||||
|
internal static bool ForceCheckout { get; private set; }
|
||||||
|
|
||||||
|
/* We need to do a checkout, verifying that the content/date or size has changed.
|
||||||
|
* In order to do this checkout we need the changes to have reached the disk.
|
||||||
|
* That's why we save the changed files in this array, and when they are reloaded
|
||||||
|
* in AssetPostprocessor.OnPostprocessAllAssets we process them. */
|
||||||
|
internal static string[] ModifiedAssets { get; set; }
|
||||||
|
|
||||||
|
static AssetModificationProcessor()
|
||||||
|
{
|
||||||
|
ForceCheckout = EditorPrefs.GetBool(
|
||||||
|
UnityConstants.FORCE_CHECKOUT_KEY_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Enable(
|
||||||
|
string wkPath,
|
||||||
|
IAssetStatusCache assetStatusCache)
|
||||||
|
{
|
||||||
|
mWkPath = wkPath;
|
||||||
|
mAssetStatusCache = assetStatusCache;
|
||||||
|
|
||||||
|
mIsEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Disable()
|
||||||
|
{
|
||||||
|
mIsEnabled = false;
|
||||||
|
|
||||||
|
mWkPath = null;
|
||||||
|
mAssetStatusCache = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void SetForceCheckoutOption(bool isEnabled)
|
||||||
|
{
|
||||||
|
ForceCheckout = isEnabled;
|
||||||
|
|
||||||
|
EditorPrefs.SetBool(
|
||||||
|
UnityConstants.FORCE_CHECKOUT_KEY_NAME,
|
||||||
|
isEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
static string[] OnWillSaveAssets(string[] paths)
|
||||||
|
{
|
||||||
|
if (!mIsEnabled)
|
||||||
|
return paths;
|
||||||
|
|
||||||
|
ModifiedAssets = (string[])paths.Clone();
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsOpenForEdit(string assetPath, out string message)
|
||||||
|
{
|
||||||
|
message = string.Empty;
|
||||||
|
|
||||||
|
if (!mIsEnabled)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!ForceCheckout)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (assetPath.StartsWith("ProjectSettings/"))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
string assetFullPath = AssetsPath.GetFullPathUnderWorkspace.
|
||||||
|
ForAsset(mWkPath, assetPath);
|
||||||
|
|
||||||
|
if (assetFullPath == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (MetaPath.IsMetaPath(assetFullPath))
|
||||||
|
assetFullPath = MetaPath.GetPathFromMetaPath(assetFullPath);
|
||||||
|
|
||||||
|
AssetOverlays.AssetStatus status = mAssetStatusCache.
|
||||||
|
GetStatus(assetFullPath);
|
||||||
|
|
||||||
|
if (AssetOverlays.ClassifyAssetStatus.IsAdded(status) ||
|
||||||
|
AssetOverlays.ClassifyAssetStatus.IsCheckedOut(status))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return !AssetOverlays.ClassifyAssetStatus.IsControlled(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mIsEnabled;
|
||||||
|
|
||||||
|
static IAssetStatusCache mAssetStatusCache;
|
||||||
|
static string mWkPath;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Codice.Client.Common.FsNodeReaders.Watcher;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.AssetUtils.Processor
|
||||||
|
{
|
||||||
|
class AssetPostprocessor : UnityEditor.AssetPostprocessor
|
||||||
|
{
|
||||||
|
internal struct PathToMove
|
||||||
|
{
|
||||||
|
internal readonly string SrcPath;
|
||||||
|
internal readonly string DstPath;
|
||||||
|
|
||||||
|
internal PathToMove(string srcPath, string dstPath)
|
||||||
|
{
|
||||||
|
SrcPath = srcPath;
|
||||||
|
DstPath = dstPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Enable(
|
||||||
|
string wkPath,
|
||||||
|
PlasticAssetsProcessor plasticAssetsProcessor)
|
||||||
|
{
|
||||||
|
mWkPath = wkPath;
|
||||||
|
mPlasticAssetsProcessor = plasticAssetsProcessor;
|
||||||
|
|
||||||
|
mIsEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Disable()
|
||||||
|
{
|
||||||
|
mIsEnabled = false;
|
||||||
|
|
||||||
|
mWkPath = null;
|
||||||
|
mPlasticAssetsProcessor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void SetIsRepaintInspectorNeededAfterAssetDatabaseRefresh()
|
||||||
|
{
|
||||||
|
mIsRepaintInspectorNeededAfterAssetDatabaseRefresh = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnPostprocessAllAssets(
|
||||||
|
string[] importedAssets,
|
||||||
|
string[] deletedAssets,
|
||||||
|
string[] movedAssets,
|
||||||
|
string[] movedFromAssetPaths)
|
||||||
|
{
|
||||||
|
if (!mIsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mIsRepaintInspectorNeededAfterAssetDatabaseRefresh)
|
||||||
|
{
|
||||||
|
mIsRepaintInspectorNeededAfterAssetDatabaseRefresh = false;
|
||||||
|
RepaintInspector.All();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to ensure that the FSWatcher is enabled before processing Plastic operations
|
||||||
|
// It fixes the following scenario:
|
||||||
|
// 1. Close PlasticSCM window
|
||||||
|
// 2. Create an asset, it appears with the added overlay
|
||||||
|
// 3. Open PlasticSCM window, the asset should appear as added instead of deleted locally
|
||||||
|
MonoFileSystemWatcher.IsEnabled = true;
|
||||||
|
|
||||||
|
mPlasticAssetsProcessor.MoveOnSourceControl(
|
||||||
|
GetPathsToMoveContainedOnWorkspace(
|
||||||
|
mWkPath, movedAssets, movedFromAssetPaths));
|
||||||
|
|
||||||
|
mPlasticAssetsProcessor.DeleteFromSourceControl(
|
||||||
|
GetPathsContainedOnWorkspace(mWkPath, deletedAssets));
|
||||||
|
|
||||||
|
mPlasticAssetsProcessor.AddToSourceControl(
|
||||||
|
GetPathsContainedOnWorkspace(mWkPath, importedAssets));
|
||||||
|
|
||||||
|
if (AssetModificationProcessor.ModifiedAssets == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mPlasticAssetsProcessor.CheckoutOnSourceControl(
|
||||||
|
GetPathsContainedOnWorkspace(
|
||||||
|
mWkPath, AssetModificationProcessor.ModifiedAssets));
|
||||||
|
|
||||||
|
AssetModificationProcessor.ModifiedAssets = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<PathToMove> GetPathsToMoveContainedOnWorkspace(
|
||||||
|
string wkPath,
|
||||||
|
string[] movedAssets,
|
||||||
|
string[] movedFromAssetPaths)
|
||||||
|
{
|
||||||
|
List<PathToMove> result = new List<PathToMove>(
|
||||||
|
movedAssets.Length);
|
||||||
|
|
||||||
|
for (int i = 0; i < movedAssets.Length; i++)
|
||||||
|
{
|
||||||
|
string fullSrcPath = AssetsPath.GetFullPathUnderWorkspace.
|
||||||
|
ForAsset(wkPath, movedFromAssetPaths[i]);
|
||||||
|
|
||||||
|
if (fullSrcPath == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string fullDstPath = AssetsPath.GetFullPathUnderWorkspace.
|
||||||
|
ForAsset(wkPath, movedAssets[i]);
|
||||||
|
|
||||||
|
if (fullDstPath == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result.Add(new PathToMove(
|
||||||
|
fullSrcPath, fullDstPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<string> GetPathsContainedOnWorkspace(
|
||||||
|
string wkPath, string[] assets)
|
||||||
|
{
|
||||||
|
List<string> result = new List<string>(
|
||||||
|
assets.Length);
|
||||||
|
|
||||||
|
foreach (string asset in assets)
|
||||||
|
{
|
||||||
|
string fullPath = AssetsPath.GetFullPathUnderWorkspace.
|
||||||
|
ForAsset(wkPath, asset);
|
||||||
|
|
||||||
|
if (fullPath == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result.Add(fullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mIsEnabled;
|
||||||
|
static bool mIsRepaintInspectorNeededAfterAssetDatabaseRefresh;
|
||||||
|
|
||||||
|
static PlasticAssetsProcessor mPlasticAssetsProcessor;
|
||||||
|
static string mWkPath;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.AssetUtils.Processor
|
||||||
|
{
|
||||||
|
internal static class AssetsProcessors
|
||||||
|
{
|
||||||
|
internal static void Enable(
|
||||||
|
string wkPath,
|
||||||
|
PlasticAssetsProcessor plasticAssetsProcessor,
|
||||||
|
IAssetStatusCache assetStatusCache)
|
||||||
|
{
|
||||||
|
AssetPostprocessor.Enable(wkPath, plasticAssetsProcessor);
|
||||||
|
AssetModificationProcessor.Enable(wkPath, assetStatusCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Disable()
|
||||||
|
{
|
||||||
|
AssetPostprocessor.Disable();
|
||||||
|
AssetModificationProcessor.Disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Codice.LogWrapper;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.AssetUtils.Processor
|
||||||
|
{
|
||||||
|
internal class PlasticAssetsProcessor : WorkspaceOperationsMonitor.IDisableAssetsProcessor
|
||||||
|
{
|
||||||
|
internal void SetWorkspaceOperationsMonitor(
|
||||||
|
WorkspaceOperationsMonitor workspaceOperationsMonitor)
|
||||||
|
{
|
||||||
|
mWorkspaceOperationsMonitor = workspaceOperationsMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddToSourceControl(List<string> paths)
|
||||||
|
{
|
||||||
|
if (paths.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (IsDisableBecauseExceptionHappened(DateTime.Now))
|
||||||
|
{
|
||||||
|
mLog.Warn(
|
||||||
|
"PlasticAssetsProcessor skipping AddToSourceControl operation " +
|
||||||
|
"because an exception happened in the last 60 seconds");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string path in paths)
|
||||||
|
mLog.DebugFormat("AddToSourceControl: {0}", path);
|
||||||
|
|
||||||
|
mWorkspaceOperationsMonitor.AddAssetsProcessorPathsToAdd(paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void DeleteFromSourceControl(List<string> paths)
|
||||||
|
{
|
||||||
|
if (paths.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (IsDisableBecauseExceptionHappened(DateTime.Now))
|
||||||
|
{
|
||||||
|
mLog.Warn(
|
||||||
|
"PlasticAssetsProcessor skipping DeleteFromSourceControl operation " +
|
||||||
|
"because an exception happened in the last 60 seconds");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string path in paths)
|
||||||
|
mLog.DebugFormat("DeleteFromSourceControl: {0}", path);
|
||||||
|
|
||||||
|
mWorkspaceOperationsMonitor.AddAssetsProcessorPathsToDelete(paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void MoveOnSourceControl(List<AssetPostprocessor.PathToMove> paths)
|
||||||
|
{
|
||||||
|
if (paths.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (IsDisableBecauseExceptionHappened(DateTime.Now))
|
||||||
|
{
|
||||||
|
mLog.Warn(
|
||||||
|
"PlasticAssetsProcessor skipping MoveOnSourceControl operation " +
|
||||||
|
"because an exception happened in the last 60 seconds");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (AssetPostprocessor.PathToMove path in paths)
|
||||||
|
mLog.DebugFormat("MoveOnSourceControl: {0} to {1}", path.SrcPath, path.DstPath);
|
||||||
|
|
||||||
|
mWorkspaceOperationsMonitor.AddAssetsProcessorPathsToMove(paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void CheckoutOnSourceControl(List<string> paths)
|
||||||
|
{
|
||||||
|
if (paths.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (IsDisableBecauseExceptionHappened(DateTime.Now))
|
||||||
|
{
|
||||||
|
mLog.Warn(
|
||||||
|
"PlasticAssetsProcessor skipping CheckoutOnSourceControl operation " +
|
||||||
|
"because an exception happened in the last 60 seconds");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string path in paths)
|
||||||
|
mLog.DebugFormat("CheckoutOnSourceControl: {0}", path);
|
||||||
|
|
||||||
|
mWorkspaceOperationsMonitor.AddAssetsProcessorPathsToCheckout(paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceOperationsMonitor.IDisableAssetsProcessor.Disable()
|
||||||
|
{
|
||||||
|
mLastExceptionDateTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDisableBecauseExceptionHappened(DateTime now)
|
||||||
|
{
|
||||||
|
return (now - mLastExceptionDateTime).TotalSeconds < 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime mLastExceptionDateTime = DateTime.MinValue;
|
||||||
|
WorkspaceOperationsMonitor mWorkspaceOperationsMonitor;
|
||||||
|
|
||||||
|
static readonly ILog mLog = LogManager.GetLogger("PlasticAssetsProcessor");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,536 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
using Codice.Client.BaseCommands;
|
||||||
|
using Codice.Client.Commands;
|
||||||
|
using Codice.Client.Commands.WkTree;
|
||||||
|
using Codice.LogWrapper;
|
||||||
|
using GluonGui;
|
||||||
|
using PlasticGui;
|
||||||
|
using PlasticGui.WorkspaceWindow;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
using Unity.PlasticSCM.Editor.Views.IncomingChanges;
|
||||||
|
using Unity.PlasticSCM.Editor.Views.PendingChanges;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.AssetUtils.Processor
|
||||||
|
{
|
||||||
|
internal class WorkspaceOperationsMonitor
|
||||||
|
{
|
||||||
|
public interface IDisableAssetsProcessor
|
||||||
|
{
|
||||||
|
void Disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal WorkspaceOperationsMonitor(
|
||||||
|
IPlasticAPI plasticApi,
|
||||||
|
IDisableAssetsProcessor disableAssetsProcessor,
|
||||||
|
bool isGluonMode)
|
||||||
|
{
|
||||||
|
mPlasticAPI = plasticApi;
|
||||||
|
mDisableAssetsProcessor = disableAssetsProcessor;
|
||||||
|
mIsGluonMode = isGluonMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RegisterWindow(
|
||||||
|
WorkspaceWindow workspaceWindow,
|
||||||
|
ViewHost viewHost,
|
||||||
|
NewIncomingChangesUpdater incomingChangesUpdater)
|
||||||
|
{
|
||||||
|
mWorkspaceWindow = workspaceWindow;
|
||||||
|
mViewHost = viewHost;
|
||||||
|
mNewIncomingChangesUpdater = incomingChangesUpdater;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void UnRegisterWindow()
|
||||||
|
{
|
||||||
|
mWorkspaceWindow = null;
|
||||||
|
mViewHost = null;
|
||||||
|
mNewIncomingChangesUpdater = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RegisterPendingChangesView(
|
||||||
|
PendingChangesTab pendingChangesTab)
|
||||||
|
{
|
||||||
|
mPendingChangesTab = pendingChangesTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RegisterIncomingChangesView(
|
||||||
|
IIncomingChangesTab incomingChangesTab)
|
||||||
|
{
|
||||||
|
mIncomingChangesTab = incomingChangesTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void UnRegisterViews()
|
||||||
|
{
|
||||||
|
mPendingChangesTab = null;
|
||||||
|
mIncomingChangesTab = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Start()
|
||||||
|
{
|
||||||
|
mIsRunning = true;
|
||||||
|
|
||||||
|
Thread thread = new Thread(TaskLoopThread);
|
||||||
|
thread.IsBackground = true;
|
||||||
|
thread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Stop()
|
||||||
|
{
|
||||||
|
SetAsFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddAssetsProcessorPathsToAdd(
|
||||||
|
List<string> paths)
|
||||||
|
{
|
||||||
|
AddPathsToProcess(
|
||||||
|
mAssetsProcessorPathsToAdd, paths,
|
||||||
|
mLock, mResetEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddAssetsProcessorPathsToDelete(
|
||||||
|
List<string> paths)
|
||||||
|
{
|
||||||
|
AddPathsToProcess(
|
||||||
|
mAssetsProcessorPathsToDelete, paths,
|
||||||
|
mLock, mResetEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddAssetsProcessorPathsToCheckout(
|
||||||
|
List<string> paths)
|
||||||
|
{
|
||||||
|
AddPathsToProcess(
|
||||||
|
mAssetsProcessorPathsToCheckout, paths,
|
||||||
|
mLock, mResetEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddAssetsProcessorPathsToMove(
|
||||||
|
List<AssetPostprocessor.PathToMove> paths)
|
||||||
|
{
|
||||||
|
AddPathsToMoveToProcess(
|
||||||
|
mAssetsProcessorPathsToMove, paths,
|
||||||
|
mLock, mResetEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddPathsToCheckout(
|
||||||
|
List<string> paths)
|
||||||
|
{
|
||||||
|
AddPathsToProcess(
|
||||||
|
mPathsToCheckout, paths,
|
||||||
|
mLock, mResetEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskLoopThread()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!mIsRunning)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ProcessAssetProcessorOperations(
|
||||||
|
mPlasticAPI,
|
||||||
|
mAssetsProcessorPathsToAdd,
|
||||||
|
mAssetsProcessorPathsToDelete,
|
||||||
|
mAssetsProcessorPathsToCheckout,
|
||||||
|
mAssetsProcessorPathsToMove,
|
||||||
|
mLock,
|
||||||
|
mDisableAssetsProcessor);
|
||||||
|
|
||||||
|
ProcessCheckoutOperation(
|
||||||
|
mPlasticAPI,
|
||||||
|
mPathsToCheckout,
|
||||||
|
mLock);
|
||||||
|
|
||||||
|
bool hasAssetProcessorOperations = false;
|
||||||
|
bool hasCheckoutOperations = false;
|
||||||
|
HasPendingOperationsToProcess(
|
||||||
|
mAssetsProcessorPathsToAdd,
|
||||||
|
mAssetsProcessorPathsToDelete,
|
||||||
|
mAssetsProcessorPathsToCheckout,
|
||||||
|
mAssetsProcessorPathsToMove,
|
||||||
|
mPathsToCheckout,
|
||||||
|
mLock,
|
||||||
|
out hasAssetProcessorOperations,
|
||||||
|
out hasCheckoutOperations);
|
||||||
|
|
||||||
|
if (hasAssetProcessorOperations ||
|
||||||
|
hasCheckoutOperations)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!hasAssetProcessorOperations)
|
||||||
|
EditorDispatcher.Dispatch(AfterAssetProcessorOperation);
|
||||||
|
|
||||||
|
if (!hasCheckoutOperations)
|
||||||
|
EditorDispatcher.Dispatch(AfterCheckoutOperation);
|
||||||
|
|
||||||
|
SleepUntilNextWorkload();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
mLog.ErrorFormat(
|
||||||
|
"Error running the tasks loop : {0}", e.Message);
|
||||||
|
mLog.DebugFormat(
|
||||||
|
"Stacktrace: {0}", e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AfterAssetProcessorOperation()
|
||||||
|
{
|
||||||
|
AutoRefresh.PendingChangesView(
|
||||||
|
mPendingChangesTab);
|
||||||
|
|
||||||
|
AutoRefresh.IncomingChangesView(
|
||||||
|
mIncomingChangesTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AfterCheckoutOperation()
|
||||||
|
{
|
||||||
|
RefreshAsset.VersionControlCache();
|
||||||
|
|
||||||
|
if (mIsGluonMode)
|
||||||
|
{
|
||||||
|
RefreshViewsAfterCheckoutForGluon(mViewHost);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mNewIncomingChangesUpdater != null)
|
||||||
|
mNewIncomingChangesUpdater.Update(DateTime.Now);
|
||||||
|
|
||||||
|
RefreshViewsAfterCheckoutForDeveloper(mWorkspaceWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetAsFinished()
|
||||||
|
{
|
||||||
|
if (!mIsRunning)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mIsRunning = false;
|
||||||
|
mResetEvent.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SleepUntilNextWorkload()
|
||||||
|
{
|
||||||
|
mResetEvent.Reset();
|
||||||
|
mResetEvent.WaitOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ProcessAssetProcessorOperations(
|
||||||
|
IPlasticAPI plasticApi,
|
||||||
|
List<string> assetsProcessorPathsToAdd,
|
||||||
|
List<string> assetsProcessorPathsToDelete,
|
||||||
|
List<string> assetsProcessorPathsToCheckout,
|
||||||
|
List<AssetPostprocessor.PathToMove> assetsProcessorPathsToMove,
|
||||||
|
object lockObj,
|
||||||
|
IDisableAssetsProcessor disableAssetsProcessor)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AssetsProcessorOperations.AddIfNotControlled(
|
||||||
|
plasticApi, ExtractPathsToProcess(
|
||||||
|
assetsProcessorPathsToAdd, lockObj),
|
||||||
|
FilterManager.Get().GetIgnoredFilter());
|
||||||
|
|
||||||
|
AssetsProcessorOperations.DeleteIfControlled(
|
||||||
|
plasticApi, ExtractPathsToProcess(
|
||||||
|
assetsProcessorPathsToDelete, lockObj));
|
||||||
|
|
||||||
|
AssetsProcessorOperations.CheckoutIfControlledAndChanged(
|
||||||
|
plasticApi, ExtractPathsToProcess(
|
||||||
|
assetsProcessorPathsToCheckout, lockObj));
|
||||||
|
|
||||||
|
AssetsProcessorOperations.MoveIfControlled(
|
||||||
|
plasticApi, ExtractPathsToMoveToProcess(
|
||||||
|
assetsProcessorPathsToMove, lockObj));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
|
|
||||||
|
disableAssetsProcessor.Disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ProcessCheckoutOperation(
|
||||||
|
IPlasticAPI plasticApi,
|
||||||
|
List<string> pathsToProcess,
|
||||||
|
object lockObj)
|
||||||
|
{
|
||||||
|
List<string> paths = ExtractPathsToProcess(
|
||||||
|
pathsToProcess, lockObj);
|
||||||
|
|
||||||
|
if (paths.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
plasticApi.Checkout(
|
||||||
|
paths.ToArray(),
|
||||||
|
CheckoutModifiers.ProcessSymlinks);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddPathsToProcess(
|
||||||
|
List<string> pathsToProcess,
|
||||||
|
List<string> paths,
|
||||||
|
object lockObj,
|
||||||
|
ManualResetEvent resetEvent)
|
||||||
|
{
|
||||||
|
lock (lockObj)
|
||||||
|
{
|
||||||
|
pathsToProcess.AddRange(paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetEvent.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddPathsToMoveToProcess(
|
||||||
|
List<AssetPostprocessor.PathToMove> pathsToProcess,
|
||||||
|
List<AssetPostprocessor.PathToMove> paths,
|
||||||
|
object lockObj,
|
||||||
|
ManualResetEvent resetEvent)
|
||||||
|
{
|
||||||
|
lock (lockObj)
|
||||||
|
{
|
||||||
|
pathsToProcess.AddRange(paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetEvent.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<string> ExtractPathsToProcess(
|
||||||
|
List<string> pathsToProcess,
|
||||||
|
object lockObj)
|
||||||
|
{
|
||||||
|
List<string> result;
|
||||||
|
|
||||||
|
lock (lockObj)
|
||||||
|
{
|
||||||
|
result = new List<string>(pathsToProcess);
|
||||||
|
pathsToProcess.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<AssetPostprocessor.PathToMove> ExtractPathsToMoveToProcess(
|
||||||
|
List<AssetPostprocessor.PathToMove> pathsToProcess,
|
||||||
|
object lockObj)
|
||||||
|
{
|
||||||
|
List<AssetPostprocessor.PathToMove> result;
|
||||||
|
|
||||||
|
lock (lockObj)
|
||||||
|
{
|
||||||
|
result = new List<AssetPostprocessor.PathToMove>(pathsToProcess);
|
||||||
|
pathsToProcess.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HasPendingOperationsToProcess(
|
||||||
|
List<string> assetsProcessorPathsToAdd,
|
||||||
|
List<string> assetsProcessorPathsToDelete,
|
||||||
|
List<string> assetsProcessorPathsToCheckout,
|
||||||
|
List<AssetPostprocessor.PathToMove> assetsProcessorPathsToMove,
|
||||||
|
List<string> pathsToCheckout,
|
||||||
|
object lockObj,
|
||||||
|
out bool hasAssetProcessorOperations,
|
||||||
|
out bool hasCheckoutOperations)
|
||||||
|
{
|
||||||
|
lock (lockObj)
|
||||||
|
{
|
||||||
|
hasAssetProcessorOperations =
|
||||||
|
assetsProcessorPathsToAdd.Count > 0 ||
|
||||||
|
assetsProcessorPathsToDelete.Count > 0 ||
|
||||||
|
assetsProcessorPathsToCheckout.Count > 0 ||
|
||||||
|
assetsProcessorPathsToMove.Count > 0;
|
||||||
|
|
||||||
|
hasCheckoutOperations =
|
||||||
|
pathsToCheckout.Count > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RefreshViewsAfterCheckoutForDeveloper(
|
||||||
|
IWorkspaceWindow workspaceWindow)
|
||||||
|
{
|
||||||
|
if (workspaceWindow == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
workspaceWindow.RefreshView(ViewType.BranchExplorerView);
|
||||||
|
workspaceWindow.RefreshView(ViewType.PendingChangesView);
|
||||||
|
workspaceWindow.RefreshView(ViewType.HistoryView);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RefreshViewsAfterCheckoutForGluon(
|
||||||
|
ViewHost viewHost)
|
||||||
|
{
|
||||||
|
if (viewHost == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
viewHost.RefreshView(ViewType.WorkspaceExplorerView);
|
||||||
|
viewHost.RefreshView(ViewType.CheckinView);
|
||||||
|
viewHost.RefreshView(ViewType.IncomingChangesView);
|
||||||
|
viewHost.RefreshView(ViewType.SearchView);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LogException(Exception ex)
|
||||||
|
{
|
||||||
|
mLog.WarnFormat("Message: {0}", ex.Message);
|
||||||
|
|
||||||
|
mLog.DebugFormat(
|
||||||
|
"StackTrace:{0}{1}",
|
||||||
|
Environment.NewLine, ex.StackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class AssetsProcessorOperations
|
||||||
|
{
|
||||||
|
internal static void AddIfNotControlled(
|
||||||
|
IPlasticAPI plasticApi,
|
||||||
|
List<string> paths,
|
||||||
|
IgnoredFilesFilter ignoredFilter)
|
||||||
|
{
|
||||||
|
List<string> result = new List<string>();
|
||||||
|
|
||||||
|
foreach (string path in paths)
|
||||||
|
{
|
||||||
|
string metaPath = MetaPath.GetMetaPath(path);
|
||||||
|
|
||||||
|
if (plasticApi.GetWorkspaceFromPath(path) == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (plasticApi.GetWorkspaceTreeNode(path) == null &&
|
||||||
|
!ignoredFilter.IsIgnored(path))
|
||||||
|
result.Add(path);
|
||||||
|
|
||||||
|
if (File.Exists(metaPath) &&
|
||||||
|
plasticApi.GetWorkspaceTreeNode(metaPath) == null &&
|
||||||
|
!ignoredFilter.IsIgnored(path))
|
||||||
|
result.Add(metaPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IList checkouts;
|
||||||
|
plasticApi.Add(
|
||||||
|
result.ToArray(),
|
||||||
|
GetDefaultAddOptions(),
|
||||||
|
out checkouts);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void DeleteIfControlled(
|
||||||
|
IPlasticAPI plasticApi,
|
||||||
|
List<string> paths)
|
||||||
|
{
|
||||||
|
foreach (string path in paths)
|
||||||
|
{
|
||||||
|
string metaPath = MetaPath.GetMetaPath(path);
|
||||||
|
|
||||||
|
if (plasticApi.GetWorkspaceTreeNode(path) != null)
|
||||||
|
{
|
||||||
|
plasticApi.DeleteControlled(
|
||||||
|
path, DeleteModifiers.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plasticApi.GetWorkspaceTreeNode(metaPath) != null)
|
||||||
|
{
|
||||||
|
plasticApi.DeleteControlled(
|
||||||
|
metaPath, DeleteModifiers.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void MoveIfControlled(
|
||||||
|
IPlasticAPI plasticApi,
|
||||||
|
List<AssetPostprocessor.PathToMove> paths)
|
||||||
|
{
|
||||||
|
foreach (AssetPostprocessor.PathToMove pathToMove in paths)
|
||||||
|
{
|
||||||
|
string srcMetaPath = MetaPath.GetMetaPath(pathToMove.SrcPath);
|
||||||
|
string dstMetaPath = MetaPath.GetMetaPath(pathToMove.DstPath);
|
||||||
|
|
||||||
|
if (plasticApi.GetWorkspaceTreeNode(pathToMove.SrcPath) != null)
|
||||||
|
{
|
||||||
|
plasticApi.Move(
|
||||||
|
pathToMove.SrcPath, pathToMove.DstPath,
|
||||||
|
MoveModifiers.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plasticApi.GetWorkspaceTreeNode(srcMetaPath) != null)
|
||||||
|
{
|
||||||
|
plasticApi.Move(
|
||||||
|
srcMetaPath, dstMetaPath,
|
||||||
|
MoveModifiers.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void CheckoutIfControlledAndChanged(
|
||||||
|
IPlasticAPI plasticApi,
|
||||||
|
List<string> paths)
|
||||||
|
{
|
||||||
|
List<string> result = new List<string>();
|
||||||
|
|
||||||
|
foreach (string path in paths)
|
||||||
|
{
|
||||||
|
string metaPath = MetaPath.GetMetaPath(path);
|
||||||
|
|
||||||
|
WorkspaceTreeNode node =
|
||||||
|
plasticApi.GetWorkspaceTreeNode(path);
|
||||||
|
WorkspaceTreeNode nodeMeta =
|
||||||
|
plasticApi.GetWorkspaceTreeNode(metaPath);
|
||||||
|
|
||||||
|
if (node != null && ChangedFileChecker.IsChanged(
|
||||||
|
node.LocalInfo, path, false))
|
||||||
|
result.Add(path);
|
||||||
|
|
||||||
|
if (nodeMeta != null && ChangedFileChecker.IsChanged(
|
||||||
|
nodeMeta.LocalInfo, metaPath, false))
|
||||||
|
result.Add(metaPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
plasticApi.Checkout(
|
||||||
|
result.ToArray(),
|
||||||
|
CheckoutModifiers.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
static AddOptions GetDefaultAddOptions()
|
||||||
|
{
|
||||||
|
AddOptions options = new AddOptions();
|
||||||
|
options.AddPrivateParents = true;
|
||||||
|
options.NeedCheckPlatformPath = true;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object mLock = new object();
|
||||||
|
volatile bool mIsRunning;
|
||||||
|
volatile ManualResetEvent mResetEvent = new ManualResetEvent(false);
|
||||||
|
|
||||||
|
List<string> mAssetsProcessorPathsToAdd = new List<string>();
|
||||||
|
List<string> mAssetsProcessorPathsToDelete = new List<string>();
|
||||||
|
List<string> mAssetsProcessorPathsToCheckout = new List<string>();
|
||||||
|
List<AssetPostprocessor.PathToMove> mAssetsProcessorPathsToMove =
|
||||||
|
new List<AssetPostprocessor.PathToMove>();
|
||||||
|
List<string> mPathsToCheckout = new List<string>();
|
||||||
|
|
||||||
|
PendingChangesTab mPendingChangesTab;
|
||||||
|
IIncomingChangesTab mIncomingChangesTab;
|
||||||
|
|
||||||
|
NewIncomingChangesUpdater mNewIncomingChangesUpdater;
|
||||||
|
ViewHost mViewHost;
|
||||||
|
IWorkspaceWindow mWorkspaceWindow;
|
||||||
|
|
||||||
|
readonly bool mIsGluonMode = false;
|
||||||
|
readonly IDisableAssetsProcessor mDisableAssetsProcessor;
|
||||||
|
readonly IPlasticAPI mPlasticAPI;
|
||||||
|
|
||||||
|
static readonly ILog mLog = LogManager.GetLogger("WorkspaceOperationsMonitor");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.AssetUtils
|
||||||
|
{
|
||||||
|
internal static class ProjectPath
|
||||||
|
{
|
||||||
|
internal static string FromApplicationDataPath(string dataPath)
|
||||||
|
{
|
||||||
|
return Path.GetDirectoryName(Path.GetFullPath(dataPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
using UnityEditor.PackageManager;
|
||||||
|
|
||||||
|
using Unity.PlasticSCM.Editor.AssetUtils.Processor;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.AssetUtils
|
||||||
|
{
|
||||||
|
internal static class RefreshAsset
|
||||||
|
{
|
||||||
|
internal static void BeforeLongAssetOperation()
|
||||||
|
{
|
||||||
|
UnityEditor.AssetDatabase.DisallowAutoRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void AfterLongAssetOperation()
|
||||||
|
{
|
||||||
|
UnityEditor.AssetDatabase.AllowAutoRefresh();
|
||||||
|
|
||||||
|
UnityAssetDatabase();
|
||||||
|
|
||||||
|
// Client is an API to interact with package manager
|
||||||
|
// Client.Resolve() will resolve any pending packages added or removed from the project.
|
||||||
|
// https://docs.unity3d.com/ScriptReference/PackageManager.Client.html
|
||||||
|
Client.Resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void UnityAssetDatabase()
|
||||||
|
{
|
||||||
|
UnityEditor.AssetDatabase.Refresh(
|
||||||
|
UnityEditor.ImportAssetOptions.Default);
|
||||||
|
|
||||||
|
UnityEditor.VersionControl.Provider.ClearCache();
|
||||||
|
|
||||||
|
AssetPostprocessor.SetIsRepaintInspectorNeededAfterAssetDatabaseRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void VersionControlCache()
|
||||||
|
{
|
||||||
|
UnityEditor.VersionControl.Provider.ClearCache();
|
||||||
|
|
||||||
|
RepaintInspector.All();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.AssetUtils
|
||||||
|
{
|
||||||
|
internal static class RepaintInspector
|
||||||
|
{
|
||||||
|
internal static void All()
|
||||||
|
{
|
||||||
|
UnityEditor.Editor[] editors =
|
||||||
|
Resources.FindObjectsOfTypeAll<UnityEditor.Editor>();
|
||||||
|
|
||||||
|
foreach (UnityEditor.Editor editor in editors)
|
||||||
|
editor.Repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.SceneManagement;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
|
using Codice.Client.BaseCommands;
|
||||||
|
using Codice.Client.Common;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.AssetUtils
|
||||||
|
{
|
||||||
|
internal static class SaveAssets
|
||||||
|
{
|
||||||
|
internal static void ForChangesWithConfirmation(
|
||||||
|
List<ChangeInfo> changes,
|
||||||
|
out bool isCancelled)
|
||||||
|
{
|
||||||
|
ForPaths(
|
||||||
|
GetPaths(changes), true,
|
||||||
|
out isCancelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void ForPathsWithConfirmation(
|
||||||
|
List<string> paths,
|
||||||
|
out bool isCancelled)
|
||||||
|
{
|
||||||
|
ForPaths(
|
||||||
|
paths, true,
|
||||||
|
out isCancelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void ForChangesWithoutConfirmation(
|
||||||
|
List<ChangeInfo> changes)
|
||||||
|
{
|
||||||
|
bool isCancelled;
|
||||||
|
ForPaths(
|
||||||
|
GetPaths(changes), false,
|
||||||
|
out isCancelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void ForPathsWithoutConfirmation(
|
||||||
|
List<string> paths)
|
||||||
|
{
|
||||||
|
bool isCancelled;
|
||||||
|
ForPaths(
|
||||||
|
paths, false,
|
||||||
|
out isCancelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ForPaths(
|
||||||
|
List<string> paths,
|
||||||
|
bool askForUserConfirmation,
|
||||||
|
out bool isCancelled)
|
||||||
|
{
|
||||||
|
SaveDirtyScenes(
|
||||||
|
paths,
|
||||||
|
askForUserConfirmation,
|
||||||
|
out isCancelled);
|
||||||
|
|
||||||
|
if (isCancelled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SaveDirtyScenes(
|
||||||
|
List<string> paths,
|
||||||
|
bool askForUserConfirmation,
|
||||||
|
out bool isCancelled)
|
||||||
|
{
|
||||||
|
isCancelled = false;
|
||||||
|
|
||||||
|
List<Scene> scenesToSave = new List<Scene>();
|
||||||
|
|
||||||
|
foreach (Scene dirtyScene in GetDirtyScenes())
|
||||||
|
{
|
||||||
|
if (Contains(paths, dirtyScene))
|
||||||
|
scenesToSave.Add(dirtyScene);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scenesToSave.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (askForUserConfirmation)
|
||||||
|
{
|
||||||
|
isCancelled = !EditorSceneManager.
|
||||||
|
SaveModifiedScenesIfUserWantsTo(
|
||||||
|
scenesToSave.ToArray());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorSceneManager.SaveScenes(
|
||||||
|
scenesToSave.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Scene> GetDirtyScenes()
|
||||||
|
{
|
||||||
|
List<Scene> dirtyScenes = new List<Scene>();
|
||||||
|
|
||||||
|
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||||
|
{
|
||||||
|
Scene scene = SceneManager.GetSceneAt(i);
|
||||||
|
|
||||||
|
if (!scene.isDirty)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dirtyScenes.Add(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dirtyScenes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Contains(
|
||||||
|
List<string> paths,
|
||||||
|
Scene scene)
|
||||||
|
{
|
||||||
|
foreach (string path in paths)
|
||||||
|
{
|
||||||
|
if (PathHelper.IsSamePath(
|
||||||
|
path,
|
||||||
|
Path.GetFullPath(scene.path)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<string> GetPaths(List<ChangeInfo> changeInfos)
|
||||||
|
{
|
||||||
|
List<string> result = new List<string>();
|
||||||
|
foreach (ChangeInfo change in changeInfos)
|
||||||
|
result.Add(change.GetFullPath());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
using Codice.LogWrapper;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.ProjectDownloader
|
||||||
|
{
|
||||||
|
internal static class CloudProjectDownloader
|
||||||
|
{
|
||||||
|
internal const string IS_PROJECT_DOWNLOADER_ALREADY_EXECUTED_KEY =
|
||||||
|
"PlasticSCM.ProjectDownloader.IsAlreadyExecuted";
|
||||||
|
|
||||||
|
internal const string SHOULD_PROJECT_BE_DOWNLOADED_KEY =
|
||||||
|
"PlasticSCM.ProjectDownloader.ShouldProjectBeDownloaded";
|
||||||
|
|
||||||
|
internal static void Initialize()
|
||||||
|
{
|
||||||
|
EditorApplication.update += RunOnceWhenAccessTokenIsInitialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RunOnceWhenAccessTokenIsInitialized()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(CloudProjectSettings.accessToken))
|
||||||
|
return;
|
||||||
|
|
||||||
|
EditorApplication.update -= RunOnceWhenAccessTokenIsInitialized;
|
||||||
|
|
||||||
|
Execute(CloudProjectSettings.accessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Execute(string unityAccessToken)
|
||||||
|
{
|
||||||
|
if (SessionState.GetBool(
|
||||||
|
IS_PROJECT_DOWNLOADER_ALREADY_EXECUTED_KEY, false))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DownloadRepository(unityAccessToken);
|
||||||
|
|
||||||
|
SessionState.SetBool(
|
||||||
|
IS_PROJECT_DOWNLOADER_ALREADY_EXECUTED_KEY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void DownloadRepository(string unityAccessToken)
|
||||||
|
{
|
||||||
|
DownloadRepository(unityAccessToken, Environment.GetCommandLineArgs());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void DownloadRepository(string unityAccessToken, string[] commandLineArgs)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> args = CommandLineArguments.Build(commandLineArgs);
|
||||||
|
|
||||||
|
mLog.DebugFormat(
|
||||||
|
"Processing Unity arguments: {0}", string.Join(" ", commandLineArgs));
|
||||||
|
|
||||||
|
string projectPath = ParseArguments.ProjectPath(args);
|
||||||
|
string cloudRepository = ParseArguments.CloudProject(args);
|
||||||
|
string cloudOrganization = ParseArguments.CloudOrganization(args);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(projectPath) ||
|
||||||
|
string.IsNullOrEmpty(cloudRepository) ||
|
||||||
|
string.IsNullOrEmpty(cloudOrganization))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionState.SetBool(
|
||||||
|
SHOULD_PROJECT_BE_DOWNLOADED_KEY, true);
|
||||||
|
|
||||||
|
PlasticApp.InitializeIfNeeded();
|
||||||
|
|
||||||
|
DownloadRepositoryOperation downloadOperation =
|
||||||
|
new DownloadRepositoryOperation();
|
||||||
|
|
||||||
|
downloadOperation.DownloadRepositoryToPathIfNeeded(
|
||||||
|
cloudRepository,
|
||||||
|
cloudOrganization,
|
||||||
|
Path.GetFullPath(projectPath),
|
||||||
|
unityAccessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly ILog mLog = LogManager.GetLogger("ProjectDownloader");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.ProjectDownloader
|
||||||
|
{
|
||||||
|
internal class CommandLineArguments
|
||||||
|
{
|
||||||
|
internal static Dictionary<string, string> Build(string[] args)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> result = new Dictionary<string, string>(
|
||||||
|
StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
if (args == null)
|
||||||
|
return result;
|
||||||
|
List<string> trimmedArguments = TrimArgs(args);
|
||||||
|
|
||||||
|
int index = 1;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (index > trimmedArguments.Count - 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (IsKeyValueArgumentAtIndex(trimmedArguments, index))
|
||||||
|
{
|
||||||
|
result[trimmedArguments[index]] = trimmedArguments[index + 1];
|
||||||
|
index += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[trimmedArguments[index]] = null;
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<string> TrimArgs(string[] args)
|
||||||
|
{
|
||||||
|
List<string> trimmedArguments = new List<string>();
|
||||||
|
|
||||||
|
foreach (string argument in args)
|
||||||
|
trimmedArguments.Add(argument.Trim());
|
||||||
|
|
||||||
|
return trimmedArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsKeyValueArgumentAtIndex(
|
||||||
|
List<string> trimmedArguments,
|
||||||
|
int index)
|
||||||
|
{
|
||||||
|
if (index + 1 > trimmedArguments.Count -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !trimmedArguments[index + 1].StartsWith("-");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,218 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
using Codice.Client.BaseCommands;
|
||||||
|
using Codice.Client.Commands;
|
||||||
|
using Codice.CM.Common;
|
||||||
|
using Codice.LogWrapper;
|
||||||
|
using PlasticGui;
|
||||||
|
using PlasticGui.WebApi;
|
||||||
|
using PlasticGui.WorkspaceWindow;
|
||||||
|
using PlasticGui.WorkspaceWindow.Update;
|
||||||
|
using Unity.PlasticSCM.Editor.AssetUtils;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
using Unity.PlasticSCM.Editor.WebApi;
|
||||||
|
using Unity.PlasticSCM.Editor.Configuration;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.ProjectDownloader
|
||||||
|
{
|
||||||
|
internal class DownloadRepositoryOperation
|
||||||
|
{
|
||||||
|
internal void DownloadRepositoryToPathIfNeeded(
|
||||||
|
string cloudRepository,
|
||||||
|
string cloudOrganization,
|
||||||
|
string projectPath,
|
||||||
|
string unityAccessToken)
|
||||||
|
{
|
||||||
|
RefreshAsset.BeforeLongAssetOperation();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
BuildProgressSpeedAndRemainingTime.ProgressData progressData =
|
||||||
|
new BuildProgressSpeedAndRemainingTime.ProgressData(DateTime.Now);
|
||||||
|
|
||||||
|
ThreadPool.QueueUserWorkItem(
|
||||||
|
DownloadRepository,
|
||||||
|
new DownloadRepositoryParameters()
|
||||||
|
{
|
||||||
|
CloudOrganization = cloudOrganization,
|
||||||
|
CloudRepository = cloudRepository,
|
||||||
|
ProjectPath = projectPath,
|
||||||
|
AccessToken = unityAccessToken
|
||||||
|
});
|
||||||
|
|
||||||
|
while (!mOperationFinished)
|
||||||
|
{
|
||||||
|
if (mDisplayProgress)
|
||||||
|
{
|
||||||
|
DisplayProgress(
|
||||||
|
mUpdateNotifier.GetUpdateStatus(),
|
||||||
|
progressData,
|
||||||
|
cloudRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Sleep(150);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
|
||||||
|
RefreshAsset.AfterLongAssetOperation();
|
||||||
|
|
||||||
|
if (!mOperationFailed)
|
||||||
|
{
|
||||||
|
PlasticPlugin.Enable();
|
||||||
|
ShowWindow.PlasticAfterDownloadingProject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DownloadRepository(object state)
|
||||||
|
{
|
||||||
|
DownloadRepositoryParameters parameters = (DownloadRepositoryParameters)state;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (FindWorkspace.HasWorkspace(parameters.ProjectPath))
|
||||||
|
{
|
||||||
|
// each domain reload, the package is reloaded.
|
||||||
|
// way need to check if we already downloaded it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDisplayProgress = true;
|
||||||
|
|
||||||
|
IPlasticWebRestApi restApi = new PlasticWebRestApi();
|
||||||
|
string defaultCloudAlias = restApi.GetDefaultCloudAlias();
|
||||||
|
|
||||||
|
RepositorySpec repSpec = BuildRepSpec(
|
||||||
|
parameters.CloudRepository,
|
||||||
|
parameters.CloudOrganization,
|
||||||
|
defaultCloudAlias);
|
||||||
|
|
||||||
|
TokenExchangeResponse tokenExchangeResponse =
|
||||||
|
AutoConfig.PlasticCredentials(
|
||||||
|
parameters.AccessToken,
|
||||||
|
repSpec.Server,
|
||||||
|
parameters.ProjectPath);
|
||||||
|
|
||||||
|
if (tokenExchangeResponse.Error != null)
|
||||||
|
{
|
||||||
|
mOperationFailed = true;
|
||||||
|
|
||||||
|
UnityEngine.Debug.LogErrorFormat(
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.ErrorDownloadingCloudProject),
|
||||||
|
string.Format("Unable to get TokenExchangeResponse: {0} [code {1}]",
|
||||||
|
tokenExchangeResponse.Error.Message,
|
||||||
|
tokenExchangeResponse.Error.ErrorCode));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkspaceInfo wkInfo = CreateWorkspace(
|
||||||
|
repSpec, parameters.ProjectPath);
|
||||||
|
|
||||||
|
mLog.DebugFormat("Created workspace {0} on {1}",
|
||||||
|
wkInfo.Name,
|
||||||
|
wkInfo.ClientPath);
|
||||||
|
|
||||||
|
PlasticGui.Plastic.API.Update(
|
||||||
|
wkInfo.ClientPath,
|
||||||
|
UpdateFlags.None,
|
||||||
|
null,
|
||||||
|
mUpdateNotifier);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
|
|
||||||
|
UnityEngine.Debug.LogErrorFormat(
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.ErrorDownloadingCloudProject),
|
||||||
|
ex.Message);
|
||||||
|
|
||||||
|
mOperationFailed = true;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
mOperationFinished = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DisplayProgress(
|
||||||
|
UpdateOperationStatus status,
|
||||||
|
BuildProgressSpeedAndRemainingTime.ProgressData progressData,
|
||||||
|
string cloudRepository)
|
||||||
|
{
|
||||||
|
string totalProgressMessage = UpdateProgressRender.
|
||||||
|
GetProgressString(status, progressData);
|
||||||
|
|
||||||
|
float totalProgressPercent = GetProgressBarPercent.
|
||||||
|
ForTransfer(status.UpdatedSize, status.TotalSize) / 100f;
|
||||||
|
|
||||||
|
EditorUtility.DisplayProgressBar(
|
||||||
|
string.Format("{0} {1}",
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.DownloadingProgress),
|
||||||
|
cloudRepository),
|
||||||
|
totalProgressMessage, totalProgressPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static WorkspaceInfo CreateWorkspace(
|
||||||
|
RepositorySpec repositorySpec,
|
||||||
|
string projectPath)
|
||||||
|
{
|
||||||
|
CreateWorkspaceDialogUserAssistant assistant = new CreateWorkspaceDialogUserAssistant(
|
||||||
|
PlasticGuiConfig.Get().Configuration.DefaultWorkspaceRoot,
|
||||||
|
PlasticGui.Plastic.API.GetAllWorkspacesArray());
|
||||||
|
|
||||||
|
assistant.RepositoryChanged(
|
||||||
|
repositorySpec.ToString(),
|
||||||
|
string.Empty,
|
||||||
|
string.Empty);
|
||||||
|
|
||||||
|
return PlasticGui.Plastic.API.CreateWorkspace(
|
||||||
|
projectPath,
|
||||||
|
assistant.GetProposedWorkspaceName(),
|
||||||
|
repositorySpec.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
static RepositorySpec BuildRepSpec(
|
||||||
|
string cloudRepository,
|
||||||
|
string cloudOrganization,
|
||||||
|
string defaultCloudAlias)
|
||||||
|
{
|
||||||
|
return new RepositorySpec()
|
||||||
|
{
|
||||||
|
Name = cloudRepository,
|
||||||
|
Server = CloudServer.BuildFullyQualifiedName(
|
||||||
|
cloudOrganization, defaultCloudAlias)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LogException(Exception ex)
|
||||||
|
{
|
||||||
|
mLog.WarnFormat("Message: {0}", ex.Message);
|
||||||
|
|
||||||
|
mLog.DebugFormat(
|
||||||
|
"StackTrace:{0}{1}",
|
||||||
|
Environment.NewLine, ex.StackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DownloadRepositoryParameters
|
||||||
|
{
|
||||||
|
internal string CloudRepository;
|
||||||
|
internal string CloudOrganization;
|
||||||
|
internal string ProjectPath;
|
||||||
|
internal string AccessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
volatile bool mOperationFinished = false;
|
||||||
|
volatile bool mOperationFailed = false;
|
||||||
|
volatile bool mDisplayProgress;
|
||||||
|
|
||||||
|
UpdateNotifier mUpdateNotifier = new UpdateNotifier();
|
||||||
|
|
||||||
|
static readonly ILog mLog = LogManager.GetLogger("DownloadRepositoryOperation");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.ProjectDownloader
|
||||||
|
{
|
||||||
|
internal static class ParseArguments
|
||||||
|
{
|
||||||
|
internal static string CloudProject(Dictionary<string, string> args)
|
||||||
|
{
|
||||||
|
string data;
|
||||||
|
|
||||||
|
if (!args.TryGetValue(CLOUD_PROJECT, out data))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string CloudOrganization(Dictionary<string, string> args)
|
||||||
|
{
|
||||||
|
string data;
|
||||||
|
|
||||||
|
if (!args.TryGetValue(CLOUD_ORGANIZATION, out data))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GetOrganizationNameFromData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string ProjectPath(Dictionary<string, string> args)
|
||||||
|
{
|
||||||
|
string data;
|
||||||
|
|
||||||
|
if (!args.TryGetValue(CREATE_PROJECT, out data))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string GetOrganizationNameFromData(string data)
|
||||||
|
{
|
||||||
|
// data is in format: 151d73c7-38cb-4eec-b11e-34764e707226-danipen-unity
|
||||||
|
int guidLenght = 36;
|
||||||
|
|
||||||
|
if (data.Length < guidLenght + 1)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return data.Substring(guidLenght + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const string CLOUD_PROJECT = "-cloudProject";
|
||||||
|
const string CLOUD_ORGANIZATION = "-cloudOrganization";
|
||||||
|
const string CREATE_PROJECT = "-createProject";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,264 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
using Codice.Client.Common.Threading;
|
||||||
|
using Codice.CM.Common;
|
||||||
|
using Codice.CM.WorkspaceServer;
|
||||||
|
using Codice.LogWrapper;
|
||||||
|
using Unity.PlasticSCM.Editor.AssetUtils;
|
||||||
|
using Unity.PlasticSCM.Editor.WebApi;
|
||||||
|
using Unity.PlasticSCM.Editor.ProjectDownloader;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.CollabMigration
|
||||||
|
{
|
||||||
|
public static class MigrateCollabProject
|
||||||
|
{
|
||||||
|
internal static void Initialize()
|
||||||
|
{
|
||||||
|
if (SessionState.GetInt(
|
||||||
|
IS_PROJECT_MIGRATED_ALREADY_CALCULATED_KEY,
|
||||||
|
MIGRATED_NOT_CALCULATED) == MIGRATED_NOTHING_TO_DO)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EditorApplication.update += RunOnceWhenAccessTokenAndProjectIdAreInitialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void RunOnceWhenAccessTokenAndProjectIdAreInitialized()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(CloudProjectSettings.accessToken))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!SetupCloudProjectId.HasCloudProjectId())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!SessionState.GetBool(
|
||||||
|
CloudProjectDownloader.IS_PROJECT_DOWNLOADER_ALREADY_EXECUTED_KEY, false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
EditorApplication.update -= RunOnceWhenAccessTokenAndProjectIdAreInitialized;
|
||||||
|
|
||||||
|
string projectPath = ProjectPath.FromApplicationDataPath(
|
||||||
|
ApplicationDataPath.Get());
|
||||||
|
|
||||||
|
string projectGuid = SetupCloudProjectId.GetCloudProjectId();
|
||||||
|
|
||||||
|
if (!ShouldProjectBeMigrated(projectPath, projectGuid))
|
||||||
|
{
|
||||||
|
SessionState.SetInt(
|
||||||
|
IS_PROJECT_MIGRATED_ALREADY_CALCULATED_KEY,
|
||||||
|
MIGRATED_NOTHING_TO_DO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Execute(
|
||||||
|
CloudProjectSettings.accessToken,
|
||||||
|
projectPath,
|
||||||
|
projectGuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ShouldProjectBeMigrated(
|
||||||
|
string projectPath,
|
||||||
|
string projectGuid)
|
||||||
|
{
|
||||||
|
if (SessionState.GetBool(
|
||||||
|
CloudProjectDownloader.SHOULD_PROJECT_BE_DOWNLOADED_KEY, false))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string collabPath = GetCollabSnapshotFile(
|
||||||
|
projectPath, projectGuid);
|
||||||
|
|
||||||
|
if (!File.Exists(collabPath))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FindWorkspace.HasWorkspace(ApplicationDataPath.Get()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Execute(
|
||||||
|
string unityAccessToken,
|
||||||
|
string projectPath,
|
||||||
|
string projectGuid)
|
||||||
|
{
|
||||||
|
string headCommitSha = GetCollabHeadCommitSha(projectPath, projectGuid);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(headCommitSha))
|
||||||
|
return;
|
||||||
|
|
||||||
|
PlasticApp.InitializeIfNeeded();
|
||||||
|
|
||||||
|
LaunchMigrationIfProjectIsArchivedAndMigrated(
|
||||||
|
unityAccessToken,
|
||||||
|
projectPath,
|
||||||
|
projectGuid,
|
||||||
|
headCommitSha);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void DeletePlasticDirectoryIfExists(string projectPath)
|
||||||
|
{
|
||||||
|
WorkspaceInfo wkInfo = new WorkspaceInfo("wk", projectPath);
|
||||||
|
string plasticDirectory = WorkspaceConfigFile.GetPlasticWkConfigPath(wkInfo);
|
||||||
|
|
||||||
|
if (!Directory.Exists(plasticDirectory))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Directory.Delete(plasticDirectory, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LaunchMigrationIfProjectIsArchivedAndMigrated(
|
||||||
|
string unityAccessToken,
|
||||||
|
string projectPath,
|
||||||
|
string projectGuid,
|
||||||
|
string headCommitSha)
|
||||||
|
{
|
||||||
|
IsCollabProjectMigratedResponse isMigratedResponse = null;
|
||||||
|
ChangesetFromCollabCommitResponse changesetResponse = null;
|
||||||
|
|
||||||
|
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
|
||||||
|
waiter.Execute(
|
||||||
|
/*threadOperationDelegate*/ delegate
|
||||||
|
{
|
||||||
|
isMigratedResponse = WebRestApiClient.PlasticScm.
|
||||||
|
IsCollabProjectMigrated(unityAccessToken, projectGuid);
|
||||||
|
|
||||||
|
if (isMigratedResponse.Error != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!isMigratedResponse.IsMigrated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OrganizationCredentials credentials = new OrganizationCredentials();
|
||||||
|
credentials.User = isMigratedResponse.Credentials.Email;
|
||||||
|
credentials.Password = isMigratedResponse.Credentials.Token;
|
||||||
|
|
||||||
|
string webLoginAccessToken = WebRestApiClient.CloudServer.WebLogin(
|
||||||
|
isMigratedResponse.WebServerUri,
|
||||||
|
isMigratedResponse.PlasticCloudOrganizationName,
|
||||||
|
credentials);
|
||||||
|
|
||||||
|
changesetResponse = WebRestApiClient.CloudServer.
|
||||||
|
GetChangesetFromCollabCommit(
|
||||||
|
isMigratedResponse.WebServerUri,
|
||||||
|
isMigratedResponse.PlasticCloudOrganizationName,
|
||||||
|
webLoginAccessToken, projectGuid, headCommitSha);
|
||||||
|
},
|
||||||
|
/*afterOperationDelegate*/ delegate
|
||||||
|
{
|
||||||
|
if (waiter.Exception != null)
|
||||||
|
{
|
||||||
|
ExceptionsHandler.LogException(
|
||||||
|
"IsCollabProjectArchivedAndMigrated",
|
||||||
|
waiter.Exception);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMigratedResponse.Error != null)
|
||||||
|
{
|
||||||
|
mLog.ErrorFormat(
|
||||||
|
"Unable to get IsCollabProjectMigratedResponse: {0} [code {1}]",
|
||||||
|
isMigratedResponse.Error.Message,
|
||||||
|
isMigratedResponse.Error.ErrorCode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isMigratedResponse.IsMigrated)
|
||||||
|
{
|
||||||
|
SessionState.SetInt(
|
||||||
|
IS_PROJECT_MIGRATED_ALREADY_CALCULATED_KEY,
|
||||||
|
MIGRATED_NOTHING_TO_DO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changesetResponse.Error != null)
|
||||||
|
{
|
||||||
|
mLog.ErrorFormat(
|
||||||
|
"Unable to get ChangesetFromCollabCommitResponse: {0} [code {1}]",
|
||||||
|
changesetResponse.Error.Message,
|
||||||
|
changesetResponse.Error.ErrorCode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeletePlasticDirectoryIfExists(projectPath);
|
||||||
|
|
||||||
|
MigrationDialog.Show(
|
||||||
|
null,
|
||||||
|
unityAccessToken,
|
||||||
|
projectPath,
|
||||||
|
isMigratedResponse.Credentials.Email,
|
||||||
|
isMigratedResponse.PlasticCloudOrganizationName,
|
||||||
|
new RepId(
|
||||||
|
changesetResponse.RepId,
|
||||||
|
changesetResponse.RepModuleId),
|
||||||
|
changesetResponse.ChangesetId,
|
||||||
|
changesetResponse.BranchId,
|
||||||
|
AfterWorkspaceMigrated);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AfterWorkspaceMigrated()
|
||||||
|
{
|
||||||
|
SessionState.SetInt(
|
||||||
|
IS_PROJECT_MIGRATED_ALREADY_CALCULATED_KEY,
|
||||||
|
MIGRATED_NOTHING_TO_DO);
|
||||||
|
|
||||||
|
CollabPlugin.Disable();
|
||||||
|
|
||||||
|
mLog.DebugFormat(
|
||||||
|
"Disabled Collab Plugin after the migration for Project: {0}",
|
||||||
|
ProjectPath.FromApplicationDataPath(ApplicationDataPath.Get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static string GetCollabHeadCommitSha(
|
||||||
|
string projectPath,
|
||||||
|
string projectGuid)
|
||||||
|
{
|
||||||
|
string collabPath = GetCollabSnapshotFile(
|
||||||
|
projectPath, projectGuid);
|
||||||
|
|
||||||
|
if (!File.Exists(collabPath))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
string text = File.ReadAllText(collabPath);
|
||||||
|
|
||||||
|
string[] chunks = text.Split(
|
||||||
|
new string[] { "currRevisionID" },
|
||||||
|
StringSplitOptions.None);
|
||||||
|
|
||||||
|
string current = chunks[1].Substring(3, 40);
|
||||||
|
|
||||||
|
if (!current.Contains("none"))
|
||||||
|
return current;
|
||||||
|
|
||||||
|
chunks = text.Split(
|
||||||
|
new string[] { "headRevisionID" },
|
||||||
|
StringSplitOptions.None);
|
||||||
|
|
||||||
|
return chunks[1].Substring(3, 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
static string GetCollabSnapshotFile(
|
||||||
|
string projectPath,
|
||||||
|
string projectGuid)
|
||||||
|
{
|
||||||
|
return projectPath + "/Library/Collab/CollabSnapshot_" + projectGuid + ".txt";
|
||||||
|
}
|
||||||
|
|
||||||
|
const string IS_PROJECT_MIGRATED_ALREADY_CALCULATED_KEY =
|
||||||
|
"PlasticSCM.MigrateCollabProject.IsAlreadyCalculated";
|
||||||
|
|
||||||
|
const int MIGRATED_NOT_CALCULATED = 0;
|
||||||
|
const int MIGRATED_NOTHING_TO_DO = 1;
|
||||||
|
|
||||||
|
static readonly ILog mLog = LogManager.GetLogger("MigrateCollabProject");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,417 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
using Codice.Client.BaseCommands;
|
||||||
|
using Codice.Client.BaseCommands.EventTracking;
|
||||||
|
using Codice.Client.BaseCommands.Sync;
|
||||||
|
using Codice.Client.Common.Threading;
|
||||||
|
using Codice.CM.Common;
|
||||||
|
using Codice.LogWrapper;
|
||||||
|
using CodiceApp.EventTracking;
|
||||||
|
using PlasticGui;
|
||||||
|
using PlasticGui.WorkspaceWindow;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
using Unity.PlasticSCM.Editor.UI.Progress;
|
||||||
|
using Unity.PlasticSCM.Editor.WebApi;
|
||||||
|
using Unity.PlasticSCM.Editor.Configuration;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.CollabMigration
|
||||||
|
{
|
||||||
|
internal class MigrationDialog : PlasticDialog
|
||||||
|
{
|
||||||
|
protected override Rect DefaultRect
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var baseRect = base.DefaultRect;
|
||||||
|
return new Rect(baseRect.x, baseRect.y, 710, 260);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GetTitle()
|
||||||
|
{
|
||||||
|
return "Upgrade your Collaborate project to Unity Version Control";
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: localize the strings
|
||||||
|
protected override void OnModalGUI()
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal();
|
||||||
|
|
||||||
|
DoIconArea();
|
||||||
|
|
||||||
|
GUILayout.Space(20);
|
||||||
|
|
||||||
|
DoContentArea();
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
DoButtonsArea();
|
||||||
|
|
||||||
|
mProgressControls.UpdateDeterminateProgress(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool Show(
|
||||||
|
EditorWindow parentWindow,
|
||||||
|
string unityAccessToken,
|
||||||
|
string projectPath,
|
||||||
|
string user,
|
||||||
|
string organizationName,
|
||||||
|
RepId repId,
|
||||||
|
long changesetId,
|
||||||
|
long branchId,
|
||||||
|
Action afterWorkspaceMigratedAction)
|
||||||
|
{
|
||||||
|
MigrationDialog dialog = Create(
|
||||||
|
unityAccessToken,
|
||||||
|
projectPath,
|
||||||
|
user,
|
||||||
|
organizationName,
|
||||||
|
repId,
|
||||||
|
changesetId,
|
||||||
|
branchId,
|
||||||
|
afterWorkspaceMigratedAction,
|
||||||
|
new ProgressControlsForMigration());
|
||||||
|
|
||||||
|
return dialog.RunModal(parentWindow) == ResponseType.Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoIconArea()
|
||||||
|
{
|
||||||
|
GUILayout.BeginVertical();
|
||||||
|
|
||||||
|
GUILayout.Space(30);
|
||||||
|
|
||||||
|
Rect iconRect = GUILayoutUtility.GetRect(
|
||||||
|
GUIContent.none, EditorStyles.label,
|
||||||
|
GUILayout.Width(60), GUILayout.Height(60));
|
||||||
|
|
||||||
|
GUI.DrawTexture(
|
||||||
|
iconRect,
|
||||||
|
Images.GetPlasticIcon(),
|
||||||
|
ScaleMode.ScaleToFit);
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoContentArea()
|
||||||
|
{
|
||||||
|
GUILayout.BeginVertical();
|
||||||
|
|
||||||
|
Title("Upgrade your Collaborate project to Unity Version Control");
|
||||||
|
|
||||||
|
GUILayout.Space(20);
|
||||||
|
|
||||||
|
Paragraph("Your Unity project has been upgraded (from Collaborate) to Unity Version Control free" +
|
||||||
|
" of charge by your administrator. Your local workspace will now be converted to a" +
|
||||||
|
" Unity Version Control workspace in just a few minutes. Select “Migrate” to start the conversion process.");
|
||||||
|
|
||||||
|
DrawProgressForMigration.For(
|
||||||
|
mProgressControls.ProgressData);
|
||||||
|
|
||||||
|
GUILayout.Space(40);
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: localize the strings
|
||||||
|
void DoButtonsArea()
|
||||||
|
{
|
||||||
|
using (new EditorGUILayout.HorizontalScope())
|
||||||
|
{
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
|
||||||
|
if (Application.platform == RuntimePlatform.WindowsEditor)
|
||||||
|
{
|
||||||
|
DoOkButton();
|
||||||
|
DoCloseButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoCloseButton();
|
||||||
|
DoOkButton();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoOkButton()
|
||||||
|
{
|
||||||
|
if (mIsMigrationCompleted)
|
||||||
|
{
|
||||||
|
DoOpenPlasticButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoMigrateButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoCloseButton()
|
||||||
|
{
|
||||||
|
GUI.enabled = !mProgressControls.ProgressData.IsOperationRunning;
|
||||||
|
|
||||||
|
if (NormalButton(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.CloseButton)))
|
||||||
|
{
|
||||||
|
if (mIsMigrationCompleted)
|
||||||
|
TrackFeatureUseEvent.For(
|
||||||
|
PlasticGui.Plastic.API.GetRepositorySpec(mWorkspaceInfo),
|
||||||
|
TrackFeatureUseEvent.Features.CloseDialogAfterWorkspaceMigration);
|
||||||
|
else
|
||||||
|
TrackFeatureUseEvent.For(
|
||||||
|
GetEventCloudOrganizationInfo(),
|
||||||
|
TrackFeatureUseEvent.Features.DoNotMigrateWorkspace);
|
||||||
|
|
||||||
|
CloseButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoOpenPlasticButton()
|
||||||
|
{
|
||||||
|
if (!NormalButton("Open Unity Version Control"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
TrackFeatureUseEvent.For(
|
||||||
|
PlasticGui.Plastic.API.GetRepositorySpec(mWorkspaceInfo),
|
||||||
|
TrackFeatureUseEvent.Features.OpenPlasticAfterWorkspaceMigration);
|
||||||
|
|
||||||
|
((IPlasticDialogCloser)this).CloseDialog();
|
||||||
|
ShowWindow.Plastic();
|
||||||
|
}
|
||||||
|
|
||||||
|
EventCloudOrganizationInfo GetEventCloudOrganizationInfo()
|
||||||
|
{
|
||||||
|
return new EventCloudOrganizationInfo()
|
||||||
|
{
|
||||||
|
Name = mOrganizationName,
|
||||||
|
ServerType = EventCloudOrganizationInfo.GetServerType(true),
|
||||||
|
User = mUser
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoMigrateButton()
|
||||||
|
{
|
||||||
|
GUI.enabled = !mProgressControls.ProgressData.IsOperationRunning;
|
||||||
|
|
||||||
|
if (NormalButton("Migrate"))
|
||||||
|
{
|
||||||
|
if (EditorUtility.DisplayDialog(
|
||||||
|
"Collab migration to Unity Version Control",
|
||||||
|
"Are you sure to start the migration process?",
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.YesButton),
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.NoButton)))
|
||||||
|
{
|
||||||
|
TrackFeatureUseEvent.For(
|
||||||
|
GetEventCloudOrganizationInfo(),
|
||||||
|
TrackFeatureUseEvent.Features.MigrateWorkspace);
|
||||||
|
|
||||||
|
LaunchMigration(
|
||||||
|
mUnityAccessToken, mProjectPath,
|
||||||
|
mOrganizationName, mRepId,
|
||||||
|
mChangesetId, mBranchId,
|
||||||
|
mAfterWorkspaceMigratedAction,
|
||||||
|
mProgressControls);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TrackFeatureUseEvent.For(
|
||||||
|
GetEventCloudOrganizationInfo(),
|
||||||
|
TrackFeatureUseEvent.Features.DoNotMigrateWorkspace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UpdateProgress(string wkPath,
|
||||||
|
CreateWorkspaceFromCollab.Progress progress,
|
||||||
|
ProgressControlsForMigration progressControls,
|
||||||
|
BuildProgressSpeedAndRemainingTime.ProgressData progressData)
|
||||||
|
{
|
||||||
|
string header = MigrationProgressRender.FixNotificationPath(
|
||||||
|
wkPath, progress.CurrentFile);
|
||||||
|
|
||||||
|
string message = MigrationProgressRender.GetProgressString(
|
||||||
|
progress,
|
||||||
|
progressData,
|
||||||
|
DateTime.Now,
|
||||||
|
0.05,
|
||||||
|
"Calculating...",
|
||||||
|
"Converted {0} of {1}bytes ({2} of 1 file){4}",
|
||||||
|
"Converted {0} of {1}bytes ({2} of {3} files {4})",
|
||||||
|
"remaining");
|
||||||
|
|
||||||
|
float percent = GetProgressBarPercent.ForTransfer(
|
||||||
|
progress.ProcessedSize, progress.TotalSize) / 100f;
|
||||||
|
|
||||||
|
progressControls.ShowProgress(header, message, percent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LaunchMigration(
|
||||||
|
string unityAccessToken,
|
||||||
|
string projectPath,
|
||||||
|
string organizationName,
|
||||||
|
RepId repId,
|
||||||
|
long changesetId,
|
||||||
|
long branchId,
|
||||||
|
Action afterWorkspaceMigratedAction,
|
||||||
|
ProgressControlsForMigration progressControls)
|
||||||
|
{
|
||||||
|
string serverName = string.Format(
|
||||||
|
"{0}@cloud", organizationName);
|
||||||
|
|
||||||
|
TokenExchangeResponse tokenExchangeResponse = null;
|
||||||
|
mWorkspaceInfo = null;
|
||||||
|
|
||||||
|
CreateWorkspaceFromCollab.Progress progress = new CreateWorkspaceFromCollab.Progress();
|
||||||
|
|
||||||
|
BuildProgressSpeedAndRemainingTime.ProgressData progressData =
|
||||||
|
new BuildProgressSpeedAndRemainingTime.ProgressData(DateTime.Now);
|
||||||
|
|
||||||
|
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
|
||||||
|
waiter.Execute(
|
||||||
|
/*threadOperationDelegate*/
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
tokenExchangeResponse = AutoConfig.PlasticCredentials(
|
||||||
|
unityAccessToken,
|
||||||
|
serverName,
|
||||||
|
projectPath);
|
||||||
|
|
||||||
|
if (tokenExchangeResponse.Error != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RepositoryInfo repInfo = new BaseCommandsImpl().
|
||||||
|
GetRepositoryInfo(repId, serverName);
|
||||||
|
|
||||||
|
if (repInfo == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
repInfo.SetExplicitServer(serverName);
|
||||||
|
|
||||||
|
mWorkspaceInfo = CreateWorkspaceFromCollab.Create(
|
||||||
|
projectPath, repInfo.Name, repInfo,
|
||||||
|
changesetId, branchId,
|
||||||
|
progress);
|
||||||
|
},
|
||||||
|
/*afterOperationDelegate*/
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
progressControls.HideProgress();
|
||||||
|
|
||||||
|
if (waiter.Exception != null)
|
||||||
|
{
|
||||||
|
DisplayException(progressControls, waiter.Exception);
|
||||||
|
TrackWorkspaceMigrationFinishedFailureEvent(mWorkspaceInfo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenExchangeResponse.Error != null)
|
||||||
|
{
|
||||||
|
mLog.ErrorFormat(
|
||||||
|
"Unable to get TokenExchangeResponse: {0} [code {1}]",
|
||||||
|
tokenExchangeResponse.Error.Message,
|
||||||
|
tokenExchangeResponse.Error.ErrorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenExchangeResponse.Error != null ||
|
||||||
|
mWorkspaceInfo == null)
|
||||||
|
{
|
||||||
|
progressControls.ShowError(
|
||||||
|
"Failed to convert your workspace to Unity Version Control");
|
||||||
|
TrackWorkspaceMigrationFinishedFailureEvent(mWorkspaceInfo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
progressControls.ShowSuccess(
|
||||||
|
"Your workspace has been successfully converted to Unity Version Control");
|
||||||
|
|
||||||
|
mIsMigrationCompleted = true;
|
||||||
|
|
||||||
|
TrackFeatureUseEvent.For(
|
||||||
|
PlasticGui.Plastic.API.GetRepositorySpec(mWorkspaceInfo),
|
||||||
|
TrackFeatureUseEvent.Features.WorkspaceMigrationFinishedSuccess);
|
||||||
|
|
||||||
|
afterWorkspaceMigratedAction();
|
||||||
|
},
|
||||||
|
/*timerTickDelegate*/
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
UpdateProgress(projectPath, progress, progressControls, progressData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrackWorkspaceMigrationFinishedFailureEvent(WorkspaceInfo wkInfo)
|
||||||
|
{
|
||||||
|
if (wkInfo == null)
|
||||||
|
{
|
||||||
|
TrackFeatureUseEvent.For(
|
||||||
|
GetEventCloudOrganizationInfo(),
|
||||||
|
TrackFeatureUseEvent.Features.WorkspaceMigrationFinishedFailure);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackFeatureUseEvent.For(
|
||||||
|
PlasticGui.Plastic.API.GetRepositorySpec(wkInfo),
|
||||||
|
TrackFeatureUseEvent.Features.WorkspaceMigrationFinishedFailure);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DisplayException(
|
||||||
|
ProgressControlsForMigration progressControls,
|
||||||
|
Exception ex)
|
||||||
|
{
|
||||||
|
ExceptionsHandler.LogException(
|
||||||
|
"MigrationDialog", ex);
|
||||||
|
|
||||||
|
progressControls.ShowError(
|
||||||
|
ExceptionsHandler.GetCorrectExceptionMessage(ex));
|
||||||
|
}
|
||||||
|
|
||||||
|
static MigrationDialog Create(
|
||||||
|
string unityAccessToken,
|
||||||
|
string projectPath,
|
||||||
|
string user,
|
||||||
|
string organizationName,
|
||||||
|
RepId repId,
|
||||||
|
long changesetId,
|
||||||
|
long branchId,
|
||||||
|
Action afterWorkspaceMigratedAction,
|
||||||
|
ProgressControlsForMigration progressControls)
|
||||||
|
{
|
||||||
|
var instance = CreateInstance<MigrationDialog>();
|
||||||
|
instance.IsResizable = false;
|
||||||
|
instance.mUnityAccessToken = unityAccessToken;
|
||||||
|
instance.mProjectPath = projectPath;
|
||||||
|
instance.mUser = user;
|
||||||
|
instance.mOrganizationName = organizationName;
|
||||||
|
instance.mRepId = repId;
|
||||||
|
instance.mChangesetId = changesetId;
|
||||||
|
instance.mBranchId = branchId;
|
||||||
|
instance.mAfterWorkspaceMigratedAction = afterWorkspaceMigratedAction;
|
||||||
|
instance.mProgressControls = progressControls;
|
||||||
|
instance.mEscapeKeyAction = instance.CloseButtonAction;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mIsMigrationCompleted;
|
||||||
|
|
||||||
|
ProgressControlsForMigration mProgressControls;
|
||||||
|
Action mAfterWorkspaceMigratedAction;
|
||||||
|
long mChangesetId;
|
||||||
|
long mBranchId;
|
||||||
|
RepId mRepId;
|
||||||
|
string mOrganizationName;
|
||||||
|
string mUser;
|
||||||
|
string mProjectPath;
|
||||||
|
string mUnityAccessToken;
|
||||||
|
WorkspaceInfo mWorkspaceInfo;
|
||||||
|
|
||||||
|
static readonly ILog mLog = LogManager.GetLogger("MigrationDialog");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
using Codice.Client.Commands;
|
||||||
|
using Codice.Client.Common;
|
||||||
|
using Codice.Client.BaseCommands;
|
||||||
|
using Codice.LogWrapper;
|
||||||
|
using PlasticGui;
|
||||||
|
using Codice.Client.BaseCommands.Sync;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.CollabMigration
|
||||||
|
{
|
||||||
|
internal class MigrationProgressRender
|
||||||
|
{
|
||||||
|
internal static string FixNotificationPath(string wkPath, string notification)
|
||||||
|
{
|
||||||
|
if (notification == null)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
int position = notification.ToLower().IndexOf(wkPath.ToLower());
|
||||||
|
|
||||||
|
if (position < 0)
|
||||||
|
return notification;
|
||||||
|
|
||||||
|
return notification.Remove(position, wkPath.Length + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetProgressString(
|
||||||
|
CreateWorkspaceFromCollab.Progress status,
|
||||||
|
BuildProgressSpeedAndRemainingTime.ProgressData progressData,
|
||||||
|
DateTime now,
|
||||||
|
double smoothingFactor,
|
||||||
|
string updateProgressCalculatingMessage,
|
||||||
|
string updateProgressSingularMessage,
|
||||||
|
string updateProgressPluralMessage,
|
||||||
|
string remainingMessage)
|
||||||
|
{
|
||||||
|
if (status.CurrentStatus == CreateWorkspaceFromCollab.Progress.Status.Starting)
|
||||||
|
return updateProgressCalculatingMessage;
|
||||||
|
|
||||||
|
progressData.StartTimerIfNotStarted(now);
|
||||||
|
|
||||||
|
string updatedSize;
|
||||||
|
string totalSize;
|
||||||
|
GetFormattedSizes.ForTransfer(
|
||||||
|
status.ProcessedSize,
|
||||||
|
status.TotalSize,
|
||||||
|
out updatedSize,
|
||||||
|
out totalSize);
|
||||||
|
|
||||||
|
string details = string.Format(
|
||||||
|
status.TotalFiles == 1 ?
|
||||||
|
updateProgressSingularMessage :
|
||||||
|
updateProgressPluralMessage,
|
||||||
|
updatedSize,
|
||||||
|
totalSize,
|
||||||
|
status.ProcessedFiles,
|
||||||
|
status.TotalFiles,
|
||||||
|
BuildProgressSpeedAndRemainingTime.ForTransfer(
|
||||||
|
progressData,
|
||||||
|
now,
|
||||||
|
status.TotalSize,
|
||||||
|
status.ProcessedSize,
|
||||||
|
smoothingFactor,
|
||||||
|
remainingMessage));
|
||||||
|
|
||||||
|
return details;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ILog mLog = LogManager.GetLogger("MigrationProgressRender");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
using Codice.Client.Common;
|
||||||
|
using Codice.CM.Common;
|
||||||
|
using PlasticGui;
|
||||||
|
using Unity.PlasticSCM.Editor.Configuration.CloudEdition.Welcome;
|
||||||
|
using Unity.PlasticSCM.Editor.WebApi;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration
|
||||||
|
{
|
||||||
|
internal static class AutoConfig
|
||||||
|
{
|
||||||
|
internal static TokenExchangeResponse PlasticCredentials(
|
||||||
|
string unityAccessToken,
|
||||||
|
string serverName,
|
||||||
|
string projectPath)
|
||||||
|
{
|
||||||
|
SetupUnityEditionToken.CreateCloudEditionTokenIfNeeded();
|
||||||
|
|
||||||
|
bool isClientConfigConfigured = ClientConfig.IsConfigured();
|
||||||
|
if (!isClientConfigConfigured)
|
||||||
|
{
|
||||||
|
ConfigureClientConf.FromUnityAccessToken(
|
||||||
|
unityAccessToken, serverName, projectPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenExchangeResponse tokenExchangeResponse = WebRestApiClient.
|
||||||
|
PlasticScm.TokenExchange(unityAccessToken);
|
||||||
|
|
||||||
|
if (tokenExchangeResponse.Error != null)
|
||||||
|
return tokenExchangeResponse;
|
||||||
|
|
||||||
|
CloudEditionWelcomeWindow.JoinCloudServer(
|
||||||
|
serverName,
|
||||||
|
tokenExchangeResponse.User,
|
||||||
|
tokenExchangeResponse.AccessToken);
|
||||||
|
|
||||||
|
if (!isClientConfigConfigured)
|
||||||
|
return tokenExchangeResponse;
|
||||||
|
|
||||||
|
ConfigureProfile.ForServerIfNeeded(
|
||||||
|
serverName,
|
||||||
|
tokenExchangeResponse.User);
|
||||||
|
|
||||||
|
return tokenExchangeResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ConfigureClientConf
|
||||||
|
{
|
||||||
|
internal static void FromUnityAccessToken(
|
||||||
|
string unityAccessToken,
|
||||||
|
string serverName,
|
||||||
|
string projectPath)
|
||||||
|
{
|
||||||
|
CredentialsResponse response = WebRestApiClient.
|
||||||
|
PlasticScm.GetCredentials(unityAccessToken);
|
||||||
|
|
||||||
|
if (response.Error != null)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.LogErrorFormat(
|
||||||
|
PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.ErrorGettingCredentialsCloudProject),
|
||||||
|
response.Error.Message,
|
||||||
|
response.Error.ErrorCode);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientConfigData configData = BuildClientConfigData(
|
||||||
|
serverName, projectPath, response);
|
||||||
|
|
||||||
|
ClientConfig.Get().Save(configData);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClientConfigData BuildClientConfigData(
|
||||||
|
string serverName,
|
||||||
|
string projectPath,
|
||||||
|
CredentialsResponse response)
|
||||||
|
{
|
||||||
|
SEIDWorkingMode workingMode = GetWorkingMode(response.Type);
|
||||||
|
|
||||||
|
ClientConfigData configData = new ClientConfigData();
|
||||||
|
|
||||||
|
configData.WorkspaceServer = serverName;
|
||||||
|
configData.CurrentWorkspace = projectPath;
|
||||||
|
configData.WorkingMode = workingMode.ToString();
|
||||||
|
configData.SecurityConfig = UserInfo.GetSecurityConfigStr(
|
||||||
|
workingMode,
|
||||||
|
response.Email,
|
||||||
|
GetPassword(response.Token, response.Type));
|
||||||
|
configData.LastRunningEdition = InstalledEdition.Get();
|
||||||
|
return configData;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string GetPassword(
|
||||||
|
string token,
|
||||||
|
CredentialsResponse.TokenType tokenType)
|
||||||
|
{
|
||||||
|
if (tokenType == CredentialsResponse.TokenType.Bearer)
|
||||||
|
return BEARER_PREFIX + token;
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SEIDWorkingMode GetWorkingMode(CredentialsResponse.TokenType tokenType)
|
||||||
|
{
|
||||||
|
if (tokenType == CredentialsResponse.TokenType.Bearer)
|
||||||
|
return SEIDWorkingMode.SSOWorkingMode;
|
||||||
|
|
||||||
|
return SEIDWorkingMode.LDAPWorkingMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string BEARER_PREFIX = "Bearer ";
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ConfigureProfile
|
||||||
|
{
|
||||||
|
internal static void ForServerIfNeeded(string serverName, string user)
|
||||||
|
{
|
||||||
|
ProfileManager profileManager = CmConnection.Get().GetProfileManager();
|
||||||
|
|
||||||
|
ServerProfile serverProfile = profileManager.GetProfileForServer(serverName);
|
||||||
|
|
||||||
|
if (serverProfile != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
serverProfile = ProfileManager.CreateProfile(
|
||||||
|
serverName,
|
||||||
|
SEIDWorkingMode.SSOWorkingMode,
|
||||||
|
user);
|
||||||
|
|
||||||
|
profileManager.SaveProfile(serverProfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
using Codice.Client.Common;
|
||||||
|
using Codice.CM.Common;
|
||||||
|
using PlasticGui;
|
||||||
|
using PlasticPipe.Certificates;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration
|
||||||
|
{
|
||||||
|
internal class ChannelCertificateUiImpl : IChannelCertificateUI
|
||||||
|
{
|
||||||
|
internal ChannelCertificateUiImpl()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CertOperationResult IChannelCertificateUI.AcceptNewServerCertificate(PlasticCertInfo serverCertificate)
|
||||||
|
{
|
||||||
|
return GetUserResponse(
|
||||||
|
PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.NewCertificateTitle),
|
||||||
|
PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.NewCertificateMessageUnityVCS),
|
||||||
|
serverCertificate);
|
||||||
|
}
|
||||||
|
|
||||||
|
CertOperationResult IChannelCertificateUI.AcceptChangedServerCertificate(PlasticCertInfo serverCertificate)
|
||||||
|
{
|
||||||
|
return GetUserResponse(
|
||||||
|
PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.ExistingCertificateChangedTitle),
|
||||||
|
PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.ExistingCertificateChangedMessageUnityVCS),
|
||||||
|
serverCertificate);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IChannelCertificateUI.AcceptInvalidHostname(string certHostname, string serverHostname)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
GUIActionRunner.RunGUIAction(delegate {
|
||||||
|
result = EditorUtility.DisplayDialog(
|
||||||
|
PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.InvalidCertificateHostnameTitle),
|
||||||
|
PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.InvalidCertificateHostnameMessage,
|
||||||
|
certHostname, serverHostname),
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.YesButton),
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.NoButton));
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CertOperationResult GetUserResponse(
|
||||||
|
string title, string message, PlasticCertInfo serverCertificate)
|
||||||
|
{
|
||||||
|
GuiMessage.GuiMessageResponseButton result =
|
||||||
|
GuiMessage.GuiMessageResponseButton.Neutral;
|
||||||
|
|
||||||
|
GUIActionRunner.RunGUIAction(delegate {
|
||||||
|
result = GuiMessage.ShowQuestion(
|
||||||
|
title,
|
||||||
|
GetCertificateMessageString(message, serverCertificate),
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.YesButton),
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.CancelButton),
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.NoButton));
|
||||||
|
});
|
||||||
|
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case GuiMessage.GuiMessageResponseButton.Positive:
|
||||||
|
return CertOperationResult.AddToStore;
|
||||||
|
case GuiMessage.GuiMessageResponseButton.Negative:
|
||||||
|
return CertOperationResult.DoNotAddToStore;
|
||||||
|
case GuiMessage.GuiMessageResponseButton.Neutral:
|
||||||
|
return CertOperationResult.Cancel;
|
||||||
|
default:
|
||||||
|
return CertOperationResult.Cancel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetCertificateMessageString(string message, PlasticCertInfo serverCertificate)
|
||||||
|
{
|
||||||
|
return string.Format(message,
|
||||||
|
CertificateUi.GetCnField(serverCertificate.Subject),
|
||||||
|
CertificateUi.GetCnField(serverCertificate.Issuer),
|
||||||
|
serverCertificate.Format,
|
||||||
|
serverCertificate.ExpirationDateString,
|
||||||
|
serverCertificate.KeyAlgorithm,
|
||||||
|
serverCertificate.CertHashString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,199 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
using Codice.Client.Common.Threading;
|
||||||
|
using Codice.LogWrapper;
|
||||||
|
using PlasticGui.Configuration.OAuth;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
using Unity.PlasticSCM.Editor.UI.Progress;
|
||||||
|
using Unity.PlasticSCM.Editor.WebApi;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration.CloudEdition.Welcome
|
||||||
|
{
|
||||||
|
internal class AutoLogin : OAuthSignIn.INotify
|
||||||
|
{
|
||||||
|
internal enum State : byte
|
||||||
|
{
|
||||||
|
Off = 0,
|
||||||
|
Started = 1,
|
||||||
|
Running = 2,
|
||||||
|
ResponseInit = 3,
|
||||||
|
ResponseEnd = 6,
|
||||||
|
ResponseSuccess = 7,
|
||||||
|
OrganizationChoosed = 8,
|
||||||
|
InitializingPlastic = 9,
|
||||||
|
ErrorNoToken = 20,
|
||||||
|
ErrorTokenException = 21,
|
||||||
|
ErrorResponseNull = 22,
|
||||||
|
ErrorResponseError = 23,
|
||||||
|
ErrorTokenEmpty = 24,
|
||||||
|
ErrorResponseCancel = 25
|
||||||
|
}
|
||||||
|
|
||||||
|
internal string AccessToken;
|
||||||
|
internal string UserName;
|
||||||
|
|
||||||
|
internal void Run()
|
||||||
|
{
|
||||||
|
mPlasticWindow = GetPlasticWindow();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(CloudProjectSettings.accessToken))
|
||||||
|
{
|
||||||
|
ExchangeTokensAndJoinOrganization(CloudProjectSettings.accessToken);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ErrorNoToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForConfigure(
|
||||||
|
List<string> organizations,
|
||||||
|
bool canCreateAnOrganization,
|
||||||
|
string userName,
|
||||||
|
string accessToken)
|
||||||
|
{
|
||||||
|
mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ResponseSuccess;
|
||||||
|
ChooseOrganization(organizations);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForSSO(string organization)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForProfile(string email)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForHomeView(string userName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForCredentials(
|
||||||
|
string email,
|
||||||
|
string accessToken)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.Cancel(string errorMessage)
|
||||||
|
{
|
||||||
|
mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ErrorResponseCancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExchangeTokensAndJoinOrganization(string unityAccessToken)
|
||||||
|
{
|
||||||
|
int ini = Environment.TickCount;
|
||||||
|
|
||||||
|
TokenExchangeResponse response = null;
|
||||||
|
|
||||||
|
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
|
||||||
|
waiter.Execute(
|
||||||
|
/*threadOperationDelegate*/ delegate
|
||||||
|
{
|
||||||
|
mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ResponseInit;
|
||||||
|
response = WebRestApiClient.PlasticScm.TokenExchange(unityAccessToken);
|
||||||
|
},
|
||||||
|
/*afterOperationDelegate*/ delegate
|
||||||
|
{
|
||||||
|
mLog.DebugFormat(
|
||||||
|
"TokenExchange time {0} ms",
|
||||||
|
Environment.TickCount - ini);
|
||||||
|
|
||||||
|
if (waiter.Exception != null)
|
||||||
|
{
|
||||||
|
mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ErrorTokenException;
|
||||||
|
ExceptionsHandler.LogException(
|
||||||
|
"TokenExchangeSetting",
|
||||||
|
waiter.Exception);
|
||||||
|
Debug.LogWarning(waiter.Exception.Message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response == null)
|
||||||
|
{
|
||||||
|
mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ErrorResponseNull;
|
||||||
|
Debug.LogWarning("Auto Login response null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.Error != null)
|
||||||
|
{
|
||||||
|
mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ErrorResponseError;
|
||||||
|
var warning = string.Format(
|
||||||
|
"Unable to exchange token: {0} [code {1}]",
|
||||||
|
response.Error.Message, response.Error.ErrorCode);
|
||||||
|
mLog.ErrorFormat(warning);
|
||||||
|
Debug.LogWarning(warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(response.AccessToken))
|
||||||
|
{
|
||||||
|
mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ErrorTokenEmpty;
|
||||||
|
var warning = string.Format(
|
||||||
|
"Access token is empty for user: {0}",
|
||||||
|
response.User);
|
||||||
|
mLog.InfoFormat(warning);
|
||||||
|
Debug.LogWarning(warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ResponseEnd;
|
||||||
|
AccessToken = response.AccessToken;
|
||||||
|
UserName = response.User;
|
||||||
|
GetOrganizationList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetOrganizationList()
|
||||||
|
{
|
||||||
|
OAuthSignIn.GetOrganizationsFromAccessToken(
|
||||||
|
string.Empty,
|
||||||
|
CloudProjectSettings.userName,
|
||||||
|
AccessToken,
|
||||||
|
OAuthSignIn.Mode.Configure,
|
||||||
|
new ProgressControlsForDialogs(),
|
||||||
|
this,
|
||||||
|
PlasticGui.Plastic.WebRestAPI
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChooseOrganization(
|
||||||
|
List<string> organizations)
|
||||||
|
{
|
||||||
|
mPlasticWindow = GetPlasticWindow();
|
||||||
|
|
||||||
|
CloudEditionWelcomeWindow.ShowWindow(
|
||||||
|
PlasticGui.Plastic.WebRestAPI,
|
||||||
|
mPlasticWindow.CmConnectionForTesting, null, true);
|
||||||
|
|
||||||
|
mCloudEditionWelcomeWindow = CloudEditionWelcomeWindow.GetWelcomeWindow();
|
||||||
|
mCloudEditionWelcomeWindow.FillUserAndToken(UserName, AccessToken);
|
||||||
|
if (organizations.Count == 1)
|
||||||
|
{
|
||||||
|
mCloudEditionWelcomeWindow.JoinOrganizationAndWelcomePage(organizations[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mCloudEditionWelcomeWindow.ShowOrganizationPanelFromAutoLogin(organizations);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PlasticWindow GetPlasticWindow()
|
||||||
|
{
|
||||||
|
var windows = Resources.FindObjectsOfTypeAll<PlasticWindow>();
|
||||||
|
PlasticWindow plasticWindow = windows.Length > 0 ? windows[0] : null;
|
||||||
|
|
||||||
|
if (plasticWindow == null)
|
||||||
|
plasticWindow = ShowWindow.Plastic();
|
||||||
|
|
||||||
|
return plasticWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlasticWindow mPlasticWindow;
|
||||||
|
CloudEditionWelcomeWindow mCloudEditionWelcomeWindow;
|
||||||
|
|
||||||
|
static readonly ILog mLog = LogManager.GetLogger("TokensExchange");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,273 @@
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
using PlasticGui;
|
||||||
|
using PlasticGui.WebApi;
|
||||||
|
using Unity.PlasticSCM.Editor.UI.UIElements;
|
||||||
|
using PlasticGui.Configuration.CloudEdition.Welcome;
|
||||||
|
using PlasticGui.Configuration.OAuth;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Codice.Client.Common.Servers;
|
||||||
|
using Codice.Client.Common;
|
||||||
|
using Codice.Utils;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
using Unity.PlasticSCM.Editor.Views.Welcome;
|
||||||
|
|
||||||
|
using Codice.CM.Common;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration.CloudEdition.Welcome
|
||||||
|
{
|
||||||
|
internal interface IWelcomeWindowNotify
|
||||||
|
{
|
||||||
|
void SuccessForConfigure(List<string> organizations);
|
||||||
|
void Back();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CloudEditionWelcomeWindow :
|
||||||
|
EditorWindow,
|
||||||
|
OAuthSignIn.INotify,
|
||||||
|
IWelcomeWindowNotify
|
||||||
|
{
|
||||||
|
internal static void ShowWindow(
|
||||||
|
IPlasticWebRestApi restApi,
|
||||||
|
CmConnection cmConnection,
|
||||||
|
WelcomeView welcomeView,
|
||||||
|
bool autoLogin = false)
|
||||||
|
{
|
||||||
|
sRestApi = restApi;
|
||||||
|
sCmConnection = cmConnection;
|
||||||
|
sAutoLogin = autoLogin;
|
||||||
|
CloudEditionWelcomeWindow window = GetWindow<CloudEditionWelcomeWindow>();
|
||||||
|
|
||||||
|
window.titleContent = new GUIContent(
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.SignInToUnityVCS));
|
||||||
|
window.minSize = window.maxSize = new Vector2(450, 300);
|
||||||
|
|
||||||
|
window.mWelcomeView = welcomeView;
|
||||||
|
|
||||||
|
window.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static CloudEditionWelcomeWindow GetWelcomeWindow()
|
||||||
|
{
|
||||||
|
return GetWindow<CloudEditionWelcomeWindow>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnEnable()
|
||||||
|
{
|
||||||
|
BuildComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void CancelJoinOrganization()
|
||||||
|
{
|
||||||
|
if (sAutoLogin)
|
||||||
|
{
|
||||||
|
GetWindow<PlasticWindow>().GetWelcomeView().autoLoginState = AutoLogin.State.Started;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void JoinOrganizationAndWelcomePage(string organization)
|
||||||
|
{
|
||||||
|
JoinCloudServer(organization,
|
||||||
|
mUserName,
|
||||||
|
mAccessToken);
|
||||||
|
|
||||||
|
GetWelcomePage.Run(sRestApi, organization);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void JoinCloudServer(
|
||||||
|
string cloudServer,
|
||||||
|
string username,
|
||||||
|
string accessToken)
|
||||||
|
{
|
||||||
|
SaveCloudServer.ToPlasticGuiConfig(cloudServer);
|
||||||
|
SaveCloudServer.ToPlasticGuiConfigFile(
|
||||||
|
cloudServer, GetPlasticConfigFileToSaveOrganization());
|
||||||
|
SaveCloudServer.ToPlasticGuiConfigFile(
|
||||||
|
cloudServer, GetGluonConfigFileToSaveOrganization());
|
||||||
|
|
||||||
|
KnownServers.ServersFromCloud.InitializeForWindows(
|
||||||
|
PlasticGuiConfig.Get().Configuration.DefaultCloudServer);
|
||||||
|
|
||||||
|
CloudEditionWelcome.WriteToTokensConf(
|
||||||
|
cloudServer, username, accessToken);
|
||||||
|
|
||||||
|
SetupUnityEditionToken.CreateCloudEditionTokenIfNeeded();
|
||||||
|
|
||||||
|
if (sAutoLogin)
|
||||||
|
{
|
||||||
|
ClientConfigData clientConfigData = ConfigurationChecker.GetClientConfigData();
|
||||||
|
clientConfigData.WorkspaceServer = cloudServer;
|
||||||
|
clientConfigData.WorkingMode = SEIDWorkingMode.SSOWorkingMode.ToString();
|
||||||
|
clientConfigData.SecurityConfig = username;
|
||||||
|
ClientConfig.Get().Save(clientConfigData);
|
||||||
|
|
||||||
|
GetWindow<PlasticWindow>().GetWelcomeView().autoLoginState = AutoLogin.State.OrganizationChoosed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ReplaceRootPanel(VisualElement panel)
|
||||||
|
{
|
||||||
|
rootVisualElement.Clear();
|
||||||
|
rootVisualElement.Add(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
|
||||||
|
if (mWelcomeView != null)
|
||||||
|
mWelcomeView.OnUserClosedConfigurationWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispose()
|
||||||
|
{
|
||||||
|
if (mSignInPanel != null)
|
||||||
|
mSignInPanel.Dispose();
|
||||||
|
|
||||||
|
if (mOrganizationPanel != null)
|
||||||
|
mOrganizationPanel.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForConfigure(
|
||||||
|
List<string> organizations,
|
||||||
|
bool canCreateAnOrganization,
|
||||||
|
string userName,
|
||||||
|
string accessToken)
|
||||||
|
{
|
||||||
|
ShowOrganizationPanel(
|
||||||
|
GetWindowTitle(),
|
||||||
|
organizations);
|
||||||
|
|
||||||
|
Focus();
|
||||||
|
|
||||||
|
mUserName = userName;
|
||||||
|
mAccessToken = accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ShowOrganizationPanel(
|
||||||
|
string title,
|
||||||
|
List<string> organizations)
|
||||||
|
{
|
||||||
|
mOrganizationPanel = new OrganizationPanel(
|
||||||
|
this,
|
||||||
|
sRestApi,
|
||||||
|
title,
|
||||||
|
organizations);
|
||||||
|
|
||||||
|
ReplaceRootPanel(mOrganizationPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForSSO(string organization)
|
||||||
|
{
|
||||||
|
// empty implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForProfile(string email)
|
||||||
|
{
|
||||||
|
// empty implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForHomeView(string homeView)
|
||||||
|
{
|
||||||
|
// empty implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForCredentials(
|
||||||
|
string email,
|
||||||
|
string accessToken)
|
||||||
|
{
|
||||||
|
// empty implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.Cancel(string errorMessage)
|
||||||
|
{
|
||||||
|
Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IWelcomeWindowNotify.SuccessForConfigure(
|
||||||
|
List<string> organizations)
|
||||||
|
{
|
||||||
|
ShowOrganizationPanel(
|
||||||
|
GetWindowTitle(),
|
||||||
|
organizations);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void FillUserAndToken(
|
||||||
|
string userName,
|
||||||
|
string accessToken)
|
||||||
|
{
|
||||||
|
mUserName = userName;
|
||||||
|
mAccessToken = accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ShowOrganizationPanelFromAutoLogin(
|
||||||
|
List<string> organizations)
|
||||||
|
{
|
||||||
|
ShowOrganizationPanel(
|
||||||
|
GetWindowTitle(),
|
||||||
|
organizations);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IWelcomeWindowNotify.Back()
|
||||||
|
{
|
||||||
|
rootVisualElement.Clear();
|
||||||
|
rootVisualElement.Add(mSignInPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal string GetWindowTitle()
|
||||||
|
{
|
||||||
|
return PlasticLocalization.Name.SignInToUnityVCS.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetPlasticConfigFileToSaveOrganization()
|
||||||
|
{
|
||||||
|
if (PlatformIdentifier.IsMac())
|
||||||
|
{
|
||||||
|
return "macgui.conf";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "plasticgui.conf";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetGluonConfigFileToSaveOrganization()
|
||||||
|
{
|
||||||
|
if (PlatformIdentifier.IsMac())
|
||||||
|
{
|
||||||
|
return "gluon.conf";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "gameui.conf";
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildComponents()
|
||||||
|
{
|
||||||
|
VisualElement root = rootVisualElement;
|
||||||
|
|
||||||
|
root.Clear();
|
||||||
|
|
||||||
|
mSignInPanel = new SignInPanel(
|
||||||
|
this,
|
||||||
|
sRestApi,
|
||||||
|
sCmConnection);
|
||||||
|
|
||||||
|
titleContent = new GUIContent(GetWindowTitle());
|
||||||
|
|
||||||
|
root.Add(mSignInPanel);
|
||||||
|
if (sAutoLogin)
|
||||||
|
mSignInPanel.SignInWithUnityIdButtonAutoLogin();
|
||||||
|
}
|
||||||
|
|
||||||
|
OrganizationPanel mOrganizationPanel;
|
||||||
|
SignInPanel mSignInPanel;
|
||||||
|
WelcomeView mWelcomeView;
|
||||||
|
|
||||||
|
string mUserName;
|
||||||
|
string mAccessToken;
|
||||||
|
|
||||||
|
static IPlasticWebRestApi sRestApi;
|
||||||
|
static CmConnection sCmConnection;
|
||||||
|
static bool sAutoLogin = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,232 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor.UIElements;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
using Codice.Client.Common.Threading;
|
||||||
|
using PlasticGui;
|
||||||
|
using PlasticGui.WebApi;
|
||||||
|
using PlasticGui.WebApi.Responses;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
using Unity.PlasticSCM.Editor.UI.UIElements;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration.CloudEdition.Welcome
|
||||||
|
{
|
||||||
|
internal class OrganizationPanel : VisualElement
|
||||||
|
{
|
||||||
|
internal OrganizationPanel(
|
||||||
|
CloudEditionWelcomeWindow parentWindow,
|
||||||
|
IPlasticWebRestApi restApi,
|
||||||
|
string title,
|
||||||
|
List<string> organizations)
|
||||||
|
{
|
||||||
|
mParentWindow = parentWindow;
|
||||||
|
mRestApi = restApi;
|
||||||
|
|
||||||
|
InitializeLayoutAndStyles();
|
||||||
|
|
||||||
|
BuildComponents(title, organizations);
|
||||||
|
|
||||||
|
EditorWindowFocus.OnApplicationActivated += OnEditorActivated;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Dispose()
|
||||||
|
{
|
||||||
|
EditorWindowFocus.OnApplicationActivated -= OnEditorActivated;
|
||||||
|
|
||||||
|
mParentWindow.CancelJoinOrganization();
|
||||||
|
|
||||||
|
if (mJoinSingleOrganizationButton != null)
|
||||||
|
mJoinSingleOrganizationButton.clicked -= JoinOrganizationButton_clicked;
|
||||||
|
|
||||||
|
if (mJoinMultipleOrganizationsButton != null)
|
||||||
|
mJoinMultipleOrganizationsButton.clicked -= JoinOrganizationButton_clicked;
|
||||||
|
|
||||||
|
if (mOpenUnityDashboardButton != null)
|
||||||
|
mOpenUnityDashboardButton.clicked -= OpenUnityDashboardButton_clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnEditorActivated()
|
||||||
|
{
|
||||||
|
if (!mReloadOrganizationsNeeded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mReloadOrganizationsNeeded = false;
|
||||||
|
mProgressControls.ShowProgress(PlasticLocalization.Name.LoadingOrganizations.GetString());
|
||||||
|
|
||||||
|
OrganizationsResponse organizationResponse = null;
|
||||||
|
IThreadWaiter waiter = ThreadWaiter.GetWaiter();
|
||||||
|
waiter.Execute(
|
||||||
|
/*threadOperationDelegate*/ delegate
|
||||||
|
{
|
||||||
|
organizationResponse = mRestApi.GetCloudServers();
|
||||||
|
},
|
||||||
|
/*afterOperationDelegate*/ delegate
|
||||||
|
{
|
||||||
|
mProgressControls.HideProgress();
|
||||||
|
|
||||||
|
if (waiter.Exception != null)
|
||||||
|
{
|
||||||
|
mProgressControls.ShowError(PlasticLocalization.Name.UnexpectedError.GetString());
|
||||||
|
ExceptionsHandler.LogException(typeof(OrganizationPanel).Name, waiter.Exception);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (organizationResponse.Error != null)
|
||||||
|
{
|
||||||
|
mReloadOrganizationsNeeded = true;
|
||||||
|
mProgressControls.ShowError(organizationResponse.Error.Message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessOrganizations(organizationResponse.CloudServers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessOrganizations(List<string> organizations)
|
||||||
|
{
|
||||||
|
this.Query<VisualElement>("noOrganization").Collapse();
|
||||||
|
this.Query<VisualElement>("joinSingleOrganization").Collapse();
|
||||||
|
this.Query<VisualElement>("joinMultipleOrganizations").Collapse();
|
||||||
|
|
||||||
|
if (organizations.Count == 0)
|
||||||
|
{
|
||||||
|
mReloadOrganizationsNeeded = true;
|
||||||
|
BuildNoOrganizationSection();
|
||||||
|
|
||||||
|
mOpenUnityDashboardButton = this.Q<Button>("openUnityDashboardButton");
|
||||||
|
mOpenUnityDashboardButton.clicked += OpenUnityDashboardButton_clicked;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mReloadOrganizationsNeeded = false;
|
||||||
|
|
||||||
|
if (organizations.Count == 1)
|
||||||
|
{
|
||||||
|
BuildSingleOrganizationSection(organizations.First());
|
||||||
|
|
||||||
|
mJoinSingleOrganizationButton = this.Q<Button>("joinSingleOrganizationButton");
|
||||||
|
mJoinSingleOrganizationButton.clicked += JoinOrganizationButton_clicked;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildMultipleOrganizationsSection(organizations);
|
||||||
|
|
||||||
|
mJoinMultipleOrganizationsButton = this.Q<Button>("joinMultipleOrganizationsButton");
|
||||||
|
mJoinMultipleOrganizationsButton.clicked += JoinOrganizationButton_clicked;
|
||||||
|
mOrganizationToJoin = organizations.First();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeLayoutAndStyles()
|
||||||
|
{
|
||||||
|
this.LoadLayout(typeof(OrganizationPanel).Name);
|
||||||
|
this.LoadStyle(typeof(OrganizationPanel).Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JoinOrganizationButton_clicked()
|
||||||
|
{
|
||||||
|
mParentWindow.JoinOrganizationAndWelcomePage(mOrganizationToJoin);
|
||||||
|
|
||||||
|
// TODO: Closing the window for now. Need to connect this event to the main on boarding
|
||||||
|
// workflow.
|
||||||
|
mParentWindow.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenUnityDashboardButton_clicked()
|
||||||
|
{
|
||||||
|
Application.OpenURL(UnityUrl.UnityDashboard.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildComponents(string title, List<string> organizations)
|
||||||
|
{
|
||||||
|
mParentWindow.titleContent = new UnityEngine.GUIContent(title);
|
||||||
|
|
||||||
|
mProgressControls = new ProgressControlsForDialogs(null);
|
||||||
|
|
||||||
|
mProgressContainer = this.Q<VisualElement>("progressContainer");
|
||||||
|
mProgressContainer.Add((VisualElement)mProgressControls);
|
||||||
|
|
||||||
|
ProcessOrganizations(organizations);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildSingleOrganizationSection(string organizationName)
|
||||||
|
{
|
||||||
|
this.SetControlText<Label>("confirmationMessage",
|
||||||
|
PlasticLocalization.Name.JoinOrganizationTitle);
|
||||||
|
|
||||||
|
mOrganizationToJoin = organizationName;
|
||||||
|
|
||||||
|
this.Query<VisualElement>("joinSingleOrganization").Show();
|
||||||
|
|
||||||
|
this.SetControlText<Label>("joinSingleOrganizationLabel",
|
||||||
|
PlasticLocalization.Name.YouBelongToOrganization, organizationName);
|
||||||
|
|
||||||
|
this.SetControlText<Button>("joinSingleOrganizationButton",
|
||||||
|
PlasticLocalization.Name.JoinButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildMultipleOrganizationsSection(List<string> organizationNames)
|
||||||
|
{
|
||||||
|
this.SetControlText<Label>("confirmationMessage",
|
||||||
|
PlasticLocalization.Name.JoinOrganizationTitle);
|
||||||
|
|
||||||
|
this.Query<VisualElement>("joinMultipleOrganizations").Show();
|
||||||
|
|
||||||
|
this.SetControlText<Label>("joinMultipleOrganizationsLabel",
|
||||||
|
PlasticLocalization.Name.YouBelongToSeveralOrganizations);
|
||||||
|
|
||||||
|
VisualElement organizationDropdown = this.Query<VisualElement>("organizationDropdown");
|
||||||
|
ToolbarMenu toolbarMenu = new ToolbarMenu
|
||||||
|
{
|
||||||
|
text = organizationNames.FirstOrDefault(),
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (string name in organizationNames)
|
||||||
|
{
|
||||||
|
toolbarMenu.menu.AppendAction(name, x =>
|
||||||
|
{
|
||||||
|
toolbarMenu.text = name;
|
||||||
|
mOrganizationToJoin = name;
|
||||||
|
}, DropdownMenuAction.AlwaysEnabled);
|
||||||
|
organizationDropdown.Add(toolbarMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.SetControlText<Button>("joinMultipleOrganizationsButton",
|
||||||
|
PlasticLocalization.Name.JoinButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildNoOrganizationSection()
|
||||||
|
{
|
||||||
|
this.SetControlText<Label>("confirmationMessage",
|
||||||
|
PlasticLocalization.Name.CreateOrganizationTitle);
|
||||||
|
|
||||||
|
this.Query<VisualElement>("noOrganization").Show();
|
||||||
|
|
||||||
|
this.SetControlImage("iconUnity",
|
||||||
|
Images.Name.ButtonSsoSignInUnity);
|
||||||
|
|
||||||
|
this.SetControlText<Label>("noOrganizationLabel",
|
||||||
|
PlasticLocalization.Name.ClickButtonBelowToCreateOrg);
|
||||||
|
|
||||||
|
this.SetControlText<Button>("openUnityDashboardButton",
|
||||||
|
PlasticLocalization.Name.MainSidebarOpenUnityDashboardItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
string mOrganizationToJoin = "";
|
||||||
|
bool mReloadOrganizationsNeeded;
|
||||||
|
|
||||||
|
Button mJoinSingleOrganizationButton;
|
||||||
|
Button mJoinMultipleOrganizationsButton;
|
||||||
|
Button mOpenUnityDashboardButton;
|
||||||
|
VisualElement mProgressContainer;
|
||||||
|
|
||||||
|
IProgressControls mProgressControls;
|
||||||
|
|
||||||
|
readonly CloudEditionWelcomeWindow mParentWindow;
|
||||||
|
readonly IPlasticWebRestApi mRestApi;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,166 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
using Codice.Client.Common;
|
||||||
|
using Codice.Client.Common.OAuth;
|
||||||
|
using PlasticGui;
|
||||||
|
using PlasticGui.WebApi;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
using Unity.PlasticSCM.Editor.UI.UIElements;
|
||||||
|
using PlasticGui.Configuration.CloudEdition.Welcome;
|
||||||
|
using PlasticGui.Configuration.OAuth;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration.CloudEdition.Welcome
|
||||||
|
{
|
||||||
|
internal class SignInPanel : VisualElement
|
||||||
|
{
|
||||||
|
internal SignInPanel(
|
||||||
|
CloudEditionWelcomeWindow parentWindow,
|
||||||
|
IPlasticWebRestApi restApi,
|
||||||
|
CmConnection cmConnection)
|
||||||
|
{
|
||||||
|
mParentWindow = parentWindow;
|
||||||
|
mRestApi = restApi;
|
||||||
|
mCmConnection = cmConnection;
|
||||||
|
|
||||||
|
InitializeLayoutAndStyles();
|
||||||
|
|
||||||
|
BuildComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Dispose()
|
||||||
|
{
|
||||||
|
mSignInWithUnityIdButton.clicked -= SignInWithUnityIdButton_Clicked;
|
||||||
|
mSignInWithEmailButton.clicked -= SignInWithEmailButton_Clicked;
|
||||||
|
mPrivacyPolicyStatementButton.clicked -= PrivacyPolicyStatementButton_Clicked;
|
||||||
|
mSignUpButton.clicked -= SignUpButton_Clicked;
|
||||||
|
|
||||||
|
if (mSignInWithEmailPanel != null)
|
||||||
|
mSignInWithEmailPanel.Dispose();
|
||||||
|
|
||||||
|
if (mWaitingSignInPanel != null)
|
||||||
|
mWaitingSignInPanel.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SignInWithEmailButton_Clicked()
|
||||||
|
{
|
||||||
|
mSignInWithEmailPanel = new SignInWithEmailPanel(
|
||||||
|
mParentWindow,
|
||||||
|
mParentWindow,
|
||||||
|
mRestApi);
|
||||||
|
|
||||||
|
mParentWindow.ReplaceRootPanel(mSignInWithEmailPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SignUpButton_Clicked()
|
||||||
|
{
|
||||||
|
Application.OpenURL(UnityUrl.DevOps.GetSignUp());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SignInWithUnityIdButton_Clicked()
|
||||||
|
{
|
||||||
|
mWaitingSignInPanel = new WaitingSignInPanel(
|
||||||
|
mParentWindow,
|
||||||
|
mParentWindow,
|
||||||
|
mRestApi,
|
||||||
|
mCmConnection);
|
||||||
|
|
||||||
|
mParentWindow.ReplaceRootPanel(mWaitingSignInPanel);
|
||||||
|
|
||||||
|
Guid state = Guid.NewGuid();
|
||||||
|
mWaitingSignInPanel.OAuthSignInForConfigure(
|
||||||
|
GetCloudSsoProviders.BuildAuthInfoForUnityId(string.Empty, state).SignInUrl,
|
||||||
|
state,
|
||||||
|
new GetCloudSsoToken(mRestApi));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SignInWithUnityIdButtonAutoLogin()
|
||||||
|
{
|
||||||
|
mWaitingSignInPanel = new WaitingSignInPanel(
|
||||||
|
mParentWindow,
|
||||||
|
mParentWindow,
|
||||||
|
mRestApi,
|
||||||
|
mCmConnection);
|
||||||
|
|
||||||
|
mParentWindow.ReplaceRootPanel(mWaitingSignInPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrivacyPolicyStatementButton_Clicked()
|
||||||
|
{
|
||||||
|
Application.OpenURL(SignUp.PRIVACY_POLICY_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildComponents()
|
||||||
|
{
|
||||||
|
BuildSignUpArea();
|
||||||
|
BuildSignInUnityIdArea();
|
||||||
|
BuildSignInEmailArea();
|
||||||
|
BuildPrivatePolicyArea();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildPrivatePolicyArea()
|
||||||
|
{
|
||||||
|
this.SetControlText<Label>(
|
||||||
|
"privacyStatementText",
|
||||||
|
PlasticLocalization.Name.PrivacyStatementText,
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.PrivacyStatement));
|
||||||
|
|
||||||
|
mPrivacyPolicyStatementButton = this.Query<Button>("privacyStatement");
|
||||||
|
mPrivacyPolicyStatementButton.text = PlasticLocalization.Name.PrivacyStatement.GetString();
|
||||||
|
mPrivacyPolicyStatementButton.clicked += PrivacyPolicyStatementButton_Clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildSignInEmailArea()
|
||||||
|
{
|
||||||
|
this.SetControlImage(
|
||||||
|
"iconEmail",
|
||||||
|
Images.Name.ButtonSsoSignInEmail);
|
||||||
|
|
||||||
|
mSignInWithEmailButton = this.Query<Button>("emailButton");
|
||||||
|
mSignInWithEmailButton.text = PlasticLocalization.Name.SignInWithEmail.GetString();
|
||||||
|
mSignInWithEmailButton.clicked += SignInWithEmailButton_Clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildSignInUnityIdArea()
|
||||||
|
{
|
||||||
|
this.SetControlImage(
|
||||||
|
"iconUnity",
|
||||||
|
Images.Name.ButtonSsoSignInUnity);
|
||||||
|
|
||||||
|
mSignInWithUnityIdButton = this.Query<Button>("unityIDButton");
|
||||||
|
mSignInWithUnityIdButton.text = PlasticLocalization.Name.SignInWithUnityID.GetString();
|
||||||
|
mSignInWithUnityIdButton.clicked += SignInWithUnityIdButton_Clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildSignUpArea()
|
||||||
|
{
|
||||||
|
Label signUpLabel = this.Query<Label>("signUpLabel");
|
||||||
|
signUpLabel.text = PlasticLocalization.Name.LoginOrSignUp.GetString();
|
||||||
|
|
||||||
|
mSignUpButton = this.Query<Button>("signUpButton");
|
||||||
|
mSignUpButton.text = PlasticLocalization.Name.SignUpButton.GetString();
|
||||||
|
mSignUpButton.clicked += SignUpButton_Clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeLayoutAndStyles()
|
||||||
|
{
|
||||||
|
AddToClassList("grow");
|
||||||
|
|
||||||
|
this.LoadLayout(typeof(SignInPanel).Name);
|
||||||
|
this.LoadStyle(typeof(SignInPanel).Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
SignInWithEmailPanel mSignInWithEmailPanel;
|
||||||
|
WaitingSignInPanel mWaitingSignInPanel;
|
||||||
|
Button mSignInWithUnityIdButton;
|
||||||
|
Button mSignInWithEmailButton;
|
||||||
|
Button mPrivacyPolicyStatementButton;
|
||||||
|
Button mSignUpButton;
|
||||||
|
|
||||||
|
readonly CloudEditionWelcomeWindow mParentWindow;
|
||||||
|
readonly IPlasticWebRestApi mRestApi;
|
||||||
|
readonly CmConnection mCmConnection;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,203 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
using PlasticGui;
|
||||||
|
using PlasticGui.Configuration.CloudEdition.Welcome;
|
||||||
|
using PlasticGui.Configuration.CloudEdition;
|
||||||
|
using PlasticGui.WebApi;
|
||||||
|
using Unity.PlasticSCM.Editor.UI.UIElements;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration.CloudEdition.Welcome
|
||||||
|
{
|
||||||
|
internal class SignInWithEmailPanel :
|
||||||
|
VisualElement,
|
||||||
|
Login.INotify
|
||||||
|
{
|
||||||
|
internal SignInWithEmailPanel(
|
||||||
|
CloudEditionWelcomeWindow parentWindow,
|
||||||
|
IWelcomeWindowNotify notify,
|
||||||
|
IPlasticWebRestApi restApi)
|
||||||
|
{
|
||||||
|
mParentWindow = parentWindow;
|
||||||
|
mNotify = notify;
|
||||||
|
mRestApi = restApi;
|
||||||
|
|
||||||
|
InitializeLayoutAndStyles();
|
||||||
|
|
||||||
|
BuildComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Dispose()
|
||||||
|
{
|
||||||
|
mSignInButton.clicked -= SignInButton_Clicked;
|
||||||
|
mBackButton.clicked -= BackButton_Clicked;
|
||||||
|
mSignUpButton.clicked -= SignUpButton_Clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.SuccessForConfigure(
|
||||||
|
List<string> organizations,
|
||||||
|
bool canCreateAnOrganization,
|
||||||
|
string userName,
|
||||||
|
string password)
|
||||||
|
{
|
||||||
|
mNotify.SuccessForConfigure(
|
||||||
|
organizations);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.SuccessForSSO(
|
||||||
|
string organization)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.SuccessForProfile(
|
||||||
|
string userName)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.SuccessForCredentials(string userName, string password)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.SuccessForHomeView(string userName)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.ValidationFailed(
|
||||||
|
Login.ValidationResult validationResult)
|
||||||
|
{
|
||||||
|
if (validationResult.UserError != null)
|
||||||
|
{
|
||||||
|
mEmailNotificationLabel.text = validationResult.UserError;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validationResult.PasswordError != null)
|
||||||
|
{
|
||||||
|
mPasswordNotificationLabel.text = validationResult.PasswordError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.SignUpNeeded(
|
||||||
|
Login.Data loginData)
|
||||||
|
{
|
||||||
|
ShowSignUpNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowSignUpNeeded()
|
||||||
|
{
|
||||||
|
mSignUpNeededNotificationContainer.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HideSignUpNeeded()
|
||||||
|
{
|
||||||
|
mSignUpNeededNotificationContainer.Collapse();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.Error(
|
||||||
|
string message)
|
||||||
|
{
|
||||||
|
HideSignUpNeeded();
|
||||||
|
mProgressControls.ShowError(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CleanNotificationLabels()
|
||||||
|
{
|
||||||
|
mEmailNotificationLabel.text = string.Empty;
|
||||||
|
mPasswordNotificationLabel.text = string.Empty;
|
||||||
|
|
||||||
|
HideSignUpNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SignInButton_Clicked()
|
||||||
|
{
|
||||||
|
CleanNotificationLabels();
|
||||||
|
|
||||||
|
Login.Run(
|
||||||
|
mRestApi,
|
||||||
|
new SaveCloudEditionCreds(),
|
||||||
|
mEmailField.text,
|
||||||
|
mPasswordField.text,
|
||||||
|
string.Empty,
|
||||||
|
string.Empty,
|
||||||
|
Login.Mode.Configure,
|
||||||
|
mProgressControls,
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BackButton_Clicked()
|
||||||
|
{
|
||||||
|
mNotify.Back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeLayoutAndStyles()
|
||||||
|
{
|
||||||
|
this.LoadLayout(typeof(SignInWithEmailPanel).Name);
|
||||||
|
this.LoadStyle(typeof(SignInWithEmailPanel).Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SignUpButton_Clicked()
|
||||||
|
{
|
||||||
|
Application.OpenURL(UnityUrl.DevOps.GetSignUp());
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildComponents()
|
||||||
|
{
|
||||||
|
mEmailField = this.Q<TextField>("email");
|
||||||
|
mPasswordField = this.Q<TextField>("password");
|
||||||
|
mEmailNotificationLabel = this.Q<Label>("emailNotification");
|
||||||
|
mPasswordNotificationLabel = this.Q<Label>("passwordNotification");
|
||||||
|
mSignInButton = this.Q<Button>("signIn");
|
||||||
|
mBackButton = this.Q<Button>("back");
|
||||||
|
mSignUpButton = this.Q<Button>("signUpButton");
|
||||||
|
mProgressContainer = this.Q<VisualElement>("progressContainer");
|
||||||
|
mSignUpNeededNotificationContainer = this.Q<VisualElement>("signUpNeededNotificationContainer");
|
||||||
|
|
||||||
|
mSignInButton.clicked += SignInButton_Clicked;
|
||||||
|
mBackButton.clicked += BackButton_Clicked;
|
||||||
|
mSignUpButton.clicked += SignUpButton_Clicked;
|
||||||
|
mEmailField.FocusOnceLoaded();
|
||||||
|
|
||||||
|
mProgressControls = new ProgressControlsForDialogs(new VisualElement[] { mSignInButton });
|
||||||
|
mProgressContainer.Add((VisualElement)mProgressControls);
|
||||||
|
|
||||||
|
this.SetControlText<Label>("signInLabel",
|
||||||
|
PlasticLocalization.Name.SignInWithEmail);
|
||||||
|
this.SetControlLabel<TextField>("email",
|
||||||
|
PlasticLocalization.Name.Email);
|
||||||
|
this.SetControlLabel<TextField>("password",
|
||||||
|
PlasticLocalization.Name.Password);
|
||||||
|
this.SetControlText<Button>("signIn",
|
||||||
|
PlasticLocalization.Name.SignIn);
|
||||||
|
this.SetControlText<Button>("back",
|
||||||
|
PlasticLocalization.Name.BackButton);
|
||||||
|
this.SetControlText<Label>("signUpNeededNotificationLabel",
|
||||||
|
PlasticLocalization.Name.SignUpNeededNoArgs);
|
||||||
|
this.SetControlText<Button>("signUpButton",
|
||||||
|
PlasticLocalization.Name.SignUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField mEmailField;
|
||||||
|
TextField mPasswordField;
|
||||||
|
|
||||||
|
Label mEmailNotificationLabel;
|
||||||
|
Label mPasswordNotificationLabel;
|
||||||
|
|
||||||
|
Button mSignInButton;
|
||||||
|
Button mBackButton;
|
||||||
|
Button mSignUpButton;
|
||||||
|
|
||||||
|
VisualElement mProgressContainer;
|
||||||
|
VisualElement mSignUpNeededNotificationContainer;
|
||||||
|
|
||||||
|
IProgressControls mProgressControls;
|
||||||
|
|
||||||
|
readonly CloudEditionWelcomeWindow mParentWindow;
|
||||||
|
readonly IWelcomeWindowNotify mNotify;
|
||||||
|
readonly IPlasticWebRestApi mRestApi;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using Codice.Client.Common;
|
||||||
|
using Codice.Client.Common.OAuth;
|
||||||
|
|
||||||
|
using PlasticGui;
|
||||||
|
using PlasticGui.Configuration.OAuth;
|
||||||
|
using PlasticGui.WebApi;
|
||||||
|
using Unity.PlasticSCM.Editor.UI.UIElements;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration.CloudEdition.Welcome
|
||||||
|
{
|
||||||
|
internal class WaitingSignInPanel : VisualElement
|
||||||
|
{
|
||||||
|
internal WaitingSignInPanel(
|
||||||
|
IWelcomeWindowNotify parentNotify,
|
||||||
|
OAuthSignIn.INotify notify,
|
||||||
|
IPlasticWebRestApi restApi,
|
||||||
|
CmConnection cmConnection)
|
||||||
|
{
|
||||||
|
mParentNotify = parentNotify;
|
||||||
|
|
||||||
|
mNotify = notify;
|
||||||
|
mRestApi = restApi;
|
||||||
|
mCmConnection = cmConnection;
|
||||||
|
|
||||||
|
InitializeLayoutAndStyles();
|
||||||
|
|
||||||
|
BuildComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OAuthSignInForConfigure(
|
||||||
|
Uri signInUrl,
|
||||||
|
Guid state,
|
||||||
|
IGetOauthToken getToken)
|
||||||
|
{
|
||||||
|
mSignIn = new OAuthSignIn();
|
||||||
|
|
||||||
|
mSignIn.ForConfigure(
|
||||||
|
signInUrl,
|
||||||
|
state,
|
||||||
|
mProgressControls,
|
||||||
|
mNotify,
|
||||||
|
mCmConnection,
|
||||||
|
getToken,
|
||||||
|
mRestApi);
|
||||||
|
|
||||||
|
ShowWaitingSpinner();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Dispose()
|
||||||
|
{
|
||||||
|
mCancelButton.clicked -= CancelButton_Clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CancelButton_Clicked()
|
||||||
|
{
|
||||||
|
mSignIn.Cancel();
|
||||||
|
mParentNotify.Back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildComponents()
|
||||||
|
{
|
||||||
|
this.SetControlText<Label>("signInToPlasticSCM",
|
||||||
|
PlasticLocalization.Name.SignInToUnityVCS);
|
||||||
|
|
||||||
|
this.SetControlText<Label>("completeSignInOnBrowser",
|
||||||
|
PlasticLocalization.Name.CompleteSignInOnBrowser);
|
||||||
|
|
||||||
|
mProgressContainer = this.Q<VisualElement>("progressContainer");
|
||||||
|
|
||||||
|
mProgressControls = new UI.Progress.ProgressControlsForDialogs();
|
||||||
|
|
||||||
|
mCancelButton = this.Query<Button>("cancelButton");
|
||||||
|
mCancelButton.text = PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.CancelButton);
|
||||||
|
mCancelButton.clicked += CancelButton_Clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeLayoutAndStyles()
|
||||||
|
{
|
||||||
|
this.LoadLayout(typeof(WaitingSignInPanel).Name);
|
||||||
|
this.LoadStyle(typeof(WaitingSignInPanel).Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowWaitingSpinner()
|
||||||
|
{
|
||||||
|
var spinner = new LoadingSpinner();
|
||||||
|
mProgressContainer.Add(spinner);
|
||||||
|
spinner.Start();
|
||||||
|
|
||||||
|
var checkinMessageLabel = new Label(mProgressControls.ProgressData.ProgressMessage);
|
||||||
|
checkinMessageLabel.style.paddingLeft = 20;
|
||||||
|
mProgressContainer.Add(checkinMessageLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
Button mCancelButton;
|
||||||
|
VisualElement mProgressContainer;
|
||||||
|
|
||||||
|
OAuthSignIn mSignIn;
|
||||||
|
|
||||||
|
UI.Progress.ProgressControlsForDialogs mProgressControls;
|
||||||
|
|
||||||
|
readonly IPlasticWebRestApi mRestApi;
|
||||||
|
readonly CmConnection mCmConnection;
|
||||||
|
readonly OAuthSignIn.INotify mNotify;
|
||||||
|
readonly IWelcomeWindowNotify mParentNotify;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
using Codice.Client.Commands.Mount;
|
||||||
|
using Codice.Client.Commands.WkTree;
|
||||||
|
using Codice.Client.Common;
|
||||||
|
using Codice.Client.Common.GameUI;
|
||||||
|
using Codice.CM.Common;
|
||||||
|
using Codice.CM.WorkspaceServer.DataStore.Configuration;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration
|
||||||
|
{
|
||||||
|
internal static class ConfigurePartialWorkspace
|
||||||
|
{
|
||||||
|
internal static void AsFullyChecked(WorkspaceInfo wkInfo)
|
||||||
|
{
|
||||||
|
string rootPath = WorkspacePath.GetWorkspacePathFromCmPath(
|
||||||
|
wkInfo.ClientPath, "/", Path.DirectorySeparatorChar);
|
||||||
|
|
||||||
|
WorkspaceTreeNode rootWkNode = CmConnection.Get().GetWorkspaceTreeHandler().
|
||||||
|
WkGetWorkspaceTreeNode(rootPath);
|
||||||
|
|
||||||
|
FullyCheckedDirectory rootDirectory = new FullyCheckedDirectory();
|
||||||
|
rootDirectory.MountId = MountPointId.WORKSPACE_ROOT;
|
||||||
|
rootDirectory.ItemId = rootWkNode.RevInfo.ItemId;
|
||||||
|
|
||||||
|
List<FullyCheckedDirectory> directoryList = new List<FullyCheckedDirectory>();
|
||||||
|
directoryList.Add(rootDirectory);
|
||||||
|
|
||||||
|
FullyCheckedDirectoriesStorage.Save(wkInfo, directoryList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,160 @@
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
using PlasticGui;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
using Unity.PlasticSCM.Editor.UI.Progress;
|
||||||
|
using Codice.CM.Common;
|
||||||
|
using Codice.Client.Common.Connection;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration
|
||||||
|
{
|
||||||
|
internal class CredentialsDialog : PlasticDialog
|
||||||
|
{
|
||||||
|
protected override Rect DefaultRect
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var baseRect = base.DefaultRect;
|
||||||
|
return new Rect(baseRect.x, baseRect.y, 525, 250);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static AskCredentialsToUser.DialogData RequestCredentials(
|
||||||
|
string server,
|
||||||
|
SEIDWorkingMode seidWorkingMode,
|
||||||
|
EditorWindow parentWindow)
|
||||||
|
{
|
||||||
|
CredentialsDialog dialog = Create(
|
||||||
|
server, seidWorkingMode, new ProgressControlsForDialogs());
|
||||||
|
|
||||||
|
ResponseType dialogResult = dialog.RunModal(parentWindow);
|
||||||
|
|
||||||
|
return dialog.BuildCredentialsDialogData(dialogResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModalGUI()
|
||||||
|
{
|
||||||
|
Title(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.CredentialsDialogTitle));
|
||||||
|
|
||||||
|
Paragraph(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.CredentialsDialogExplanation, mServer));
|
||||||
|
|
||||||
|
GUILayout.Space(5);
|
||||||
|
|
||||||
|
DoEntriesArea();
|
||||||
|
|
||||||
|
GUILayout.Space(10);
|
||||||
|
|
||||||
|
DrawProgressForDialogs.For(
|
||||||
|
mProgressControls.ProgressData);
|
||||||
|
|
||||||
|
GUILayout.Space(10);
|
||||||
|
|
||||||
|
DoButtonsArea();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GetTitle()
|
||||||
|
{
|
||||||
|
return PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.CredentialsDialogTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
AskCredentialsToUser.DialogData BuildCredentialsDialogData(
|
||||||
|
ResponseType dialogResult)
|
||||||
|
{
|
||||||
|
return new AskCredentialsToUser.DialogData(
|
||||||
|
dialogResult == ResponseType.Ok,
|
||||||
|
mUser, mPassword, mSaveProfile, mSeidWorkingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoEntriesArea()
|
||||||
|
{
|
||||||
|
mUser = TextEntry(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.UserName), mUser,
|
||||||
|
ENTRY_WIDTH, ENTRY_X);
|
||||||
|
|
||||||
|
GUILayout.Space(5);
|
||||||
|
|
||||||
|
mPassword = PasswordEntry(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.Password), mPassword,
|
||||||
|
ENTRY_WIDTH, ENTRY_X);
|
||||||
|
|
||||||
|
GUILayout.Space(5);
|
||||||
|
|
||||||
|
mSaveProfile = ToggleEntry(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.RememberCredentialsAsProfile),
|
||||||
|
mSaveProfile, ENTRY_WIDTH, ENTRY_X);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoButtonsArea()
|
||||||
|
{
|
||||||
|
using (new EditorGUILayout.HorizontalScope())
|
||||||
|
{
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
|
||||||
|
if (Application.platform == RuntimePlatform.WindowsEditor)
|
||||||
|
{
|
||||||
|
DoOkButton();
|
||||||
|
DoCancelButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoCancelButton();
|
||||||
|
DoOkButton();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoOkButton()
|
||||||
|
{
|
||||||
|
if (!AcceptButton(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.OkButton)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
OkButtonWithValidationAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoCancelButton()
|
||||||
|
{
|
||||||
|
if (!NormalButton(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.CancelButton)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CancelButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OkButtonWithValidationAction()
|
||||||
|
{
|
||||||
|
CredentialsDialogValidation.AsyncValidation(
|
||||||
|
BuildCredentialsDialogData(ResponseType.Ok), this, mProgressControls);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CredentialsDialog Create(
|
||||||
|
string server,
|
||||||
|
SEIDWorkingMode seidWorkingMode,
|
||||||
|
ProgressControlsForDialogs progressControls)
|
||||||
|
{
|
||||||
|
var instance = CreateInstance<CredentialsDialog>();
|
||||||
|
instance.mServer = server;
|
||||||
|
instance.mSeidWorkingMode = seidWorkingMode;
|
||||||
|
instance.mProgressControls = progressControls;
|
||||||
|
instance.mEnterKeyAction = instance.OkButtonWithValidationAction;
|
||||||
|
instance.mEscapeKeyAction = instance.CancelButtonAction;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
string mUser;
|
||||||
|
string mPassword = string.Empty;
|
||||||
|
|
||||||
|
ProgressControlsForDialogs mProgressControls;
|
||||||
|
bool mSaveProfile;
|
||||||
|
|
||||||
|
string mServer;
|
||||||
|
SEIDWorkingMode mSeidWorkingMode;
|
||||||
|
|
||||||
|
const float ENTRY_WIDTH = 345f;
|
||||||
|
const float ENTRY_X = 150f;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
using System;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
using Codice.CM.Common;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Codice.Client.Common;
|
||||||
|
using Codice.Client.Common.Connection;
|
||||||
|
using PlasticGui;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
using Codice.Client.Common.Threading;
|
||||||
|
using Unity.PlasticSCM.Editor.WebApi;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration
|
||||||
|
{
|
||||||
|
internal class CredentialsUiImpl : AskCredentialsToUser.IGui
|
||||||
|
{
|
||||||
|
AskCredentialsToUser.DialogData AskCredentialsToUser.IGui.AskUserForCredentials(string servername, SEIDWorkingMode seidWorkingMode)
|
||||||
|
{
|
||||||
|
AskCredentialsToUser.DialogData result = null;
|
||||||
|
|
||||||
|
if (!PlasticPlugin.ConnectionMonitor.IsConnected)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
GUIActionRunner.RunGUIAction(delegate
|
||||||
|
{
|
||||||
|
result = CredentialsDialog.RequestCredentials(
|
||||||
|
servername, seidWorkingMode, ParentWindow.Get());
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AskCredentialsToUser.IGui.ShowSaveProfileErrorMessage(string message)
|
||||||
|
{
|
||||||
|
if (!PlasticPlugin.ConnectionMonitor.IsConnected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GUIActionRunner.RunGUIAction(delegate
|
||||||
|
{
|
||||||
|
GuiMessage.ShowError(string.Format(
|
||||||
|
PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.CredentialsErrorSavingProfile),
|
||||||
|
message));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
AskCredentialsToUser.DialogData AskCredentialsToUser.IGui.AskUserForOidcCredentials(
|
||||||
|
string server)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("OIDC authentication not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
AskCredentialsToUser.DialogData AskCredentialsToUser.IGui.AskUserForSsoCredentials(
|
||||||
|
string cloudServer)
|
||||||
|
{
|
||||||
|
AskCredentialsToUser.DialogData result = null;
|
||||||
|
|
||||||
|
if (!PlasticPlugin.ConnectionMonitor.IsConnected)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
GUIActionRunner.RunGUIAction(delegate
|
||||||
|
{
|
||||||
|
result = RunSSOCredentialsRequest(
|
||||||
|
cloudServer, CloudProjectSettings.accessToken);
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
AskCredentialsToUser.DialogData RunSSOCredentialsRequest(
|
||||||
|
string cloudServer,
|
||||||
|
string unityAccessToken)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(unityAccessToken))
|
||||||
|
{
|
||||||
|
return SSOCredentialsDialog.RequestCredentials(
|
||||||
|
cloudServer, ParentWindow.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenExchangeResponse tokenExchangeResponse =
|
||||||
|
WaitUntilTokenExchange(unityAccessToken);
|
||||||
|
|
||||||
|
// There is no internet connection, so no way to get credentials
|
||||||
|
if (tokenExchangeResponse == null)
|
||||||
|
{
|
||||||
|
return new AskCredentialsToUser.DialogData(
|
||||||
|
false, null, null, false,
|
||||||
|
SEIDWorkingMode.SSOWorkingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenExchangeResponse.Error == null)
|
||||||
|
{
|
||||||
|
return new AskCredentialsToUser.DialogData(
|
||||||
|
true,
|
||||||
|
tokenExchangeResponse.User,
|
||||||
|
tokenExchangeResponse.AccessToken,
|
||||||
|
false,
|
||||||
|
SEIDWorkingMode.SSOWorkingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SSOCredentialsDialog.RequestCredentials(
|
||||||
|
cloudServer, ParentWindow.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
static TokenExchangeResponse WaitUntilTokenExchange(
|
||||||
|
string unityAccessToken)
|
||||||
|
{
|
||||||
|
TokenExchangeResponse result = null;
|
||||||
|
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = WebRestApiClient.PlasticScm.
|
||||||
|
TokenExchange(unityAccessToken);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExceptionsHandler.LogException(
|
||||||
|
"CredentialsUiImpl", ex);
|
||||||
|
}
|
||||||
|
}).Wait();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,196 @@
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
using Codice.Utils;
|
||||||
|
using PlasticGui;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration
|
||||||
|
{
|
||||||
|
internal class EncryptionConfigurationDialog : PlasticDialog
|
||||||
|
{
|
||||||
|
protected override Rect DefaultRect
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var baseRect = base.DefaultRect;
|
||||||
|
return new Rect(baseRect.x, baseRect.y, 650, 425);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static EncryptionConfigurationDialogData RequestEncryptionPassword(
|
||||||
|
string server,
|
||||||
|
EditorWindow parentWindow)
|
||||||
|
{
|
||||||
|
EncryptionConfigurationDialog dialog = Create(server);
|
||||||
|
|
||||||
|
ResponseType dialogResult = dialog.RunModal(parentWindow);
|
||||||
|
|
||||||
|
EncryptionConfigurationDialogData result =
|
||||||
|
dialog.BuildEncryptionConfigurationData();
|
||||||
|
|
||||||
|
result.Result = dialogResult == ResponseType.Ok;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModalGUI()
|
||||||
|
{
|
||||||
|
Title(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.EncryptionConfiguration));
|
||||||
|
|
||||||
|
GUILayout.Space(20);
|
||||||
|
|
||||||
|
Paragraph(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.EncryptionConfigurationExplanation, mServer));
|
||||||
|
|
||||||
|
DoPasswordArea();
|
||||||
|
|
||||||
|
Paragraph(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.EncryptionConfigurationRemarks, mServer));
|
||||||
|
|
||||||
|
GUILayout.Space(10);
|
||||||
|
|
||||||
|
DoNotificationArea();
|
||||||
|
|
||||||
|
GUILayout.Space(10);
|
||||||
|
|
||||||
|
DoButtonsArea();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GetTitle()
|
||||||
|
{
|
||||||
|
return PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.EncryptionConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
EncryptionConfigurationDialogData BuildEncryptionConfigurationData()
|
||||||
|
{
|
||||||
|
return new EncryptionConfigurationDialogData(
|
||||||
|
CryptoServices.GetEncryptedPassword(mPassword.Trim()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoPasswordArea()
|
||||||
|
{
|
||||||
|
Paragraph(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.EncryptionConfigurationEnterPassword));
|
||||||
|
|
||||||
|
GUILayout.Space(5);
|
||||||
|
|
||||||
|
mPassword = PasswordEntry(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.Password), mPassword,
|
||||||
|
PASSWORD_TEXT_WIDTH, PASSWORD_TEXT_X);
|
||||||
|
|
||||||
|
GUILayout.Space(5);
|
||||||
|
|
||||||
|
mRetypePassword = PasswordEntry(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.RetypePassword), mRetypePassword,
|
||||||
|
PASSWORD_TEXT_WIDTH, PASSWORD_TEXT_X);
|
||||||
|
|
||||||
|
GUILayout.Space(18f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoNotificationArea()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(mErrorMessage))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var rect = GUILayoutUtility.GetRect(
|
||||||
|
GUILayoutUtility.GetLastRect().width, 30);
|
||||||
|
|
||||||
|
EditorGUI.HelpBox(rect, mErrorMessage, MessageType.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoButtonsArea()
|
||||||
|
{
|
||||||
|
using (new EditorGUILayout.HorizontalScope())
|
||||||
|
{
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
|
||||||
|
if (Application.platform == RuntimePlatform.WindowsEditor)
|
||||||
|
{
|
||||||
|
DoOkButton();
|
||||||
|
DoCancelButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoCancelButton();
|
||||||
|
DoOkButton();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoOkButton()
|
||||||
|
{
|
||||||
|
if (!AcceptButton(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.OkButton)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
OkButtonWithValidationAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoCancelButton()
|
||||||
|
{
|
||||||
|
if (!NormalButton(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.CancelButton)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CancelButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OkButtonWithValidationAction()
|
||||||
|
{
|
||||||
|
if (IsValidPassword(
|
||||||
|
mPassword.Trim(), mRetypePassword.Trim(),
|
||||||
|
out mErrorMessage))
|
||||||
|
{
|
||||||
|
mErrorMessage = string.Empty;
|
||||||
|
OkButtonAction();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mPassword = string.Empty;
|
||||||
|
mRetypePassword = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsValidPassword(
|
||||||
|
string password, string retypePassword,
|
||||||
|
out string errorMessage)
|
||||||
|
{
|
||||||
|
errorMessage = string.Empty;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(password))
|
||||||
|
{
|
||||||
|
errorMessage = PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.InvalidEmptyPassword);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!password.Equals(retypePassword))
|
||||||
|
{
|
||||||
|
errorMessage = PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.PasswordDoesntMatch);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EncryptionConfigurationDialog Create(string server)
|
||||||
|
{
|
||||||
|
var instance = CreateInstance<EncryptionConfigurationDialog>();
|
||||||
|
instance.mServer = server;
|
||||||
|
instance.mEnterKeyAction = instance.OkButtonWithValidationAction;
|
||||||
|
instance.mEscapeKeyAction = instance.CancelButtonAction;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
string mPassword = string.Empty;
|
||||||
|
string mRetypePassword = string.Empty;
|
||||||
|
string mErrorMessage = string.Empty;
|
||||||
|
|
||||||
|
string mServer = string.Empty;
|
||||||
|
|
||||||
|
const float PASSWORD_TEXT_WIDTH = 250f;
|
||||||
|
const float PASSWORD_TEXT_X = 200f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
using Codice.Client.Common.Encryption;
|
||||||
|
using PlasticGui;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration
|
||||||
|
{
|
||||||
|
internal class MissingEncryptionPasswordPromptHandler :
|
||||||
|
ClientEncryptionServiceProvider.IEncryptioPasswordProvider
|
||||||
|
{
|
||||||
|
string ClientEncryptionServiceProvider.IEncryptioPasswordProvider
|
||||||
|
.GetEncryptionEncryptedPassword(string server)
|
||||||
|
{
|
||||||
|
string result = null;
|
||||||
|
|
||||||
|
GUIActionRunner.RunGUIAction(delegate
|
||||||
|
{
|
||||||
|
result = AskForEncryptionPassword(server);
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
string AskForEncryptionPassword(string server)
|
||||||
|
{
|
||||||
|
EncryptionConfigurationDialogData dialogData =
|
||||||
|
EncryptionConfigurationDialog.RequestEncryptionPassword(server, ParentWindow.Get());
|
||||||
|
|
||||||
|
if (!dialogData.Result)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return dialogData.EncryptedPassword;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,296 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
using PlasticGui;
|
||||||
|
using Unity.PlasticSCM.Editor.UI;
|
||||||
|
using Unity.PlasticSCM.Editor.UI.Progress;
|
||||||
|
using Codice.CM.Common;
|
||||||
|
using Codice.Client.Common.OAuth;
|
||||||
|
using Codice.Client.Common.Connection;
|
||||||
|
using Unity.PlasticSCM.Editor.Configuration.CloudEdition.Welcome;
|
||||||
|
using PlasticGui.Configuration.CloudEdition.Welcome;
|
||||||
|
using PlasticGui.Configuration.OAuth;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using PlasticGui.WebApi.Responses;
|
||||||
|
using PlasticGui.Configuration.CloudEdition;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration
|
||||||
|
{
|
||||||
|
internal class SSOCredentialsDialog : PlasticDialog, OAuthSignIn.INotify, Login.INotify
|
||||||
|
{
|
||||||
|
protected override Rect DefaultRect
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var baseRect = base.DefaultRect;
|
||||||
|
return new Rect(baseRect.x, baseRect.y, 525, 450);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static AskCredentialsToUser.DialogData RequestCredentials(
|
||||||
|
string cloudServer,
|
||||||
|
EditorWindow parentWindow)
|
||||||
|
{
|
||||||
|
SSOCredentialsDialog dialog = Create(
|
||||||
|
cloudServer, new ProgressControlsForDialogs());
|
||||||
|
|
||||||
|
ResponseType dialogResult = dialog.RunModal(parentWindow);
|
||||||
|
|
||||||
|
return dialog.BuildCredentialsDialogData(dialogResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModalGUI()
|
||||||
|
{
|
||||||
|
Title(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.CredentialsDialogTitle));
|
||||||
|
|
||||||
|
Paragraph(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.CredentialsDialogExplanation, mServer));
|
||||||
|
|
||||||
|
GUILayout.Space(20);
|
||||||
|
|
||||||
|
DoEntriesArea();
|
||||||
|
|
||||||
|
GUILayout.Space(10);
|
||||||
|
|
||||||
|
DrawProgressForDialogs.For(
|
||||||
|
mProgressControls.ProgressData);
|
||||||
|
|
||||||
|
GUILayout.Space(10);
|
||||||
|
|
||||||
|
DoButtonsArea();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GetTitle()
|
||||||
|
{
|
||||||
|
return PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.CredentialsDialogTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
AskCredentialsToUser.DialogData BuildCredentialsDialogData(
|
||||||
|
ResponseType dialogResult)
|
||||||
|
{
|
||||||
|
return new AskCredentialsToUser.DialogData(
|
||||||
|
dialogResult == ResponseType.Ok,
|
||||||
|
mEmail, mPassword, false, SEIDWorkingMode.SSOWorkingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForSSO(string organization)
|
||||||
|
{
|
||||||
|
OkButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForProfile(string email)
|
||||||
|
{
|
||||||
|
OkButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForCredentials(
|
||||||
|
string email,
|
||||||
|
string accessToken)
|
||||||
|
{
|
||||||
|
OkButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.SuccessForHomeView(string usrName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void OAuthSignIn.INotify.Cancel(string errorMessage)
|
||||||
|
{
|
||||||
|
CancelButtonAction();
|
||||||
|
}
|
||||||
|
void OAuthSignIn.INotify.SuccessForConfigure(
|
||||||
|
List<string> organizations,
|
||||||
|
bool canCreateAnOrganization,
|
||||||
|
string userName,
|
||||||
|
string accessToken)
|
||||||
|
{
|
||||||
|
mEmail = userName;
|
||||||
|
mPassword = accessToken;
|
||||||
|
|
||||||
|
if (!organizations.Contains(mServer))
|
||||||
|
{
|
||||||
|
CancelButtonAction();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloudEditionWelcomeWindow.JoinCloudServer(
|
||||||
|
mServer, userName, accessToken);
|
||||||
|
|
||||||
|
GetWindow<PlasticWindow>().InitializePlastic();
|
||||||
|
OkButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoButtonsArea()
|
||||||
|
{
|
||||||
|
using (new EditorGUILayout.HorizontalScope())
|
||||||
|
{
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
|
||||||
|
if (Application.platform == RuntimePlatform.WindowsEditor)
|
||||||
|
{
|
||||||
|
DoOkButton();
|
||||||
|
DoCancelButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoCancelButton();
|
||||||
|
DoOkButton();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OAuthSignInForConfigure(Uri signInUrl, Guid state, IGetOauthToken getOauthToken)
|
||||||
|
{
|
||||||
|
OAuthSignIn mSignIn = new OAuthSignIn();
|
||||||
|
|
||||||
|
mSignIn.ForConfigure(
|
||||||
|
signInUrl,
|
||||||
|
state,
|
||||||
|
mProgressControls,
|
||||||
|
this,
|
||||||
|
GetWindow<PlasticWindow>().CmConnectionForTesting,
|
||||||
|
getOauthToken,
|
||||||
|
PlasticGui.Plastic.WebRestAPI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoUnityIDButton()
|
||||||
|
{
|
||||||
|
if (NormalButton("Sign in with Unity ID"))
|
||||||
|
{
|
||||||
|
Guid state = Guid.NewGuid();
|
||||||
|
OAuthSignInForConfigure(
|
||||||
|
GetCloudSsoProviders.BuildAuthInfoForUnityId(string.Empty, state).SignInUrl,
|
||||||
|
state,
|
||||||
|
new GetCloudSsoToken(PlasticGui.Plastic.WebRestAPI));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoEntriesArea()
|
||||||
|
{
|
||||||
|
Paragraph("Sign in with Unity ID");
|
||||||
|
GUILayout.Space(5);
|
||||||
|
|
||||||
|
DoUnityIDButton();
|
||||||
|
|
||||||
|
GUILayout.Space(25);
|
||||||
|
Paragraph(" --or-- ");
|
||||||
|
|
||||||
|
Paragraph("Sign in with email");
|
||||||
|
|
||||||
|
mEmail = TextEntry(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.Email), mEmail,
|
||||||
|
ENTRY_WIDTH, ENTRY_X);
|
||||||
|
|
||||||
|
GUILayout.Space(5);
|
||||||
|
|
||||||
|
mPassword = PasswordEntry(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.Password), mPassword,
|
||||||
|
ENTRY_WIDTH, ENTRY_X);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoOkButton()
|
||||||
|
{
|
||||||
|
if (!AcceptButton(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.OkButton)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
OkButtonWithValidationAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoCancelButton()
|
||||||
|
{
|
||||||
|
if (!NormalButton(PlasticLocalization.GetString(
|
||||||
|
PlasticLocalization.Name.CancelButton)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CancelButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OkButtonWithValidationAction()
|
||||||
|
{
|
||||||
|
Login.Run(
|
||||||
|
PlasticGui.Plastic.WebRestAPI,
|
||||||
|
new SaveCloudEditionCreds(),
|
||||||
|
mEmail,
|
||||||
|
mPassword,
|
||||||
|
string.Empty,
|
||||||
|
string.Empty,
|
||||||
|
Login.Mode.Configure,
|
||||||
|
mProgressControls,
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.SuccessForConfigure(
|
||||||
|
List<string> organizations,
|
||||||
|
bool canCreateAnOrganization,
|
||||||
|
string userName,
|
||||||
|
string password)
|
||||||
|
{
|
||||||
|
OkButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.SuccessForSSO(
|
||||||
|
string organization)
|
||||||
|
{
|
||||||
|
OkButtonAction();
|
||||||
|
}
|
||||||
|
void Login.INotify.SuccessForCredentials(string userName, string password)
|
||||||
|
{
|
||||||
|
OkButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Login.INotify.SuccessForProfile(
|
||||||
|
string userName)
|
||||||
|
{
|
||||||
|
OkButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.SuccessForHomeView(string userName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.ValidationFailed(
|
||||||
|
Login.ValidationResult validationResult)
|
||||||
|
{
|
||||||
|
CancelButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.SignUpNeeded(
|
||||||
|
Login.Data loginData)
|
||||||
|
{
|
||||||
|
CancelButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login.INotify.Error(
|
||||||
|
string message)
|
||||||
|
{
|
||||||
|
CancelButtonAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
static SSOCredentialsDialog Create(
|
||||||
|
string server,
|
||||||
|
ProgressControlsForDialogs progressControls)
|
||||||
|
{
|
||||||
|
var instance = CreateInstance<SSOCredentialsDialog>();
|
||||||
|
instance.mServer = server;
|
||||||
|
instance.mProgressControls = progressControls;
|
||||||
|
instance.mEnterKeyAction = instance.OkButtonWithValidationAction;
|
||||||
|
instance.mEscapeKeyAction = instance.CancelButtonAction;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
string mEmail;
|
||||||
|
string mPassword = string.Empty;
|
||||||
|
|
||||||
|
ProgressControlsForDialogs mProgressControls;
|
||||||
|
|
||||||
|
string mServer;
|
||||||
|
|
||||||
|
const float ENTRY_WIDTH = 345f;
|
||||||
|
const float ENTRY_X = 150f;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,314 @@
|
||||||
|
using System;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
using PlasticGui;
|
||||||
|
using Codice.CM.Common;
|
||||||
|
using Codice.Client.Common;
|
||||||
|
using Unity.PlasticSCM.Editor.UI.UIElements;
|
||||||
|
using PlasticGui.Configuration.TeamEdition;
|
||||||
|
using PlasticGui.Configuration;
|
||||||
|
using PlasticGui.WebApi;
|
||||||
|
using Unity.PlasticSCM.Editor.Views.Welcome;
|
||||||
|
|
||||||
|
namespace Unity.PlasticSCM.Editor.Configuration.TeamEdition
|
||||||
|
{
|
||||||
|
internal class TeamEditionConfigurationWindow : EditorWindow
|
||||||
|
{
|
||||||
|
internal static void ShowWindow(IPlasticWebRestApi restApi, WelcomeView welcomeView)
|
||||||
|
{
|
||||||
|
TeamEditionConfigurationWindow window = GetWindow<TeamEditionConfigurationWindow>();
|
||||||
|
window.mRestApi = restApi;
|
||||||
|
window.mWelcomeView = welcomeView;
|
||||||
|
window.titleContent = new GUIContent(
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.WelcomeToUnityVCS));
|
||||||
|
window.minSize = window.maxSize = new Vector2(650, 300);
|
||||||
|
window.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnEnable()
|
||||||
|
{
|
||||||
|
InitializeLayoutAndStyles();
|
||||||
|
|
||||||
|
BuildComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispose()
|
||||||
|
{
|
||||||
|
mConnectButton.clicked -= ConnectButton_Clicked;
|
||||||
|
mCheckConnectionButton.clicked -= CheckConnectionButton_Clicked;
|
||||||
|
mOkButton.clicked -= OkButton_Clicked;
|
||||||
|
mCancelButton.clicked -= CancelButton_Clicked;
|
||||||
|
mServerTextField.UnregisterValueChangedCallback(OnServerTextFieldChanged);
|
||||||
|
mUseSslToggle.UnregisterValueChangedCallback(OnUseSslToggleChanged);
|
||||||
|
|
||||||
|
mLoadingSpinner.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectButton_Clicked()
|
||||||
|
{
|
||||||
|
ConfigurationConnectServerButtonClickEvent.Click(
|
||||||
|
server: mUserAssistant.GetProposedServer(),
|
||||||
|
HideValidation: HideValidation,
|
||||||
|
ShowError: ShowServerValidationError,
|
||||||
|
ShowProgress: ShowProgress,
|
||||||
|
HideProgress: HideProgress,
|
||||||
|
ShowNotification: ShowServerNotificationMessage,
|
||||||
|
DisableButtons: () => { mConnectButton.SetEnabled(false); },
|
||||||
|
EnableButtons: () => { mConnectButton.SetEnabled(true); },
|
||||||
|
UpdatePasswordEntries: (seidWorkingMode) =>
|
||||||
|
{
|
||||||
|
UpdatePasswordEntries(ValidateServerAndCreds.
|
||||||
|
IsPasswordRequired(seidWorkingMode));
|
||||||
|
},
|
||||||
|
NotifyWorkingMode: (mode) => { mSEIDWorkingMode = mode; },
|
||||||
|
NotifyConnectedStatus: (b) => { });
|
||||||
|
|
||||||
|
mUserTextField.SetEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
|
||||||
|
if (mWelcomeView != null)
|
||||||
|
mWelcomeView.OnUserClosedConfigurationWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckConnectionButton_Clicked()
|
||||||
|
{
|
||||||
|
ConfigurationCheckCredentialsButtonClickEvent.Click(
|
||||||
|
mSEIDWorkingMode,
|
||||||
|
mUserTextField.value,
|
||||||
|
mPasswordTextField.value,
|
||||||
|
Edition.Team,
|
||||||
|
mUserAssistant,
|
||||||
|
HideCredentialsValidationError,
|
||||||
|
ShowCheckCredentialsError,
|
||||||
|
ShowProgress,
|
||||||
|
HideProgress,
|
||||||
|
ShowNotification: ShowCredentialsNotificationMessage,
|
||||||
|
DisableButtons: () => { mCheckConnectionButton.SetEnabled(false); mConnectButton.SetEnabled(false); },
|
||||||
|
EnableButtons: () => { mCheckConnectionButton.SetEnabled(true); mConnectButton.SetEnabled(true); },
|
||||||
|
NotifyWorkingMode: (mode) => { mSEIDWorkingMode = mode; },
|
||||||
|
NotifyConnectedStatus: (status) => { },
|
||||||
|
restApi: mRestApi,
|
||||||
|
cmConnection: CmConnection.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CancelButton_Clicked()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OkButton_Clicked()
|
||||||
|
{
|
||||||
|
if (!ValidateServerAndCreds.IsValidInput(
|
||||||
|
mUserAssistant.GetProposedServer(),
|
||||||
|
mUserTextField.value,
|
||||||
|
mSEIDWorkingMode,
|
||||||
|
mPasswordTextField.value,
|
||||||
|
ShowCheckCredentialsError))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigurationActions.SaveClientConfig(
|
||||||
|
mServerTextField.value,
|
||||||
|
mSEIDWorkingMode,
|
||||||
|
mUserTextField.value,
|
||||||
|
mPasswordTextField.value);
|
||||||
|
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HideCredentialsValidationError()
|
||||||
|
{
|
||||||
|
mCredentialsLabel.RemoveFromClassList("error");
|
||||||
|
mCredentialsLabel.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildComponents()
|
||||||
|
{
|
||||||
|
VisualElement root = rootVisualElement;
|
||||||
|
|
||||||
|
root.Query<Label>("plasticConfigurationTitle").First().text =
|
||||||
|
PlasticLocalization.GetString(PlasticLocalization.Name.PlasticConfigurationTitleUnityVCS);
|
||||||
|
|
||||||
|
root.SetControlText<Label>(
|
||||||
|
"plasticConfigurationExplanation",
|
||||||
|
PlasticLocalization.Name.PlasticConfigurationExplanation);
|
||||||
|
|
||||||
|
root.SetControlText<Label>("configurationServerInfo",
|
||||||
|
PlasticLocalization.Name.PlasticSCMServerLabel);
|
||||||
|
|
||||||
|
root.SetControlText<Button>(
|
||||||
|
"connect",
|
||||||
|
PlasticLocalization.Name.Connect);
|
||||||
|
|
||||||
|
root.SetControlText<Label>("useSsl",
|
||||||
|
PlasticLocalization.Name.UseSsl);
|
||||||
|
|
||||||
|
root.SetControlText<Label>("configurationUserNameInfo",
|
||||||
|
PlasticLocalization.Name.ConfigurationUserNameInfo);
|
||||||
|
|
||||||
|
root.SetControlText<Label>("configurationCredentialsInfo",
|
||||||
|
PlasticLocalization.Name.ConfigurationCredentialsInfo);
|
||||||
|
|
||||||
|
root.SetControlText<Button>("check",
|
||||||
|
PlasticLocalization.Name.Check);
|
||||||
|
|
||||||
|
root.SetControlText<Label>("credentialsOk",
|
||||||
|
PlasticLocalization.Name.CredentialsOK);
|
||||||
|
|
||||||
|
root.SetControlText<Button>("okButton",
|
||||||
|
PlasticLocalization.Name.OkButton);
|
||||||
|
|
||||||
|
root.SetControlText<Button>("cancelButton",
|
||||||
|
PlasticLocalization.Name.CancelButton);
|
||||||
|
|
||||||
|
mSpinnerContainer = root.Query<VisualElement>("spinnerContainer").First();
|
||||||
|
mSpinnerLabel = root.Query<Label>("spinnerLabel").First();
|
||||||
|
|
||||||
|
mLoadingSpinner = new LoadingSpinner();
|
||||||
|
mSpinnerContainer.Add(mLoadingSpinner);
|
||||||
|
mSpinnerContainer.Hide();
|
||||||
|
|
||||||
|
mCheckConnectionButton = root.Query<Button>("check").First();
|
||||||
|
mCheckConnectionButton.clicked += CheckConnectionButton_Clicked;
|
||||||
|
|
||||||
|
mConnectButton = root.Query<Button>("connect").First();
|
||||||
|
mConnectButton.clicked += ConnectButton_Clicked;
|
||||||
|
|
||||||
|
mServerTextField = root.Query<TextField>("serverTextField").First();
|
||||||
|
mServerTextField.RegisterValueChangedCallback(OnServerTextFieldChanged);
|
||||||
|
|
||||||
|
mUseSslToggle = root.Query<Toggle>("useSslToogle").First();
|
||||||
|
mUseSslToggle.RegisterValueChangedCallback(OnUseSslToggleChanged);
|
||||||
|
|
||||||
|
mUserTextField = root.Query<TextField>("userTextField").First();
|
||||||
|
mUserTextField.SetEnabled(false);
|
||||||
|
|
||||||
|
mPasswordTextField = root.Query<TextField>("passwordTextField").First();
|
||||||
|
mPasswordTextField.isPasswordField = true;
|
||||||
|
|
||||||
|
mConnectedLabel = root.Query<Label>("connectedLabel").First();
|
||||||
|
|
||||||
|
mCredentialsLabel = root.Query<Label>("credentialsOk").First();
|
||||||
|
|
||||||
|
mOkButton = root.Query<Button>("okButton").First();
|
||||||
|
mOkButton.clicked += OkButton_Clicked;
|
||||||
|
|
||||||
|
mCancelButton = root.Query<Button>("cancelButton").First();
|
||||||
|
mCancelButton.clicked += CancelButton_Clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnUseSslToggleChanged(ChangeEvent<bool> evt)
|
||||||
|
{
|
||||||
|
mUserAssistant.OnSslChanged(mServerTextField.value, evt.newValue);
|
||||||
|
mServerTextField.value = mUserAssistant.GetProposedServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeLayoutAndStyles()
|
||||||
|
{
|
||||||
|
VisualElement root = rootVisualElement;
|
||||||
|
|
||||||
|
root.LoadLayout(typeof(TeamEditionConfigurationWindow).Name);
|
||||||
|
|
||||||
|
root.LoadStyle(typeof(TeamEditionConfigurationWindow).Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnServerTextFieldChanged(ChangeEvent<string> evt)
|
||||||
|
{
|
||||||
|
mUserAssistant.OnServerChanged(evt.newValue);
|
||||||
|
mUseSslToggle.value = mUserAssistant.IsSslServer(evt.newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowServerNotificationMessage(string message)
|
||||||
|
{
|
||||||
|
mConnectedLabel.text = message;
|
||||||
|
mConnectedLabel.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowServerValidationError(string message)
|
||||||
|
{
|
||||||
|
mConnectedLabel.text = message;
|
||||||
|
mConnectedLabel.AddToClassList("error");
|
||||||
|
mConnectedLabel.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowCredentialsNotificationMessage(string message)
|
||||||
|
{
|
||||||
|
mCredentialsLabel.text = message;
|
||||||
|
mCredentialsLabel.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowCheckCredentialsError(string message)
|
||||||
|
{
|
||||||
|
mCredentialsLabel.text = message;
|
||||||
|
mCredentialsLabel.AddToClassList("error");
|
||||||
|
mCredentialsLabel.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HideValidation()
|
||||||
|
{
|
||||||
|
mConnectedLabel.RemoveFromClassList("error");
|
||||||
|
mConnectedLabel.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowProgress(string text)
|
||||||
|
{
|
||||||
|
mSpinnerLabel.text = text;
|
||||||
|
|
||||||
|
mSpinnerContainer.Show();
|
||||||
|
mSpinnerLabel.Show();
|
||||||
|
mLoadingSpinner.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HideProgress()
|
||||||
|
{
|
||||||
|
mLoadingSpinner.Stop();
|
||||||
|
mSpinnerContainer.Hide();
|
||||||
|
mSpinnerLabel.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdatePasswordEntries(bool bIsPasswordRequired)
|
||||||
|
{
|
||||||
|
if (!bIsPasswordRequired)
|
||||||
|
{
|
||||||
|
mPasswordTextField.Collapse();
|
||||||
|
mUserTextField.SetEnabled(false);
|
||||||
|
mUserTextField.value = Environment.UserName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mUserTextField.SetEnabled(true);
|
||||||
|
mPasswordTextField.Show();
|
||||||
|
mUserTextField.SelectAll();
|
||||||
|
mUserTextField.FocusWorkaround();
|
||||||
|
}
|
||||||
|
|
||||||
|
Button mConnectButton;
|
||||||
|
Label mConnectedLabel;
|
||||||
|
TextField mServerTextField;
|
||||||
|
TextField mPasswordTextField;
|
||||||
|
Toggle mUseSslToggle;
|
||||||
|
LoadingSpinner mLoadingSpinner;
|
||||||
|
Label mSpinnerLabel;
|
||||||
|
VisualElement mSpinnerContainer;
|
||||||
|
Button mCheckConnectionButton;
|
||||||
|
Label mCredentialsLabel;
|
||||||
|
Button mOkButton;
|
||||||
|
Button mCancelButton;
|
||||||
|
|
||||||
|
SEIDWorkingMode mSEIDWorkingMode = SEIDWorkingMode.UPWorkingMode;
|
||||||
|
|
||||||
|
ConfigurationDialogUserAssistant mUserAssistant =
|
||||||
|
new ConfigurationDialogUserAssistant();
|
||||||
|
|
||||||
|
IPlasticWebRestApi mRestApi;
|
||||||
|
WelcomeView mWelcomeView;
|
||||||
|
TextField mUserTextField;
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue