diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 1ff0c42..0000000 --- a/.gitattributes +++ /dev/null @@ -1,63 +0,0 @@ -############################################################################### -# Set default behavior to automatically normalize line endings. -############################################################################### -* text=auto - -############################################################################### -# Set default behavior for command prompt diff. -# -# This is need for earlier builds of msysgit that does not have it on by -# default for csharp files. -# Note: This is only used by command line -############################################################################### -#*.cs diff=csharp - -############################################################################### -# Set the merge driver for project and solution files -# -# Merging from the command prompt will add diff markers to the files if there -# are conflicts (Merging from VS is not affected by the settings below, in VS -# the diff markers are never inserted). Diff markers may cause the following -# file extensions to fail to load in VS. An alternative would be to treat -# these files as binary and thus will always conflict and require user -# intervention with every merge. To do so, just uncomment the entries below -############################################################################### -#*.sln merge=binary -#*.csproj merge=binary -#*.vbproj merge=binary -#*.vcxproj merge=binary -#*.vcproj merge=binary -#*.dbproj merge=binary -#*.fsproj merge=binary -#*.lsproj merge=binary -#*.wixproj merge=binary -#*.modelproj merge=binary -#*.sqlproj merge=binary -#*.wwaproj merge=binary - -############################################################################### -# behavior for image files -# -# image files are treated as binary by default. -############################################################################### -#*.jpg binary -#*.png binary -#*.gif binary - -############################################################################### -# diff behavior for common document formats -# -# Convert binary document formats to text before diffing them. This feature -# is only available from the command line. Turn it on by uncommenting the -# entries below. -############################################################################### -#*.doc diff=astextplain -#*.DOC diff=astextplain -#*.docx diff=astextplain -#*.DOCX diff=astextplain -#*.dot diff=astextplain -#*.DOT diff=astextplain -#*.pdf diff=astextplain -#*.PDF diff=astextplain -#*.rtf diff=astextplain -#*.RTF diff=astextplain diff --git a/.github/workflows/build-listing.yml b/.github/workflows/build-listing.yml new file mode 100644 index 0000000..1944c53 --- /dev/null +++ b/.github/workflows/build-listing.yml @@ -0,0 +1,78 @@ +name: Build Repo Listing + +env: + listPublishDirectory: Website + pathToCi: ci + +on: + workflow_dispatch: + workflow_run: + workflows: [Build Release] + types: + - completed + release: + types: [published, created, edited, unpublished, deleted, released] + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow one concurrent deployment +concurrency: + group: "pages" + cancel-in-progress: true + +jobs: + + # Build the VPM Listing Website and deploy to GitHub Pages + build-listing: + name: build-listing + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + + # Checkout Local Repository + - name: Checkout Local Repository + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac + + # Checkout Automation Repository without removing prior checkouts + - name: Checkout Automation Repository + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac + with: + repository: vrchat-community/package-list-action + path: ${{ env.pathToCi }} + clean: false + + # Load cached data from previous runs + - name: Restore Cache + uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 + with: + path: | + ${{ env.pathToCi }}/.nuke/temp + ~/.nuget/packages + key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj') }} + + # Build Package Version Listing with Nuke + - name: Build Package Version Listing + run: ${{ env.pathToCi }}/build.cmd BuildRepoListing --root ${{ env.pathToCi }} --list-publish-directory $GITHUB_WORKSPACE/${{ env.listPublishDirectory }} --current-package-name ${{ vars.PACKAGE_NAME }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Prepare for GitHub Pages deployment + - name: Setup Pages + uses: actions/configure-pages@f156874f8191504dae5b037505266ed5dda6c382 + + # Upload the VPM Listing Website to GitHub Pages artifacts + - name: Upload Pages Artifact + uses: actions/upload-pages-artifact@a753861a5debcf57bf8b404356158c8e1e33150c + with: + path: ${{ env.listPublishDirectory }} + + # Deploy the uploaded VPM Listing Website to GitHub Pages + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@9dbe3824824f8a1377b8e298bafde1a50ede43e5 \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..da57779 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,87 @@ +name: Build Release + +on: + workflow_dispatch: + +jobs: + + # Validate Repository Configuration + config: + runs-on: ubuntu-latest + outputs: + config_package: ${{ steps.config_package.outputs.configPackage }} + steps: + + # Ensure that required repository variable has been created for the Package + - name: Validate Package Config + id: config_package + run: | + if [ "${{ vars.PACKAGE_NAME }}" != "" ]; then + echo "configPackage=true" >> $GITHUB_OUTPUT; + else + echo "configPackage=false" >> $GITHUB_OUTPUT; + fi + + # Build and release the Package + # If the repository is not configured properly, this job will be skipped + build: + needs: config + runs-on: ubuntu-latest + permissions: + contents: write + env: + packagePath: Packages/${{ vars.PACKAGE_NAME }} + if: needs.config.outputs.config_package == 'true' + steps: + + # Checkout Local Repository + - name: Checkout + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac + + # Get the Package version based on the package.json file + - name: Get Version + id: version + uses: zoexx/github-action-json-file-properties@b9f36ce6ee6fe2680cd3c32b2c62e22eade7e590 + with: + file_path: "${{ env.packagePath }}/package.json" + prop_path: "version" + + # Configure the Environment Variables needed for releasing the Package + - name: Set Environment Variables + run: | + echo "zipFile=${{ vars.PACKAGE_NAME }}-${{ steps.version.outputs.value }}".zip >> $GITHUB_ENV + echo "unityPackage=${{ vars.PACKAGE_NAME }}-${{ steps.version.outputs.value }}.unitypackage" >> $GITHUB_ENV + echo "version=${{ steps.version.outputs.value }}" >> $GITHUB_ENV + + # Zip the Package for release + - name: Create Package Zip + working-directory: "${{ env.packagePath }}" + run: zip -r "${{ github.workspace }}/${{ env.zipFile }}" . + + # Build a list of .meta files for future use + - name: Track Package Meta Files + run: find "${{ env.packagePath }}/" -name \*.meta >> metaList + + # Make a UnityPackage version of the Package for release + - name: Create UnityPackage + uses: pCYSl5EDgo/create-unitypackage@cfcd3cf0391a5ef1306342794866a9897c32af0b + with: + package-path: ${{ env.unityPackage }} + include-files: metaList + + # Make a release tag of the version from the package.json file + - name: Create Tag + id: tag_version + uses: rickstaa/action-create-tag@88dbf7ff6fe2405f8e8f6c6fdfd78829bc631f83 + with: + tag: "${{ env.version }}" + + # Publish the Release to GitHub + - name: Make Release + uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 + with: + files: | + ${{ env.zipFile }} + ${{ env.unityPackage }} + ${{ env.packagePath }}/package.json + tag_name: ${{ env.version }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9491a2f..88cb423 100644 --- a/.gitignore +++ b/.gitignore @@ -1,363 +1,67 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Ww][Ii][Nn]32/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Oo]ut/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory +# This .gitignore file should be placed at the root of your Unity project directory +# +# Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore +# +/[Ll]ibrary/ +/[Tt]emp/ +/[Oo]bj/ +/[Bb]uild/ +/[Bb]uilds/ +/[Ll]ogs/ +/[Mm]emoryCaptures/ + +# Asset meta data should only be ignored when the corresponding asset is also ignored +!/[Aa]ssets/**/*.meta + +# Uncomment this line if you wish to ignore the asset store tools plugin +# /[Aa]ssets/AssetStoreTools* + +# Autogenerated Jetbrains Rider plugin +[Aa]ssets/Plugins/Editor/JetBrains* + +# Visual Studio cache directory .vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* +# Gradle cache directory +.gradle/ -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# ASP.NET Scaffolding -ScaffoldingReadMe.txt - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh +# Autogenerated VS/MD/Consulo solution and project files +ExportedObj/ +.consulo/ +*.csproj +*.unityproj +*.sln +*.suo *.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.vspscc -*.vssscc -.builds +*.user +*.userprefs *.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb +*.booproj +*.svd +*.pdb +*.mdb *.opendb -*.opensdf -*.sdf -*.cachefile *.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Coverlet is a free, cross platform Code Coverage Tool -coverage*.json -coverage*.xml -coverage*.info - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ -# Local History for Visual Studio -.localhistory/ +# Unity3D generated meta files +*.pidb.meta +*.pdb.meta +*.mdb.meta -# BeatPulse healthcheck temp database -healthchecksdb +# Unity3D generated file on crash reports +sysinfo.txt -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ +# Builds +*.apk +*.unitypackage -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ +# Crashlytics generated file +crashlytics-build.properties -# Fody - auto-generated XML schema -FodyWeavers.xsd \ No newline at end of file +.idea/.idea.vpm-package-maker/.idea +Assets/PackageMakerWindowData.asset* +Assets/AwtterInstalledPackages.json* +ProjectSettings +UserSettings +.idea +.vscode diff --git a/.vsconfig b/.vsconfig new file mode 100644 index 0000000..d70cd98 --- /dev/null +++ b/.vsconfig @@ -0,0 +1,6 @@ +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Workload.ManagedGame" + ] +} diff --git a/Assets/.gitkeep b/Assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/AwtterSDK.csproj b/AwtterSDK.csproj deleted file mode 100644 index 53cab84..0000000 --- a/AwtterSDK.csproj +++ /dev/null @@ -1,100 +0,0 @@ - - - - - Debug - AnyCPU - {20238743-A52D-4C81-A0BE-B91819CBCD03} - Library - Properties - AwtterSDK - AwtterSDK - v4.8 - 512 - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - ..\..\..\..\..\Program Files\Unity\Hub\Editor\2019.4.30f1\Editor\Data\Managed\UnityEditor.dll - - - ..\..\..\..\..\Program Files\Unity\Hub\Editor\2019.4.30f1\Editor\Data\Managed\UnityEngine\UnityEngine.dll - - - ..\..\..\..\..\Program Files\Unity\Hub\Editor\2019.4.30f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll - - - False - ..\..\..\..\..\Program Files\Unity\Hub\Editor\2019.4.30f1\Editor\Data\Managed\UnityEngine\UnityEngine.ImageConversionModule.dll - - - ..\..\..\..\..\Program Files\Unity\Hub\Editor\2019.4.30f1\Editor\Data\Managed\UnityEngine\UnityEngine.IMGUIModule.dll - - - False - ..\..\..\..\..\Program Files\Unity\Hub\Editor\2019.4.16f1\Editor\Data\Managed\UnityEngine\UnityEngine.JSONSerializeModule.dll - - - False - ..\..\..\..\..\Program Files\Unity\Hub\Editor\2019.4.30f1\Editor\Data\Managed\UnityEngine\UnityEngine.TextRenderingModule.dll - - - ..\..\..\..\..\Program Files\Unity\Hub\Editor\2019.4.30f1\Editor\Data\Managed\UnityEngine\UnityEngine.UIModule.dll - - - ..\..\..\..\..\Program Files\Unity\Hub\Editor\2019.4.30f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityWebRequestModule.dll - - - False - ..\..\..\..\..\Program Files\Unity\Hub\Editor\2019.4.30f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityWebRequestTextureModule.dll - - - ..\..\..\..\..\Program Files\Unity\Hub\Editor\2019.4.30f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityWebRequestWWWModule.dll - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/AwtterSDK.sln b/AwtterSDK.sln deleted file mode 100644 index a62283c..0000000 --- a/AwtterSDK.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32210.308 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AwtterSDK", "AwtterSDK.csproj", "{20238743-A52D-4C81-A0BE-B91819CBCD03}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {20238743-A52D-4C81-A0BE-B91819CBCD03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {20238743-A52D-4C81-A0BE-B91819CBCD03}.Debug|Any CPU.Build.0 = Debug|Any CPU - {20238743-A52D-4C81-A0BE-B91819CBCD03}.Release|Any CPU.ActiveCfg = Release|Any CPU - {20238743-A52D-4C81-A0BE-B91819CBCD03}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {8537716D-1DFC-4BB2-8720-189451B16E31} - EndGlobalSection -EndGlobal diff --git a/Editor/AssetsTreeView/AssetElement.cs b/Editor/AssetsTreeView/AssetElement.cs deleted file mode 100644 index 799c2b0..0000000 --- a/Editor/AssetsTreeView/AssetElement.cs +++ /dev/null @@ -1,21 +0,0 @@ -using AwtterSDK.Editor.Enums; -using System; -using UnityEditor.TreeViewExamples; - -namespace AwtterSDK.Editor.AssetsTreeView -{ - [Serializable] - internal class AssetElement : TreeElement - { - public string Name { get; set; } - public PackageStatus Status { get; set; } = PackageStatus.None; - public string Version { get; set; } = "-"; - public string Icon { get; set; } - - public AssetElement(string name, string icon, int depth, int id) : base(name, depth, id) - { - Name = name; - Icon = icon; - } - } -} diff --git a/Editor/AssetsTreeView/AssetsView.cs b/Editor/AssetsTreeView/AssetsView.cs deleted file mode 100644 index be36a48..0000000 --- a/Editor/AssetsTreeView/AssetsView.cs +++ /dev/null @@ -1,206 +0,0 @@ -using AwtterSDK.Editor.Enums; -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor; -using UnityEditor.IMGUI.Controls; -using UnityEditor.TreeViewExamples; -using UnityEngine; -using UnityEngine.Networking; - -namespace AwtterSDK.Editor.AssetsTreeView -{ - internal class AssetsView : TreeViewWithTreeModel - { - const float kRowHeights = 20f; - const float kToggleWidth = 18f; - public bool showControls = true; - - - enum MyColumns - { - Icon, - Name, - Status, - Version - } - - public static void TreeToList(TreeViewItem root, IList result) - { - if (root == null) - throw new NullReferenceException("root"); - if (result == null) - throw new NullReferenceException("result"); - - result.Clear(); - - if (root.children == null) - return; - - Stack stack = new Stack(); - for (int i = root.children.Count - 1; i >= 0; i--) - stack.Push(root.children[i]); - - while (stack.Count > 0) - { - TreeViewItem current = stack.Pop(); - result.Add(current); - - if (current.hasChildren && current.children[0] != null) - { - for (int i = current.children.Count - 1; i >= 0; i--) - { - stack.Push(current.children[i]); - } - } - } - } - - public AssetsView(TreeViewState state, MultiColumnHeader multicolumnHeader, TreeModel model) : base(state, multicolumnHeader, model) - { - // Custom setup - extraSpaceBeforeIconAndLabel = 0f; - rowHeight = kRowHeights; - columnIndexForTreeFoldouts = 2; - showAlternatingRowBackgrounds = true; - customFoldoutYOffset = (kRowHeights - EditorGUIUtility.singleLineHeight) * 0.5f; // center foldout in the row since we also center content. See RowGUI - showBorder = true; - Reload(); - } - - - protected override bool CanStartDrag(CanStartDragArgs args) => false; - - // Note we We only build the visible rows, only the backend has the full tree information. - // The treeview only creates info for the row list. - protected override IList BuildRows(TreeViewItem root) - { - var rows = base.BuildRows(root); - return rows; - } - - int GetIcon1Index(TreeViewItem item) => 0; - - protected override void RowGUI(RowGUIArgs args) - { - var item = (TreeViewItem)args.item; - - for (int i = 0; i < args.GetNumVisibleColumns(); ++i) - { - CellGUI(args.GetCellRect(i), item, (MyColumns)args.GetColumn(i), ref args); - } - } - - - void CellGUI(Rect cellRect, TreeViewItem item, MyColumns column, ref RowGUIArgs args) - { - CenterRectUsingSingleLineHeight(ref cellRect); - switch (column) - { - case MyColumns.Icon: - { - GUI.DrawTexture(cellRect, AwtterSdkInstaller.GetTextureOrDownload(item.data.Icon), ScaleMode.ScaleToFit); - } - break; - case MyColumns.Name: - { - args.label = item.data.name; - args.rowRect = cellRect; - base.RowGUI(args); - } - break; - case MyColumns.Status: - { - args.rowRect = cellRect; - var defColor = GUI.color; - Rect statusRect = cellRect; - cellRect.x += 25f; - - switch (item.data.Status) - { - case PackageStatus.None: - case PackageStatus.NotInstalled: - statusRect.width = 25f; - GUI.color = Color.red; - EditorGUI.LabelField(statusRect, "❌"); - GUI.color = defColor; - EditorGUI.LabelField(cellRect, " Not Installed"); - break; - case PackageStatus.Installed: - statusRect.width = 25f; - GUI.color = Color.green; - EditorGUI.LabelField(statusRect, "✔️"); - GUI.color = defColor; - EditorGUI.LabelField(cellRect, " Installed"); - break; - } - } - break; - case MyColumns.Version: - { - EditorGUI.LabelField(cellRect, item.data.Version); - } - break; - } - } - - public static MultiColumnHeaderState CreateDefaultMultiColumnHeaderState(float treeViewWidth) - { - var columns = new[] - { - new MultiColumnHeaderState.Column - { - headerContent = new GUIContent(EditorGUIUtility.FindTexture("FilterByLabel"), "Icon"), - contextMenuText = "Icon", - headerTextAlignment = TextAlignment.Center, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Right, - width = 30, - minWidth = 30, - maxWidth = 30, - autoResize = false, - allowToggleVisibility = true, - canSort = false, - }, - new MultiColumnHeaderState.Column - { - headerContent = new GUIContent("Name"), - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 150, - minWidth = 60, - autoResize = false, - allowToggleVisibility = false - }, - new MultiColumnHeaderState.Column - { - headerContent = new GUIContent("Status"), - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Left, - width = 150, - minWidth = 60, - autoResize = false, - allowToggleVisibility = false, - canSort = false, - }, - new MultiColumnHeaderState.Column - { - headerContent = new GUIContent("Version"), - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Left, - width = 150, - minWidth = 60, - autoResize = false, - allowToggleVisibility = false, - canSort = false, - }, - }; - - var state = new MultiColumnHeaderState(columns); - return state; - } - } -} diff --git a/Editor/AwtterSdkInstaller.cs b/Editor/AwtterSdkInstaller.cs deleted file mode 100644 index f6e2805..0000000 --- a/Editor/AwtterSdkInstaller.cs +++ /dev/null @@ -1,485 +0,0 @@ -using System; -using System.IO; - -using UnityEditor; - -using UnityEngine; -using UnityEngine.Networking; - -using AwtterSDK.Editor.Enums; -using UnityEditor.IMGUI.Controls; -using UnityEditor.TreeViewExamples; -using System.Collections.Generic; -using AwtterSDK.Editor.Models; -using AwtterSDK.Editor.Interfaces; -using AwtterSDK.Editor.Installations; -using System.Net; -using AwtterSDK.Editor.AssetsTreeView; -using System.Linq; - -namespace AwtterSDK -{ - class AwtterSdkAssets : AssetPostprocessor - { - static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) - { - AwtterSdkInstaller.CheckPackages = true; - } - } - - public class AwtterSdkInstaller : EditorWindow - { - public static bool LoggedIn; - public static bool BaseInstalled; - public static int BaseType; - - public static Texture DefaultTexture; - public static Queue TexturesToDownload = new Queue(); - public static Dictionary CachedTextures = new Dictionary(); - - public static bool CheckPackages = true; - static AwtterSdkInstaller _window; - - [NonSerialized] bool m_Initialized; - [SerializeField] TreeViewState m_TreeViewState; - [SerializeField] MultiColumnHeaderState m_MultiColumnHeaderState; - AssetsView m_TreeView; - - Dictionary _installationCheckers = new Dictionary() - { - { "vrcsdk", new VrcSdkInstallation() }, - { "poiyomi", new PoyomiInstallation() }, - { "basemodel", new BaseInstallation() }, - }; - - DownloadableContent _downloadableContent = null; - DownloadableContent _downloadableContentTemplate = new DownloadableContent() - { - Models = new List() - { - new BaseModel() - { - Name = "Awtter", - ShortName = "awtter", - Version = "2.9.42", - IconLink = "https://shadedoes3d.com/static/core/img/thumb/Otter.jpg", - DownloadLink = "file:///C:/Users/Kille/Desktop/Awtter_v2.9.42_Unity.unitypackage", - Dependencies = new string[] { "vrcsdk", "poiyomi" }, - AvaliableDLC = new List() - { - new DLC() - { - Name = "Test DLC", - DownloadLink = "", - IconLink = "https://upload.wikimedia.org/wikipedia/commons/6/6d/Windows_Settings_app_icon.png", - Dependencies = new string [] { "vrcsdk", "poiyomi", "awtter" } - } - } - }, - new BaseModel() - { - Name = "Awdeer", - ShortName = "awdeer", - Version = "2.9.42", - IconLink = "https://shadedoes3d.com/static/core/img/thumb/Otter.jpg", - DownloadLink = "file:///C:/Users/Kille/Desktop/Awtter_v2.9.42_Unity.unitypackage", - Dependencies = new string[] { "vrcsdk", "poiyomi" }, - AvaliableDLC = new List() - { - new DLC() - { - Name = "Test DLC", - DownloadLink = "", - Dependencies = new string [] { "vrcsdk", "poiyomi", "awdeer" } - } - } - } - }, - Packages = new List() - { - new Package() - { - Name = "VRC SDK", - ShortName = "vrcsdk", - Version = "2022.02.16.19.13", - AutoDetect = true, - IconLink = "https://cdn.discordapp.com/attachments/939894161472102462/953747349866434610/o8smnmp6erp21.png", - DownloadLink = "https://files.vrchat.cloud/sdk/VRCSDK3-AVATAR-2022.02.16.19.13_Public.unitypackage", - }, - new Package() - { - Name = "Poiyomi Toon Shader", - ShortName = "poiyomi", - Version = "7.3.850", - IconLink = "https://cdn.discordapp.com/attachments/939894161472102462/953738819566456922/8877018.png", - DownloadLink = "https://github.com/poiyomi/PoiyomiToonShader/releases/download/V7.3.050/PoiyomiToon7.3.050.unitypackage" - } - } - }; - - - [MenuItem("Awtter SDK/Open Installer")] - static void Init() - { - //_window = (AwtterSdkInstaller)EditorWindow.GetWindowWithRect(typeof(AwtterSdkInstaller), new Rect(0, 0, 525, 248), false, "Awtter SDK | Installer"); - _window = (AwtterSdkInstaller)EditorWindow.GetWindow(typeof(AwtterSdkInstaller), false, "Awtter SDK | Installer"); - _window.Show(); - CheckPackages = true; - } - - internal List CreateView() - { - if (_downloadableContent == null) return new List(); - - List elements = new List() - { - new AssetElement(string.Empty, string.Empty, -1, 0), - new AssetElement("Base Models", string.Empty, 0, 1), - }; - - int id = 1; - - for (int x = 0; x < _downloadableContent.Models.Count; x++) - { - id++; - elements.Add(new AssetElement(_downloadableContent.Models[x].Name, _downloadableContent.Models[x].IconLink, 1, id)); - _downloadableContent.Models[x].ViewID = elements.Count - 1; - - id++; - elements.Add(new AssetElement("DLCS", "", 2, id)); - for (int y = 0; y < _downloadableContent.Models[x].AvaliableDLC.Count; y++) - { - id++; - elements.Add(new AssetElement(_downloadableContent.Models[x].AvaliableDLC[y].Name, _downloadableContent.Models[x].AvaliableDLC[y].IconLink, 3, id)); - _downloadableContent.Models[x].AvaliableDLC[y].ViewID = elements.Count - 1; - } - } - id++; - - elements.Add(new AssetElement("Packages", "", 0, id)); - for (int x = 0; x < _downloadableContent.Packages.Count; x++) - { - id++; - elements.Add(new AssetElement(_downloadableContent.Packages[x].Name, _downloadableContent.Packages[x].IconLink, 1, id)); - _downloadableContent.Packages[x].ViewID = elements.Count - 1; - } - return elements; - } - - public static Texture GetTextureOrDownload(string url) - { - if (DefaultTexture == null) DefaultTexture = EditorGUIUtility.FindTexture("Folder Icon"); - if (string.IsNullOrEmpty(url)) return DefaultTexture; - - if (!CachedTextures.ContainsKey(url)) - { - CachedTextures.Add(url, null); - AwtterSdkInstaller.TexturesToDownload.Enqueue(url); - } - - return CachedTextures[url] ?? DefaultTexture; - } - - void InitIfNeeded() - { - if (!m_Initialized) - { - if (m_TreeViewState == null) - m_TreeViewState = new TreeViewState(); - - bool firstInit = m_MultiColumnHeaderState == null; - var headerState = AssetsView.CreateDefaultMultiColumnHeaderState(100); - if (MultiColumnHeaderState.CanOverwriteSerializedFields(m_MultiColumnHeaderState, headerState)) - MultiColumnHeaderState.OverwriteSerializedFields(m_MultiColumnHeaderState, headerState); - m_MultiColumnHeaderState = headerState; - - var multiColumnHeader = new MyMultiColumnHeader(headerState); - if (firstInit) - multiColumnHeader.ResizeToFit(); - - var treeModel = new TreeModel(CreateView()); - - m_TreeView = new AssetsView(m_TreeViewState, multiColumnHeader, treeModel); - m_Initialized = true; - } - } - - void CheckInstalledPackages() - { - _installationCheckers["basemodel"].Check(); - for(int x = 0; x < _downloadableContent.Models.Count; x++) - { - bool modelInstalled = _installationCheckers["basemodel"].IsInstalled && _installationCheckers["basemodel"].TypeInstalled == _downloadableContent.Models[x].ShortName; - - if (modelInstalled) - { - BaseInstalled = true; - BaseType = x; - } - - m_TreeView.treeModel.m_Data[_downloadableContent.Models[x].ViewID].Status = modelInstalled ? PackageStatus.Installed : PackageStatus.NotInstalled; - m_TreeView.treeModel.m_Data[_downloadableContent.Models[x].ViewID].Version = modelInstalled ? _installationCheckers["basemodel"].InstalledVersion ?? "-" : "-"; - } - - foreach (var package in _downloadableContent.Packages) - { - if (_installationCheckers.TryGetValue(package.ShortName, out ICheckInstallStatus installStatus)) - { - installStatus.Check(); - m_TreeView.treeModel.m_Data[package.ViewID].Status = installStatus.IsInstalled ? PackageStatus.Installed : PackageStatus.NotInstalled; - m_TreeView.treeModel.m_Data[package.ViewID].Version = installStatus.InstalledVersion ?? "-"; - } - } - - CheckPackages = false; - } - - string username, password; - - void Login() - { - if (!File.Exists("Assets/downloadableContent.json")) - File.WriteAllText("Assets/downloadableContent.json", JsonUtility.ToJson(_downloadableContentTemplate, true)); - - _downloadableContent = JsonUtility.FromJson(File.ReadAllText("Assets/downloadableContent.json")); - LoggedIn = true; - } - - void Logout() - { - LoggedIn = false; - } - - void OnGUI() - { - if (!LoggedIn) - { - GUILayout.Space(150); - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - GUILayout.BeginVertical("Account", "window", GUILayout.Height(120), GUILayout.Width(300)); - GUI.enabled = false; - username = EditorGUILayout.TextField("Email", username); - password = EditorGUILayout.PasswordField("Password", password); - GUI.enabled = true; - if (GUILayout.Button("Login")) Login(); - if (GUILayout.Button("Register")) Application.OpenURL("https://shadedoes3d.com"); - GUILayout.EndVertical(); - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - return; - } - - if (TexturesToDownload.Count != 0) - { - var link = TexturesToDownload.Dequeue(); - - using (WebClient client = new WebClient()) - { - byte[] data = client.DownloadData(link); - Texture2D tex = new Texture2D(2, 2); - tex.LoadImage(data); - - CachedTextures[link] = tex; - } - } - InitIfNeeded(); - if (CheckPackages) CheckInstalledPackages(); - TopToolBar(toolbarRect); - m_TreeView.OnGUI(packagesTreeViewRect); - BottomToolBar(bottomToolbarRect); - } - - void TopToolBar(Rect rect) - { - GUILayout.BeginArea(rect); - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Logout")) Logout(); - EditorGUILayout.EndHorizontal(); - CreateBox("Installed assets"); - GUILayout.EndArea(); - } - - void BottomToolBar(Rect rect) - { - GUILayout.BeginArea(rect); - if (BaseInstalled) - { - CreateBox("Install DLCS"); - for(int x = 0; x < _downloadableContent.Models[BaseType].AvaliableDLC.Count; x++) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField(_downloadableContent.Models[BaseType].AvaliableDLC[x].Name); - GUILayout.FlexibleSpace(); - _downloadableContent.Models[BaseType].AvaliableDLC[x].Install = EditorGUILayout.Toggle(_downloadableContent.Models[BaseType].AvaliableDLC[x].Install); - EditorGUILayout.EndHorizontal(); - } - } - else - { - CreateBox("Installation options"); - BaseType = EditorGUILayout.Popup("Model base", BaseType, _downloadableContent.Models.Select(x => x.Name).ToArray()); - EditorGUILayout.BeginHorizontal(); - - EditorGUILayout.BeginVertical(); - CreateBox("Base"); - GUILayout.Label($"Name {_downloadableContent.Models[BaseType].Name}"); - EditorGUILayout.EndVertical(); - - EditorGUILayout.BeginVertical(); - CreateBox("Avaliable DLCS"); - for (int x = 0; x < _downloadableContent.Models[BaseType].AvaliableDLC.Count; x++) - { - EditorGUILayout.BeginHorizontal(); - GUILayout.Label(_downloadableContent.Models[BaseType].AvaliableDLC[x].Name); - GUILayout.FlexibleSpace(); - _downloadableContent.Models[BaseType].AvaliableDLC[x].Install = EditorGUILayout.Toggle(_downloadableContent.Models[BaseType].AvaliableDLC[x].Install); - EditorGUILayout.EndHorizontal(); - } - EditorGUILayout.EndVertical(); - EditorGUILayout.EndHorizontal(); - } - - if (GUILayout.Button("Install")) - { - foreach(var dependency in _downloadableContent.Models[BaseType].Dependencies) - { - if (_installationCheckers.TryGetValue(dependency, out ICheckInstallStatus status) && !status.IsInstalled) - { - var missingDependency = _downloadableContent.Packages.FirstOrDefault(p => p.ShortName == dependency); - if (missingDependency == null) - { - Debug.LogError($"Not found {dependency} dependency for base {_downloadableContent.Models[BaseType].Name}."); - } - else - { - DownloadFile(missingDependency.DownloadLink, $"Downloading file", $"Downloading {dependency}..."); - } - } - } - if (!BaseInstalled) DownloadFile(_downloadableContent.Models[BaseType].DownloadLink, "Downloading file", $"Downloading base model {_downloadableContent.Models[BaseType].Name}..."); - } - - - GUI.enabled = true; - GUILayout.EndArea(); - } - - void CreateBox(string text, bool flexible = true) - { - EditorGUILayout.BeginHorizontal("box"); - if (flexible) GUILayout.FlexibleSpace(); - GUILayout.Label(text, EditorStyles.boldLabel); - if (flexible) GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - } - - void DownloadFile(string url, string progressTitle, string progressInfo) - { - string fileName = Path.GetFileName(url); - - UnityWebRequest www = new UnityWebRequest(url); - www.downloadHandler = new DownloadHandlerBuffer(); - AsyncOperation request = www.SendWebRequest(); - - while (!request.isDone) - { - EditorUtility.DisplayProgressBar(progressTitle, progressInfo, www.downloadProgress); - } - - EditorUtility.ClearProgressBar(); - if (www.error == null) - { - File.WriteAllBytes(Path.Combine("Assets", fileName), www.downloadHandler.data); - - AssetDatabase.ImportPackage(Path.Combine("Assets", fileName), false); - AssetDatabase.DeleteAsset(Path.Combine("Assets", fileName)); - } - else - { - Debug.Log(www.error); - } - } - - Rect toolbarRect - { - get { return new Rect(0f, 0f, position.width, 25f); } - } - - Rect packagesTreeViewRect - { - get { return new Rect(0f, 30f, position.width, 140f); } - } - - Rect bottomToolbarRect - { - get { return new Rect(0f, 175f, position.width, position.height - 160f); } - } - } - - internal class MyMultiColumnHeader : MultiColumnHeader - { - Mode m_Mode; - - public enum Mode - { - LargeHeader, - DefaultHeader, - MinimumHeaderWithoutSorting - } - - public MyMultiColumnHeader(MultiColumnHeaderState state) - : base(state) - { - mode = Mode.DefaultHeader; - } - - public Mode mode - { - get - { - return m_Mode; - } - set - { - m_Mode = value; - switch (m_Mode) - { - case Mode.LargeHeader: - canSort = true; - height = 37f; - break; - case Mode.DefaultHeader: - canSort = true; - height = DefaultGUI.defaultHeight; - break; - case Mode.MinimumHeaderWithoutSorting: - canSort = false; - height = DefaultGUI.minimumHeight; - break; - } - } - } - - protected override void ColumnHeaderGUI(MultiColumnHeaderState.Column column, Rect headerRect, int columnIndex) - { - // Default column header gui - base.ColumnHeaderGUI(column, headerRect, columnIndex); - - // Add additional info for large header - if (mode == Mode.LargeHeader) - { - // Show example overlay stuff on some of the columns - if (columnIndex > 2) - { - headerRect.xMax -= 3f; - var oldAlignment = EditorStyles.largeLabel.alignment; - EditorStyles.largeLabel.alignment = TextAnchor.UpperRight; - GUI.Label(headerRect, 36 + columnIndex + "%", EditorStyles.largeLabel); - EditorStyles.largeLabel.alignment = oldAlignment; - } - } - } - } -} diff --git a/Editor/Installations/BaseInstallation.cs b/Editor/Installations/BaseInstallation.cs deleted file mode 100644 index 14ba105..0000000 --- a/Editor/Installations/BaseInstallation.cs +++ /dev/null @@ -1,37 +0,0 @@ -using AwtterSDK.Editor.Interfaces; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace AwtterSDK.Editor.Installations -{ - internal class BaseInstallation : ICheckInstallStatus - { - bool _isInstalled; - string _installedVersion; - string _typeInstalled; - public bool IsInstalled => _isInstalled; - public string InstalledVersion => _installedVersion; - public string TypeInstalled => _typeInstalled; - - public void Check() - { - _isInstalled = Directory.Exists("Assets/1) Model (fbx)"); - if (_isInstalled) - { - foreach (var file in new DirectoryInfo("Assets/1) Model (fbx)").GetFiles("*.fbx")) - { - var sp = file.Name.Split(' '); - _typeInstalled = file.Name.ToLower().Contains("awtter") ? "awtter" : "awdeer"; - _installedVersion = sp.FirstOrDefault(p => p.Contains(".")); - break; - } - } - else - _installedVersion = null; - } - } -} diff --git a/Editor/Installations/DlcInstallation.cs b/Editor/Installations/DlcInstallation.cs deleted file mode 100644 index bac5932..0000000 --- a/Editor/Installations/DlcInstallation.cs +++ /dev/null @@ -1,43 +0,0 @@ -using AwtterSDK.Editor.Interfaces; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace AwtterSDK.Editor.Installations -{ - internal class DlcInstallation : ICheckInstallStatus - { - bool _isInstalled; - string _installedVersion; - string _typeInstalled; - string _path; - public bool IsInstalled => _isInstalled; - public string InstalledVersion => _installedVersion; - public string TypeInstalled => _typeInstalled; - - public DlcInstallation(string path) - { - _path = path; - } - - public void Check() - { - _isInstalled = Directory.Exists(_path); - if (_isInstalled) - { - foreach (var file in new DirectoryInfo(_path).GetFiles("*.fbx")) - { - var sp = file.Name.Split(' '); - _typeInstalled = file.Name.ToLower().Contains("awtter") ? "awtter" : "awdeer"; - _installedVersion = sp.FirstOrDefault(p => p.Contains(".")); - break; - } - } - else - _installedVersion = null; - } - } -} diff --git a/Editor/Installations/PoyomiInstallation.cs b/Editor/Installations/PoyomiInstallation.cs deleted file mode 100644 index 98745db..0000000 --- a/Editor/Installations/PoyomiInstallation.cs +++ /dev/null @@ -1,40 +0,0 @@ -using AwtterSDK.Editor.Interfaces; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace AwtterSDK.Editor.Installations -{ - internal class PoyomiInstallation : ICheckInstallStatus - { - bool _isInstalled; - string _installedVersion; - public bool IsInstalled => _isInstalled; - public string InstalledVersion => _installedVersion; - public string TypeInstalled => null; - - public void Check() - { - _isInstalled = Directory.Exists("Assets/_PoiyomiShaders"); - if (_isInstalled) - { - if (File.Exists("Assets/_PoiyomiShaders/Shaders/Pro/Shaders/S_Poiyomi_Toon.shader")) - { - var content = File.ReadAllLines("Assets/_PoiyomiShaders/Shaders/Pro/Shaders/S_Poiyomi_Toon.shader"); - var versionLine = content.FirstOrDefault(p => p.Contains("shader_master_label")); - if (versionLine != null) - { - var line = versionLine.Split('(', ')')[1]; - var sLine = line.Split(' ').FirstOrDefault(p => p.Contains("V")); - _installedVersion = sLine.Substring(1, sLine.IndexOf('<') - 1); - } - } - } - else - _installedVersion = null; - } - } -} diff --git a/Editor/Installations/VrcSdkInstallation.cs b/Editor/Installations/VrcSdkInstallation.cs deleted file mode 100644 index 1028ebe..0000000 --- a/Editor/Installations/VrcSdkInstallation.cs +++ /dev/null @@ -1,28 +0,0 @@ -using AwtterSDK.Editor.Interfaces; -using AwtterSDK.Editor.Models; -using System; -using System.IO; - -namespace AwtterSDK.Editor.Installations -{ - internal class VrcSdkInstallation : ICheckInstallStatus - { - bool _isInstalled; - string _installedVersion; - public bool IsInstalled => _isInstalled; - public string InstalledVersion => _installedVersion; - public string TypeInstalled => null; - - public void Check() - { - _isInstalled = Directory.Exists("Assets/VRCSDK"); - if (_isInstalled) - { - if (File.Exists("Assets/VRCSDK/version.txt")) - _installedVersion = File.ReadAllText("Assets/VRCSDK/version.txt"); - } - else - _installedVersion = null; - } - } -} diff --git a/Editor/Models/BaseModel.cs b/Editor/Models/BaseModel.cs deleted file mode 100644 index 8088475..0000000 --- a/Editor/Models/BaseModel.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace AwtterSDK.Editor.Models -{ - [Serializable] - internal class BaseModel - { - [NonSerialized] - public int ViewID; - [NonSerialized] - public bool Install; - public string Name; - public string ShortName; - public string Version; - public string IconLink; - public string DownloadLink; - public string[] Dependencies = new string[0]; - public List AvaliableDLC = new List(); - } -} diff --git a/Editor/Models/DLC.cs b/Editor/Models/DLC.cs deleted file mode 100644 index 3820df4..0000000 --- a/Editor/Models/DLC.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace AwtterSDK.Editor.Models -{ - [Serializable] - internal class DLC - { - [NonSerialized] - public int ViewID; - [NonSerialized] - public bool Install; - public string Name; - public string Version; - public string IconLink; - public string DownloadLink; - public string[] Dependencies = new string[0]; - } -} diff --git a/Editor/Models/DownloadableContent.cs b/Editor/Models/DownloadableContent.cs deleted file mode 100644 index 600328b..0000000 --- a/Editor/Models/DownloadableContent.cs +++ /dev/null @@ -1,13 +0,0 @@ -using AwtterSDK.Editor.Enums; -using System; -using System.Collections.Generic; - -namespace AwtterSDK.Editor.Models -{ - [Serializable] - internal class DownloadableContent - { - public List Models = new List(); - public List Packages = new List(); - } -} diff --git a/Editor/Models/Package.cs b/Editor/Models/Package.cs deleted file mode 100644 index 4e50994..0000000 --- a/Editor/Models/Package.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; - -namespace AwtterSDK.Editor.Models -{ - [Serializable] - public class Package - { - [NonSerialized] - public int ViewID; - [NonSerialized] - public bool Install; - public string Name; - public string ShortName; - public string IconLink; - public string Version; - public bool AutoDetect = true; - public string DownloadLink; - } -} diff --git a/Editor/TreeDataModel/TreeElement.cs b/Editor/TreeDataModel/TreeElement.cs deleted file mode 100644 index df11a15..0000000 --- a/Editor/TreeDataModel/TreeElement.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using UnityEngine; - - -namespace UnityEditor.TreeViewExamples -{ - - [Serializable] - public class TreeElement - { - [SerializeField] int m_ID; - [SerializeField] string m_Name; - [SerializeField] int m_Depth; - [NonSerialized] TreeElement m_Parent; - [NonSerialized] List m_Children = new List(); - - public int depth - { - get { return m_Depth; } - set { m_Depth = value; } - } - - public TreeElement parent - { - get { return m_Parent; } - set { m_Parent = value; } - } - - public List children - { - get { return m_Children; } - set { m_Children = value; } - } - - public bool hasChildren - { - get { return children != null && children.Count > 0; } - } - - public string name - { - get { return m_Name; } set { m_Name = value; } - } - - public int id - { - get { return m_ID; } set { m_ID = value; } - } - - public TreeElement () - { - } - - public TreeElement (string name, int depth, int id) - { - m_Name = name; - m_ID = id; - m_Depth = depth; - } - } - -} - - diff --git a/Editor/TreeDataModel/TreeElementUtility.cs b/Editor/TreeDataModel/TreeElementUtility.cs deleted file mode 100644 index 3ee77f5..0000000 --- a/Editor/TreeDataModel/TreeElementUtility.cs +++ /dev/null @@ -1,172 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - - -namespace UnityEditor.TreeViewExamples -{ - - // TreeElementUtility and TreeElement are useful helper classes for backend tree data structures. - // See tests at the bottom for examples of how to use. - - public static class TreeElementUtility - { - public static void TreeToList(T root, IList result) where T : TreeElement - { - if (result == null) - throw new NullReferenceException("The input 'IList result' list is null"); - result.Clear(); - - Stack stack = new Stack(); - stack.Push(root); - - while (stack.Count > 0) - { - T current = stack.Pop(); - result.Add(current); - - if (current.children != null && current.children.Count > 0) - { - for (int i = current.children.Count - 1; i >= 0; i--) - { - stack.Push((T)current.children[i]); - } - } - } - } - - // Returns the root of the tree parsed from the list (always the first element). - // Important: the first item and is required to have a depth value of -1. - // The rest of the items should have depth >= 0. - public static T ListToTree(IList list) where T : TreeElement - { - // Validate input - ValidateDepthValues (list); - - // Clear old states - foreach (var element in list) - { - element.parent = null; - element.children = null; - } - - // Set child and parent references using depth info - for (int parentIndex = 0; parentIndex < list.Count; parentIndex++) - { - var parent = list[parentIndex]; - bool alreadyHasValidChildren = parent.children != null; - if (alreadyHasValidChildren) - continue; - - int parentDepth = parent.depth; - int childCount = 0; - - // Count children based depth value, we are looking at children until it's the same depth as this object - for (int i = parentIndex + 1; i < list.Count; i++) - { - if (list[i].depth == parentDepth + 1) - childCount++; - if (list[i].depth <= parentDepth) - break; - } - - // Fill child array - List childList = null; - if (childCount != 0) - { - childList = new List(childCount); // Allocate once - childCount = 0; - for (int i = parentIndex + 1; i < list.Count; i++) - { - if (list[i].depth == parentDepth + 1) - { - list[i].parent = parent; - childList.Add(list[i]); - childCount++; - } - - if (list[i].depth <= parentDepth) - break; - } - } - - parent.children = childList; - } - - return list[0]; - } - - // Check state of input list - public static void ValidateDepthValues(IList list) where T : TreeElement - { - if (list.Count == 0) - throw new ArgumentException("list should have items, count is 0, check before calling ValidateDepthValues", "list"); - - if (list[0].depth != -1) - throw new ArgumentException("list item at index 0 should have a depth of -1 (since this should be the hidden root of the tree). Depth is: " + list[0].depth, "list"); - - for (int i = 0; i < list.Count - 1; i++) - { - int depth = list[i].depth; - int nextDepth = list[i + 1].depth; - if (nextDepth > depth && nextDepth - depth > 1) - throw new ArgumentException(string.Format("Invalid depth info in input list. Depth cannot increase more than 1 per row. Index {0} has depth {1} while index {2} has depth {3}", i, depth, i + 1, nextDepth)); - } - - for (int i = 1; i < list.Count; ++i) - if (list[i].depth < 0) - throw new ArgumentException("Invalid depth value for item at index " + i + ". Only the first item (the root) should have depth below 0."); - - if (list.Count > 1 && list[1].depth != 0) - throw new ArgumentException("Input list item at index 1 is assumed to have a depth of 0", "list"); - } - - - // For updating depth values below any given element e.g after reparenting elements - public static void UpdateDepthValues(T root) where T : TreeElement - { - if (root == null) - throw new ArgumentNullException("root", "The root is null"); - - if (!root.hasChildren) - return; - - Stack stack = new Stack(); - stack.Push(root); - while (stack.Count > 0) - { - TreeElement current = stack.Pop(); - if (current.children != null) - { - foreach (var child in current.children) - { - child.depth = current.depth + 1; - stack.Push(child); - } - } - } - } - - // Returns true if there is an ancestor of child in the elements list - static bool IsChildOf(T child, IList elements) where T : TreeElement - { - while (child != null) - { - child = (T)child.parent; - if (elements.Contains(child)) - return true; - } - return false; - } - - public static IList FindCommonAncestorsWithinList(IList elements) where T : TreeElement - { - if (elements.Count == 1) - return new List(elements); - - List result = new List(elements); - result.RemoveAll(g => IsChildOf(g, elements)); - return result; - } - } -} diff --git a/Editor/TreeDataModel/TreeModel.cs b/Editor/TreeDataModel/TreeModel.cs deleted file mode 100644 index f9b9239..0000000 --- a/Editor/TreeDataModel/TreeModel.cs +++ /dev/null @@ -1,231 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - - -namespace UnityEditor.TreeViewExamples -{ - // The TreeModel is a utility class working on a list of serializable TreeElements where the order and the depth of each TreeElement define - // the tree structure. Note that the TreeModel itself is not serializable (in Unity we are currently limited to serializing lists/arrays) but the - // input list is. - // The tree representation (parent and children references) are then build internally using TreeElementUtility.ListToTree (using depth - // values of the elements). - // The first element of the input list is required to have depth == -1 (the hiddenroot) and the rest to have - // depth >= 0 (otherwise an exception will be thrown) - - public class TreeModel where T : TreeElement - { - public IList m_Data; - T m_Root; - int m_MaxID; - - public T root { get { return m_Root; } set { m_Root = value; } } - public event Action modelChanged; - public int numberOfDataElements - { - get { return m_Data.Count; } - } - - public TreeModel (IList data) - { - SetData (data); - } - - public T Find (int id) - { - return m_Data.FirstOrDefault (element => element.id == id); - } - - public void SetData (IList data) - { - Init (data); - } - - void Init (IList data) - { - if (data == null) - throw new ArgumentNullException("data", "Input data is null. Ensure input is a non-null list."); - - m_Data = data; - if (m_Data.Count > 0) - m_Root = TreeElementUtility.ListToTree(data); - - m_MaxID = m_Data.Max(e => e.id); - } - - public int GenerateUniqueID () - { - return ++m_MaxID; - } - - public IList GetAncestors (int id) - { - var parents = new List(); - TreeElement T = Find(id); - if (T != null) - { - while (T.parent != null) - { - parents.Add(T.parent.id); - T = T.parent; - } - } - return parents; - } - - public IList GetDescendantsThatHaveChildren (int id) - { - T searchFromThis = Find(id); - if (searchFromThis != null) - { - return GetParentsBelowStackBased(searchFromThis); - } - return new List(); - } - - IList GetParentsBelowStackBased(TreeElement searchFromThis) - { - Stack stack = new Stack(); - stack.Push(searchFromThis); - - var parentsBelow = new List(); - while (stack.Count > 0) - { - TreeElement current = stack.Pop(); - if (current.hasChildren) - { - parentsBelow.Add(current.id); - foreach (var T in current.children) - { - stack.Push(T); - } - } - } - - return parentsBelow; - } - - public void RemoveElements (IList elementIDs) - { - IList elements = m_Data.Where (element => elementIDs.Contains (element.id)).ToArray (); - RemoveElements (elements); - } - - public void RemoveElements (IList elements) - { - foreach (var element in elements) - if (element == m_Root) - throw new ArgumentException("It is not allowed to remove the root element"); - - var commonAncestors = TreeElementUtility.FindCommonAncestorsWithinList (elements); - - foreach (var element in commonAncestors) - { - element.parent.children.Remove (element); - element.parent = null; - } - - TreeElementUtility.TreeToList(m_Root, m_Data); - - Changed(); - } - - public void AddElements (IList elements, TreeElement parent, int insertPosition) - { - if (elements == null) - throw new ArgumentNullException("elements", "elements is null"); - if (elements.Count == 0) - throw new ArgumentNullException("elements", "elements Count is 0: nothing to add"); - if (parent == null) - throw new ArgumentNullException("parent", "parent is null"); - - if (parent.children == null) - parent.children = new List(); - - parent.children.InsertRange(insertPosition, elements.Cast ()); - foreach (var element in elements) - { - element.parent = parent; - element.depth = parent.depth + 1; - TreeElementUtility.UpdateDepthValues(element); - } - - TreeElementUtility.TreeToList(m_Root, m_Data); - - Changed(); - } - - public void AddRoot (T root) - { - if (root == null) - throw new ArgumentNullException("root", "root is null"); - - if (m_Data == null) - throw new InvalidOperationException("Internal Error: data list is null"); - - if (m_Data.Count != 0) - throw new InvalidOperationException("AddRoot is only allowed on empty data list"); - - root.id = GenerateUniqueID (); - root.depth = -1; - m_Data.Add (root); - } - - public void AddElement (T element, TreeElement parent, int insertPosition) - { - if (element == null) - throw new ArgumentNullException("element", "element is null"); - if (parent == null) - throw new ArgumentNullException("parent", "parent is null"); - - if (parent.children == null) - parent.children = new List (); - - parent.children.Insert (insertPosition, element); - element.parent = parent; - - TreeElementUtility.UpdateDepthValues(parent); - TreeElementUtility.TreeToList(m_Root, m_Data); - - Changed (); - } - - public void MoveElements(TreeElement parentElement, int insertionIndex, List elements) - { - if (insertionIndex < 0) - throw new ArgumentException("Invalid input: insertionIndex is -1, client needs to decide what index elements should be reparented at"); - - // Invalid reparenting input - if (parentElement == null) - return; - - // We are moving items so we adjust the insertion index to accomodate that any items above the insertion index is removed before inserting - if (insertionIndex > 0) - insertionIndex -= parentElement.children.GetRange(0, insertionIndex).Count(elements.Contains); - - // Remove draggedItems from their parents - foreach (var draggedItem in elements) - { - draggedItem.parent.children.Remove(draggedItem); // remove from old parent - draggedItem.parent = parentElement; // set new parent - } - - if (parentElement.children == null) - parentElement.children = new List(); - - // Insert dragged items under new parent - parentElement.children.InsertRange(insertionIndex, elements); - - TreeElementUtility.UpdateDepthValues (root); - TreeElementUtility.TreeToList (m_Root, m_Data); - - Changed (); - } - - public void Changed () - { - if (modelChanged != null) - modelChanged (); - } - } -} diff --git a/Editor/TreeDataModel/TreeViewWithTreeModel.cs b/Editor/TreeDataModel/TreeViewWithTreeModel.cs deleted file mode 100644 index c69143e..0000000 --- a/Editor/TreeDataModel/TreeViewWithTreeModel.cs +++ /dev/null @@ -1,241 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.IMGUI.Controls; -using UnityEngine; - - -namespace UnityEditor.TreeViewExamples -{ - - internal class TreeViewItem : TreeViewItem where T : TreeElement - { - public T data { get; set; } - - public TreeViewItem (int id, int depth, string displayName, T data) : base (id, depth, displayName) - { - this.data = data; - } - } - - internal class TreeViewWithTreeModel : TreeView where T : TreeElement - { - TreeModel m_TreeModel; - readonly List m_Rows = new List(100); - public event Action treeChanged; - - public TreeModel treeModel { get { return m_TreeModel; } } - public event Action> beforeDroppingDraggedItems; - - - public TreeViewWithTreeModel (TreeViewState state, TreeModel model) : base (state) - { - Init (model); - } - - public TreeViewWithTreeModel (TreeViewState state, MultiColumnHeader multiColumnHeader, TreeModel model) - : base(state, multiColumnHeader) - { - Init (model); - } - - void Init (TreeModel model) - { - m_TreeModel = model; - m_TreeModel.modelChanged += ModelChanged; - } - - void ModelChanged () - { - if (treeChanged != null) - treeChanged (); - - Reload (); - } - - protected override TreeViewItem BuildRoot() - { - int depthForHiddenRoot = -1; - return new TreeViewItem(m_TreeModel.root.id, depthForHiddenRoot, m_TreeModel.root.name, m_TreeModel.root); - } - - protected override IList BuildRows (TreeViewItem root) - { - if (m_TreeModel.root == null) - { - Debug.LogError ("tree model root is null. did you call SetData()?"); - } - - m_Rows.Clear (); - if (!string.IsNullOrEmpty(searchString)) - { - Search (m_TreeModel.root, searchString, m_Rows); - } - else - { - if (m_TreeModel.root.hasChildren) - AddChildrenRecursive(m_TreeModel.root, 0, m_Rows); - } - - // We still need to setup the child parent information for the rows since this - // information is used by the TreeView internal logic (navigation, dragging etc) - SetupParentsAndChildrenFromDepths (root, m_Rows); - - return m_Rows; - } - - void AddChildrenRecursive (T parent, int depth, IList newRows) - { - foreach (T child in parent.children) - { - var item = new TreeViewItem(child.id, depth, child.name, child); - newRows.Add(item); - - if (child.hasChildren) - { - if (IsExpanded(child.id)) - { - AddChildrenRecursive (child, depth + 1, newRows); - } - else - { - item.children = CreateChildListForCollapsedParent(); - } - } - } - } - - void Search(T searchFromThis, string search, List result) - { - if (string.IsNullOrEmpty(search)) - throw new ArgumentException("Invalid search: cannot be null or empty", "search"); - - const int kItemDepth = 0; // tree is flattened when searching - - Stack stack = new Stack(); - foreach (var element in searchFromThis.children) - stack.Push((T)element); - while (stack.Count > 0) - { - T current = stack.Pop(); - // Matches search? - if (current.name.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0) - { - result.Add(new TreeViewItem(current.id, kItemDepth, current.name, current)); - } - - if (current.children != null && current.children.Count > 0) - { - foreach (var element in current.children) - { - stack.Push((T)element); - } - } - } - SortSearchResult(result); - } - - protected virtual void SortSearchResult (List rows) - { - rows.Sort ((x,y) => EditorUtility.NaturalCompare (x.displayName, y.displayName)); // sort by displayName by default, can be overriden for multicolumn solutions - } - - protected override IList GetAncestors (int id) - { - return m_TreeModel.GetAncestors(id); - } - - protected override IList GetDescendantsThatHaveChildren (int id) - { - return m_TreeModel.GetDescendantsThatHaveChildren(id); - } - - - // Dragging - //----------- - - const string k_GenericDragID = "GenericDragColumnDragging"; - - protected override bool CanStartDrag (CanStartDragArgs args) - { - return true; - } - - protected override void SetupDragAndDrop(SetupDragAndDropArgs args) - { - if (hasSearch) - return; - - DragAndDrop.PrepareStartDrag(); - var draggedRows = GetRows().Where(item => args.draggedItemIDs.Contains(item.id)).ToList(); - DragAndDrop.SetGenericData(k_GenericDragID, draggedRows); - DragAndDrop.objectReferences = new UnityEngine.Object[] { }; // this IS required for dragging to work - string title = draggedRows.Count == 1 ? draggedRows[0].displayName : "< Multiple >"; - DragAndDrop.StartDrag (title); - } - - protected override DragAndDropVisualMode HandleDragAndDrop (DragAndDropArgs args) - { - // Check if we can handle the current drag data (could be dragged in from other areas/windows in the editor) - var draggedRows = DragAndDrop.GetGenericData(k_GenericDragID) as List; - if (draggedRows == null) - return DragAndDropVisualMode.None; - - // Parent item is null when dragging outside any tree view items. - switch (args.dragAndDropPosition) - { - case DragAndDropPosition.UponItem: - case DragAndDropPosition.BetweenItems: - { - bool validDrag = ValidDrag(args.parentItem, draggedRows); - if (args.performDrop && validDrag) - { - T parentData = ((TreeViewItem)args.parentItem).data; - OnDropDraggedElementsAtIndex(draggedRows, parentData, args.insertAtIndex == -1 ? 0 : args.insertAtIndex); - } - return validDrag ? DragAndDropVisualMode.Move : DragAndDropVisualMode.None; - } - - case DragAndDropPosition.OutsideItems: - { - if (args.performDrop) - OnDropDraggedElementsAtIndex(draggedRows, m_TreeModel.root, m_TreeModel.root.children.Count); - - return DragAndDropVisualMode.Move; - } - default: - Debug.LogError("Unhandled enum " + args.dragAndDropPosition); - return DragAndDropVisualMode.None; - } - } - - public virtual void OnDropDraggedElementsAtIndex (List draggedRows, T parent, int insertIndex) - { - if (beforeDroppingDraggedItems != null) - beforeDroppingDraggedItems (draggedRows); - - var draggedElements = new List (); - foreach (var x in draggedRows) - draggedElements.Add (((TreeViewItem) x).data); - - var selectedIDs = draggedElements.Select (x => x.id).ToArray(); - m_TreeModel.MoveElements (parent, insertIndex, draggedElements); - SetSelection(selectedIDs, TreeViewSelectionOptions.RevealAndFrame); - } - - - bool ValidDrag(TreeViewItem parent, List draggedItems) - { - TreeViewItem currentParent = parent; - while (currentParent != null) - { - if (draggedItems.Contains(currentParent)) - return false; - currentParent = currentParent.parent; - } - return true; - } - - } - -} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Packages/.gitignore b/Packages/.gitignore new file mode 100644 index 0000000..c5a384f --- /dev/null +++ b/Packages/.gitignore @@ -0,0 +1,5 @@ +/*/ +!com.vrchat.core.* + +# Change this to match your new package name +!com.killers0992.awttersdk \ No newline at end of file diff --git a/Packages/com.killers0992.awttersdk/Editor.meta b/Packages/com.killers0992.awttersdk/Editor.meta new file mode 100644 index 0000000..9eb8c90 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9f181a8663a6cfb4ca7a47de1f257036 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/AwboiSplashButtons.cs b/Packages/com.killers0992.awttersdk/Editor/AwboiSplashButtons.cs new file mode 100644 index 0000000..8583d7d --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/AwboiSplashButtons.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Security.Cryptography; +using System.Text; +using UnityEditor; +using UnityEngine; +using UnityEngine.Networking; + +namespace AWBOI.SplashScreen +{ + [Serializable] + [CreateAssetMenu(fileName = "AwboiSplashButtons", menuName = "ScriptableObjects/AwboiSplashButtons", order = 1)] + public class AwboiSplashButtons : ScriptableObject + { + public string credPath; + + public string SceneFolder; + public List Buttons; + + } + + [Serializable] + public class SplashButton + { + public bType ButtonType; + public string ButtonText; + public string Link; + + [Tooltip("(Optional) Icon shown in the Splash Screen.")] + public Texture2D Image; + + + public enum bType + { + WebLink, + File + } + + public SplashButton(string text, string link) + { + ButtonText = text; + Link = link; + } + } +} + + diff --git a/Editor/Enums/BaseType.cs.meta b/Packages/com.killers0992.awttersdk/Editor/AwboiSplashButtons.cs.meta similarity index 83% rename from Editor/Enums/BaseType.cs.meta rename to Packages/com.killers0992.awttersdk/Editor/AwboiSplashButtons.cs.meta index e0e3f4c..ae11982 100644 --- a/Editor/Enums/BaseType.cs.meta +++ b/Packages/com.killers0992.awttersdk/Editor/AwboiSplashButtons.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: d9dd63c86a9f19f49b7339e840227c71 +guid: e67598300076cd947a9689bf2265919e MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Packages/com.killers0992.awttersdk/Editor/AwboiSplashButtonsInspector.cs b/Packages/com.killers0992.awttersdk/Editor/AwboiSplashButtonsInspector.cs new file mode 100644 index 0000000..8df53ed --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/AwboiSplashButtonsInspector.cs @@ -0,0 +1,145 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using UnityEngine.SceneManagement; +using UnityEngine.Networking; +using System.Text; +using System.Security.Cryptography; +using System; +using UnityEditor.SceneManagement; +using AwtterSDK; + +namespace AWBOI.SplashScreen +{ + [CustomEditor(typeof(AWBOI.SplashScreen.AwboiSplashButtons))] + public class AwboiSplashButtonsInspector : Editor + { + public bool NamesFoldout = false; + public bool ButtonsFoldout = false; + + #region EDITOR_GUI + + public override void OnInspectorGUI() + { + if (AwtterSdkInstaller.LoggedInUser != null && !AwtterSdkInstaller.LoggedInUser.Admin) return; + + serializedObject.Update(); + + EditorGUILayout.Separator(); + EditorGUILayout.Space(25); + var SceneFolder = serializedObject.FindProperty(nameof(AwboiSplashButtons.SceneFolder)); + EditorGUILayout.PropertyField(SceneFolder, new GUIContent(nameof(AwboiSplashButtons.SceneFolder), "This should be the path to the folder that contains the scenes listed in Scenes.")); + + EditorGUILayout.Separator(); + + + HandleButtons(); + + serializedObject.ApplyModifiedProperties(); + } + + public void HandleButtons() + { + EditorGUILayout.BeginVertical("Box"); + + var Buttons = serializedObject.FindProperty("Buttons"); + EditorGUI.indentLevel += 1; + EditorGUILayout.BeginHorizontal(); + ButtonsFoldout = EditorGUILayout.Foldout(ButtonsFoldout, new GUIContent($"{Buttons.arraySize} Splash Buttons: ")); + if (GUILayout.Button(new GUIContent("Add New Button"))) + { + var splashButtons = serializedObject.targetObject as AWBOI.SplashScreen.AwboiSplashButtons; + + var button = new AWBOI.SplashScreen.SplashButton("New Button", ""); + splashButtons.Buttons.Add(button); + ButtonsFoldout = true; + } + EditorGUILayout.EndHorizontal(); + + + if (Buttons.arraySize > 0) + { + EditorGUI.indentLevel += 1; + if (ButtonsFoldout) + { + EditorGUILayout.BeginVertical(GUI.skin.box); + for (int i = 0; i < Buttons.arraySize; i++) + { + var button = Buttons.GetArrayElementAtIndex(i); + DrawButton(Buttons, button as SerializedProperty, i); + GUILayout.Space(25); + } + EditorGUILayout.EndVertical(); + } + EditorGUI.indentLevel -= 1; + } + + EditorGUILayout.EndVertical(); + EditorGUI.indentLevel -= 1; + + } + + public void DrawButton(SerializedProperty buttons, SerializedProperty button, int index) + { + var allbuttons = target as AWBOI.SplashScreen.AwboiSplashButtons; + var thisButton = allbuttons.Buttons[index]; + + var bText = button.FindPropertyRelative("ButtonText"); + var bType = button.FindPropertyRelative("ButtonType"); + var link = button.FindPropertyRelative("Link"); + var image = button.FindPropertyRelative("Image"); + + + EditorGUILayout.PropertyField(bType); + EditorGUILayout.PropertyField(bText); + + switch (thisButton.ButtonType) + { + case AWBOI.SplashScreen.SplashButton.bType.WebLink: + EditorGUILayout.PropertyField(link); + break; + case AWBOI.SplashScreen.SplashButton.bType.File: + EditorGUILayout.PropertyField(link, new GUIContent("File Path")); + break; + } + EditorGUILayout.PropertyField(image); + + UIArrayHandler(buttons, index); + } + + public void DrawName(SerializedProperty names, SerializedProperty _name, int index) + { + var name = _name.FindPropertyRelative("Name"); + var image = _name.FindPropertyRelative("Image"); + + EditorGUILayout.PropertyField(name); + EditorGUILayout.PropertyField(image); + + UIArrayHandler(names, index); + } + + public void UIArrayHandler(SerializedProperty serArray, int itemIdx) + { + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Up", GUILayout.Width(64))) + { + if (itemIdx > 0) + serArray.MoveArrayElement(itemIdx, itemIdx - 1); + } + if (GUILayout.Button("Down", GUILayout.Width(64))) + { + if (itemIdx < serArray.arraySize - 1) + serArray.MoveArrayElement(itemIdx, itemIdx + 1); + } + if (GUILayout.Button("Delete", GUILayout.Width(64))) + { + serArray.DeleteArrayElementAtIndex(itemIdx); + return; + } + GUILayout.EndHorizontal(); + } + #endregion + } +} diff --git a/Editor/TreeDataModel/TreeElement.cs.meta b/Packages/com.killers0992.awttersdk/Editor/AwboiSplashButtonsInspector.cs.meta similarity index 69% rename from Editor/TreeDataModel/TreeElement.cs.meta rename to Packages/com.killers0992.awttersdk/Editor/AwboiSplashButtonsInspector.cs.meta index 05b01d6..c356198 100644 --- a/Editor/TreeDataModel/TreeElement.cs.meta +++ b/Packages/com.killers0992.awttersdk/Editor/AwboiSplashButtonsInspector.cs.meta @@ -1,8 +1,7 @@ fileFormatVersion: 2 -guid: 69be32fe4d27dde489209c5885c1e5dc -timeCreated: 1472024155 -licenseType: Pro +guid: 0e9750bdfe3420b48bf355fb32821cd9 MonoImporter: + externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 diff --git a/Packages/com.killers0992.awttersdk/Editor/AwtterApi.cs b/Packages/com.killers0992.awttersdk/Editor/AwtterApi.cs new file mode 100644 index 0000000..ef8c8de --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/AwtterApi.cs @@ -0,0 +1,119 @@ +namespace AwtterSDK.Editor +{ + using UnityEngine.Networking; + using UnityEngine; + + using Newtonsoft.Json; + + using System.Collections; + + using AwtterSDK; + using AwtterSDK.Editor.Models.API; + using AwtterSDK.Editor.Enums; + + public class AwtterApi + { + public static IEnumerator GetProducts(bool isFirst = true) + { + using (var www = UnityWebRequest.Get("https://awtterspace.com/api/products")) + { + www.SetRequestHeader("Authorization", $"Token {TokenCache.Token}"); + + yield return www.SendWebRequest(); + + if (www.responseCode != 200) yield break; + + AwtterSdkInstaller.Products = JsonConvert.DeserializeObject(www.downloadHandler.text); + + if (!AwtterSdkInstaller.LoggedIn && isFirst) + { + Debug.Log("[Awtter SDK] Logged in using cache!"); + AwtterSdkInstaller.LoggedIn = true; + } + } + yield break; + } + + public static IEnumerator GetConfig() + { + using (var www = UnityWebRequest.Get("https://awtterspace.com/api/config")) + { + yield return www.SendWebRequest(); + + if (www.responseCode != 200) yield break; + + var okResponse = JsonConvert.DeserializeObject(www.downloadHandler.text); + + if (okResponse.Status == StatusType.Success) + AwtterSdkInstaller.RemoteConfig = okResponse.Data; + } + yield break; + } + + + public static IEnumerator GetCurrentUser() + { + using (var www = UnityWebRequest.Get("https://awtterspace.com/api/users/me")) + { + www.SetRequestHeader("Authorization", $"Token {TokenCache.Token}"); + + yield return www.SendWebRequest(); + + if (www.responseCode != 200) yield break; + + var model = JsonConvert.DeserializeObject(www.downloadHandler.text); + + if (model.Status != StatusType.Success) yield break; + + AwtterSdkInstaller.LoggedInUser = model.Data; + } + yield break; + } + + public static IEnumerator GetToolbox() + { + using (var www = UnityWebRequest.Get("https://awtterspace.com/api/products/toolbox")) + { + www.SetRequestHeader("Authorization", $"Token {TokenCache.Token}"); + + yield return www.SendWebRequest(); + + if (www.responseCode != 200) yield break; + + var model = JsonConvert.DeserializeObject(www.downloadHandler.text); + + if (model.Status != StatusType.Success) yield break; + + foreach (var tool in model.Data.Files) + { + tool.IsTool = true; + } + + model.Data.Files.RemoveAll(x => x.Name == "7zip"); + + AwtterSdkInstaller.Toolbox = model.Data; + } + yield break; + } + + public static IEnumerator GetPatreon() + { + using (var www = UnityWebRequest.Get("https://awtterspace.com/api/patreon/me")) + { + www.SetRequestHeader("Authorization", $"Token {TokenCache.Token}"); + + yield return www.SendWebRequest(); + + if (www.responseCode != 200) yield break; + + var model = JsonConvert.DeserializeObject(www.downloadHandler.text); + + if (model.Status != StatusType.Success) yield break; + + AwtterSdkInstaller.Patreon = model.Data; + AwtterSdkInstaller.RefreshAwtterPackages = true; + } + yield break; + } + } +} diff --git a/Editor/TreeDataModel/TreeElementUtility.cs.meta b/Packages/com.killers0992.awttersdk/Editor/AwtterApi.cs.meta similarity index 69% rename from Editor/TreeDataModel/TreeElementUtility.cs.meta rename to Packages/com.killers0992.awttersdk/Editor/AwtterApi.cs.meta index 12d8902..5dcf3b9 100644 --- a/Editor/TreeDataModel/TreeElementUtility.cs.meta +++ b/Packages/com.killers0992.awttersdk/Editor/AwtterApi.cs.meta @@ -1,8 +1,7 @@ fileFormatVersion: 2 -guid: fd65e8f324e17a344a97ddcf5a8d89d2 -timeCreated: 1471616285 -licenseType: Pro +guid: 74d99c8b22511bd48bf7fb29d5d86490 MonoImporter: + externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 diff --git a/Packages/com.killers0992.awttersdk/Editor/AwtterSDK.Editor.asmdef b/Packages/com.killers0992.awttersdk/Editor/AwtterSDK.Editor.asmdef new file mode 100644 index 0000000..4cd07f8 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/AwtterSDK.Editor.asmdef @@ -0,0 +1,34 @@ +{ + "name": "Awtter SDK.Editor", + "rootNamespace": "", + "references": [ + "GUID:478a2357cc57436488a56e564b08d223" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [ + { + "name": "com.unity.nuget.newtonsoft-json", + "expression": "2.0.2", + "define": "NEWTONSOFT_JSON" + }, + { + "name": "com.unity.editorcoroutines", + "expression": "1.0.0", + "define": "EDITOR_COROUTINES" + }, + { + "name": "com.unity.sharp-zip-lib", + "expression": "1.3.2-preview", + "define": "SHARP_ZIPLIB" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.killers0992.awttersdk/Editor/AwtterSDK.Editor.asmdef.meta b/Packages/com.killers0992.awttersdk/Editor/AwtterSDK.Editor.asmdef.meta new file mode 100644 index 0000000..c50ca6e --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/AwtterSDK.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f26b5e4d746969f42a2b3457370f0268 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/AwtterSdkInstaller.cs b/Packages/com.killers0992.awttersdk/Editor/AwtterSdkInstaller.cs new file mode 100644 index 0000000..9510dad --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/AwtterSdkInstaller.cs @@ -0,0 +1,469 @@ +namespace AwtterSDK +{ + using UnityEditor; + + using System.Collections.Generic; + + using AwtterSDK.Editor.Pages; + using AwtterSDK.Editor.Interfaces; + using AwtterSDK.Editor.Models.API; + using AwtterSDK.Editor; + using AwtterSDK.Editor.Models; + using AwtterSDK.Editor.Installations; + using UnityEngine; + using AWBOI.SplashScreen; + using Unity.EditorCoroutines.Editor; + using System.IO; + using Newtonsoft.Json; + using System.Linq; + using AwtterSDK.Editor.Enums; + using System; + using Assets.Awtter_SDK.Editor.Models; + + class SdkRefresh : AssetPostprocessor + { + static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) + { + AwtterSdkInstaller.Refresh = true; + } + } + + public class AwtterSdkInstaller : EditorWindow + { + private static AwtterSdkInstaller _window; + private static string _installedPackagesPath => Path.Combine(Application.dataPath, "AwtterInstalledPackages.json"); + + private static bool? _showOnStartup; + public static bool ShowOnStartup + { + get + { + if (!_showOnStartup.HasValue) + _showOnStartup = EditorPrefs.GetBool("AwShowOnStartup", true); + + return _showOnStartup.Value; + } + set + { + EditorPrefs.SetBool("AwShowOnStartup", value); + _showOnStartup = value; + } + } + + static AwtterSdkInstaller() + { + EditorApplication.update -= OnEditorUpdate; + EditorApplication.update += OnEditorUpdate; + } + + public static void CloseWindow() + { + if (_window == null) return; + + _window.Close(); + _window = null; + } + + + [MenuItem("Awtter tools/ASDK control panel")] + static void Init() + { + _window = (AwtterSdkInstaller)EditorWindow.GetWindow(typeof(AwtterSdkInstaller), false, "Awtter SDK"); + _window.minSize = new Vector2(320f, 640f); + + _window.Show(); + } + + + static void OnEditorUpdate() + { + EditorApplication.update -= OnEditorUpdate; + + if (ShowOnStartup) + Init(); + } + + private static bool _isLoggedIn = false; + + public static bool Refresh; + + public static SdkStatus LastPage; + + public static bool UpdateCurrentUser; + + + public static ToolboxOkResponseModel Toolbox; + + public static UserModel LoggedInUser; + + public static PatreonOkResponseModel Patreon; + + public static bool LoggedIn + { + get => _isLoggedIn; + set + { + if (value) + UpdateCurrentUser = true; + else + { + LoggedInUser = null; + } + + _isLoggedIn = value; + } + } + + + public static VrcPackages VrcPackages; + + public static bool RefreshAwtterPackages; + private static ProductsModel _products; + + public static ProductsModel Products + { + get => _products; + set + { + if (_products == value) return; + + _products = value; + RefreshAwtterPackages = true; + } + } + + public static Dictionary Pages = new Dictionary() + { + { SdkStatus.NotLoggedIn, new LoginPage() }, + { SdkStatus.TosNotAccepted, new TosPage() }, + { SdkStatus.BaseNotInstalled, new ModelSelectionPage() }, + { SdkStatus.ViewAdditionalPackages , new AddPackagesPage() }, + { SdkStatus.InstallInProgress, new InstallProgressPage() }, + { SdkStatus.BaseInstalled, new ScenesPage() }, + { SdkStatus.ViewSettings, new SettingsPage() }, + { SdkStatus.ManagePackages, new ManagePackagesPage() }, + { SdkStatus.PatreonItems, new PatreonBenefitsPage() }, + { SdkStatus.ResetPage, new ResetPage() }, + }; + + public static List UnityPackages = new List(); + + void AddIfMissing(bool force = false) + { + if (Shared == null || force) + { + Shared = new SharedPage(this); + } + else if (Shared != null && Shared._main == null) + { + Shared._main = this; + } + + if (UpdateCurrentUser || force) + { + SaveInstalledPackagesStorage(); + + EditorCoroutineUtility.StartCoroutine(AwtterApi.GetCurrentUser(), this); + EditorCoroutineUtility.StartCoroutine(AwtterApi.GetPatreon(), this); + EditorCoroutineUtility.StartCoroutine(AwtterApi.GetToolbox(), this); + UpdateCurrentUser = false; + } + + if ((RefreshAwtterPackages || force) && Products?.Data != null) + { + UpdateAwtterPackages(); + RefreshAwtterPackages = false; + } + } + + public void UpdateAwtterPackages() + { + AvaliableBases = Products.Data.SelectMany((x) => + { + var files = x.Files.Where(y => + { + if (!y.IsBaseModel) return false; + + if (y.IsInstalled) + CurrentBase = y.ToBaseView(x); + + return true; + }); + return files.Select(z => z.ToBaseView(x)); + }).ToList(); + + if (Patreon?.Benefits != null) + AvaliableBases.AddRange(Patreon.Benefits.SelectMany((x) => + { + var files = x.Files.Where(y => + { + if (!y.IsBaseModel) return false; + + if (y.IsInstalled) + CurrentBase = y.ToBaseView(x, true); + + return true; + }); + return files.Select(z => z.ToBaseView(x, true)); + }).ToList()); + + AvaliableDlcs = Products.Data.SelectMany((x) => + { + var files = x.Files.Where(y => + { + if (!y.IsDLC) return false; + + if (!y.IsProp && x.BaseName != CurrentBase?.BaseName) return false; + + if (y.Id == CurrentBase?.Id) return false; + + return true; + }); + + return files.Select(z => z.ToDLCView(x)); + }).ToList(); + + if (Patreon != null && Patreon.Benefits != null) + AvaliableDlcs.AddRange(Patreon.Benefits.SelectMany((x) => + { + var files = x.Files.Where(y => + { + if (!y.IsDLC) return false; + + if (!y.IsProp && x.BaseName != CurrentBase?.BaseName) return false; + + if (y.Id == CurrentBase?.Id) return false; + + return true; + }); + + return files.Select(z => z.ToDLCView(x, true)); + }).ToList()); + + if (Toolbox?.Files != null) + AvaliableTools = Toolbox.Files.Select((x) => x.ToToolView(Toolbox)).ToList(); + } + + public void SaveInstalledPackagesStorage() + { + if (!File.Exists(_installedPackagesPath)) + { + File.WriteAllText(_installedPackagesPath, JsonConvert.SerializeObject(new InstalledPackagesModel(), Formatting.Indented)); + } + else if (InstalledPackages != null) + { + File.WriteAllText(_installedPackagesPath, JsonConvert.SerializeObject(InstalledPackages, Formatting.Indented)); + } + + + InstalledPackages = JsonConvert.DeserializeObject(File.ReadAllText(_installedPackagesPath)); + InstalledPackages.CheckTools(); + + if (InstalledPackages.BaseModel == null) + CurrentBase = null; + + RefreshAwtterPackages = true; + } + + public static InstalledPackagesModel InstalledPackages { get; private set; } + + private AwboiSplashButtons _settings; + public AwboiSplashButtons Settings + { + get + { + if (_settings == null) + { + _settings = AssetDatabase.LoadAssetAtPath(Path.Combine(Paths.MainPath, "Editor", "Resources", "SplashMenuButtons.asset")); + + if (_settings == null) + { + Debug.Log("still null"); + } + + SaveInstalledPackagesStorage(); + } + + return _settings; + } + } + + public SharedPage Shared { get; private set; } + + public static bool IsBaseIntalled => CurrentBase?.IsInstalled == true; + public static BaseView CurrentBase { get; internal set; } + + public static List FilesToInstall = new List(); + + public static List AvaliableBases { get; private set; } = new List(); + public static List AvaliableDlcs { get; private set; } = new List(); + public static List AvaliableTools { get; private set; } = new List(); + + private static bool _isInstalling; + + public static bool IsInstalling + { + get => _isInstalling; + set + { + if (!value) + { + _isInstalling = value; + Refresh = true; + ScenesPage.DoRefreshScenes = true; + return; + } + + FilesToInstall.Clear(); + + foreach (var pack in UnityPackages) + { + if (pack.InstallStatus.IsInstalled) continue; + + FilesToInstall.Add(new FileToInstallModel() + { + Id = pack.Id, + Name = pack.Name, + Displayname = pack.Name, + Icon = pack.Icon, + DownloadUrl = pack.Url, + RequiresAuth = pack.RequiresAuth + }); + } + + if (CurrentBase?.IsInstalled == false) + { + FilesToInstall.Add(new FileToInstallModel() + { + Id = CurrentBase.Id, + Name = CurrentBase.Name, + Version = CurrentBase.Version, + IsBaseModel = true, + Displayname = CurrentBase.Name, + Icon = CurrentBase.Icon, + DownloadUrl = CurrentBase.DownloadUrl, + RequiresAuth = true, + }); + } + + + foreach (var dlc in AvaliableDlcs.Where(x => x.Install)) + { + FilesToInstall.Add(new FileToInstallModel() + { + Id = dlc.Id, + Name = dlc.Name, + Version = dlc.Version, + IsDLC = true, + Displayname = dlc.Name, + Icon = dlc.Icon, + DownloadUrl = dlc.DownloadUrl, + RequiresAuth = true, + }); + dlc.Install = false; + } + + foreach (var tool in AvaliableTools.Where(x => x.Install)) + { + FilesToInstall.Add(new FileToInstallModel() + { + Id = tool.Id, + Name = tool.Name, + Version = tool.Version, + Displayname = tool.Name, + Icon = tool.Icon, + DownloadUrl = tool.DownloadUrl, + RequiresAuth = true, + }); + tool.Install = false; + } + + _isInstalling = value; + } + } + + public static bool ViewManagePackages; + public static bool ViewSettings; + public static bool ViewAdditionalPackages; + public static bool ViewPatreonItems; + public static bool ViewReset; + + public static DateTime RemoteConfigGetDelay = DateTime.Now; + public static ConfigResponseModel RemoteConfig = null; + + public static SdkStatus CurrentStatus + { + get + { + if (!LoggedIn || RemoteConfig == null) + return SdkStatus.NotLoggedIn; + + if (!TosPage.TosAccepted || (RemoteConfig != null && RemoteConfig.Tos.Version > TosPage.TosVersion)) + return SdkStatus.TosNotAccepted; + + if (IsInstalling) + return SdkStatus.InstallInProgress; + + if (ViewSettings) + return SdkStatus.ViewSettings; + + if (ViewAdditionalPackages) + return SdkStatus.ViewAdditionalPackages; + + if (ViewPatreonItems) + return SdkStatus.PatreonItems; + + if (!IsBaseIntalled) + return SdkStatus.BaseNotInstalled; + + if (ViewReset) + return SdkStatus.ResetPage; + + if (ViewManagePackages) + return SdkStatus.ManagePackages; + + return SdkStatus.BaseInstalled; + } + } + + void OnGUI() + { + if (RemoteConfigGetDelay < DateTime.Now) + { + RemoteConfigGetDelay = DateTime.Now.AddSeconds(30); + EditorCoroutineUtility.StartCoroutine(AwtterApi.GetConfig(), this); + } + + AddIfMissing(Refresh); + + if (Refresh) + Refresh = false; + + TextureCache.DownloadIfNeeded(); + + if (LastPage != CurrentStatus) + { + if (Pages.ContainsKey(LastPage)) + Pages[LastPage].Reset(); + + LastPage = CurrentStatus; + Pages[LastPage].Load(this); + } + + Shared.Top(position); + + if (Application.isPlaying) + { + EditorGUILayout.BeginVertical(); + GUILayout.FlexibleSpace(); + GUILayout.Label("Exit playmode to access panel", Shared.WindowCustomButton); + GUILayout.FlexibleSpace(); + EditorGUILayout.EndVertical(); + } + else + Pages[LastPage].DrawGUI(position); + + Shared.Bottom(position); + } + } +} diff --git a/Editor/TreeDataModel/TreeModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/AwtterSdkInstaller.cs.meta similarity index 69% rename from Editor/TreeDataModel/TreeModel.cs.meta rename to Packages/com.killers0992.awttersdk/Editor/AwtterSdkInstaller.cs.meta index 0ee779c..af84ce0 100644 --- a/Editor/TreeDataModel/TreeModel.cs.meta +++ b/Packages/com.killers0992.awttersdk/Editor/AwtterSdkInstaller.cs.meta @@ -1,8 +1,7 @@ fileFormatVersion: 2 -guid: 6f9fab1cf2636a6439c644bf08108abb -timeCreated: 1472122507 -licenseType: Pro +guid: 9924a23c899555f48952c00c4d145c13 MonoImporter: + externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 diff --git a/Packages/com.killers0992.awttersdk/Editor/ChangeLogsMenu.cs b/Packages/com.killers0992.awttersdk/Editor/ChangeLogsMenu.cs new file mode 100644 index 0000000..38e9035 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/ChangeLogsMenu.cs @@ -0,0 +1,53 @@ +using AwtterSDK; +using AwtterSDK.Editor; +using System; +using System.Collections.Generic; +using System.IO; +using UnityEditor; +using UnityEngine; + +namespace Assets.Awtter_SDK.Editor +{ + public class ChangeLogsMenu : EditorWindow + { + private static ChangeLogsMenu _window; + + public static void ShowChangelogs() + { + _window = (ChangeLogsMenu)EditorWindow.GetWindow(typeof(ChangeLogsMenu), false, "Awtter SDK | Changelogs"); + _window.minSize = new Vector2(600f, 600f); + + var position = _window.position; + position.center = new Rect(0f, 0f, Screen.currentResolution.width, Screen.currentResolution.height).center; + _window.position = position; + + _window.Show(); + } + + public string ChangeLogsPath => Path.Combine(Paths.MainPath, "Editor", "Textures", "changelogs.txt"); + + public string[] Changelogs = null; + + public Vector2 scroll = Vector2.zero; + + private void OnGUI() + { + if (Changelogs == null) + { + Changelogs = File.ReadAllLines(ChangeLogsPath); + } + + scroll = GUILayout.BeginScrollView(scroll, false, true); + foreach(var line in Changelogs) + { + GUILayout.Label(line); + } + GUILayout.EndScrollView(); + + if (GUILayout.Button($"CLOSE", GUILayout.MinWidth(50), GUILayout.MinHeight(32))) + { + Close(); + } + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/ChangeLogsMenu.cs.meta b/Packages/com.killers0992.awttersdk/Editor/ChangeLogsMenu.cs.meta new file mode 100644 index 0000000..60074a0 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/ChangeLogsMenu.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d8434e19d1bea99468ef59dfee139492 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Enums.meta b/Packages/com.killers0992.awttersdk/Editor/Enums.meta new file mode 100644 index 0000000..ec53577 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Enums.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4ee821fa31533fd469d54d385616f8e5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Enums/DownloadStatus.cs b/Packages/com.killers0992.awttersdk/Editor/Enums/DownloadStatus.cs new file mode 100644 index 0000000..28e7186 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Enums/DownloadStatus.cs @@ -0,0 +1,11 @@ +namespace AwtterSDK.Editor.Enums +{ + public enum DownloadStatus + { + Waiting, + Installing, + Importing, + Installed, + Failed, + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Enums/DownloadStatus.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Enums/DownloadStatus.cs.meta new file mode 100644 index 0000000..7c4d59c --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Enums/DownloadStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b8326f49cf67a2a43ad749f6a4782804 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Enums/SdkStatus.cs b/Packages/com.killers0992.awttersdk/Editor/Enums/SdkStatus.cs new file mode 100644 index 0000000..648551d --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Enums/SdkStatus.cs @@ -0,0 +1,21 @@ +using System; + +namespace AwtterSDK.Editor.Enums +{ + [Flags] + public enum SdkStatus + { + None, + NotLoggedIn, + PatreonItems, + TosNotAccepted, + InstallInProgress, + BaseInstalled, + ViewAdditionalPackages, + BaseNotInstalled, + ViewScenes, + ViewSettings, + ManagePackages, + ResetPage, + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Enums/SdkStatus.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Enums/SdkStatus.cs.meta new file mode 100644 index 0000000..9eb7fbe --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Enums/SdkStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 394d1ae8a78fb7e44a722e6dce42de02 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Enums/StatusType.cs b/Packages/com.killers0992.awttersdk/Editor/Enums/StatusType.cs new file mode 100644 index 0000000..4591f66 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Enums/StatusType.cs @@ -0,0 +1,9 @@ +namespace AwtterSDK.Editor.Enums +{ + public enum StatusType + { + Error, + Failure, + Success, + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Enums/StatusType.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Enums/StatusType.cs.meta new file mode 100644 index 0000000..ef90ffc --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Enums/StatusType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 42fb1c3675a7428499d28db935f41019 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/FilesCache.cs b/Packages/com.killers0992.awttersdk/Editor/FilesCache.cs new file mode 100644 index 0000000..3a28b53 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/FilesCache.cs @@ -0,0 +1,76 @@ +using AwtterSDK.Editor.Models; +using System; +using System.Data; +using System.IO; +using Unity.SharpZipLib.Zip; +using UnityEditor; + +namespace AwtterSDK.Editor +{ + public class FilesCache + { + private static FastZip _fastZip; + + public static FastZip Zip + { + get + { + if (_fastZip == null) + _fastZip = new FastZip(); + + return _fastZip; + } + } + + private static string _mainPath; + public static string MainPath + { + get + { + if (_mainPath == null) + { + _mainPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Awtter SDK"); + if (!Directory.Exists(_mainPath)) Directory.CreateDirectory(_mainPath); + } + + return _mainPath; + } + } + + private static string _cachePath; + public static string CachePath + { + get + { + if (_cachePath == null) + { + _cachePath = Path.Combine(MainPath, "Cache"); + if (!Directory.Exists(_cachePath)) Directory.CreateDirectory(_cachePath); + } + + return _cachePath; + } + } + + public static string CacheFile(FileToInstallModel file, byte[] bytes) + { + string path = Path.Combine(CachePath, file.IsUnityPackage ? $"{file.Id}_{file.Version}" : $"{file.Name}_{file.Version}"); + + File.WriteAllBytes(path, bytes); + return path; + } + + public static bool GetCachedFile(FileToInstallModel file) + { + string path = Path.Combine(CachePath, file.IsUnityPackage ? $"{file.Id}_{file.Version}" : $"{file.Name}_{file.Version}"); + if (!File.Exists(path)) + return false; + + if (file.IsUnityPackage) + AssetDatabase.ImportPackage(path, false); + else + Zip.ExtractZip(path, Path.Combine(Paths.MainPath, file.Name), null); + return true; + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/FilesCache.cs.meta b/Packages/com.killers0992.awttersdk/Editor/FilesCache.cs.meta new file mode 100644 index 0000000..67b3b2e --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/FilesCache.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 502bc24218a71234ba736db60c802151 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Installations.meta b/Packages/com.killers0992.awttersdk/Editor/Installations.meta new file mode 100644 index 0000000..22c02c9 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Installations.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: edd8696c0fb923c4eaed0cc49ea18fd2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Installations/MergerInstallation.cs b/Packages/com.killers0992.awttersdk/Editor/Installations/MergerInstallation.cs new file mode 100644 index 0000000..e19cdad --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Installations/MergerInstallation.cs @@ -0,0 +1,35 @@ +using AwtterSDK.Editor.Interfaces; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AwtterSDK.Editor.Installations +{ + public class MergerInstallation : ICheckInstallStatus + { + Version _version; + bool _isInstalled; + public bool IsInstalled => _isInstalled; + public Version InstalledVersion => _version; + + public void Check() + { + _isInstalled = Directory.Exists("Assets/AwboiMerger"); + + if (_isInstalled) + { + var targetFile = "Assets/AwboiMerger/AWBOI_MERGER.dll"; + + if (File.Exists(targetFile)) + { + var ver = FileVersionInfo.GetVersionInfo(targetFile); + Version.TryParse(ver.FileVersion, out _version); + } + } + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Installations/MergerInstallation.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Installations/MergerInstallation.cs.meta new file mode 100644 index 0000000..b83d894 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Installations/MergerInstallation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 05b159cda066256418a5117969a23bf4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Installations/PoyiomiInstallation.cs b/Packages/com.killers0992.awttersdk/Editor/Installations/PoyiomiInstallation.cs new file mode 100644 index 0000000..61b1e63 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Installations/PoyiomiInstallation.cs @@ -0,0 +1,53 @@ +using AwtterSDK.Editor.Interfaces; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using UnityEngine; + +namespace AwtterSDK.Editor.Installations +{ + public class PoyomiInstallation : ICheckInstallStatus + { + bool _isInstalled; + Version _version; + + public bool IsInstalled => _isInstalled; + + public Version InstalledVersion => _version; + + public void Check() + { + _isInstalled = Directory.Exists("Assets/_PoiyomiShaders"); + + if (_isInstalled) + { + if (Directory.Exists("Assets/_PoiyomiShaders/Shaders")) + { + foreach(var dir in Directory.GetDirectories("Assets/_PoiyomiShaders/Shaders")) + { + foreach(var file in Directory.GetFiles(dir, "*.shader")) + { + var content = File.ReadAllLines(file); + var versionLine = content.FirstOrDefault(p => p.Contains("shader_master_label")); + if (versionLine != null) + { + var line = versionLine.Split('(', ')')[1]; + var line2 = line.Split('"')[1]; + var line3 = line2.Split(' ')[1]; + + var finalVersion = Regex.Replace(line3, @"<[^>]*>", String.Empty); + + Version.TryParse(finalVersion, out _version); + return; + } + } + } + } + } + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Installations/PoyiomiInstallation.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Installations/PoyiomiInstallation.cs.meta new file mode 100644 index 0000000..942ed36 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Installations/PoyiomiInstallation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 40cc607ca743ed547880d6d1c68b7948 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Installations/PumkinInstallation.cs b/Packages/com.killers0992.awttersdk/Editor/Installations/PumkinInstallation.cs new file mode 100644 index 0000000..04cdf35 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Installations/PumkinInstallation.cs @@ -0,0 +1,41 @@ +using AwtterSDK.Editor.Interfaces; +using AwtterSDK.Editor.Models; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using UnityEngine; + +namespace AwtterSDK.Editor.Installations +{ + public class PumkinInstallation : ICheckInstallStatus + { + bool _isInstalled; + Version _version; + + public bool IsInstalled => _isInstalled; + + public Version InstalledVersion => _version; + + public void Check() + { + _isInstalled = Directory.Exists("Assets/PumkinsAvatarTools"); + + if (_isInstalled) + { + var targetFile = "Assets/PumkinsAvatarTools/thry_module_manifest.json"; + + if (File.Exists(targetFile)) + { + var manifest = JsonConvert.DeserializeObject(File.ReadAllText(targetFile)); + + Version.TryParse(manifest.Version, out _version); + } + } + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Installations/PumkinInstallation.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Installations/PumkinInstallation.cs.meta new file mode 100644 index 0000000..c227276 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Installations/PumkinInstallation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e2b46fbfac6edf44b9f1bd9464b8b397 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Interfaces.meta b/Packages/com.killers0992.awttersdk/Editor/Interfaces.meta new file mode 100644 index 0000000..82b0030 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Interfaces.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b192143f6c2bb584582bda71e886e5e2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Interfaces/ICheckInstallStatus.cs b/Packages/com.killers0992.awttersdk/Editor/Interfaces/ICheckInstallStatus.cs similarity index 68% rename from Editor/Interfaces/ICheckInstallStatus.cs rename to Packages/com.killers0992.awttersdk/Editor/Interfaces/ICheckInstallStatus.cs index 65d3dbe..81c411d 100644 --- a/Editor/Interfaces/ICheckInstallStatus.cs +++ b/Packages/com.killers0992.awttersdk/Editor/Interfaces/ICheckInstallStatus.cs @@ -7,11 +7,10 @@ namespace AwtterSDK.Editor.Interfaces { - internal interface ICheckInstallStatus + public interface ICheckInstallStatus { bool IsInstalled { get; } - string InstalledVersion { get; } - string TypeInstalled { get; } + Version InstalledVersion { get; } void Check(); } } diff --git a/Packages/com.killers0992.awttersdk/Editor/Interfaces/ICheckInstallStatus.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Interfaces/ICheckInstallStatus.cs.meta new file mode 100644 index 0000000..4c920d6 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Interfaces/ICheckInstallStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d9908f9437d05b04186e4b176488e645 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Interfaces/IPage.cs b/Packages/com.killers0992.awttersdk/Editor/Interfaces/IPage.cs new file mode 100644 index 0000000..b4138bf --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Interfaces/IPage.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace AwtterSDK.Editor.Interfaces +{ + public interface IPage + { + void Load(AwtterSdkInstaller main); + void DrawGUI(Rect pos); + void Reset(); + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Interfaces/IPage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Interfaces/IPage.cs.meta new file mode 100644 index 0000000..251e12d --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Interfaces/IPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b1aaf48ac902234459136a7205db9988 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models.meta b/Packages/com.killers0992.awttersdk/Editor/Models.meta new file mode 100644 index 0000000..a1d7ec4 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e24b6c0d716d3ef4880287f318e31f6a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API.meta new file mode 100644 index 0000000..ec185ca --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 336c3f59da27e6d45bc4ae5a050435d1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthBadResponseModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthBadResponseModel.cs new file mode 100644 index 0000000..51d7278 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthBadResponseModel.cs @@ -0,0 +1,10 @@ +namespace AwtterSDK.Editor.Models.API +{ + using AwtterSDK.Editor.Enums; + + public class AuthBadResponseModel + { + public StatusType Status { get; set; } + public string Message { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthBadResponseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthBadResponseModel.cs.meta new file mode 100644 index 0000000..786c386 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthBadResponseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6384feda004a7254ba2030e192f7480d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthOkResponseModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthOkResponseModel.cs new file mode 100644 index 0000000..5363fd5 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthOkResponseModel.cs @@ -0,0 +1,10 @@ +using AwtterSDK.Editor.Enums; + +namespace AwtterSDK.Editor.Models.API +{ + public class AuthOkResponseModel + { + public StatusType Status { get; set; } + public AuthResponseModel Data { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthOkResponseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthOkResponseModel.cs.meta new file mode 100644 index 0000000..123e93a --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthOkResponseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b05ea5fe61abb454783687041e1f4941 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthResponseModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthResponseModel.cs new file mode 100644 index 0000000..5feb2d1 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthResponseModel.cs @@ -0,0 +1,7 @@ +namespace AwtterSDK.Editor.Models.API +{ + public class AuthResponseModel + { + public string Token { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthResponseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthResponseModel.cs.meta new file mode 100644 index 0000000..568bf8f --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/AuthResponseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f73a622891071a847bb0060169726d86 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/AwtterSdkResponseModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/AwtterSdkResponseModel.cs new file mode 100644 index 0000000..aca3619 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/AwtterSdkResponseModel.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AwtterSDK.Editor.Models.API +{ + public class AwtterSdkResponseModel + { + private Version _version; + public Version Version2 + { + get + { + if (_version == null) + System.Version.TryParse(Version, out _version); + + return _version; + } + } + + public string Version { get; set; } + public string Path { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/AwtterSdkResponseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/AwtterSdkResponseModel.cs.meta new file mode 100644 index 0000000..f19eebb --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/AwtterSdkResponseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0b19af3122c34174ab553daa7d9d9f17 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/ConfigOkResponseModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/ConfigOkResponseModel.cs new file mode 100644 index 0000000..8c87851 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/ConfigOkResponseModel.cs @@ -0,0 +1,15 @@ +using AwtterSDK.Editor.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AwtterSDK.Editor.Models.API +{ + public class ConfigOkResponseModel + { + public StatusType Status { get; set; } + public ConfigResponseModel Data { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/ConfigOkResponseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/ConfigOkResponseModel.cs.meta new file mode 100644 index 0000000..2948654 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/ConfigOkResponseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 07bd81a127782f1458f4e7a1fce9292b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/ConfigResponseModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/ConfigResponseModel.cs new file mode 100644 index 0000000..a6dbaf4 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/ConfigResponseModel.cs @@ -0,0 +1,12 @@ +namespace AwtterSDK.Editor.Models.API +{ + public class ConfigResponseModel + { + public string AppName { get; set; } + public string AppVersion { get; set; } + public string ApiVersion { get; set; } + public TosResponseModel Tos { get; set; } + public AwtterSdkResponseModel AwtterSdk { get; set; } + public MergerResponseModel AwtterMerger { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/ConfigResponseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/ConfigResponseModel.cs.meta new file mode 100644 index 0000000..45d27a1 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/ConfigResponseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9fd490ee86cfc1141967c00802bb9253 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/CurrentUserResponseModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/CurrentUserResponseModel.cs new file mode 100644 index 0000000..70856dc --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/CurrentUserResponseModel.cs @@ -0,0 +1,10 @@ +using AwtterSDK.Editor.Enums; + +namespace AwtterSDK.Editor.Models.API +{ + public class CurrentUserResponseModel + { + public StatusType Status { get; set; } + public UserModel Data { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/CurrentUserResponseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/CurrentUserResponseModel.cs.meta new file mode 100644 index 0000000..2fea200 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/CurrentUserResponseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dbeeee25a7a82d445a565d209ec300bb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/DiscordInfoModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/DiscordInfoModel.cs new file mode 100644 index 0000000..e799c73 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/DiscordInfoModel.cs @@ -0,0 +1,9 @@ +namespace AwtterSDK.Editor.Models.API +{ + public class DiscordInfoModel + { + public string Tag { get; set; } + public long Id { get; set; } + public bool Active { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/DiscordInfoModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/DiscordInfoModel.cs.meta new file mode 100644 index 0000000..fb964d6 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/DiscordInfoModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a50c7effa790f8546b3463f4b5ba7976 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/FileModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/FileModel.cs new file mode 100644 index 0000000..26cd951 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/FileModel.cs @@ -0,0 +1,144 @@ +using Assets.Awtter_SDK.Editor.Models; +using System.Linq; + +namespace AwtterSDK.Editor.Models.API +{ + public class FileModel + { + private string _simpleName; + private int? _id; + public int Id + { + get + { + if (!_id.HasValue) + { + string splitId = Path.Split('/').Last(); + + if (int.TryParse(splitId, out int id)) + _id = id; + } + + return _id.Value; + } + } + + + public string Path { get; set; } + public string Name { get; set; } + + public string NameSimple + { + get + { + if (_simpleName == null) + _simpleName = Name.ToLower().Replace(" ", ""); + + return _simpleName; + } + } + + public string Version { get; set; } + public bool IsTool { get; set; } + public bool IsProp { get; set; } + public bool IsVrcUnitypackage { get; set; } + public bool IsMergerCompatible { get; set; } + public bool IsBaseModel => IsVrcUnitypackage && !IsMergerCompatible; + public bool IsDLC => IsVrcUnitypackage && IsMergerCompatible || IsProp; + + public bool IsInstalled + { + get + { + if (AwtterSdkInstaller.InstalledPackages == null) return false; + + if (IsBaseModel) + return AwtterSdkInstaller.InstalledPackages?.BaseModel?.Id == Id; + else if (IsTool) + return AwtterSdkInstaller.InstalledPackages.Tools.ContainsKey(NameSimple); + else + return AwtterSdkInstaller.InstalledPackages.Dlcs.ContainsKey(Id); + } + } + + public InstalledPackageModel GetBase() + { + if (IsInstalled) + { + var baseModel = AwtterSdkInstaller.InstalledPackages?.BaseModel; + if (baseModel == null) return null; + + AwtterSdkInstaller.InstalledPackages.BaseModel.File = this; + return baseModel; + } + return null; + } + + public InstalledPackageModel GetDLC() + { + if (IsInstalled) + { + var dlc = AwtterSdkInstaller.InstalledPackages.Dlcs[Id]; + if (dlc == null) return null; + + AwtterSdkInstaller.InstalledPackages.Dlcs[Id].File = this; + return dlc; + } + return null; + } + + public InstalledPackageModel GetTool() + { + if (IsInstalled) + { + var name = Name.ToLower().Replace(" ", ""); + + var tool = AwtterSdkInstaller.InstalledPackages.Tools[name]; + if (tool == null) return null; + + AwtterSdkInstaller.InstalledPackages.Tools[name].Id = tool.Id; + AwtterSdkInstaller.InstalledPackages.Tools[name].File = this; + return tool; + } + return null; + } + + + public BaseView ToBaseView(ProductModel product, bool isPatreon = false) => new BaseView() + { + Id = Id, + IsPatreon = isPatreon, + ProductId = product.Id, + Icon = product.Icon, + Version = Version, + InstalledVersion = GetBase()?.Version, + BaseName = product.BaseName, + DownloadUrl = Path, + Name = Name, + }; + + public DlcView ToDLCView(ProductModel product, bool isPatreon = false) => new DlcView() + { + Id = Id, + IsPatreon = isPatreon, + ProductId = product.Id, + Icon = product.Icon, + Version = Version, + InstalledVersion = GetDLC()?.Version, + DownloadUrl = Path, + IsProp = IsProp, + IsDlc = IsDLC, + Name = Name, + }; + + public ToolView ToToolView(ToolboxOkResponseModel product, bool isPatreon = false) => new ToolView() + { + Id = Id, + Icon = product.Icon, + Version = Version, + InstalledVersion = GetTool()?.Version, + DownloadUrl = Path, + Name = Name, + }; + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/FileModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/FileModel.cs.meta new file mode 100644 index 0000000..33afdf8 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/FileModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: badd21cd7da070a4e8fa4ef4e171fde5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Enums/PackageStatus.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/MergerResponseModel.cs similarity index 50% rename from Editor/Enums/PackageStatus.cs rename to Packages/com.killers0992.awttersdk/Editor/Models/API/MergerResponseModel.cs index 7a177dd..8266fa1 100644 --- a/Editor/Enums/PackageStatus.cs +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/MergerResponseModel.cs @@ -4,13 +4,10 @@ using System.Text; using System.Threading.Tasks; -namespace AwtterSDK.Editor.Enums +namespace AwtterSDK.Editor.Models.API { - public enum PackageStatus + public class MergerResponseModel { - None, - NotInstalled, - Installed, - Outdated, + public string Version { get; set; } } } diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/MergerResponseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/MergerResponseModel.cs.meta new file mode 100644 index 0000000..e7ca490 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/MergerResponseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3f807ed829adcac4498b4680250deb8c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/PatreonOkResponseModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/PatreonOkResponseModel.cs new file mode 100644 index 0000000..e93d341 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/PatreonOkResponseModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AwtterSDK.Editor.Models.API +{ + public class PatreonOkResponseModel + { + public bool Active { get; set; } + public string Tier { get; set; } + public List Benefits { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/PatreonOkResponseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/PatreonOkResponseModel.cs.meta new file mode 100644 index 0000000..6b75d39 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/PatreonOkResponseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e356a333da498e14dad4f8d859587617 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/PatreonResponseModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/PatreonResponseModel.cs new file mode 100644 index 0000000..0dcec2a --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/PatreonResponseModel.cs @@ -0,0 +1,15 @@ +using AwtterSDK.Editor.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AwtterSDK.Editor.Models.API +{ + public class PatreonResponseModel + { + public StatusType Status { get; set; } + public PatreonOkResponseModel Data { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/PatreonResponseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/PatreonResponseModel.cs.meta new file mode 100644 index 0000000..d5cbb31 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/PatreonResponseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5f843ec8ef2809042a3c5ce0ec90ccfa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/ProductModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/ProductModel.cs new file mode 100644 index 0000000..fbbfb9c --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/ProductModel.cs @@ -0,0 +1,55 @@ +namespace AwtterSDK.Editor.Models.API +{ + using System.Collections.Generic; + using System.Linq; + + public class ProductModel + { + private int? _id; + public int Id + { + get + { + if (!_id.HasValue) + { + string splitId = Path.Split('/').Last(); + + if (int.TryParse(splitId, out int id)) + _id = id; + } + + return _id.Value; + } + } + + public string Path { get; set; } + public string Name { get; set; } + public string BaseName { get; set; } + public bool IsBaseModel { get; set; } + public string Icon { get; set; } + + public FileModel IsInstalled(bool findBase = false) + { + var vrcPackage = Files.FirstOrDefault(x => x.IsVrcUnitypackage); + + if (vrcPackage == null) return null; + + foreach(var file in Files) + { + string id = file.Path.Split('/')[5]; + + if (!int.TryParse(id, out int fileId)) continue; + + if (AwtterSdkInstaller.InstalledPackages.BaseModel != null && + AwtterSdkInstaller.InstalledPackages.BaseModel.Id == fileId && findBase) + return file; + + if (AwtterSdkInstaller.InstalledPackages.Dlcs.ContainsKey(fileId) && !findBase) return file; + } + + return null; + } + + public List Files { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/ProductModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/ProductModel.cs.meta new file mode 100644 index 0000000..f4c8cb9 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/ProductModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f55d70c3fcae7f4409e5895a0838a2d7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/ProductsModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/ProductsModel.cs new file mode 100644 index 0000000..7a52d27 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/ProductsModel.cs @@ -0,0 +1,10 @@ +namespace AwtterSDK.Editor.Models.API +{ + using System.Collections.Generic; + + public class ProductsModel + { + public string Status { get; set; } + public List Data { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/ProductsModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/ProductsModel.cs.meta new file mode 100644 index 0000000..5596241 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/ProductsModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8685129e354afd04ba68be0fd2ca7b89 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/ToolboxOkResponseModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/ToolboxOkResponseModel.cs new file mode 100644 index 0000000..7ff3900 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/ToolboxOkResponseModel.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AwtterSDK.Editor.Models.API +{ + public class ToolboxOkResponseModel + { + public string Path { get; set; } + public string Name { get; set; } + public string Icon { get; set; } + public List Files { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/ToolboxOkResponseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/ToolboxOkResponseModel.cs.meta new file mode 100644 index 0000000..ae9d676 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/ToolboxOkResponseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 744df01ddb31e3748806ad0a32b73eff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/ToolboxResponseModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/ToolboxResponseModel.cs new file mode 100644 index 0000000..8f34982 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/ToolboxResponseModel.cs @@ -0,0 +1,10 @@ +using AwtterSDK.Editor.Enums; + +namespace AwtterSDK.Editor.Models.API +{ + public class ToolboxResponseModel + { + public StatusType Status { get; set; } + public ToolboxOkResponseModel Data { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/ToolboxResponseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/ToolboxResponseModel.cs.meta new file mode 100644 index 0000000..3a39109 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/ToolboxResponseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9bc23ec014f9c08459aeb14fbe0a0152 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/TosResponseModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/TosResponseModel.cs new file mode 100644 index 0000000..bbef205 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/TosResponseModel.cs @@ -0,0 +1,8 @@ +namespace AwtterSDK.Editor.Models.API +{ + public class TosResponseModel + { + public string Text { get; set; } + public int Version { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/TosResponseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/TosResponseModel.cs.meta new file mode 100644 index 0000000..f89b277 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/TosResponseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d2f80d8660782ad4b914996dd09136b6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/UserModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/UserModel.cs new file mode 100644 index 0000000..f00981d --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/UserModel.cs @@ -0,0 +1,11 @@ +namespace AwtterSDK.Editor.Models.API +{ + public class UserModel + { + public int Id { get; set; } + public string Username { get; set; } + public string Email { get; set; } + public bool Admin { get; set; } + public DiscordInfoModel Discord { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/UserModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/UserModel.cs.meta new file mode 100644 index 0000000..d51aa29 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/UserModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 26ba624af77ce0a4fa896373930882b1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcFile.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcFile.cs new file mode 100644 index 0000000..c86ed19 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcFile.cs @@ -0,0 +1,11 @@ +namespace AwtterSDK.Editor.Models.API +{ + public class VrcFile + { + public string Name { get; set; } + public string DisplayName { get; set; } + public string Version { get; set; } + public string Unity { get; set; } + public string Url { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcFile.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcFile.cs.meta new file mode 100644 index 0000000..7cd0157 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcFile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cbdfd60557c014e42bb8bdc86fa8d1ba +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcPackage.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcPackage.cs new file mode 100644 index 0000000..e77dec7 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcPackage.cs @@ -0,0 +1,9 @@ +namespace AwtterSDK.Editor.Models.API +{ + using System.Collections.Generic; + + public class VrcPackage + { + public Dictionary Versions { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcPackage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcPackage.cs.meta new file mode 100644 index 0000000..8b02b3c --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcPackage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c83a84a9b98e0da429dbcbe383329e50 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcPackages.cs b/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcPackages.cs new file mode 100644 index 0000000..3f33445 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcPackages.cs @@ -0,0 +1,9 @@ +namespace AwtterSDK.Editor.Models.API +{ + using System.Collections.Generic; + + public class VrcPackages + { + public Dictionary Packages { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcPackages.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcPackages.cs.meta new file mode 100644 index 0000000..6a0c51f --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/API/VrcPackages.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a35577b1897a8e749886167302bd8c73 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/BaseView.cs b/Packages/com.killers0992.awttersdk/Editor/Models/BaseView.cs new file mode 100644 index 0000000..5d4e72a --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/BaseView.cs @@ -0,0 +1,34 @@ +using System; + +namespace AwtterSDK.Editor.Models +{ + public class BaseView + { + public int Id { get; set; } + public int ProductId { get; set; } + public string BaseName { get; set; } + public string Icon { get; set; } + public string Name { get; set; } + public string Version { get; set; } + public string InstalledVersion { get; set; } + public string DownloadUrl { get; set; } + public bool IsPatreon { get; set; } + + private Version _newVersion; + private Version _currentVersion; + public bool IsOutdated + { + get + { + if (_newVersion == null && !System.Version.TryParse(Version, out _newVersion)) + return false; + + if (_currentVersion == null && !System.Version.TryParse(InstalledVersion, out _currentVersion)) + return false; + + return _newVersion.CompareTo(_currentVersion) > 0; + } + } + public bool IsInstalled => AwtterSdkInstaller.InstalledPackages?.BaseModel?.Id == Id; + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/BaseView.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/BaseView.cs.meta new file mode 100644 index 0000000..3e7bfe9 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/BaseView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3bc9262f165a8f9428f5d448ae78df99 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/DlcView.cs b/Packages/com.killers0992.awttersdk/Editor/Models/DlcView.cs new file mode 100644 index 0000000..32e54e2 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/DlcView.cs @@ -0,0 +1,36 @@ +using System; + +namespace AwtterSDK.Editor.Models +{ + public class DlcView + { + public int Id { get; set; } + public int ProductId { get; set; } + public string Icon { get; set; } + public string Name { get; set; } + public string Version { get; set; } + public string InstalledVersion { get; set; } + public string DownloadUrl { get; set; } + public bool IsProp { get; set; } + public bool IsDlc { get; set; } + public bool IsPatreon { get; set; } + public bool IsInstalled => AwtterSdkInstaller.InstalledPackages != null && AwtterSdkInstaller.InstalledPackages.Dlcs.ContainsKey(Id); + + private Version _newVersion; + private Version _currentVersion; + public bool IsOutdated + { + get + { + if (_newVersion == null && !System.Version.TryParse(Version, out _newVersion)) + return false; + + if (_currentVersion == null && !System.Version.TryParse(InstalledVersion, out _currentVersion)) + return false; + + return _currentVersion.CompareTo(_newVersion) > 0; + } + } + public bool Install { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/DlcView.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/DlcView.cs.meta new file mode 100644 index 0000000..67eae51 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/DlcView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 56a402abb55228047ba2437db01245bb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/FileToInstallModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/FileToInstallModel.cs new file mode 100644 index 0000000..1498dec --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/FileToInstallModel.cs @@ -0,0 +1,41 @@ +using AwtterSDK.Editor.Enums; +using UnityEngine; + +namespace AwtterSDK.Editor.Models +{ + public class FileToInstallModel + { + public int Id { get; set; } + public string Name { get; set; } + public string Version { get; set; } + public string Displayname { get; set; } + public string Icon { get; set; } + public bool IsBaseModel { get; set; } + public bool IsDLC { get; set; } + public bool IsUnityPackage { get; set; } = true; + public bool RequiresAuth { get; set; } + public string DownloadUrl { get; set; } + public DownloadStatus DownloadStatus { get; set; } = DownloadStatus.Waiting; + public float DownloadProgress { get; set; } + + public Color DownloadStatusColor + { + get + { + switch (DownloadStatus) + { + case DownloadStatus.Waiting: + return Color.black; + case DownloadStatus.Installing: + return Color.cyan; + case DownloadStatus.Importing: + return Color.yellow; + case DownloadStatus.Installed: + return Color.green; + default: + return Color.red; + } + } + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/FileToInstallModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/FileToInstallModel.cs.meta new file mode 100644 index 0000000..711545e --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/FileToInstallModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 560efa7c3adae1745bb618e4c3ccbd16 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/InstalledBaseModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/InstalledBaseModel.cs new file mode 100644 index 0000000..42fd564 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/InstalledBaseModel.cs @@ -0,0 +1,13 @@ +using AwtterSDK.Editor.Models.API; +using Newtonsoft.Json; + +namespace AwtterSDK.Editor.Models +{ + public class InstalledPackageModel + { + public int Id { get; set; } + public string Version { get; set; } + [JsonIgnore] + public FileModel File { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/InstalledBaseModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/InstalledBaseModel.cs.meta new file mode 100644 index 0000000..4321615 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/InstalledBaseModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9e17d418fcb492442ac589254a6a3241 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/InstalledPackagesModel.cs b/Packages/com.killers0992.awttersdk/Editor/Models/InstalledPackagesModel.cs new file mode 100644 index 0000000..47122c0 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/InstalledPackagesModel.cs @@ -0,0 +1,37 @@ +using AwtterSDK.Editor.Installations; +using AwtterSDK.Editor.Interfaces; +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace AwtterSDK.Editor.Models +{ + public class InstalledPackagesModel + { + public static Dictionary CheckInstallStatuses = new Dictionary() + { + { "poiyomi", new PoyomiInstallation() }, + { "awttermerger", new MergerInstallation() }, + { "pumkintool", new PumkinInstallation() }, + }; + + public InstalledPackageModel BaseModel { get; set; } + public Dictionary Dlcs { get; set; } = new Dictionary(); + + [JsonIgnore] + public Dictionary Tools = new Dictionary(); + + public void CheckTools() + { + Tools.Clear(); + foreach (var tool in CheckInstallStatuses) + { + tool.Value.Check(); + if (tool.Value.IsInstalled) + Tools.Add(tool.Key, new InstalledPackageModel() + { + Version = tool.Value.InstalledVersion == null ? string.Empty : tool.Value.InstalledVersion.ToString(), + }); + } + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/InstalledPackagesModel.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/InstalledPackagesModel.cs.meta new file mode 100644 index 0000000..36886c3 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/InstalledPackagesModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 817806a468fc5c549816e3c58f932f90 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/PackageManifest.cs b/Packages/com.killers0992.awttersdk/Editor/Models/PackageManifest.cs new file mode 100644 index 0000000..88f8499 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/PackageManifest.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AwtterSDK.Editor.Models +{ + public class PackageManifest + { + public string Version { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/PackageManifest.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/PackageManifest.cs.meta new file mode 100644 index 0000000..9d43610 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/PackageManifest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cbe46a760df972e48ae3ac1b36f6c94e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/SceneInfo.cs b/Packages/com.killers0992.awttersdk/Editor/Models/SceneInfo.cs new file mode 100644 index 0000000..444e4b9 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/SceneInfo.cs @@ -0,0 +1,8 @@ +namespace AwtterSDK.Editor.Models +{ + public class SceneInfo + { + public string SceneName { get; set; } + public string FullPath { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/SceneInfo.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/SceneInfo.cs.meta new file mode 100644 index 0000000..e4009b7 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/SceneInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9eac8d7a130e62f4ca98a116ac78a8c1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/ToolView.cs b/Packages/com.killers0992.awttersdk/Editor/Models/ToolView.cs new file mode 100644 index 0000000..063e71a --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/ToolView.cs @@ -0,0 +1,76 @@ +using AwtterSDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Awtter_SDK.Editor.Models +{ + public class ToolView + { + public static List InstallByDefault = new List() + { + "awttermerger", + "poiyomi", + }; + + private bool? _install; + private string _simpleName; + + public int Id { get; set; } + public string Icon { get; set; } + + public string SimpleName + { + get + { + if (_simpleName == null) + _simpleName = Name.ToLower().Replace(" ", ""); + + return _simpleName; + } + } + + public string Name { get; set; } + public string Version { get; set; } + public string InstalledVersion { get; set; } + public string DownloadUrl { get; set; } + public bool IsInstalled => AwtterSdkInstaller.InstalledPackages != null && AwtterSdkInstaller.InstalledPackages.Tools.ContainsKey(SimpleName); + + private Version _newVersion; + private Version _currentVersion; + public bool IsOutdated + { + get + { + if (_newVersion == null && !System.Version.TryParse(Version, out _newVersion)) + return false; + + if (_currentVersion == null && !System.Version.TryParse(InstalledVersion, out _currentVersion)) + return false; + + return _currentVersion.CompareTo(_newVersion) > 0; + } + } + public bool Install + { + get + { + if (!_install.HasValue) + { + if (InstallByDefault.Contains(SimpleName) && !IsInstalled) + _install = true; + else + _install = false; + } + + return _install.Value; + } + set + { + _install = value; + } + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/ToolView.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/ToolView.cs.meta new file mode 100644 index 0000000..aaaa452 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/ToolView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b1ebd4ae08c89ea4aba07d99641aa597 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/UnityPackageFile.cs b/Packages/com.killers0992.awttersdk/Editor/Models/UnityPackageFile.cs new file mode 100644 index 0000000..3d9add4 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/UnityPackageFile.cs @@ -0,0 +1,14 @@ +namespace AwtterSDK.Editor.Models +{ + using AwtterSDK.Editor.Interfaces; + + public class UnityPackageFile + { + public int Id { get; set; } + public string Name { get; set; } + public string Icon { get; set; } + public string Url { get; set; } + public bool RequiresAuth { get; set; } + public ICheckInstallStatus InstallStatus { get; set; } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Models/UnityPackageFile.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Models/UnityPackageFile.cs.meta new file mode 100644 index 0000000..494b056 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Models/UnityPackageFile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 89e15e8bd6934f4418a5c0ef2631c7d1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages.meta b/Packages/com.killers0992.awttersdk/Editor/Pages.meta new file mode 100644 index 0000000..bf2d0e3 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 846ddafbf46c85c42a9854f25d51ba98 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/AddPackagesPage.cs b/Packages/com.killers0992.awttersdk/Editor/Pages/AddPackagesPage.cs new file mode 100644 index 0000000..08851e2 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/AddPackagesPage.cs @@ -0,0 +1,110 @@ +using AwtterSDK.Editor.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace AwtterSDK.Editor.Pages +{ + public class AddPackagesPage : IPage + { + private AwtterSdkInstaller _main; + public GUIStyle CustomButton; + public Vector2 Scroll = Vector2.zero; + + public void Load(AwtterSdkInstaller main) + { + _main = main; + + CustomButton = new GUIStyle(GUI.skin.button); + CustomButton.fontSize = 15; + CustomButton.alignment = TextAnchor.MiddleCenter; + } + + public void DrawGUI(Rect pos) + { + GUILayout.Space(15); + Utils.CreateBox("Additional packages"); + GUILayout.Space(15); + Scroll = GUILayout.BeginScrollView(Scroll); + if (AwtterSdkInstaller.AvaliableDlcs.Any(x => !x.IsProp && x.IsDlc && !x.IsPatreon)) + { + Utils.CreateBox("DLCS"); + GUILayout.Space(5); + foreach(var dlc in AwtterSdkInstaller.AvaliableDlcs.Where(x => x.IsDlc && !x.IsPatreon)) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(dlc.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUI.color = dlc.Install ? Color.green : Color.white; + if (GUILayout.Button(dlc.Name, CustomButton, GUILayout.Height(32))) + { + dlc.Install = !dlc.Install; + } + GUI.color = Color.white; + GUILayout.EndHorizontal(); + } + GUILayout.Space(5); + } + + if (AwtterSdkInstaller.AvaliableDlcs.Any(x => x.IsProp && !x.IsPatreon)) + { + Utils.CreateBox("Props"); + GUILayout.Space(5); + foreach (var prop in AwtterSdkInstaller.AvaliableDlcs.Where(x => x.IsProp && !x.IsPatreon )) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(prop.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUI.color = prop.Install ? Color.green : Color.white; + if (GUILayout.Button(prop.Name, CustomButton, GUILayout.Height(32))) + { + prop.Install = !prop.Install; + } + GUI.color = Color.white; + GUILayout.EndHorizontal(); + } + GUILayout.Space(5); + } + + if (AwtterSdkInstaller.AvaliableTools.Any(x => !x.IsInstalled)) + { + Utils.CreateBox("Tools"); + GUILayout.Space(5); + foreach (var tool in AwtterSdkInstaller.AvaliableTools.Where(x => !x.IsInstalled)) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(tool.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUI.color = tool.Install ? Color.green : Color.white; + if (GUILayout.Button(tool.Name, CustomButton, GUILayout.Height(32))) + { + tool.Install = !tool.Install; + } + GUI.color = Color.white; + GUILayout.EndHorizontal(); + } + GUILayout.Space(5); + } + + GUILayout.EndScrollView(); + GUILayout.Space(15); + GUILayout.BeginHorizontal(); + GUI.color = Color.red; + if (GUILayout.Button("Go back", _main.Shared.WindowCustomButton3, GUILayout.MinHeight(27))) + AwtterSdkInstaller.ViewAdditionalPackages = false; + GUI.color = Color.white; + + GUILayout.Space(10); + GUI.color = Color.green; + if (GUILayout.Button("Run SDK Installer", _main.Shared.WindowCustomButton3, GUILayout.MinHeight(27))) + AwtterSdkInstaller.IsInstalling = true; + GUI.color = Color.white; + GUILayout.EndHorizontal(); + } + + + public void Reset() + { + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/AddPackagesPage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Pages/AddPackagesPage.cs.meta new file mode 100644 index 0000000..4dba1ee --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/AddPackagesPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 092739bc522f34a4ea3bbdeae5a9a6b8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/InstallPage.cs b/Packages/com.killers0992.awttersdk/Editor/Pages/InstallPage.cs new file mode 100644 index 0000000..7903a49 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/InstallPage.cs @@ -0,0 +1,357 @@ +using AwtterSDK.Editor.Installations; +using AwtterSDK.Editor.Interfaces; +using AwtterSDK.Editor.Models; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Unity.EditorCoroutines.Editor; +using Unity.SharpZipLib.Zip; +using UnityEditor; +using UnityEngine; +using UnityEngine.Networking; + +namespace AwtterSDK.Editor.Pages +{ + class AwtterSdkAssets : AssetPostprocessor + { + static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) + { + if (AwtterSdkInstaller.IsInstalling) return; + + InstallPage.CheckForChanges = true; + AwtterSdkInstaller.Refresh = true; + } + } + + public class InstallPage : IPage + { + public static bool CheckForChanges; + + public List PackagesToInstall = new List(); + + public GUIStyle CustomButton; + public GUIStyle CustomLabel; + + public Vector2 BasesScroll = Vector2.zero; + public Vector2 DlcsScroll = Vector2.zero; + public Vector2 InstallStatus = Vector2.zero; + public Vector2 OutdateStatus = Vector2.zero; + + public bool ShowingBases; + + public bool IsUpToDate; + + private AwtterSdkInstaller _main; + + public void Load(AwtterSdkInstaller main) + { + _main = main; + CustomLabel = new GUIStyle(GUI.skin.label); + CustomLabel.richText = true; + CustomLabel.alignment = TextAnchor.MiddleCenter; + + CustomButton = new GUIStyle(GUI.skin.button); + CustomButton.fontSize = 15; + CustomButton.alignment = TextAnchor.MiddleCenter; + + CheckChanges(); + } + + void RefreshDlcs() + { + foreach (var dlc in AwtterSdkInstaller.AvaliableDlcs) + dlc.Install = false; + } + + void CheckChanges() + { + if (AwtterSdkInstaller.Products == null) return; + + RefreshDlcs(); + + PackagesToInstall.Clear(); + + foreach (var package in AwtterSdkInstaller.UnityPackages) + { + package.InstallStatus.Check(); + if (!package.InstallStatus.IsInstalled) + PackagesToInstall.Add(package); + } + } + + public void DrawGUI(Rect pos) + { + if (CheckForChanges) + CheckChanges(); + + GUILayout.Space(10f); + + if (EditorGUILayout.DropdownButton(AwtterSdkInstaller.CurrentBase == null ? new GUIContent("Select base to install") : + new GUIContent($"Selected base {AwtterSdkInstaller.CurrentBase.Name}"), FocusType.Keyboard, GUILayout.Height(25))) + ShowingBases = !ShowingBases; + + GUILayout.Space(10f); + + if (ShowingBases) + { + GUILayout.BeginVertical("window", GUILayout.Height(130f)); + BasesScroll = GUILayout.BeginScrollView(BasesScroll); + foreach (var baseModel in AwtterSdkInstaller.AvaliableBases.Where(x => !x.IsInstalled)) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(baseModel.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUI.color = AwtterSdkInstaller.CurrentBase == baseModel ? Color.green : Color.white; + if (GUILayout.Button(baseModel.Name, CustomButton, GUILayout.Height(32))) + { + if (AwtterSdkInstaller.CurrentBase != baseModel) + { + AwtterSdkInstaller.CurrentBase = baseModel; + _main.UpdateAwtterPackages(); + ShowingBases = false; + } + } + GUI.color = Color.white; + GUILayout.EndHorizontal(); + } + GUILayout.EndScrollView(); + GUILayout.EndVertical(); + } + else + { + GUILayout.BeginVertical("window", GUILayout.Height(130f)); + if (AwtterSdkInstaller.AvaliableDlcs.Where(x => !x.IsInstalled).Count() == 0) + { + GUILayout.Label("You dont have any owned DLCS!", CustomLabel); + } + else + { + DlcsScroll = GUILayout.BeginScrollView(DlcsScroll); + foreach (var dlc in AwtterSdkInstaller.AvaliableDlcs.Where(x => !x.IsInstalled)) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(dlc.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUI.color = dlc.Install ? Color.green : Color.white; + if (GUILayout.Button(dlc.Name, CustomButton, GUILayout.Height(32))) + { + dlc.Install = !dlc.Install; + } + GUI.color = Color.white; + GUILayout.EndHorizontal(); + } + GUILayout.EndScrollView(); + } + GUILayout.EndVertical(); + } + GUILayout.Space(15f); + + if (GUILayout.Button("▶ Run SDK Installer", _main.Shared.WindowCustomButton3, GUILayout.MinHeight(27))) + AwtterSdkInstaller.IsInstalling = true; + + GUI.enabled = true; + + GUILayout.Space(15f); + + InstallStatus = GUILayout.BeginScrollView(InstallStatus, false, true); + bool anythingToShow = false; + + if (AwtterSdkInstaller.CurrentBase != null) + { + Utils.CreateBox("Base Model"); + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(AwtterSdkInstaller.CurrentBase.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUILayout.Label(AwtterSdkInstaller.CurrentBase.Name, CustomLabel, GUILayout.Height(32)); + GUILayout.EndHorizontal(); + anythingToShow = true; + } + + if (AwtterSdkInstaller.AvaliableDlcs.Any(x => x.Install)) + { + Utils.CreateBox("DLCS"); + + foreach (var dlc in AwtterSdkInstaller.AvaliableDlcs.Where(x => x.Install)) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(dlc.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUILayout.Label(dlc.Name, CustomLabel, GUILayout.Height(32)); + GUILayout.EndHorizontal(); + GUILayout.Space(15); + } + anythingToShow = true; + } + + if (PackagesToInstall.Count != 0) + { + Utils.CreateBox("Unity Packages"); + + foreach (var file in PackagesToInstall) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(file.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUILayout.Label(file.Name, CustomLabel, GUILayout.Height(32)); + GUILayout.EndHorizontal(); + GUILayout.Space(15); + } + anythingToShow = true; + } + + IsUpToDate = !anythingToShow; + if (IsUpToDate) + GUILayout.Label("Everything is up to date", CustomLabel); + + GUILayout.EndScrollView(); + } + + /* public IEnumerator InstallationProcess() + { + + + int currentPackage = 1; + foreach (var vrcFile in AwtterSdkInstaller.VrcFilesToInstall) + { + using (var www = UnityWebRequest.Get(vrcFile.Url)) + { + AsyncOperation request = www.SendWebRequest(); + + while (!request.isDone) + { + EditorUtility.DisplayProgressBar($"Downloading VRC Packages ( {currentPackage}/{AwtterSdkInstaller.VrcFilesToInstall.Count} )", vrcFile.DisplayName, www.downloadProgress); + } + + switch (www.responseCode) + { + case 200: + File.WriteAllBytes(Path.Combine(packagesFolder, $"{vrcFile.Name}.zip"), www.downloadHandler.data); + + zip.ExtractZip(Path.Combine(packagesFolder, $"{vrcFile.Name}.zip"), Path.Combine(packagesFolder, vrcFile.Name), null); + + File.Delete(Path.Combine(packagesFolder, $"{vrcFile.Name}.zip")); + break; + default: + Debug.LogError($"[Awtter SDK] Failed downloading vrchat package {vrcFile.Name}, responseCode {www.responseCode}, message {www.downloadHandler.text}"); + break; + } + EditorUtility.ClearProgressBar(); + } + currentPackage++; + } + + currentPackage = 1; + foreach (var package in PackagesToInstall) + { + bool poi = false; + if (package.InstallStatus is PoyomiInstallation d) + { + package.Url = $""; + poi = true; + } + + using (var www = UnityWebRequest.Get(package.Url)) + { + if (poi) + www.SetRequestHeader("Authorization", $"Token {TokenCache.Token}"); + + AsyncOperation request = www.SendWebRequest(); + + while (!request.isDone) + { + EditorUtility.DisplayProgressBar($"Downloading Unity Packages ( {currentPackage}/{AwtterSdkInstaller.UnityPackages.Count} )", package.Name, www.downloadProgress); + } + + switch (www.responseCode) + { + case 200: + + break; + default: + Debug.LogError($"[Awtter SDK] Failed downloading unity package {package.Name}, responseCode {www.responseCode}, message {www.downloadHandler.text}"); + break; + } + EditorUtility.ClearProgressBar(); + } + currentPackage++; + } + + if (!AwtterSdkInstaller.IsBaseIntalled && AwtterSdkInstaller.CurrentBase != null) + { + using (var www = UnityWebRequest.Get(AwtterSdkInstaller.CurrentBase.DownloadUrl)) + { + www.SetRequestHeader("Authorization", $"Token {TokenCache.Token}"); + + AsyncOperation request = www.SendWebRequest(); + + while (!request.isDone) + { + EditorUtility.DisplayProgressBar($"Downloading Base Model", AwtterSdkInstaller.CurrentBase.Name, www.downloadProgress); + } + + switch (www.responseCode) + { + case 200: + string fileName = "BaseModel.unitypackage"; + + File.WriteAllBytes(Path.Combine(Application.dataPath, fileName), www.downloadHandler.data); + + AssetDatabase.ImportPackage(Path.Combine(Application.dataPath, fileName), false); + File.Delete(Path.Combine(Application.dataPath, fileName)); + + AwtterSdkInstaller.InstalledPackages.BaseModel = new InstalledPackageModel() + { + Id = AwtterSdkInstaller.CurrentBase.Id, + Version = AwtterSdkInstaller.CurrentBase.Version + }; + break; + default: + Debug.LogError($"[Awtter SDK] Failed downloading model base {AwtterSdkInstaller.CurrentBase.Name}, responseCode {www.responseCode}, message {www.downloadHandler.text}"); + break; + } + EditorUtility.ClearProgressBar(); + } + } + + currentPackage = 1; + foreach (var dlc in SelectedDlcs) + { + using (var www = UnityWebRequest.Get(dlc.DownloadUrl)) + { + www.SetRequestHeader("Authorization", $"Token {TokenCache.Token}"); + + AsyncOperation request = www.SendWebRequest(); + + while (!request.isDone) + { + EditorUtility.DisplayProgressBar($"Downloading Dlcs ( {currentPackage}/{SelectedDlcs.Count} )", dlc.Name, www.downloadProgress); + } + + switch (www.responseCode) + { + case 200: + string fileName = $"Dlc{dlc.Id}.unitypackage"; + + File.WriteAllBytes(Path.Combine(Application.dataPath, fileName), www.downloadHandler.data); + + AssetDatabase.ImportPackage(Path.Combine(Application.dataPath, fileName), false); + File.Delete(Path.Combine(Application.dataPath, fileName)); + + + break; + default: + Debug.LogError($"[Awtter SDK] Failed downloading dlc {dlc.Name}, responseCode {www.responseCode}, message {www.downloadHandler.text}"); + break; + } + + EditorUtility.ClearProgressBar(); + } + } + + _main.SaveInstalledPackagesStorage(); + _main.UpdateAwtterPackages(); + IsInstalling = false; + yield break; + }*/ + + public void Reset() + { + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/InstallPage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Pages/InstallPage.cs.meta new file mode 100644 index 0000000..f13a68b --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/InstallPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2167825f0fbe7484db9ed566e54216cb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/InstallProgressPage.cs b/Packages/com.killers0992.awttersdk/Editor/Pages/InstallProgressPage.cs new file mode 100644 index 0000000..922af3e --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/InstallProgressPage.cs @@ -0,0 +1,120 @@ +using AwtterSDK.Editor.Interfaces; +using AwtterSDK.Editor.Models; +using System; +using System.Collections; +using System.Collections.Generic; +using Unity.EditorCoroutines.Editor; +using UnityEditor; +using UnityEngine; +using UnityEngine.Networking; + +namespace AwtterSDK.Editor.Pages +{ + public class InstallProgressPage : IPage + { + private AwtterSdkInstaller _main; + private Vector2 _progressScroll = Vector2.zero; + + private GUIStyle CustomLabel; + + public void Load(AwtterSdkInstaller main) + { + _main = main; + CustomLabel = new GUIStyle(GUI.skin.label); + CustomLabel.richText = true; + CustomLabel.alignment = TextAnchor.MiddleCenter; + EditorCoroutineUtility.StartCoroutine(DownloadFile(AwtterSdkInstaller.FilesToInstall), this); + } + + public void DrawGUI(Rect pos) + { + GUILayout.Space(7); + GUILayout.Label("Installation progress", CustomLabel); + + _progressScroll = GUILayout.BeginScrollView(_progressScroll, false, true); + foreach (var file in AwtterSdkInstaller.FilesToInstall) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(file.Icon), GUILayout.Height(45), GUILayout.Width(45)); + GUILayout.Label(file.Displayname, CustomLabel, GUILayout.Height(32)); + GUILayout.EndHorizontal(); + Rect myRect = GUILayoutUtility.GetLastRect(); + GUI.color = file.DownloadStatusColor; + EditorGUI.ProgressBar(new Rect(myRect.x, myRect.y + 32f, myRect.width, 16f), file.DownloadProgress, String.Format("{0:P2}", file.DownloadProgress)); + GUI.color = Color.white; + GUILayout.Space(30); + } + GUILayout.EndScrollView(); + GUILayout.Space(7); + EditorGUILayout.HelpBox("Wait until installing finishes!", MessageType.Warning); + } + + private bool Download(int index, int maximumIndex, FileToInstallModel file) + { + using (var www = UnityWebRequest.Get(file.DownloadUrl)) + { + if (file.RequiresAuth) + www.SetRequestHeader("Authorization", $"Token {TokenCache.Token}"); + + AsyncOperation request = www.SendWebRequest(); + + while (!request.isDone) + { + EditorUtility.DisplayProgressBar($"Downloading packages", $"Downloading {file.Displayname} {index}/{maximumIndex}", request.progress); + } + + switch (www.responseCode) + { + case 200: + FilesCache.CacheFile(file, www.downloadHandler.data); + return true; + default: + Debug.LogError($"[Awtter SDK] Failed downloading {file.Displayname}, responseCode {www.responseCode}, message {www.downloadHandler.text}"); + break; + } + } + return false; + } + + private IEnumerator DownloadFile(List files) + { + for(int x =0; x < files.Count; x++) + { + var file = files[x]; + + if (!FilesCache.GetCachedFile(file)) + { + Download(x + 1, files.Count, file); + if (!FilesCache.GetCachedFile(file)) continue; + } + + if (file.IsBaseModel) + { + AwtterSdkInstaller.InstalledPackages.BaseModel = new InstalledPackageModel() + { + Id = file.Id, + Version = file.Version + }; + } + else if (file.IsDLC) + { + if (AwtterSdkInstaller.InstalledPackages.Dlcs.ContainsKey(file.Id)) break; + + AwtterSdkInstaller.InstalledPackages.Dlcs.Add(file.Id, new InstalledPackageModel() + { + Id = file.Id, + Version = file.Version + }); + } + } + EditorUtility.ClearProgressBar(); + AwtterSdkInstaller.IsInstalling = false; + yield break; + } + + public void Reset() + { + _progressScroll = Vector2.zero; + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/InstallProgressPage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Pages/InstallProgressPage.cs.meta new file mode 100644 index 0000000..4f555b2 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/InstallProgressPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f2d507748b8cc2498ab230f6d98dea2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/LoginPage.cs b/Packages/com.killers0992.awttersdk/Editor/Pages/LoginPage.cs new file mode 100644 index 0000000..03dfe2e --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/LoginPage.cs @@ -0,0 +1,123 @@ +namespace AwtterSDK.Editor.Pages +{ + using UnityEditor; + + using UnityEngine; + using UnityEngine.Networking; + + using AwtterSDK.Editor.Interfaces; + using AwtterSDK.Editor.Models.API; + + using Unity.EditorCoroutines.Editor; + + using System.Collections; + using System.Collections.Generic; + using AwtterSDK.Editor; + using Newtonsoft.Json; + using AwtterSDK; + using AwtterSDK.Editor.Enums; + + public class LoginPage : IPage + { + public bool TryLogin = true; + + public string Username = string.Empty; + public string Password = string.Empty; + + public string ErrorBox = null; + + private AwtterSdkInstaller _main; + + public void Load(AwtterSdkInstaller main) + { + _main = main; + } + + public void DrawGUI(Rect pos) + { + if (TryLogin) + { + EditorCoroutineUtility.StartCoroutine(Login(true), this); + TryLogin = false; + } + GUILayout.FlexibleSpace(); + GUILayout.BeginVertical("Account", "window", GUILayout.Height(120)); + + Username = EditorGUILayout.TextField("Email or Username", Username); + Password = EditorGUILayout.PasswordField("Password", Password); + + if (ErrorBox != null) + EditorGUILayout.HelpBox(ErrorBox, MessageType.Error); + + if (Username.Length == 0 || Password.Length == 0) + GUI.enabled = false; + + if (GUILayout.Button("Login")) + EditorCoroutineUtility.StartCoroutine(Login(), this); + + GUI.enabled = true; + + if (GUILayout.Button("Register")) + Application.OpenURL("https://shadedoes3d.com/accounts/register/"); + + GUILayout.EndVertical(); + GUILayout.FlexibleSpace(); + } + + public IEnumerator Login(bool first = false) + { + yield return AwtterApi.GetProducts(); + + if (AwtterSdkInstaller.LoggedIn) + yield break; + + if (first) yield break; + + using (var www = UnityWebRequest.Post("https://shadedoes3d.com/api/auth", new Dictionary() + { + { "username", Username }, + { "password", Password } + })) + { + yield return www.SendWebRequest(); + + switch (www.responseCode) + { + // Success response. + case 200: + var authResponse = JsonConvert.DeserializeObject(www.downloadHandler.text); + + if (authResponse.Status != StatusType.Success) + { + ErrorBox = $"Response code {authResponse.Status}"; + Debug.LogError($"[Awtter SDK] {ErrorBox}!"); + yield break; + } + + TokenCache.Token = authResponse.Data.Token; + + Debug.Log("[Awtter SDK] Logged in!"); + yield return AwtterApi.GetProducts(false); + AwtterSdkInstaller.LoggedIn = true; + break; + // Bad response. + case 404: + var badResponse = JsonConvert.DeserializeObject(www.downloadHandler.text); + ErrorBox = badResponse.Message; + Debug.LogError($"[Awtter SDK] {ErrorBox}!"); + break; + } + } + } + + public void Reset() + { + TryLogin = true; + + Username = string.Empty; + Password = string.Empty; + + ErrorBox = null; + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/LoginPage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Pages/LoginPage.cs.meta new file mode 100644 index 0000000..5d7c691 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/LoginPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15fd74ec46b9ecb4b87ca01d505d55ab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/ManagePackagesPage.cs b/Packages/com.killers0992.awttersdk/Editor/Pages/ManagePackagesPage.cs new file mode 100644 index 0000000..e501613 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/ManagePackagesPage.cs @@ -0,0 +1,109 @@ +using AwtterSDK.Editor.Interfaces; +using System; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace AwtterSDK.Editor.Pages +{ + public class ManagePackagesPage : IPage + { + private Vector2 _packagesScroll = Vector2.zero; + private AwtterSdkInstaller _main; + private GUIStyle CustomLabel; + + public void Load(AwtterSdkInstaller main) + { + _main = main; + CustomLabel = new GUIStyle(GUI.skin.label); + CustomLabel.richText = true; + CustomLabel.alignment = TextAnchor.MiddleCenter; + } + + public void DrawGUI(Rect pos) + { + EditorGUILayout.Space(10); + _packagesScroll = GUILayout.BeginScrollView(_packagesScroll, false, true, GUILayout.Height(281)); + Utils.CreateBox("Base"); + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(AwtterSdkInstaller.CurrentBase.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUILayout.Label(AwtterSdkInstaller.CurrentBase.Name, CustomLabel, GUILayout.Height(32)); + GUILayout.EndHorizontal(); + GUI.color = AwtterSdkInstaller.CurrentBase.IsOutdated ? Color.yellow : Color.green; + GUI.enabled = false; + GUILayout.BeginHorizontal(); + GUILayout.Label($"Version {(AwtterSdkInstaller.CurrentBase.IsOutdated ? $"{AwtterSdkInstaller.CurrentBase.Version} > {AwtterSdkInstaller.CurrentBase.Version}" : AwtterSdkInstaller.CurrentBase.InstalledVersion)}"); + GUILayout.FlexibleSpace(); + GUILayout.Button(AwtterSdkInstaller.CurrentBase.IsOutdated ? $"🗱 Update" : $"✔ Installed", _main.Shared.WindowCustomButton3, GUILayout.Height(26), GUILayout.Width(150)); + GUILayout.EndHorizontal(); + GUI.enabled = true; + GUI.color = Color.white; + GUILayout.Space(30); + + if (AwtterSdkInstaller.AvaliableDlcs.Count != 0) + Utils.CreateBox("DLCS"); + foreach (var dlc in AwtterSdkInstaller.AvaliableDlcs) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(dlc.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUILayout.Label(dlc.Name, CustomLabel, GUILayout.Height(32)); + GUILayout.EndHorizontal(); + GUI.color = dlc.Install ? Color.yellow : dlc.IsInstalled ? Color.green : dlc.IsOutdated ? Color.yellow : Color.cyan; + GUI.enabled = !dlc.IsInstalled; + GUILayout.BeginHorizontal(); + GUILayout.Label($"Version {(dlc.IsInstalled ? dlc.IsOutdated ? $"{dlc.Version} > {dlc.Version}" : dlc.InstalledVersion : dlc.Version)}"); + GUILayout.FlexibleSpace(); + if (GUILayout.Button(dlc.IsInstalled ? $"✔ Installed" : dlc.IsOutdated ? $"🗱 Update" : $"⇩ Install", _main.Shared.WindowCustomButton3, GUILayout.Height(26), GUILayout.Width(150))) + { + dlc.Install = !dlc.Install; + } + GUILayout.EndHorizontal(); + GUI.enabled = true; + GUI.color = Color.white; + GUILayout.Space(30); + } + + if (AwtterSdkInstaller.AvaliableTools.Count != 0) + Utils.CreateBox("Tools"); + foreach (var tool in AwtterSdkInstaller.AvaliableTools) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(tool.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUILayout.Label(tool.Name, CustomLabel, GUILayout.Height(32)); + GUILayout.EndHorizontal(); + GUI.color = tool.Install ? Color.yellow : tool.IsInstalled ? Color.green : tool.IsOutdated ? Color.yellow : Color.cyan; + GUI.enabled = !tool.IsInstalled; + GUILayout.BeginHorizontal(); + GUILayout.Label($"Version {(tool.IsInstalled ? tool.IsOutdated ? $"{tool.Version} > {tool.Version}" : tool.InstalledVersion : tool.Version)}"); + GUILayout.FlexibleSpace(); + if (GUILayout.Button(tool.IsInstalled ? $"✔ Installed" : tool.IsOutdated ? $"🗱 Update" : $"⇩ Install", _main.Shared.WindowCustomButton3, GUILayout.Height(26), GUILayout.Width(150))) + { + tool.Install = !tool.Install; + } + GUILayout.EndHorizontal(); + GUI.enabled = true; + GUI.color = Color.white; + GUILayout.Space(30); + } + GUILayout.EndScrollView(); + + GUI.enabled = AwtterSdkInstaller.AvaliableDlcs.Any(x => x.Install) || AwtterSdkInstaller.AvaliableTools.Any(x => x.Install); + GUI.color = (AwtterSdkInstaller.AvaliableDlcs.Any(x => x.Install) || AwtterSdkInstaller.AvaliableTools.Any(x => x.Install)) ? Color.green : Color.gray; + if (GUILayout.Button("▶ Run SDK Installer", _main.Shared.WindowCustomButton3, GUILayout.Height(27))) + AwtterSdkInstaller.IsInstalling = true; + GUI.color = Color.white; + GUI.enabled = true; + EditorGUILayout.BeginVertical(); + if (GUILayout.Button($"Show scenes")) + { + AwtterSdkInstaller.ViewManagePackages = !AwtterSdkInstaller.ViewManagePackages; + } + EditorGUILayout.EndVertical(); + } + + public void Reset() + { + _packagesScroll = Vector2.zero; + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/ManagePackagesPage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Pages/ManagePackagesPage.cs.meta new file mode 100644 index 0000000..54a9796 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/ManagePackagesPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2698c3439f4941e47b05c526f7fd9c2c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/ModelSelectionPage.cs b/Packages/com.killers0992.awttersdk/Editor/Pages/ModelSelectionPage.cs new file mode 100644 index 0000000..403186d --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/ModelSelectionPage.cs @@ -0,0 +1,197 @@ +using AwtterSDK.Editor.Installations; +using AwtterSDK.Editor.Interfaces; +using AwtterSDK.Editor.Models; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Unity.EditorCoroutines.Editor; +using Unity.SharpZipLib.Zip; +using UnityEditor; +using UnityEngine; +using UnityEngine.Networking; +using UnityEngine.UIElements; + +namespace AwtterSDK.Editor.Pages +{ + public class ModelSelectionPage : IPage + { + public static Color OrangeColor = new Color(1.0f, 0.64f, 0.0f); + public static Texture2D Green; + + public static bool CheckForChanges; + + public List PackagesToInstall = new List(); + + public GUIStyle CustomButton2; + public GUIStyle CustomButton; + public GUIStyle CustomLabel; + + public Vector2 Scroll = Vector2.zero; + public Vector2 InstallStatus = Vector2.zero; + + public bool ShowingBases; + + public bool IsUpToDate; + + private AwtterSdkInstaller _main; + + public void Load(AwtterSdkInstaller main) + { + Green = Utils.CreateTexture(10, 10, Color.green); + _main = main; + CustomLabel = new GUIStyle(GUI.skin.label); + CustomLabel.richText = true; + CustomLabel.alignment = TextAnchor.MiddleCenter; + + CustomButton = new GUIStyle(GUI.skin.button); + CustomButton.fontSize = 15; + CustomButton.alignment = TextAnchor.MiddleCenter; + CustomButton.normal.textColor = Color.white; + + CustomButton2 = new GUIStyle(GUI.skin.button); + CustomButton2.fontSize = 15; + CustomButton2.alignment = TextAnchor.MiddleCenter; + CustomButton2.normal.textColor = Color.green; + + CheckChanges(); + } + + void RefreshDlcs() + { + foreach (var dlc in AwtterSdkInstaller.AvaliableDlcs) + dlc.Install = false; + } + + void CheckChanges() + { + if (AwtterSdkInstaller.Products == null) return; + + RefreshDlcs(); + + PackagesToInstall.Clear(); + + foreach (var package in AwtterSdkInstaller.UnityPackages) + { + package.InstallStatus.Check(); + if (!package.InstallStatus.IsInstalled) + PackagesToInstall.Add(package); + } + } + + public void DrawGUI(Rect pos) + { + if (CheckForChanges) + CheckChanges(); + + GUILayout.Space(15); + Utils.CreateBox("BASE MODEL SELECTION"); + GUILayout.Space(15); + Scroll = GUILayout.BeginScrollView(Scroll); + GUILayout.Space(5); + foreach (var baseModel in AwtterSdkInstaller.AvaliableBases.Where(x => !x.IsPatreon)) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(baseModel.Icon), GUILayout.Height(32), GUILayout.Width(32)); + if (GUILayout.Button(baseModel.Name, AwtterSdkInstaller.CurrentBase?.Id == baseModel.Id ? CustomButton2 : CustomButton, GUILayout.Height(32))) + { + AwtterSdkInstaller.CurrentBase = AwtterSdkInstaller.CurrentBase?.Id == baseModel.Id ? null : baseModel; + _main.UpdateAwtterPackages(); + } + GUILayout.EndHorizontal(); + } + GUILayout.EndScrollView(); + GUILayout.Space(15); + + GUI.color = Color.cyan; + if (GUILayout.Button("PATREON ITEMS", _main.Shared.WindowCustomButton3, GUILayout.MinHeight(15))) + AwtterSdkInstaller.ViewPatreonItems = true; + GUI.color = Color.white; + GUILayout.Space(6); + + GUI.color = OrangeColor; + if (GUILayout.Button("DLCs - Props - Tools ", _main.Shared.WindowCustomButton3, GUILayout.MinHeight(15))) + AwtterSdkInstaller.ViewAdditionalPackages = true; + GUI.color = Color.white; + GUILayout.Space(6); + GUI.color = Color.green; + + if (GUILayout.Button("Run SDK Installer", _main.Shared.WindowCustomButton3, GUILayout.MinHeight(27))) + AwtterSdkInstaller.IsInstalling = true; + + GUI.enabled = true; + GUI.color = Color.white; + GUILayout.Space(15); + + GUILayout.Space(15f); + + InstallStatus = GUILayout.BeginScrollView(InstallStatus, false, true); + bool anythingToShow = false; + + if (AwtterSdkInstaller.CurrentBase != null) + { + Utils.CreateBox("Base Model"); + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(AwtterSdkInstaller.CurrentBase.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUILayout.Label(AwtterSdkInstaller.CurrentBase.Name, CustomLabel, GUILayout.Height(32)); + GUILayout.EndHorizontal(); + anythingToShow = true; + } + + if (AwtterSdkInstaller.AvaliableDlcs.Any(x => x.Install)) + { + Utils.CreateBox("DLCS"); + + foreach (var dlc in AwtterSdkInstaller.AvaliableDlcs.Where(x => x.Install)) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(dlc.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUILayout.Label(dlc.Name, CustomLabel, GUILayout.Height(32)); + GUILayout.EndHorizontal(); + GUILayout.Space(15); + } + anythingToShow = true; + } + + if (AwtterSdkInstaller.AvaliableTools.Any(x => x.Install)) + { + Utils.CreateBox("Tools"); + + foreach (var tool in AwtterSdkInstaller.AvaliableTools.Where(x => x.Install)) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(tool.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUILayout.Label(tool.Name, CustomLabel, GUILayout.Height(32)); + GUILayout.EndHorizontal(); + GUILayout.Space(15); + } + anythingToShow = true; + } + + if (PackagesToInstall.Count != 0) + { + Utils.CreateBox("Unity Packages"); + + foreach (var file in PackagesToInstall) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(file.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUILayout.Label(file.Name, CustomLabel, GUILayout.Height(32)); + GUILayout.EndHorizontal(); + GUILayout.Space(15); + } + anythingToShow = true; + } + + IsUpToDate = !anythingToShow; + if (IsUpToDate) + GUILayout.Label("Everything is up to date", CustomLabel); + + GUILayout.EndScrollView(); + } + + public void Reset() + { + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/ModelSelectionPage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Pages/ModelSelectionPage.cs.meta new file mode 100644 index 0000000..0eeabd3 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/ModelSelectionPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9291f272a5abee4478af6a37ef7fcb15 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/PatreonBenefitsPage.cs b/Packages/com.killers0992.awttersdk/Editor/Pages/PatreonBenefitsPage.cs new file mode 100644 index 0000000..c5d4c94 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/PatreonBenefitsPage.cs @@ -0,0 +1,145 @@ +using AwtterSDK.Editor.Interfaces; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace AwtterSDK.Editor.Pages +{ + public class PatreonBenefitsPage : IPage + { + private AwtterSdkInstaller _main; + private Texture2D _awtterInboxImage; + + public Texture2D AwtterInboxImage + { + get + { + if (_awtterInboxImage == null) + _awtterInboxImage = AssetDatabase.LoadAssetAtPath(Path.Combine(Paths.MainPath, "Editor", "Textures", "inbox.png")); + + return _awtterInboxImage; + } + } + + public GUIStyle CustomButton; + public GUIStyle CustomButton2; + + public Vector2 Scroll = Vector2.zero; + + public void Load(AwtterSdkInstaller main) + { + _main = main; + + CustomButton = new GUIStyle(GUI.skin.button); + CustomButton.fontSize = 15; + CustomButton.alignment = TextAnchor.MiddleCenter; + + CustomButton2 = new GUIStyle(GUI.skin.button); + CustomButton2.fontSize = 15; + CustomButton2.alignment = TextAnchor.MiddleCenter; + CustomButton2.normal.textColor = Color.green; + } + + public void DrawGUI(Rect pos) + { + GUILayout.Space(15); + Utils.CreateBox("Patreon items"); + GUILayout.Space(15); + + if (AwtterSdkInstaller.Patreon == null || !AwtterSdkInstaller.Patreon.Active) + { + Utils.CreateBox("Looks like there's nothing here, are you a Patreon ?"); + if (AwtterInboxImage != null) + GUI.DrawTexture(new Rect(0, 360, pos.size.x, 180), AwtterInboxImage, ScaleMode.ScaleToFit); + GUILayout.Space(238); + End(); + return; + } + + Scroll = GUILayout.BeginScrollView(Scroll); + if (AwtterSdkInstaller.AvaliableBases.Any(x => x.IsPatreon)) + { + Utils.CreateBox("BASES"); + GUILayout.Space(5); + foreach (var baseModel in AwtterSdkInstaller.AvaliableBases.Where(x => x.IsPatreon)) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(baseModel.Icon), GUILayout.Height(32), GUILayout.Width(32)); + if (GUILayout.Button(baseModel.Name, AwtterSdkInstaller.CurrentBase?.Id == baseModel.Id ? CustomButton2 : CustomButton, GUILayout.Height(32))) + { + AwtterSdkInstaller.CurrentBase = AwtterSdkInstaller.CurrentBase?.Id == baseModel.Id ? null : baseModel; + _main.UpdateAwtterPackages(); + } + + GUILayout.EndHorizontal(); + } + GUILayout.Space(5); + } + if (AwtterSdkInstaller.AvaliableDlcs.Any(x => !x.IsProp && x.IsDlc && x.IsPatreon)) + { + Utils.CreateBox("DLCS"); + GUILayout.Space(5); + foreach (var dlc in AwtterSdkInstaller.AvaliableDlcs.Where(x => x.IsDlc && x.IsPatreon)) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(dlc.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUI.color = dlc.Install ? Color.green : Color.white; + if (GUILayout.Button(dlc.Name, CustomButton, GUILayout.Height(32))) + { + dlc.Install = !dlc.Install; + } + GUI.color = Color.white; + GUILayout.EndHorizontal(); + } + GUILayout.Space(5); + } + if (AwtterSdkInstaller.AvaliableDlcs.Any(x => x.IsProp && x.IsPatreon)) + { + Utils.CreateBox("Props"); + GUILayout.Space(5); + foreach (var prop in AwtterSdkInstaller.AvaliableDlcs.Where(x => x.IsProp && x.IsPatreon)) + { + GUILayout.BeginHorizontal(); + GUILayout.Box(TextureCache.GetTextureOrDownload(prop.Icon), GUILayout.Height(32), GUILayout.Width(32)); + GUI.color = prop.Install ? Color.green : Color.white; + if (GUILayout.Button(prop.Name, CustomButton, GUILayout.Height(32))) + { + prop.Install = !prop.Install; + } + GUI.color = Color.white; + GUILayout.EndHorizontal(); + } + GUILayout.Space(5); + } + GUILayout.EndScrollView(); + GUILayout.Space(15); + End(); + } + + void End() + { + GUILayout.BeginHorizontal(); + GUI.color = Color.red; + if (GUILayout.Button("Go back", _main.Shared.WindowCustomButton3, GUILayout.MinHeight(27))) + AwtterSdkInstaller.ViewPatreonItems = false; + GUI.color = Color.white; + + GUILayout.Space(10); + GUI.color = Color.green; + if (GUILayout.Button("Run SDK Installer", _main.Shared.WindowCustomButton3, GUILayout.MinHeight(27))) + AwtterSdkInstaller.IsInstalling = true; + GUI.color = Color.white; + GUILayout.EndHorizontal(); + } + + + public void Reset() + { + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/PatreonBenefitsPage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Pages/PatreonBenefitsPage.cs.meta new file mode 100644 index 0000000..cc7337a --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/PatreonBenefitsPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e17567f4b40c16342adcaf4bf6a8a19a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/ResetPage.cs b/Packages/com.killers0992.awttersdk/Editor/Pages/ResetPage.cs new file mode 100644 index 0000000..06c3e88 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/ResetPage.cs @@ -0,0 +1,94 @@ +using AwtterSDK.Editor.Interfaces; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace AwtterSDK.Editor.Pages +{ + public class ResetPage : IPage + { + private Texture2D _awttersdkwarningimage; + public Texture2D AwtterSdkWarningImage + { + get + { + if (_awttersdkwarningimage == null) + _awttersdkwarningimage = AssetDatabase.LoadAssetAtPath(Path.Combine(Paths.MainPath, "Editor", "Textures", "warningsdk.png")); + + return _awttersdkwarningimage; + } + } + + private AwtterSdkInstaller _main; + + public void Load(AwtterSdkInstaller main) + { + _main = main; + } + + public void DrawGUI(Rect pos) + { + GUI.DrawTexture(new Rect(0, 290, pos.size.x, 120), AwtterSdkWarningImage, ScaleMode.ScaleToFit); + GUILayout.Space(135); + + EditorGUILayout.BeginVertical(); + GUILayout.BeginHorizontal("box"); + GUILayout.FlexibleSpace(); + GUILayout.Label("You are about to clean all the Awtter related content"); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal("box"); + GUILayout.FlexibleSpace(); + GUILayout.Label("from your current project."); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + GUILayout.Space(10); + + GUILayout.BeginHorizontal("box"); + GUILayout.FlexibleSpace(); + GUILayout.Label("Do you wish to continue ?"); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + + EditorGUILayout.EndVertical(); + + GUILayout.Space(32); + + EditorGUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + GUI.color = Color.green; + + if (GUILayout.Button($"YES", _main.Shared.WindowCustomButton3, GUILayout.MinWidth(50), GUILayout.MinHeight(32))) + { + FileUtil.DeleteFileOrDirectory("Assets/_Shade The Bat"); + FileUtil.DeleteFileOrDirectory("Assets/AwtterInstalledPackages.json"); + + AssetDatabase.Refresh(); + + AwtterSdkInstaller.ViewReset = !AwtterSdkInstaller.ViewReset; + } + GUI.color = Color.red; + GUILayout.Space(50); + + if (GUILayout.Button($"BACK", _main.Shared.WindowCustomButton3, GUILayout.MinWidth(50), GUILayout.MinHeight(32))) + { + AwtterSdkInstaller.ViewReset = !AwtterSdkInstaller.ViewReset; + } + GUILayout.FlexibleSpace(); + GUI.color = Color.white; + EditorGUILayout.EndHorizontal(); + GUILayout.FlexibleSpace(); + } + + + public void Reset() + { + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/ResetPage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Pages/ResetPage.cs.meta new file mode 100644 index 0000000..fa881d6 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/ResetPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 11218eb64c797454ebb5ee7e0b056216 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/ScenesPage.cs b/Packages/com.killers0992.awttersdk/Editor/Pages/ScenesPage.cs new file mode 100644 index 0000000..3ddea77 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/ScenesPage.cs @@ -0,0 +1,87 @@ +using AwtterSDK.Editor.Interfaces; +using AwtterSDK.Editor.Models; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; + +namespace AwtterSDK.Editor.Pages +{ + public class ScenesPage : IPage + { + private AwtterSdkInstaller _main; + private Vector2 _scenesScroll = Vector2.zero; + private List _scenes = new List(); + + public static bool DoRefreshScenes; + + public void Load(AwtterSdkInstaller main) + { + _main = main; + RefreshScenes(); + } + + void RefreshScenes() + { + _scenes = Directory.GetFiles(Application.dataPath, "*.unity", SearchOption.AllDirectories) + .Select(x => new SceneInfo() + { + SceneName = Path.GetFileNameWithoutExtension(x), + FullPath = x, + }).ToList(); + } + + public void DrawGUI(Rect pos) + { + if (DoRefreshScenes) + RefreshScenes(); + + EditorGUILayout.Space(10); + Utils.CreateBox("Select your scene!"); + _scenesScroll = EditorGUILayout.BeginScrollView(_scenesScroll, GUILayout.Height(240)); + + foreach (var scene in _scenes) + { + GUI.color = EditorSceneManager.GetActiveScene().name == scene.SceneName ? Color.green : Color.white; + if (GUILayout.Button($"{scene.SceneName}", GUILayout.Height(30))) + { + if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) + EditorSceneManager.OpenScene(scene.FullPath); + } + GUI.color = Color.white; + } + + EditorGUILayout.EndScrollView(); + + if (AwtterSdkInstaller.CurrentBase.IsOutdated || AwtterSdkInstaller.AvaliableDlcs.Any(x => x.IsOutdated)) + { + EditorGUILayout.HelpBox(String.Concat( + AwtterSdkInstaller.CurrentBase.IsOutdated ? $"Your base is outdated!" + Environment.NewLine : String.Empty, + AwtterSdkInstaller.AvaliableDlcs.Any(x => x.IsOutdated) ? "Your DLCS are outdated!" : String.Empty), MessageType.Warning); + } + else + GUILayout.Space(5); + + EditorGUILayout.BeginVertical(); + GUI.color = ModelSelectionPage.OrangeColor; + if (GUILayout.Button($"Manage packages", _main.Shared.WindowCustomButton3)) + { + AwtterSdkInstaller.ViewManagePackages = !AwtterSdkInstaller.ViewManagePackages; + } + GUI.color = Color.red; + if (GUILayout.Button("Reset", _main.Shared.WindowCustomButton3)) + { + AwtterSdkInstaller.ViewReset = true; + } + GUI.color = Color.white; + EditorGUILayout.EndVertical(); + } + + public void Reset() + { + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/ScenesPage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Pages/ScenesPage.cs.meta new file mode 100644 index 0000000..2b37ae5 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/ScenesPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b8a6472a48c355f4a823fb4d6fcbe588 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/SettingsPage.cs b/Packages/com.killers0992.awttersdk/Editor/Pages/SettingsPage.cs new file mode 100644 index 0000000..e6d33af --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/SettingsPage.cs @@ -0,0 +1,53 @@ +using AwtterSDK; +using AwtterSDK.Editor.Interfaces; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace AwtterSDK.Editor.Pages +{ + public class SettingsPage : IPage + { + private long _directorySize = 0; + + public void Load(AwtterSdkInstaller main) + { + _directorySize = Utils.DirectorySize(new System.IO.DirectoryInfo(FilesCache.CachePath)); + } + + public void DrawGUI(Rect pos) + { + Utils.CreateBox("Cache"); + EditorGUILayout.BeginHorizontal(); + GUILayout.Label($"Used space {Utils.FormatSize(_directorySize)}"); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Clear cache")) + { + foreach(var file in Directory.GetFiles(FilesCache.CachePath)) + { + File.Delete(file); + } + Load(null); + } + EditorGUILayout.EndHorizontal(); + GUILayout.FlexibleSpace(); + EditorGUILayout.BeginVertical(); + if (GUILayout.Button($"Go back")) + { + AwtterSdkInstaller.ViewSettings = false; + } + EditorGUILayout.EndVertical(); + } + + + public void Reset() + { + _directorySize = 0; + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/SettingsPage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Pages/SettingsPage.cs.meta new file mode 100644 index 0000000..d654b7d --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/SettingsPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 22dd86d360bf0c246a13a6a0504aa107 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/SharedPage.cs b/Packages/com.killers0992.awttersdk/Editor/Pages/SharedPage.cs new file mode 100644 index 0000000..aeda520 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/SharedPage.cs @@ -0,0 +1,202 @@ +using Assets.Awtter_SDK.Editor; +using AWBOI.SplashScreen; +using System.IO; +using UnityEditor; +using UnityEngine; + +namespace AwtterSDK.Editor.Pages +{ + public class SharedPage + { + private Texture2D _windowBackground; + private Texture2D _awtterSdkImage; + + internal AwtterSdkInstaller _main; + + public Texture2D WindowBackground + { + get + { + if (_windowBackground == null) + _windowBackground = Utils.CreateTexture((int)_main.maxSize.x, (int)_main.maxSize.y, new Color32(35, 35, 35, 255)); + + return _windowBackground; + } + } + + public Texture2D AwtterSdkImage + { + get + { + if (_awtterSdkImage == null) + _awtterSdkImage = AssetDatabase.LoadAssetAtPath(Path.Combine(Paths.MainPath, "Editor", "Textures", "sdk.png")); + + return _awtterSdkImage; + } + } + + public GUIStyle WindowCustomButton; + public GUIStyle WindowCustomButton2; + public GUIStyle WindowCustomButton3; + public GUIStyle WindowCustomButton4; + + public SharedPage(AwtterSdkInstaller main) + { + _main = main; + Load(); + } + + public void Load() + { + + if (WindowCustomButton == null) + { + WindowCustomButton = new GUIStyle(GUI.skin.button); + WindowCustomButton.alignment = TextAnchor.MiddleCenter; + WindowCustomButton.fontStyle = FontStyle.Bold; + + WindowCustomButton.border = new RectOffset(0, 0, 0, 0); + WindowCustomButton.normal.background = Utils.CreateTexture(150, 150, new Color32(80, 80, 80, 255)); + WindowCustomButton.hover.background = Utils.CreateTexture(150, 150, new Color32(73, 69, 69, 255)); + } + + if (WindowCustomButton2 == null) + { + WindowCustomButton2 = new GUIStyle(GUI.skin.button); + WindowCustomButton2.alignment = TextAnchor.MiddleLeft; + WindowCustomButton2.fontStyle = FontStyle.Bold; + + WindowCustomButton2.border = new RectOffset(0, 0, 0, 0); + WindowCustomButton2.normal.background = Utils.CreateTexture(150, 150, new Color32(80, 80, 80, 255)); + WindowCustomButton2.hover.background = Utils.CreateTexture(150, 150, new Color32(73, 69, 69, 255)); + } + + if (WindowCustomButton3 == null) + { + WindowCustomButton3 = new GUIStyle(GUI.skin.button); + WindowCustomButton3.alignment = TextAnchor.MiddleCenter; + WindowCustomButton3.fontStyle = FontStyle.Bold; + WindowCustomButton3.fontSize = 20; + + WindowCustomButton3.border = new RectOffset(0, 0, 0, 0); + WindowCustomButton3.normal.background = Utils.CreateTexture(150, 150, new Color32(80, 80, 80, 255)); + WindowCustomButton3.hover.background = Utils.CreateTexture(150, 150, new Color32(73, 69, 69, 255)); + } + + if (WindowCustomButton4 == null) + { + WindowCustomButton4 = new GUIStyle(GUI.skin.button); + WindowCustomButton4.alignment = TextAnchor.MiddleCenter; + WindowCustomButton4.fontStyle = FontStyle.Bold; + WindowCustomButton4.fontSize = 20; + + WindowCustomButton4.border = new RectOffset(0, 0, 0, 0); + WindowCustomButton4.normal.background = Utils.CreateTexture(150, 150, new Color32(82, 78, 183, 255)); + WindowCustomButton4.hover.background = Utils.CreateTexture(150, 150, new Color32(82, 78, 183, 255)); + } + } + + public void Top(Rect pos) + { + GUI.DrawTexture(new Rect(0, 0, pos.size.x, pos.size.y), WindowBackground, ScaleMode.StretchToFill); + LinkButtons(); + if (AwtterSdkImage != null) + GUI.DrawTexture(new Rect(0, 78, pos.size.x, 180), AwtterSdkImage, ScaleMode.ScaleToFit); + GUILayout.Space(170); + + if (AwtterSdkInstaller.LoggedInUser != null) + LoggedIn(); + } + + void LoggedIn() + { + EditorGUILayout.BeginHorizontal(); + GUILayout.Label($"Logged in as {AwtterSdkInstaller.LoggedInUser?.Username ?? "-|-"} [{AwtterSdkInstaller.LoggedInUser?.Id}]!"); + GUILayout.FlexibleSpace(); + if (GUILayout.Button($"Settings", _main.Shared.WindowCustomButton)) + AwtterSdkInstaller.ViewSettings = !AwtterSdkInstaller.ViewSettings; + if (GUILayout.Button("Logout", _main.Shared.WindowCustomButton, GUILayout.MinHeight(16))) + { + TokenCache.Token = string.Empty; + AwtterSdkInstaller.LoggedIn = false; + } + EditorGUILayout.EndHorizontal(); + } + + void LinkButtons() + { + EditorGUILayout.BeginVertical(); + int count = 0; + EditorGUILayout.BeginHorizontal(); + + for (int x = 0; x < _main.Settings.Buttons.Count; x++) + { + ButtonLink(_main.Settings.Buttons[x]); + + count++; + + switch (count) + { + case 2: + EditorGUILayout.EndHorizontal(); + count = 0; + if (x != _main.Settings.Buttons.Count-1) + EditorGUILayout.BeginHorizontal(); + break; + } + } + + EditorGUILayout.EndVertical(); + } + + void ButtonLink(SplashButton button) + { + GUIContent content = new GUIContent(); + if (button.Image != null) + { + content.image = (Texture2D)button.Image; + content.text = button.ButtonText; + } + else + { + content = new GUIContent(button.ButtonText); + } + + if (GUILayout.Button(content, WindowCustomButton, GUILayout.MinWidth(160), GUILayout.MinHeight(25))) + { + switch (button.ButtonType) + { + case SplashButton.bType.WebLink: + Application.OpenURL(button.Link); + break; + case SplashButton.bType.File: + if (button.Link != "") + { + if (button.Link == "changelogs") + { + ChangeLogsMenu.ShowChangelogs(); + } + else + { + Application.OpenURL(Path.Combine(Paths.MainPath, button.Link)); + } + } + break; + } + } + } + + public void Bottom(Rect pos) + { + EditorGUILayout.BeginHorizontal(GUILayout.MaxHeight(32)); + GUILayout.Label("Show window on startup"); + GUI.color = AwtterSdkInstaller.ShowOnStartup ? Color.green : Color.red; + if (GUILayout.Button(AwtterSdkInstaller.ShowOnStartup ? $"Enabled" : "Disabled", WindowCustomButton, GUILayout.MaxWidth(64))) + { + AwtterSdkInstaller.ShowOnStartup = !AwtterSdkInstaller.ShowOnStartup; + } + GUI.color = Color.white; + EditorGUILayout.EndHorizontal(); + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/SharedPage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Pages/SharedPage.cs.meta new file mode 100644 index 0000000..d280e7d --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/SharedPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aee7fed77c334f94a8f026f5095a27a2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/TosPage.cs b/Packages/com.killers0992.awttersdk/Editor/Pages/TosPage.cs new file mode 100644 index 0000000..9d2addd --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/TosPage.cs @@ -0,0 +1,116 @@ +namespace AwtterSDK.Editor.Pages +{ + using AwtterSDK.Editor.Interfaces; + using System; + using UnityEditor; + using UnityEngine; + + public class TosPage : IPage + { + private static bool? _tosAccepted; + private static int? _tosVersion; + + public static bool TosAccepted + { + get + { + if (!_tosAccepted.HasValue) + _tosAccepted = EditorPrefs.GetBool("AwSdkTos"); + + return _tosAccepted.Value; + } + set + { + EditorPrefs.SetBool("AwSdkTos", value); + _tosAccepted = value; + } + } + + public static int TosVersion + { + get + { + if (!_tosVersion.HasValue) + _tosVersion = EditorPrefs.GetInt("AwSdkTosVersion"); + + return _tosVersion.Value; + } + set + { + EditorPrefs.SetInt("AwSdkTosVersion", value); + _tosVersion = value; + } + } + + static string[] _tosLines = null; + + public Vector2 ScrollPosition = Vector2.zero; + public GUIStyle CustomLabel; + + private AwtterSdkInstaller _main; + + public void Load(AwtterSdkInstaller main) + { + _main = main; + CustomLabel = new GUIStyle(GUI.skin.label); + CustomLabel.richText = true; + } + + public void DrawGUI(Rect pos) + { + GUILayout.FlexibleSpace(); + GUILayout.BeginVertical("Terms of service", "window", GUILayout.Height(250)); + + if (AwtterSdkInstaller.RemoteConfig != null) + { + if (TosAccepted && AwtterSdkInstaller.RemoteConfig.Tos.Version > TosVersion) + TosAccepted = false; + } + + if (_tosLines == null) + { + if (AwtterSdkInstaller.RemoteConfig != null) + _tosLines = AwtterSdkInstaller.RemoteConfig.Tos.Text.Split( + new string[] { Environment.NewLine }, + StringSplitOptions.None + ); + + GUILayout.FlexibleSpace(); + GUILayout.Label("Loading TOS..."); + GUILayout.FlexibleSpace(); + GUILayout.EndVertical(); + return; + } + + ScrollPosition = GUILayout.BeginScrollView(ScrollPosition, false, true); + + foreach(var line in _tosLines) + { + if (line.StartsWith("https://")) + { + if (GUILayout.Button(line)) + Application.OpenURL(line); + } + else + GUILayout.Label(line, CustomLabel); + } + + GUILayout.EndScrollView(); + + if (GUILayout.Button("Accept TOS")) + { + TosVersion = AwtterSdkInstaller.RemoteConfig.Tos.Version; + TosAccepted = true; + } + + GUILayout.EndVertical(); + GUILayout.FlexibleSpace(); + } + + public void Reset() + { + _tosLines = null; + ScrollPosition = Vector2.zero; + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Pages/TosPage.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Pages/TosPage.cs.meta new file mode 100644 index 0000000..7e781c6 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Pages/TosPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fb614e7f3ef28e040abc2d1290fe43fe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Paths.cs b/Packages/com.killers0992.awttersdk/Editor/Paths.cs new file mode 100644 index 0000000..c4722e3 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Paths.cs @@ -0,0 +1,21 @@ +using System.IO; +using UnityEngine; + +namespace AwtterSDK.Editor +{ + public class Paths + { + private static string _packagesPath; + public static string PackagesPath + { + get + { + if (_packagesPath == null) + _packagesPath = Path.Combine(Application.dataPath, "../", "Packages"); + + return _packagesPath; + } + } + public static string MainPath => "Packages\\com.killers0992.awttersdk"; + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Paths.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Paths.cs.meta new file mode 100644 index 0000000..fc2d08e --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Paths.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c7f1cd74c7f7a8d45b4bad6ac4b4bd32 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Resources.meta b/Packages/com.killers0992.awttersdk/Editor/Resources.meta new file mode 100644 index 0000000..75fbbab --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 798a322a58b59c64cbf451e2c974e637 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Resources/SplashMenuButtons.asset b/Packages/com.killers0992.awttersdk/Editor/Resources/SplashMenuButtons.asset new file mode 100644 index 0000000..6be3bf3 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Resources/SplashMenuButtons.asset @@ -0,0 +1,41 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e67598300076cd947a9689bf2265919e, type: 3} + m_Name: SplashMenuButtons + m_EditorClassIdentifier: + credPath: + SceneFolder: "-\u0295\u2022\u1D25\u2022\u0294 OPEN THIS FIRST \u0295\u2022\u1D25\u2022\u0294" + Buttons: + - ButtonType: 1 + ButtonText: ' ' + Link: + Image: {fileID: 0} + - ButtonType: 1 + ButtonText: ' ' + Link: + Image: {fileID: 0} + - ButtonType: 0 + ButtonText: ' Community' + Link: https://discord.com/invite/awtter + Image: {fileID: 2800000, guid: 6ad00a3d7db1458468acc3941a4e253a, type: 3} + - ButtonType: 0 + ButtonText: ' Store' + Link: https://shadethebat.art + Image: {fileID: 2800000, guid: 446a7d09a45b13943a049803667788aa, type: 3} + - ButtonType: 0 + ButtonText: ' Support' + Link: https://www.patreon.com/shadethebat + Image: {fileID: 2800000, guid: 0051dc466632f704eb5d088260c60fb5, type: 3} + - ButtonType: 0 + ButtonText: ' How to upload 3.0' + Link: https://www.youtube.com/watch?v=mGnFyus_U_U + Image: {fileID: 2800000, guid: 812656142d0b1ee438797d5b6132ed45, type: 3} diff --git a/Packages/com.killers0992.awttersdk/Editor/Resources/SplashMenuButtons.asset.meta b/Packages/com.killers0992.awttersdk/Editor/Resources/SplashMenuButtons.asset.meta new file mode 100644 index 0000000..94ca1f4 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Resources/SplashMenuButtons.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e888ffe0587e2054899ee8f7d4503a20 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/TextureCache.cs b/Packages/com.killers0992.awttersdk/Editor/TextureCache.cs new file mode 100644 index 0000000..b49a3f4 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/TextureCache.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using Unity.EditorCoroutines.Editor; +using UnityEditor; +using UnityEngine; + +namespace AwtterSDK.Editor +{ + public class TextureCache + { + public static TextureCache Object = new TextureCache(); + + public static Texture DefaultTexture; + public static List DownloadingInProgress = new List(); + public static Queue TexturesToDownload = new Queue(); + public static Dictionary CachedTextures = new Dictionary(); + + public static Texture GetTextureOrDownload(string url) + { + if (DefaultTexture == null) DefaultTexture = EditorGUIUtility.FindTexture("Folder Icon"); + if (string.IsNullOrEmpty(url)) return DefaultTexture; + + if (!CachedTextures.ContainsKey(url)) + { + CachedTextures.Add(url, null); + TexturesToDownload.Enqueue(url); + } + + return CachedTextures[url] ?? DefaultTexture; + } + + public static void DownloadIfNeeded() + { + if (TexturesToDownload.Count == 0) return; + + EditorCoroutineUtility.StartCoroutine(Download(), Object); + } + + public static IEnumerator Download() + { + while (TexturesToDownload.Count != 0) + { + var link = TexturesToDownload.Dequeue(); + + if (DownloadingInProgress.Contains(link)) continue; + + DownloadingInProgress.Add(link); + + using (WebClient client = new WebClient()) + { + byte[] data; + try + { + data = client.DownloadData(link); + } + catch (WebException ex) + { + Debug.LogError($"[Awtter SDK] Failed download icon for {link},\n{ex}"); + continue; + } + Texture2D tex = new Texture2D(2, 2); + tex.LoadImage(data); + + CachedTextures[link] = tex; + } + } + yield break; + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/TextureCache.cs.meta b/Packages/com.killers0992.awttersdk/Editor/TextureCache.cs.meta new file mode 100644 index 0000000..1673df4 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/TextureCache.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3fc2eddc1bf6efa4b9de59d7a36494b7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures.meta b/Packages/com.killers0992.awttersdk/Editor/Textures.meta new file mode 100644 index 0000000..f58c4c3 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Textures.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2bbc6469df03bb0448746f38d9193042 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/Discord_Logo_sans_texte.svg.png b/Packages/com.killers0992.awttersdk/Editor/Textures/Discord_Logo_sans_texte.svg.png new file mode 100644 index 0000000..66b7f84 Binary files /dev/null and b/Packages/com.killers0992.awttersdk/Editor/Textures/Discord_Logo_sans_texte.svg.png differ diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/Discord_Logo_sans_texte.svg.png.meta b/Packages/com.killers0992.awttersdk/Editor/Textures/Discord_Logo_sans_texte.svg.png.meta new file mode 100644 index 0000000..bf131ae --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Textures/Discord_Logo_sans_texte.svg.png.meta @@ -0,0 +1,127 @@ +fileFormatVersion: 2 +guid: 6ad00a3d7db1458468acc3941a4e253a +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 12 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 32 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/changelogs.txt b/Packages/com.killers0992.awttersdk/Editor/Textures/changelogs.txt new file mode 100644 index 0000000..e0aa966 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Textures/changelogs.txt @@ -0,0 +1,57 @@ +AWTTER 3.0.74h + +SDK : + • Now called ASDK (Awtter Space Development Kit) + • DLCs can be installed from SDK anytime (manage packages) + • The SDK now force-installs post processing, Awtter Merger and Cameratool + • Patreon content has its own section + • Reset project option (cleans everything Awtter related) + + +Merger : + • Works better with 3.0 content + + +Textures : + • (Substance P) symmetry fixed + • (Substance P) Exploded version added + • (Substance P + PSD) New eyes texture + • (PSD) file fixed with thicker edges for mipmap issues + + +Unity + • Model back on T•pose + • UI/Environment rework (to match T•pose) + • UI/Environment accessories transparency fixed + • Chubby neck fluff fix + • Now full synced between PC and Quest + • It's now possible to trigger PC only things on Quest (only PC will see) + • Back collar polygons are back + • Tail dynamics adjusted to avoid back destruction + • Hands gestures should now be symmetrical + • The boop animation does the sound again (louder than 2.9) + • New radial toggle : Big beans + • New radial toggle : Avatar lightning + • AA viseme fixed + • Sad animation is now animated properly + • Facetracking now uses smooth and binary techs + • Facetracking fixes + • Sounds load SDK warning fixed + • Passive blink is back + • Two materials added for the eyes, using body texture + • Glitter (star eyes) is now only on the eyes material so you can add glitter to your body now + • Body material set to outline + • Cheeks outline issue fixed + + +Fbx (model) + • Shapekeys cleanup + • Small pupils blendshape fixed + • Cheekpuff (facetracking) fixed + • Neck weightpaint fixed and smoothed + • Pointy butt fixed + • Pointy crotch fixed + • Back / Tail open mesh fixed + • 2D fluff is now double meshed to avoid using backface render for optimization + • Viseme "aa" fixed + • Viseme "oh" fixed \ No newline at end of file diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/changelogs.txt.meta b/Packages/com.killers0992.awttersdk/Editor/Textures/changelogs.txt.meta new file mode 100644 index 0000000..81d605c --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Textures/changelogs.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9c166a0352984e641a0a8766d72d460a +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/inbox.png b/Packages/com.killers0992.awttersdk/Editor/Textures/inbox.png new file mode 100644 index 0000000..94fc346 Binary files /dev/null and b/Packages/com.killers0992.awttersdk/Editor/Textures/inbox.png differ diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/inbox.png.meta b/Packages/com.killers0992.awttersdk/Editor/Textures/inbox.png.meta new file mode 100644 index 0000000..de01f48 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Textures/inbox.png.meta @@ -0,0 +1,116 @@ +fileFormatVersion: 2 +guid: 3f9d3dc60505489468fca8b0fd788d64 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/otterslove.png b/Packages/com.killers0992.awttersdk/Editor/Textures/otterslove.png new file mode 100644 index 0000000..d149350 Binary files /dev/null and b/Packages/com.killers0992.awttersdk/Editor/Textures/otterslove.png differ diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/otterslove.png.meta b/Packages/com.killers0992.awttersdk/Editor/Textures/otterslove.png.meta new file mode 100644 index 0000000..a9bb498 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Textures/otterslove.png.meta @@ -0,0 +1,127 @@ +fileFormatVersion: 2 +guid: 446a7d09a45b13943a049803667788aa +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 12 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 32 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/patreon.png b/Packages/com.killers0992.awttersdk/Editor/Textures/patreon.png new file mode 100644 index 0000000..fa05c52 Binary files /dev/null and b/Packages/com.killers0992.awttersdk/Editor/Textures/patreon.png differ diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/patreon.png.meta b/Packages/com.killers0992.awttersdk/Editor/Textures/patreon.png.meta new file mode 100644 index 0000000..8b7a51c --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Textures/patreon.png.meta @@ -0,0 +1,127 @@ +fileFormatVersion: 2 +guid: 0051dc466632f704eb5d088260c60fb5 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 12 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 32 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/sdk.png b/Packages/com.killers0992.awttersdk/Editor/Textures/sdk.png new file mode 100644 index 0000000..d98f704 Binary files /dev/null and b/Packages/com.killers0992.awttersdk/Editor/Textures/sdk.png differ diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/sdk.png.meta b/Packages/com.killers0992.awttersdk/Editor/Textures/sdk.png.meta new file mode 100644 index 0000000..d735cde --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Textures/sdk.png.meta @@ -0,0 +1,116 @@ +fileFormatVersion: 2 +guid: 2025b468e635cac4c8e45dbd88388ba2 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/warningsdk.png b/Packages/com.killers0992.awttersdk/Editor/Textures/warningsdk.png new file mode 100644 index 0000000..99722fb Binary files /dev/null and b/Packages/com.killers0992.awttersdk/Editor/Textures/warningsdk.png differ diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/warningsdk.png.meta b/Packages/com.killers0992.awttersdk/Editor/Textures/warningsdk.png.meta new file mode 100644 index 0000000..a275999 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Textures/warningsdk.png.meta @@ -0,0 +1,116 @@ +fileFormatVersion: 2 +guid: 85c1bfeeeaff35b47a20a2b8e1b1ab5f +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/youtube.png b/Packages/com.killers0992.awttersdk/Editor/Textures/youtube.png new file mode 100644 index 0000000..6ba11a3 Binary files /dev/null and b/Packages/com.killers0992.awttersdk/Editor/Textures/youtube.png differ diff --git a/Packages/com.killers0992.awttersdk/Editor/Textures/youtube.png.meta b/Packages/com.killers0992.awttersdk/Editor/Textures/youtube.png.meta new file mode 100644 index 0000000..872fe82 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Textures/youtube.png.meta @@ -0,0 +1,127 @@ +fileFormatVersion: 2 +guid: 812656142d0b1ee438797d5b6132ed45 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 12 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 32 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/TokenCache.cs b/Packages/com.killers0992.awttersdk/Editor/TokenCache.cs new file mode 100644 index 0000000..9a847aa --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/TokenCache.cs @@ -0,0 +1,122 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using UnityEditor; + +namespace AwtterSDK.Editor +{ + internal static class TokenCache + { + static string _token; + internal static string Token + { + get + { + if (_token == null) + ReadToken(); + + return _token; + } + set + { + if (_token == value) return; + + _token = value; + SaveToken(value); + } + } + + static void SaveToken(string rawToken) + { + if (string.IsNullOrEmpty(rawToken)) + { + EditorPrefs.SetString("AwSdkKey", string.Empty); + EditorPrefs.SetString("AwSdkToken", string.Empty); + return; + } + + AesCryptoServiceProvider crypto = new AesCryptoServiceProvider(); + crypto.KeySize = 128; + crypto.BlockSize = 128; + crypto.GenerateKey(); + + EditorPrefs.SetString("AwSdkKey", Convert.ToBase64String(crypto.Key)); + EditorPrefs.SetString("AwSdkToken", AesOperation.EncryptString(crypto.Key, rawToken)); + } + + static void ReadToken() + { + string key = EditorPrefs.GetString("AwSdkKey"); + string token = EditorPrefs.GetString("AwSdkToken"); + + if (!String.IsNullOrEmpty(key) && !String.IsNullOrEmpty(token)) + _token = AesOperation.DecryptString(Convert.FromBase64String(key), token); + } + } + + static class AesOperation + { + public static string EncryptString(byte[] key, string plainText) + { + byte[] iv = new byte[16]; + byte[] array; + + using (Aes aes = Aes.Create()) + { + aes.Key = key; + aes.IV = iv; + + ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); + + using (MemoryStream memoryStream = new MemoryStream()) + { + using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write)) + { + using (StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream)) + { + streamWriter.Write(plainText); + } + + array = memoryStream.ToArray(); + } + } + } + + return Convert.ToBase64String(array); + } + + public static string DecryptString(byte[] key, string cipherText) + { + if (string.IsNullOrEmpty(cipherText)) return string.Empty; + + byte[] iv = new byte[16]; + byte[] buffer = null; + try + { + buffer = Convert.FromBase64String(cipherText); + } + catch (FormatException) + { + return string.Empty; + } + + using (Aes aes = Aes.Create()) + { + aes.Key = key; + aes.IV = iv; + ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); + + using (MemoryStream memoryStream = new MemoryStream(buffer)) + { + using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read)) + { + using (StreamReader streamReader = new StreamReader((Stream)cryptoStream)) + { + return streamReader.ReadToEnd(); + } + } + } + } + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/TokenCache.cs.meta b/Packages/com.killers0992.awttersdk/Editor/TokenCache.cs.meta new file mode 100644 index 0000000..a5294fb --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/TokenCache.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fa77eb8c0fc480f41943317e04d7d923 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Tools.meta b/Packages/com.killers0992.awttersdk/Editor/Tools.meta new file mode 100644 index 0000000..52ba46c --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Tools.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 876cb2a1363956840bd2813fe7fe9dd9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Tools/CameraToolsMenu.cs b/Packages/com.killers0992.awttersdk/Editor/Tools/CameraToolsMenu.cs new file mode 100644 index 0000000..01c875b --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Tools/CameraToolsMenu.cs @@ -0,0 +1,277 @@ +namespace AwtterSDK.Editor.Tools +{ + using System; + using System.Collections.Generic; + using System.IO; + using UnityEditor; + using UnityEngine; + using UnityEngine.Rendering; + + public class CameraToolsMenu : EditorWindow + { + public class CameraRes + { + public CameraRes(string name, int width, int height, string scan, string ratio) + { + Name = name; + Resolution = new Vector3(width, height); + Scan = scan; + Ratio = ratio; + } + + public string Name { get; set; } + public Vector3 Resolution { get; set; } + public string Scan { get; set; } + public string Ratio { get; set; } + } + + public static List Resolutions { get; } = new List() + { + new CameraRes("16K Full", 16384, 8640, "", "16384∶8640"), + new CameraRes("16K", 15360, 8640, "", "16:9"), + new CameraRes("12K", 12288, 6480, "", "16:9"), + new CameraRes("UW10K", 10240, 4320, "", "21:9"), + new CameraRes("8K UHD", 7680, 4320, "4320p", "16:9"), + new CameraRes("4K UHD", 3840, 2160, "2160p", "16:9"), + new CameraRes("UWQHD", 3440, 1440, "", "21:9"), + new CameraRes("WQHD", 2560, 1440, "", "16:9"), + new CameraRes("Full HD", 1920, 1080, "1080p", "16:9"), + new CameraRes("", 1440, 1080, "1080i", "16:9"), + new CameraRes("", 1280, 1080, "1880i", "16:9"), + new CameraRes("HD", 1280, 720, "720p", "16:9"), + new CameraRes("VGA", 640, 480, "", "4:3"), + new CameraRes("Custom", -1, -1, "", ""), + }; + + public static Camera TargetCamera; + public static int PictureResolutionWidth = 4096; + public static int PictureResolutionHeight = 2048; + + [MenuItem("Awtter tools/Camera tool")] + static void Init() + { + CameraToolsMenu window = (CameraToolsMenu)EditorWindow.GetWindow(typeof(CameraToolsMenu), false, "Camera tool"); + window.minSize = new Vector2(288f, 250f); + window.Show(); + } + + private RenderTexture PictureRT; + private bool Transparent; + private string OutputPath = String.Empty; + + private Camera[] CamerasInScene; + + void RefreshCameras() + { + CamerasInScene = UnityEngine.Object.FindObjectsOfType(); + } + + private Vector2 CamerasScroll = Vector2.zero; + + + private Vector2 ResolutionsScroll = Vector2.zero; + private int SelectedResolutionIndex = 0; + + private GUIStyle ButtonCustom1; + private GUIStyle ButtonCustom2; + + public void OnGUI() + { + if (ButtonCustom1 == null) + { + ButtonCustom1 = new GUIStyle(GUI.skin.button); + ButtonCustom1.alignment = TextAnchor.MiddleLeft; + } + + if (ButtonCustom2 == null) + { + ButtonCustom2 = new GUIStyle(EditorStyles.boldLabel); + ButtonCustom2.alignment = TextAnchor.MiddleLeft; + ButtonCustom2.focused.textColor = Color.cyan; + } + + if (CamerasInScene == null) + RefreshCameras(); + + GUILayout.BeginVertical(); + Utils.CreateBox("Target camera"); + TargetCamera = (Camera)EditorGUILayout.ObjectField(TargetCamera, typeof(Camera), true); + GUILayout.Space(5); + GUILayout.Label("Select camera from current scene:"); + CamerasScroll = GUILayout.BeginScrollView(CamerasScroll, false, true, GUILayout.Height(60)); + + foreach(var camera in CamerasInScene) + { + if (TargetCamera == camera) GUI.color = Color.green; + if (GUILayout.Button(camera.name)) + { + if (TargetCamera == camera) + TargetCamera = null; + else + { + TargetCamera = camera; + EditorApplication.ExecuteMenuItem("Window/General/Game"); + } + } + GUI.color = Color.white; + } + + GUILayout.EndScrollView(); + if (GUILayout.Button("Refresh", GUILayout.Height(16))) + { + RefreshCameras(); + } + GUILayout.EndVertical(); + + GUILayout.Space(5f); + MakeBox("Picture"); + + GUILayout.Space(5); + GUILayout.Label("Select resolution:"); + + GUILayout.BeginHorizontal(); + Utils.CreateBox("Name", true, GUILayout.Width(55)); + GUILayout.FlexibleSpace(); + Utils.CreateBox("Resolution", true, GUILayout.Width(80)); + GUILayout.FlexibleSpace(); + Utils.CreateBox("Scan", true, GUILayout.Width(50)); + GUILayout.FlexibleSpace(); + Utils.CreateBox("Ratio", true, GUILayout.Width(90)); + GUILayout.Space(10); + GUILayout.EndHorizontal(); + + ResolutionsScroll = GUILayout.BeginScrollView(ResolutionsScroll, false, true, GUILayout.Height(150)); + + for(int x = 0; x < Resolutions.Count; x++) + { + if (SelectedResolutionIndex == x) GUI.color = Color.green; + + GUILayout.BeginHorizontal(); + GUILayout.Space(5); + if (GUILayout.Button(Resolutions[x].Name, ButtonCustom2, GUILayout.Width(55))) + { + SelectedResolutionIndex = x; + PictureResolutionWidth = (int)Resolutions[x].Resolution.x; + PictureResolutionHeight = (int)Resolutions[x].Resolution.y; + } + GUILayout.FlexibleSpace(); + if (Resolutions[x].Resolution.x == -1 && SelectedResolutionIndex == x) + { + GUI.color = Color.white; + PictureResolutionWidth = EditorGUILayout.IntField(PictureResolutionWidth,GUILayout.Width(35)); + GUILayout.Label("x", GUILayout.Width(10)); + PictureResolutionHeight = EditorGUILayout.IntField(PictureResolutionHeight, GUILayout.Width(35)); + GUI.color = Color.green; + } + else + { + if (GUILayout.Button(Resolutions[x].Resolution.x != -1 ? $"{Resolutions[x].Resolution.x}x{Resolutions[x].Resolution.y}" : "", ButtonCustom2, GUILayout.Width(80))) + { + SelectedResolutionIndex = x; + PictureResolutionWidth = (int)Resolutions[x].Resolution.x; + PictureResolutionHeight = (int)Resolutions[x].Resolution.y; + } + } + GUILayout.FlexibleSpace(); + if (GUILayout.Button(Resolutions[x].Scan, ButtonCustom2, GUILayout.Width(50))) + { + SelectedResolutionIndex = x; + PictureResolutionWidth = (int)Resolutions[x].Resolution.x; + PictureResolutionHeight = (int)Resolutions[x].Resolution.y; + } + GUILayout.FlexibleSpace(); + if (GUILayout.Button(Resolutions[x].Ratio, ButtonCustom2, GUILayout.Width(90))) + { + SelectedResolutionIndex = x; + PictureResolutionWidth = (int)Resolutions[x].Resolution.x; + PictureResolutionHeight = (int)Resolutions[x].Resolution.y; + } + GUILayout.EndHorizontal(); + + GUI.color = Color.white; + } + + GUILayout.EndScrollView(); + + GUI.enabled = TargetCamera != null; + Transparent = GUILayout.Toggle(Transparent, "Transparent"); + + if (TargetCamera != null) + { + if (TargetCamera.clearFlags == CameraClearFlags.Depth && !Transparent) + TargetCamera.clearFlags = CameraClearFlags.Skybox; + else if (TargetCamera.clearFlags != CameraClearFlags.Depth && Transparent) + TargetCamera.clearFlags = CameraClearFlags.Depth; + } + + GUI.enabled = true; + GUILayout.Space(15f); + GUILayout.BeginHorizontal(); + GUILayout.Label("Output path"); + if (GUILayout.Button("Open")) + { + OutputPath = EditorUtility.OpenFolderPanel("Output path", OutputPath, "Pics"); + } + GUILayout.EndHorizontal(); + GUI.enabled = false; + GUILayout.TextField(OutputPath); + GUI.enabled = true; + GUI.enabled = TargetCamera != null; + + if (GUILayout.Button("Take picture")) + CapturePicture(TargetCamera, PictureResolutionWidth, PictureResolutionHeight); + + GUI.enabled = true; + } + + void MakeBox(string name) + { + GUILayout.BeginHorizontal("box"); + GUILayout.FlexibleSpace(); + GUILayout.Label(name, EditorStyles.boldLabel); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + } + + public void CapturePicture(Camera targetCamera, int width, int height) + { + PictureRT = new RenderTexture(new RenderTextureDescriptor(width, width)); + PictureRT.depth = 24; + + PictureRT.dimension = TextureDimension.Tex2D; + + if (PictureRT.width != width) + PictureRT.width = width; + + if (PictureRT.height != height) + PictureRT.height = height; + + targetCamera.targetTexture = PictureRT; + targetCamera.Render(); + + Save("Picture", PictureRT); + + targetCamera.targetTexture = null; + DestroyImmediate(PictureRT); + } + + public void Save(string type, RenderTexture rt) + { + Texture2D tex = new Texture2D(rt.width, rt.height, Transparent ? TextureFormat.ARGB32 : TextureFormat.RGB565, false); + + RenderTexture.active = rt; + tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0); + RenderTexture.active = null; + + byte[] bytes = tex.EncodeToPNG(); + + if (!Directory.Exists(OutputPath)) + Directory.CreateDirectory(OutputPath); + + string path = Path.Combine(OutputPath, $"{type}_{DateTime.Now.ToString("yyyy-dd-M-HH-mm-ss")}.png"); + + File.WriteAllBytes(path, bytes); + Debug.Log($"{type} saved at location {path}"); + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Tools/CameraToolsMenu.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Tools/CameraToolsMenu.cs.meta new file mode 100644 index 0000000..c619e1a --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Tools/CameraToolsMenu.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4c93b9ece7f549478581e9a03716207 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/Editor/Utils.cs b/Packages/com.killers0992.awttersdk/Editor/Utils.cs new file mode 100644 index 0000000..27c7f1c --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Utils.cs @@ -0,0 +1,75 @@ +using System; +using System.IO; +using UnityEditor; +using UnityEngine; + +namespace AwtterSDK.Editor +{ + public static class Utils + { + static readonly string[] suffixes = + { "Bytes", "KB", "MB", "GB", "TB", "PB" }; + + public static Texture2D CreateTexture(int width, int height, Color col) + { + Color[] pix = new Color[width*height]; + + for (int i = 0; i < pix.Length; i++) + pix[i] = col; + + Texture2D result = new Texture2D(width, height, TextureFormat.RGBA32, false); + result.SetPixels(pix); + result.Apply(); + + return result; + } + + public static long DirectorySize(DirectoryInfo d) + { + long size = 0; + FileInfo[] fis = d.GetFiles(); + foreach (FileInfo fi in fis) + { + size += fi.Length; + } + + DirectoryInfo[] dis = d.GetDirectories(); + foreach (DirectoryInfo di in dis) + { + size += DirectorySize(di); + } + return size; + } + + + public static string FormatSize(long bytes) + { + int counter = 0; + decimal number = (decimal)bytes; + while (Math.Round(number / 1024) >= 1) + { + number = number / 1024; + counter++; + } + return string.Format("{0:n1}{1}", number, suffixes[counter]); + } + + public static void CreateBox(string text, bool flexible = true) + { + EditorGUILayout.BeginHorizontal("box"); + if (flexible) GUILayout.FlexibleSpace(); + GUILayout.Label(text, EditorStyles.boldLabel); + if (flexible) GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); + } + + public static void CreateBox(string text, bool flexible = true, params GUILayoutOption[] options) + { + EditorGUILayout.BeginHorizontal("box"); + if (flexible) GUILayout.FlexibleSpace(); + GUILayout.Label(text, EditorStyles.boldLabel, options); + if (flexible) GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); + } + } +} diff --git a/Packages/com.killers0992.awttersdk/Editor/Utils.cs.meta b/Packages/com.killers0992.awttersdk/Editor/Utils.cs.meta new file mode 100644 index 0000000..9294e73 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/Editor/Utils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ab697af992f8cf947a93d9f25d515502 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.killers0992.awttersdk/package.json b/Packages/com.killers0992.awttersdk/package.json new file mode 100644 index 0000000..32dcab5 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/package.json @@ -0,0 +1,18 @@ +{ + "name": "com.killers0992.awttersdk", + "displayName": "Awtter SDK", + "version": "1.2.9", + "description": "Tool for managing content from AwtterSpace.", + "vrchatVersion": "2022.1.1", + "author": { + "name": "Killers0992", + "email": "killers0992@gmail.com", + "url": "https://killers.dev" + }, + "dependencies": { + "com.unity.postprocessing": "3.1.1", + "com.unity.nuget.newtonsoft-json": "3.0.2", + "com.unity.editorcoroutines": "1.0.0", + "com.unity.sharp-zip-lib": "1.3.4-preview" + } +} diff --git a/Packages/com.killers0992.awttersdk/package.json.meta b/Packages/com.killers0992.awttersdk/package.json.meta new file mode 100644 index 0000000..def42f8 --- /dev/null +++ b/Packages/com.killers0992.awttersdk/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0b6f5121587f2a94b979e618ae0751d5 +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.bootstrap/Editor.meta b/Packages/com.vrchat.core.bootstrap/Editor.meta new file mode 100644 index 0000000..d8de383 --- /dev/null +++ b/Packages/com.vrchat.core.bootstrap/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5ee5eebf1b35bbd49ae7983db316180a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.bootstrap/Editor/Bootstrap.cs b/Packages/com.vrchat.core.bootstrap/Editor/Bootstrap.cs new file mode 100644 index 0000000..e1a0917 --- /dev/null +++ b/Packages/com.vrchat.core.bootstrap/Editor/Bootstrap.cs @@ -0,0 +1,92 @@ +using System; +using System.IO; +using System.Net; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace VRC.PackageManagement.Core +{ + public class Bootstrap + { + // JSON property names in Project Manifest + public const string UNITY_PACKAGES_FOLDER = "Packages"; + public const string UNITY_MANIFEST_FILENAME = "manifest.json"; + + // VRC Values + public const string VRC_CONFIG = "https://api.vrchat.cloud/api/1/config"; + public const string VRC_AGENT = "VCCBootstrap 1.0"; + public const string VRC_RESOLVER_PACKAGE = "com.vrchat.core.vpm-resolver"; + + // Finds url for bootstrap package without using JSON + private static Regex _bootstrapRegex = new Regex("\"bootstrap\"\\s*:\\s*\"(.+?(?=\"))\""); + public static string ManifestPath => Path.Combine(Directory.GetCurrentDirectory(), UNITY_PACKAGES_FOLDER, UNITY_MANIFEST_FILENAME); + + // Path where we expect the target package to exist + public static string ResolverPath => + Path.Combine(Directory.GetCurrentDirectory(), UNITY_PACKAGES_FOLDER, VRC_RESOLVER_PACKAGE); + + [InitializeOnLoadMethod] + public static async void CheckForRestore() + { + if (!new DirectoryInfo(ResolverPath).Exists) + { + try + { + await AddResolver(); + } + catch (Exception e) + { + Debug.LogError($"Could not download and install the VPM Package Resolver - you may be missing packages. Exception: {e.Message}"); + } + } + } + + public static async Task AddResolver() + { + var configData = await GetRemoteString(VRC_CONFIG); + if (string.IsNullOrWhiteSpace(configData)) + { + Debug.LogWarning($"Could not get VPM libraries, try again later"); + return; + } + var bootstrapMatch = _bootstrapRegex.Match(configData); + if (!bootstrapMatch.Success || bootstrapMatch.Groups.Count < 2) + { + Debug.LogError($"Could not find bootstrap in config, try again later"); + return; + } + + var url = bootstrapMatch.Groups[1].Value; + + var targetFile = Path.Combine(Path.GetTempPath(), $"resolver-{DateTime.Now.ToString("yyyyMMddTHHmmss")}.unitypackage"); + + // Download to dir + using (var client = new WebClient()) + { + // Add User Agent or else CloudFlare will return 1020 + client.Headers.Add(HttpRequestHeader.UserAgent, VRC_AGENT); + + await client.DownloadFileTaskAsync(url, targetFile); + + if (File.Exists(targetFile)) + { + Debug.Log($"Downloaded Resolver to {targetFile}"); + AssetDatabase.ImportPackage(targetFile, false); + } + } + return; + } + + public static async Task GetRemoteString(string url) + { + using (var client = new WebClient()) + { + // Add User Agent or else CloudFlare will return 1020 + client.Headers.Add(HttpRequestHeader.UserAgent, VRC_AGENT); + return await client.DownloadStringTaskAsync(url); + } + } + } +} diff --git a/Packages/com.vrchat.core.bootstrap/Editor/Bootstrap.cs.meta b/Packages/com.vrchat.core.bootstrap/Editor/Bootstrap.cs.meta new file mode 100644 index 0000000..d7ac1ae --- /dev/null +++ b/Packages/com.vrchat.core.bootstrap/Editor/Bootstrap.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eea11c44cabdaaa43ac0a21dbbbd9824 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.bootstrap/Editor/VRChat.Bootstrapper.Editor.asmdef b/Packages/com.vrchat.core.bootstrap/Editor/VRChat.Bootstrapper.Editor.asmdef new file mode 100644 index 0000000..115b3e2 --- /dev/null +++ b/Packages/com.vrchat.core.bootstrap/Editor/VRChat.Bootstrapper.Editor.asmdef @@ -0,0 +1,15 @@ +{ + "name": "VRChat.Bootstrapper.Editor", + "references": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.vrchat.core.bootstrap/Editor/VRChat.Bootstrapper.Editor.asmdef.meta b/Packages/com.vrchat.core.bootstrap/Editor/VRChat.Bootstrapper.Editor.asmdef.meta new file mode 100644 index 0000000..1d60f49 --- /dev/null +++ b/Packages/com.vrchat.core.bootstrap/Editor/VRChat.Bootstrapper.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e0d8a3ed977bd0948b99f4bce8e56a07 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.bootstrap/License.md b/Packages/com.vrchat.core.bootstrap/License.md new file mode 100644 index 0000000..275530c --- /dev/null +++ b/Packages/com.vrchat.core.bootstrap/License.md @@ -0,0 +1,11 @@ +# VRCHAT INC. +### VRCHAT DISTRO LICENSE FILE +Version: February 24, 2022 + +**SUMMARY OF TERMS:** Any materials subject to this Distro Asset License may be distributed by you, with or without modifications, on a non-commercial basis (i.e., at no charge), in accordance with the full terms of the Materials License Agreement. + +This Distro License File is a "License File" as defined in the VRChat Materials License Agreement, found at https://hello.vrchat.com/legal/sdk (or any successor link designated by VRChat) (as may be revised from time to time, the "Materials License Agreement"). + +This Distro License File applies to all the files in the Folder containing this Distro License File and those in all Child Folders within that Folder (except with respect to files in any Child Folder that contains a different License File) (such files, other than this Distro License File, the "Covered Files"). All capitalized terms used but not otherwise defined in this Distro License File have the meanings provided in the Materials License Agreement. + +This Distro License File only provides a summary of the terms applicable to the Covered Files. To understand your rights and obligations and the full set of terms that apply to use of the Covered Files, please see the relevant sections of the Materials License Agreement, including terms applicable to Distro Materials. \ No newline at end of file diff --git a/Packages/com.vrchat.core.bootstrap/License.md.meta b/Packages/com.vrchat.core.bootstrap/License.md.meta new file mode 100644 index 0000000..3a508bc --- /dev/null +++ b/Packages/com.vrchat.core.bootstrap/License.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a84f4a071b4a7fa49985f447a0ce2fe2 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.bootstrap/package.json b/Packages/com.vrchat.core.bootstrap/package.json new file mode 100644 index 0000000..d0b5080 --- /dev/null +++ b/Packages/com.vrchat.core.bootstrap/package.json @@ -0,0 +1,17 @@ +{ + "name" : "com.vrchat.core.bootstrap", + "displayName" : "VRChat Package Bootstrapper", + "version" : "0.1.15", + "unity" : "2019.4", + "description" : "Tool to Download VPM Packages", + "vrchatVersion" : "2022.1.1", + "author" : { + "name" : "VRChat", + "email" : "developer@vrchat.com", + "url" : "https://github.com/vrchat/packages" + }, + "url" : "", + "dependencies" : { + "com.unity.nuget.newtonsoft-json" : "2.0.2" + } +} diff --git a/Packages/com.vrchat.core.bootstrap/package.json.meta b/Packages/com.vrchat.core.bootstrap/package.json.meta new file mode 100644 index 0000000..9aea588 --- /dev/null +++ b/Packages/com.vrchat.core.bootstrap/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6c5fffb4815ba9046ad0a2e878396439 +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor.meta b/Packages/com.vrchat.core.vpm-resolver/Editor.meta new file mode 100644 index 0000000..0f0ccc3 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1058b5946fb23674cad310b1f4bd5b61 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies.meta new file mode 100644 index 0000000..72fd76e --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f4e8a9c940ed84943bb0433246ec42bb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/ICSharpCode.SharpZipLib.dll b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/ICSharpCode.SharpZipLib.dll new file mode 100644 index 0000000..5fa13c7 Binary files /dev/null and b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/ICSharpCode.SharpZipLib.dll differ diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/ICSharpCode.SharpZipLib.dll.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/ICSharpCode.SharpZipLib.dll.meta new file mode 100644 index 0000000..7627233 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/ICSharpCode.SharpZipLib.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ec897c206a99abe41b093d5cc5ddc3fe +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/SemanticVersioning.License.txt b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/SemanticVersioning.License.txt new file mode 100644 index 0000000..6643721 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/SemanticVersioning.License.txt @@ -0,0 +1,7 @@ +Copyright (c) 2016 Adam Reeve + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/SemanticVersioning.License.txt.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/SemanticVersioning.License.txt.meta new file mode 100644 index 0000000..a0fc49d --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/SemanticVersioning.License.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1417544c34d9a4f4aacebf76247940a9 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/SemanticVersioning.dll b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/SemanticVersioning.dll new file mode 100644 index 0000000..e021672 Binary files /dev/null and b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/SemanticVersioning.dll differ diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/SemanticVersioning.dll.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/SemanticVersioning.dll.meta new file mode 100644 index 0000000..cc2ba32 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/SemanticVersioning.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 65d82c6541a90644390df2caa29c2209 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.License.txt b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.License.txt new file mode 100644 index 0000000..37ec93a --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.License.txt @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.License.txt.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.License.txt.meta new file mode 100644 index 0000000..649b319 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.License.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1a7454bc513adb84d9ae85ed7e7268ba +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.File.dll b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.File.dll new file mode 100644 index 0000000..1600c05 Binary files /dev/null and b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.File.dll differ diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.File.dll.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.File.dll.meta new file mode 100644 index 0000000..53d8dd7 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.File.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 0c56563958a156145b708466db0e35cc +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.File.txt b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.File.txt new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.File.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.File.txt.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.File.txt.meta new file mode 100644 index 0000000..028d199 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.File.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ca344e99cdd379947ab3e8e5b346428c +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.Unity3D.License.md b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.Unity3D.License.md new file mode 100644 index 0000000..d9f6ecd --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.Unity3D.License.md @@ -0,0 +1,23 @@ + +The MIT License (MIT) + +Copyright (c) 2020 Kurai András +Copyright (c) 2022-Present VRChat Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.Unity3D.License.md.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.Unity3D.License.md.meta new file mode 100644 index 0000000..597bf25 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.Unity3D.License.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 598e678340a8c6e4e9a3debcdc6a9579 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.Unity3D.dll b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.Unity3D.dll new file mode 100644 index 0000000..eb78a0f Binary files /dev/null and b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.Unity3D.dll differ diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.Unity3D.dll.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.Unity3D.dll.meta new file mode 100644 index 0000000..932224a --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.Sinks.Unity3D.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: cfc1421f162f0354d8a64d569417d9c9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.dll b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.dll new file mode 100644 index 0000000..dab49d2 Binary files /dev/null and b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.dll differ diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.dll.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.dll.meta new file mode 100644 index 0000000..2ef53f9 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/Serilog.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 702a5a2579f8edf43b5e7bfb2f52e2c6 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/YamlDotNet.License.txt b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/YamlDotNet.License.txt new file mode 100644 index 0000000..d4f2924 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/YamlDotNet.License.txt @@ -0,0 +1,19 @@ +Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Antoine Aubry and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/YamlDotNet.License.txt.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/YamlDotNet.License.txt.meta new file mode 100644 index 0000000..a8bc0bc --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/YamlDotNet.License.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3547422b181c5af49901e93c1122bbdd +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/YamlDotNet.dll b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/YamlDotNet.dll new file mode 100644 index 0000000..d0bbb75 Binary files /dev/null and b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/YamlDotNet.dll differ diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/YamlDotNet.dll.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/YamlDotNet.dll.meta new file mode 100644 index 0000000..4b5ebc3 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/YamlDotNet.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 9fd667e0ec0d1d84c9e17dad407f2272 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/vpm-core-lib.dll b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/vpm-core-lib.dll new file mode 100644 index 0000000..2b4a4f6 Binary files /dev/null and b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/vpm-core-lib.dll differ diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/vpm-core-lib.dll.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/vpm-core-lib.dll.meta new file mode 100644 index 0000000..71e73f6 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Dependencies/vpm-core-lib.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 140aba2a5b760e94cb3ed9f39a52610a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker.meta new file mode 100644 index 0000000..b14bc72 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5da3ddd939264fc40a113d615f3ca77a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker/PackageMakerWindow.cs b/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker/PackageMakerWindow.cs new file mode 100644 index 0000000..5e726f5 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker/PackageMakerWindow.cs @@ -0,0 +1,485 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; +using VRC.PackageManagement.Core.Types.Packages; + +namespace VRC.PackageManagement.PackageMaker +{ + public class PackageMakerWindow : EditorWindow + { + // VisualElements + private VisualElement _rootView; + private TextField _targetAssetFolderField; + private TextField _packageIDField; + private Button _actionButton; + private EnumField _targetVRCPackageField; + private TextField _authorNameField; + private TextField _authorEmailField; + private TextField _authorUrlField; + private static string _projectDir; + private PackageMakerWindowData _windowData; + + private void LoadDataFromSave() + { + if (!string.IsNullOrWhiteSpace(_windowData.targetAssetFolder)) + { + _targetAssetFolderField.SetValueWithoutNotify(_windowData.targetAssetFolder); + } + _packageIDField.SetValueWithoutNotify(_windowData.packageID); + _targetVRCPackageField.SetValueWithoutNotify(_windowData.relatedPackage); + _authorEmailField.SetValueWithoutNotify(_windowData.authorEmail); + _authorNameField.SetValueWithoutNotify(_windowData.authorName); + _authorUrlField.SetValueWithoutNotify(_windowData.authorUrl); + + RefreshActionButtonState(); + } + + private void OnEnable() + { + _projectDir = Directory.GetParent(Application.dataPath).FullName; + Refresh(); + } + + [MenuItem("VRChat SDK/Utilities/Package Maker")] + public static void ShowWindow() + { + PackageMakerWindow wnd = GetWindow(); + wnd.titleContent = new GUIContent("Package Maker"); + } + + [MenuItem("Assets/Export VPM as UnityPackage")] + private static void ExportAsUnityPackage () + { + + var foldersToExport = new List(); + StringBuilder exportFilename = new StringBuilder("exported"); + foreach (string guid in Selection.assetGUIDs) + { + string selectedFolder = AssetDatabase.GUIDToAssetPath(guid); + var manifestPath = Path.Combine(selectedFolder, VRCPackageManifest.Filename); + var manifest = VRCPackageManifest.GetManifestAtPath(manifestPath); + if (manifest == null) + { + Debug.LogWarning($"Could not read valid Package Manifest at {manifestPath}. You need to create this first to export a VPM Package."); + continue; + } + exportFilename.Append($"-{manifest.Id}-{manifest.Version}"); + foldersToExport.Add(selectedFolder); + } + + exportFilename.Append(".unitypackage"); + var exportDir = Path.Combine(Directory.GetCurrentDirectory(), "Exports"); + Directory.CreateDirectory(exportDir); + AssetDatabase.ExportPackage + ( + foldersToExport.ToArray(), + Path.Combine(exportDir, exportFilename.ToString()), + ExportPackageOptions.Recurse | ExportPackageOptions.Interactive + ); + } + + private void Refresh() + { + if (_windowData == null) + { + _windowData = PackageMakerWindowData.GetOrCreate(); + } + + if (_rootView == null) return; + + if (_windowData != null) + { + LoadDataFromSave(); + } + } + + private void RefreshActionButtonState() + { + _actionButton.SetEnabled( + StringIsValidAssetFolder(_windowData.targetAssetFolder) && + !string.IsNullOrWhiteSpace(_windowData.packageID) && + _authorNameField.value != null && + IsValidEmail(_authorEmailField.value) + ); + } + + /// + /// Unity calls the CreateGUI method automatically when the window needs to display + /// + private void CreateGUI() + { + if (_windowData == null) + { + _windowData = PackageMakerWindowData.GetOrCreate(); + } + + _rootView = rootVisualElement; + _rootView.name = "root-view"; + _rootView.styleSheets.Add((StyleSheet) Resources.Load("PackageMakerWindowStyle")); + + // Create Target Asset folder and register for drag and drop events + _rootView.Add(CreateTargetFolderElement()); + _rootView.Add(CreatePackageIDElement()); + _rootView.Add(CreateAuthorElement()); + _rootView.Add(CreateTargetVRCPackageElement()); + _rootView.Add(CreateActionButton()); + + Refresh(); + } + + public enum VRCPackageEnum + { + None = 0, + Worlds = 1, + Avatars = 2, + Base = 3 + } + + private VisualElement CreateTargetVRCPackageElement() + { + _targetVRCPackageField = new EnumField("Related VRChat Package", VRCPackageEnum.None); + _targetVRCPackageField.RegisterValueChangedCallback(OnTargetVRCPackageChanged); + var box = new Box(); + box.Add(_targetVRCPackageField); + return box; + } + + private void OnTargetVRCPackageChanged(ChangeEvent evt) + { + _windowData.relatedPackage = (VRCPackageEnum)evt.newValue; + _windowData.Save(); + } + + private VisualElement CreateActionButton() + { + _actionButton = new Button(OnActionButtonPressed) + { + text = "Convert Assets to Package", + name = "action-button" + }; + return _actionButton; + } + + private void OnActionButtonPressed() + { + bool result = EditorUtility.DisplayDialog("One-Way Conversion", + $"This process will move the assets from {_windowData.targetAssetFolder} into a new Package with the id {_windowData.packageID} and give it references to {_windowData.relatedPackage}.", + "Ok", "Wait, not yet."); + if (result) + { + string newPackageFolderPath = Path.Combine(_projectDir, "Packages", _windowData.packageID); + Directory.CreateDirectory(newPackageFolderPath); + var fullTargetAssetFolder = Path.Combine(_projectDir, _windowData.targetAssetFolder); + DoMigration(fullTargetAssetFolder, newPackageFolderPath); + ForceRefresh(); + } + } + + public static void ForceRefresh () + { + MethodInfo method = typeof( UnityEditor.PackageManager.Client ).GetMethod( "Resolve", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly ); + if( method != null ) + method.Invoke( null, null ); + + AssetDatabase.Refresh(); + } + + private VisualElement CreatePackageIDElement() + { + var box = new Box() + { + name = "package-name-box" + }; + + _packageIDField = new TextField("Package ID", 255, false, false, '*'); + _packageIDField.RegisterValueChangedCallback(OnPackageIDChanged); + box.Add(_packageIDField); + + box.Add(new Label("Lowercase letters, numbers and dots only.") + { + name="description", + tooltip = "Standard practice is reverse domain notation like com.vrchat.packagename. Needs to be unique across VRChat, so if you don't own a domain you can try your username.", + }); + + return box; + } + + private VisualElement CreateAuthorElement() + { + // Construct author fields + _authorNameField = new TextField("Author Name"); + _authorEmailField = new TextField("Author Email"); + _authorUrlField = new TextField("Author URL (optional)"); + + // Save name to window data and toggle the Action Button if its status changed + _authorNameField.RegisterValueChangedCallback((evt) => + { + _windowData.authorName = evt.newValue; + Debug.Log($"Window author name is {evt.newValue}"); + RefreshActionButtonState(); + }); + + // Save email to window data if valid and toggle the Action Button if its status changed + _authorEmailField.RegisterValueChangedCallback((evt) => + { + // Only save email if it appears valid + if (IsValidEmail(evt.newValue)) + { + _windowData.authorEmail = evt.newValue; + } + RefreshActionButtonState(); + }); + + // Save url to window data, doesn't affect action button state + _authorUrlField.RegisterValueChangedCallback((evt) => + { + _windowData.authorUrl = evt.newValue; + }); + + // Add new fields to layout + var box = new Box(); + box.Add(_authorNameField); + box.Add(_authorEmailField); + box.Add(_authorUrlField); + return box; + } + + private bool IsValidEmail(string evtNewValue) + { + try + { + var addr = new System.Net.Mail.MailAddress(evtNewValue); + return addr.Address == evtNewValue; + } + catch + { + return false; + } + } + + private Regex packageIdRegex = new Regex("[^a-z0-9.]"); + private void OnPackageIDChanged(ChangeEvent evt) + { + if (evt.newValue != null) + { + string newId = packageIdRegex.Replace(evt.newValue, "-"); + _packageIDField.SetValueWithoutNotify(newId); + _windowData.packageID = newId; + _windowData.Save(); + } + RefreshActionButtonState(); + } + + private VisualElement CreateTargetFolderElement() + { + var targetFolderBox = new Box() + { + name = "editor-target-box" + }; + + _targetAssetFolderField = new TextField("Target Folder"); + _targetAssetFolderField.RegisterCallback(OnTargetAssetFolderDragEnter, TrickleDown.TrickleDown); + _targetAssetFolderField.RegisterCallback(OnTargetAssetFolderDragLeave, TrickleDown.TrickleDown); + _targetAssetFolderField.RegisterCallback(OnTargetAssetFolderDragUpdated, TrickleDown.TrickleDown); + _targetAssetFolderField.RegisterCallback(OnTargetAssetFolderDragPerform, TrickleDown.TrickleDown); + _targetAssetFolderField.RegisterCallback(OnTargetAssetFolderDragExited, TrickleDown.TrickleDown); + _targetAssetFolderField.RegisterValueChangedCallback(OnTargetAssetFolderValueChanged); + targetFolderBox.Add(_targetAssetFolderField); + + targetFolderBox.Add(new Label("Drag and Drop an Assets Folder to Convert Above"){name="description"}); + return targetFolderBox; + } + + #region TargetAssetFolder Field Events + + private bool StringIsValidAssetFolder(string targetFolder) + { + return !string.IsNullOrWhiteSpace(targetFolder) && AssetDatabase.IsValidFolder(targetFolder); + } + + private void OnTargetAssetFolderValueChanged(ChangeEvent evt) + { + string targetFolder = evt.newValue; + + if (StringIsValidAssetFolder(targetFolder)) + { + _windowData.targetAssetFolder = evt.newValue; + _windowData.Save(); + RefreshActionButtonState(); + } + else + { + _targetAssetFolderField.SetValueWithoutNotify(evt.previousValue); + } + } + + private void OnTargetAssetFolderDragExited(DragExitedEvent evt) + { + DragAndDrop.visualMode = DragAndDropVisualMode.None; + } + + private void OnTargetAssetFolderDragPerform(DragPerformEvent evt) + { + var targetFolder = DragAndDrop.paths[0]; + if (!string.IsNullOrWhiteSpace(targetFolder) && AssetDatabase.IsValidFolder(targetFolder)) + { + _targetAssetFolderField.value = targetFolder; + } + else + { + Debug.LogError($"Could not accept {targetFolder}. Needs to be a folder within the project"); + } + } + + private void OnTargetAssetFolderDragUpdated(DragUpdatedEvent evt) + { + if (DragAndDrop.paths.Length == 1) + { + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + DragAndDrop.AcceptDrag(); + } + else + { + DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; + } + } + + private void OnTargetAssetFolderDragLeave(DragLeaveEvent evt) + { + DragAndDrop.visualMode = DragAndDropVisualMode.None; + } + + private void OnTargetAssetFolderDragEnter(DragEnterEvent evt) + { + if (DragAndDrop.paths.Length == 1) + { + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + DragAndDrop.AcceptDrag(); + } + } + + #endregion + + #region Migration Logic + + private void DoMigration(string corePath, string targetDir) + { + + EditorUtility.DisplayProgressBar("Migrating Package", "Creating Starter Package", 0.1f); + + // Convert PackageType enum to VRC Package ID string + string packageType = null; + switch (_windowData.relatedPackage) + { + case VRCPackageEnum.Avatars: + packageType = "com.vrchat.avatars"; + break; + case VRCPackageEnum.Base: + packageType = "com.vrchat.base"; + break; + case VRCPackageEnum.Worlds: + packageType = "com.vrchat.worlds"; + break; + } + + string parentDir = new DirectoryInfo(targetDir)?.Parent.FullName; + var packageDir = Core.Utilities.CreateStarterPackage(_windowData.packageID, parentDir, packageType); + + // Modify manifest to add author + // Todo: add support for passing author into CreateStarterPackage + var manifest = + VRCPackageManifest.GetManifestAtPath(Path.Combine(packageDir, VRCPackageManifest.Filename)) as + VRCPackageManifest; + manifest.author = new Author() + { + email = _windowData.authorEmail, + name = _windowData.authorName, + url = _windowData.authorUrl + }; + manifest.Save(); + + var allFiles = GetAllFiles(corePath).ToList(); + MoveFilesToPackageDir(allFiles, corePath, targetDir); + + // Clear target asset folder since it should no longer exist + _windowData.targetAssetFolder = ""; + } + + private static IEnumerable GetAllFiles(string path) + { + var excludedPaths = new List() + { + "Editor.meta" + }; + return Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories) + .Where( + s => excludedPaths.All(entry => !s.Contains(entry)) + ); + } + + public static void MoveFilesToPackageDir(List files, string pathBase, string targetDir) + { + EditorUtility.DisplayProgressBar("Migrating Package", "Moving Package Files", 0f); + float totalFiles = files.Count; + + for (int i = 0; i < files.Count; i++) + { + try + { + EditorUtility.DisplayProgressBar("Migrating Package", "Moving Package Files", i / totalFiles); + var file = files[i]; + string simplifiedPath = file.Replace($"{pathBase}\\", ""); + + string dest = null; + if (simplifiedPath.Contains("Editor\\")) + { + // Remove extra 'Editor' subfolders + dest = simplifiedPath.Replace("Editor\\", ""); + dest = Path.Combine(targetDir, "Editor", dest); + } + else + { + // Make complete path to Runtime folder + dest = Path.Combine(targetDir, "Runtime", simplifiedPath); + } + + string targetEnclosingDir = Path.GetDirectoryName(dest); + Directory.CreateDirectory(targetEnclosingDir); + var sourceFile = Path.Combine(pathBase, simplifiedPath); + File.Move(sourceFile, dest); + } + catch (Exception e) + { + Debug.LogError($"Error moving {files[i]}: {e.Message}"); + continue; + } + } + + Directory.Delete(pathBase, true); // cleans up leftover folders since only files are moved + EditorUtility.ClearProgressBar(); + } + + // Important while we're doing copy-and-rename in order to rename paths with "Assets" without renaming paths with "Sample Assets" + public static string ReplaceFirst(string text, string search, string replace) + { + int pos = text.IndexOf(search); + if (pos < 0) + { + return text; + } + + return text.Substring(0, pos) + replace + text.Substring(pos + search.Length); + } + + #endregion + } + +} \ No newline at end of file diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker/PackageMakerWindow.cs.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker/PackageMakerWindow.cs.meta new file mode 100644 index 0000000..e2b9647 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker/PackageMakerWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d75fcaecb8b9e7f4bbe783e5f4c9838a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker/PackageMakerWindowData.cs b/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker/PackageMakerWindowData.cs new file mode 100644 index 0000000..df8eef6 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker/PackageMakerWindowData.cs @@ -0,0 +1,48 @@ +using System.IO; +using UnityEditor; +using UnityEngine; +using VRC.PackageManagement.PackageMaker; + +public class PackageMakerWindowData : ScriptableObject +{ + public static string defaultAssetPath = Path.Combine("Assets", "PackageMakerWindowData.asset"); + public string targetAssetFolder; + public string packageID; + + public string authorName; + public string authorEmail; + public string authorUrl; + public PackageMakerWindow.VRCPackageEnum relatedPackage; + + public static PackageMakerWindowData GetOrCreate() + { + var existingData = AssetDatabase.AssetPathToGUID(defaultAssetPath); + if (string.IsNullOrWhiteSpace(existingData)) + { + return Create(); + } + else + { + var saveData = AssetDatabase.LoadAssetAtPath(defaultAssetPath); + if (saveData == null) + { + Debug.LogError($"Could not load saved data but the save file exists. Resetting."); + return Create(); + } + return saveData; + } + } + + public static PackageMakerWindowData Create() + { + var saveData = CreateInstance(); + AssetDatabase.CreateAsset(saveData, defaultAssetPath); + AssetDatabase.SaveAssets(); + return saveData; + } + + public void Save() + { + AssetDatabase.SaveAssets(); + } +} diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker/PackageMakerWindowData.cs.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker/PackageMakerWindowData.cs.meta new file mode 100644 index 0000000..da310c3 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/PackageMaker/PackageMakerWindowData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0adae93375f5d5840a30b6e47f324172 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver.meta new file mode 100644 index 0000000..25636fb --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0aa72fa778aef5b4cb5fa177c19d3636 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver/Resolver.cs b/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver/Resolver.cs new file mode 100644 index 0000000..addd3b6 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver/Resolver.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Serilog; +using Serilog.Sinks.Unity3D; +using UnityEditor; +using UnityEngine; +using VRC.PackageManagement.Core; +using VRC.PackageManagement.Core.Types; +using VRC.PackageManagement.Core.Types.Packages; +using Version = VRC.PackageManagement.Core.Types.VPMVersion.Version; + +namespace VRC.PackageManagement.Resolver +{ + + [InitializeOnLoad] + public class Resolver + { + private const string _projectLoadedKey = "PROJECT_LOADED"; + + private static string _projectDir; + public static string ProjectDir + { + get + { + if (_projectDir != null) + { + return _projectDir; + } + + try + { + _projectDir = new DirectoryInfo(Assembly.GetExecutingAssembly().Location).Parent.Parent.Parent + .FullName; + return _projectDir; + } + catch (Exception) + { + return ""; + } + } + } + + static Resolver() + { + SetupLogging(); + if (!SessionState.GetBool(_projectLoadedKey, false)) + { +#pragma warning disable 4014 + CheckResolveNeeded(); +#pragma warning restore 4014 + } + } + + private static void SetupLogging() + { + VRCLibLogger.SetLoggerDirectly( + new LoggerConfiguration() + .MinimumLevel.Information() + .WriteTo.Unity3D() + .CreateLogger() + ); + } + + private static async Task CheckResolveNeeded() + { + SessionState.SetBool(_projectLoadedKey, true); + + //Wait for project to finish compiling + while (EditorApplication.isCompiling || EditorApplication.isUpdating) + { + await Task.Delay(250); + } + + try + { + + if (string.IsNullOrWhiteSpace(ProjectDir)) + { + return; + } + + if (VPMProjectManifest.ResolveIsNeeded(ProjectDir)) + { + Debug.Log($"Resolve needed."); + var result = EditorUtility.DisplayDialog("VRChat Package Management", + $"This project requires some VRChat Packages which are not in the project yet.\n\nPress OK to download and install them.", + "OK", "Show Me What's Missing"); + if (result) + { + ResolveStatic(ProjectDir); + } + else + { + ResolverWindow.ShowWindow(); + } + } + } + catch (Exception) + { + // Unity says we can't open windows from this function so it throws an exception but also works fine. + } + } + + public static bool VPMManifestExists() + { + return VPMProjectManifest.Exists(ProjectDir, out _); + } + + public static void CreateManifest() + { + VPMProjectManifest.Load(ProjectDir); + ResolverWindow.Refresh(); + } + + public static void ResolveManifest() + { + ResolveStatic(ProjectDir); + } + + public static void ResolveStatic(string dir) + { + // Todo: calculate and show actual progress + EditorUtility.DisplayProgressBar($"Getting all VRChat Packages", "Downloading and Installing...", 0.5f); + VPMProjectManifest.Resolve(ProjectDir); + EditorUtility.ClearProgressBar(); + ForceRefresh(); + } + + public static List GetAllVersionsOf(string id) + { + var project = new UnityProject(ProjectDir); + + var versions = new List(); + foreach (var provider in Repos.GetAll) + { + var packagesWithVersions = provider.GetAllWithVersions(); + + foreach (var packageVersionList in packagesWithVersions) + { + foreach (var package in packageVersionList.Value.VersionsDescending) + { + if (package.Id != id) + continue; + if (Version.TryParse(package.Version, out var result)) + { + if (!versions.Contains(package.Version)) + versions.Add(package.Version); + } + } + } + } + + // Sort packages in project to the top + var sorted = from entry in versions orderby project.VPMProvider.HasPackage(entry) descending select entry; + + return sorted.ToList(); + } + + public static List GetAffectedPackageList(IVRCPackage package) + { + List list = new List(); + + var project = new UnityProject(ProjectDir); + + if (Repos.GetAllDependencies(package, out Dictionary dependencies, null)) + { + foreach (KeyValuePair item in dependencies) + { + project.VPMProvider.Refresh(); + if (project.VPMProvider.GetPackage(item.Key, item.Value) == null) + { + IVRCPackage d = Repos.GetPackageWithVersionMatch(item.Key, item.Value); + if (d != null) + { + list.Add(d.Id + " " + d.Version + "\n"); + } + } + } + + return list; + } + + return null; + } + + public static void ForceRefresh () + { + UnityEditor.PackageManager.Client.Resolve(); + AssetDatabase.Refresh(); + } + + } +} \ No newline at end of file diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver/Resolver.cs.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver/Resolver.cs.meta new file mode 100644 index 0000000..a540340 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver/Resolver.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f872e3586f8b4f06bab3c9facd14f6e6 +timeCreated: 1659048476 \ No newline at end of file diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver/ResolverWindow.cs b/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver/ResolverWindow.cs new file mode 100644 index 0000000..fad3f54 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver/ResolverWindow.cs @@ -0,0 +1,292 @@ +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; +using VRC.PackageManagement.Core; +using VRC.PackageManagement.Core.Types; +using VRC.PackageManagement.Core.Types.Packages; +using Version = VRC.PackageManagement.Core.Types.VPMVersion.Version; + +namespace VRC.PackageManagement.Resolver +{ + public class ResolverWindow : EditorWindow + { + // VisualElements + private static VisualElement _rootView; + private static Button _refreshButton; + private static Button _createButton; + private static Button _resolveButton; + private static Box _manifestInfo; + private static Label _manifestLabel; + private static bool _isUpdating; + private static Color _colorPositive = Color.green; + private static Color _colorNegative = new Color(1, 0.3f, 0.3f); + + + [MenuItem("VRChat SDK/Utilities/Package Resolver")] + public static void ShowWindow() + { + ResolverWindow wnd = GetWindow(); + wnd.titleContent = new GUIContent("Package Resolver"); + } + + public static void Refresh() + { + if (_rootView == null || string.IsNullOrWhiteSpace(Resolver.ProjectDir)) return; + + _manifestInfo.SetEnabled(!_isUpdating); + _refreshButton.SetEnabled(!_isUpdating); + _manifestLabel.text = (_isUpdating ? "Working ..." : "Required Packages"); + _manifestInfo.Clear(); + _manifestInfo.Add(_manifestLabel); + + bool needsResolve = VPMProjectManifest.ResolveIsNeeded(Resolver.ProjectDir); + string resolveStatus = needsResolve ? "Please press \"Resolve\" to Download them." : "All of them are in the project."; + + // check for vpm dependencies + if (!Resolver.VPMManifestExists()) + { + TextElement noManifestText = new TextElement(); + noManifestText.text = "No VPM Manifest"; + noManifestText.style.color = _colorNegative; + _manifestInfo.Add(noManifestText); + } + else + { + var manifest = VPMProjectManifest.Load(Resolver.ProjectDir); + var project = new UnityProject(Resolver.ProjectDir); + + // Here is where we detect if all dependencies are installed + var allDependencies = (manifest.locked != null && manifest.locked.Count > 0) + ? manifest.locked + : manifest.dependencies; + + foreach (var pair in allDependencies) + { + var id = pair.Key; + var version = pair.Value.version; + IVRCPackage package = project.VPMProvider.GetPackage(id, version); + _manifestInfo.Add(CreateDependencyRow(id, version, project, (package != null))); + } + + } + _resolveButton.SetEnabled(needsResolve); + Resolver.ForceRefresh(); + } + + /// + /// Unity calls the CreateGUI method automatically when the window needs to display + /// + private void CreateGUI() + { + _rootView = rootVisualElement; + _rootView.name = "root-view"; + _rootView.styleSheets.Add((StyleSheet)Resources.Load("ResolverWindowStyle")); + + // Main Container + var container = new Box() + { + name = "buttons" + }; + _rootView.Add(container); + + // Create Button + if (!Resolver.VPMManifestExists()) + { + _createButton = new Button(Resolver.CreateManifest) + { + text = "Create", + name = "create-button-base" + }; + container.Add(_createButton); + } + else + { + _resolveButton = new Button(Resolver.ResolveManifest) + { + text = "Resolve All", + name = "resolve-button-base" + }; + container.Add(_resolveButton); + } + + // Manifest Info + _manifestInfo = new Box() + { + name = "manifest-info", + }; + _manifestLabel = (new Label("Required Packages") { name = "manifest-header" }); + + _rootView.Add(_manifestInfo); + + // Refresh Button + var refreshBox = new Box(); + _refreshButton = new Button(Refresh) + { + text = "Refresh", + name = "refresh-button-base" + }; + refreshBox.Add(_refreshButton); + _rootView.Add(refreshBox); + + Refresh(); + } + + private static VisualElement CreateDependencyRow(string id, string version, UnityProject project, bool havePackage) + { + // Table + + VisualElement row = new Box() { name = "package-box" }; + VisualElement column1 = new Box() { name = "package-box" }; + VisualElement column2 = new Box() { name = "package-box" }; + VisualElement column3 = new Box() { name = "package-box" }; + VisualElement column4 = new Box() { name = "package-box" }; + + column1.style.minWidth = 200; + column2.style.minWidth = 100; + column3.style.minWidth = 100; + column4.style.minWidth = 100; + + row.Add(column1); + row.Add(column2); + row.Add(column3); + row.Add(column4); + + // Package Name + Status + + TextElement text = new TextElement { text = $"{id} {version} " }; + + column1.Add(text); + + if (!havePackage) + { + TextElement missingText = new TextElement { text = "MISSING" }; + missingText.style.color = _colorNegative; + missingText.style.display = (_isUpdating ? DisplayStyle.None : DisplayStyle.Flex); + column2.Add(missingText); + } + + // Version Popup + + var choices = new List(); + foreach (string n in Resolver.GetAllVersionsOf(id)) + { + choices.Add(n); + } + + var popupField = new PopupField(choices, 0); + popupField.value = choices[0]; + popupField.style.display = (_isUpdating ? DisplayStyle.None : DisplayStyle.Flex); + + column3.Add(popupField); + + // Button + + Button updateButton = new Button() { text = "Update" }; + if (havePackage) + RefreshUpdateButton(updateButton, version, choices[0]); + else + RefreshMissingButton(updateButton); + + updateButton.clicked += (() => + { + IVRCPackage package = Repos.GetPackageWithVersionMatch(id, popupField.value); + + // Check and warn on Dependencies if Updating or Downgrading + if (Version.TryParse(version, out var currentVersion) && + Version.TryParse(popupField.value, out var newVersion)) + { + Dictionary dependencies = new Dictionary(); + StringBuilder dialogMsg = new StringBuilder(); + List affectedPackages = Resolver.GetAffectedPackageList(package); + for (int v = 0; v < affectedPackages.Count; v++) + { + dialogMsg.Append(affectedPackages[v]); + } + + if (affectedPackages.Count > 1) + { + dialogMsg.Insert(0, "This will update multiple packages:\n\n"); + dialogMsg.AppendLine("\nAre you sure?"); + if (EditorUtility.DisplayDialog("Package Has Dependencies", dialogMsg.ToString(), "OK", "Cancel")) + OnUpdatePackageClicked(project, package); + } + else + { + OnUpdatePackageClicked(project, package); + } + } + + }); + column4.Add(updateButton); + + popupField.RegisterCallback>((evt) => + { + if (havePackage) + RefreshUpdateButton(updateButton, version, evt.newValue); + else + RefreshMissingButton(updateButton); + }); + + return row; + } + + private static void RefreshUpdateButton(Button button, string currentVersion, string highestAvailableVersion) + { + if (currentVersion == highestAvailableVersion) + { + button.style.display = DisplayStyle.None; + } + else + { + button.style.display = (_isUpdating ? DisplayStyle.None : DisplayStyle.Flex); + if (Version.TryParse(currentVersion, out var currentVersionObject) && + Version.TryParse(highestAvailableVersion, out var highestAvailableVersionObject)) + { + if (currentVersionObject < highestAvailableVersionObject) + { + SetButtonColor(button, _colorPositive); + button.text = "Update"; + } + else + { + SetButtonColor(button, _colorNegative); + button.text = "Downgrade"; + } + } + } + } + + private static void RefreshMissingButton(Button button) + { + button.text = "Resolve"; + SetButtonColor(button, Color.white); + button.style.display = (_isUpdating ? DisplayStyle.None : DisplayStyle.Flex); + } + + private static void SetButtonColor(Button button, Color color) + { + button.style.color = color; + color.a = 0.25f; + button.style.borderRightColor = + button.style.borderLeftColor = + button.style.borderTopColor = + button.style.borderBottomColor = + color; + } + + private static async void OnUpdatePackageClicked(UnityProject project, IVRCPackage package) + { + _isUpdating = true; + Refresh(); + await Task.Delay(500); + await Task.Run(() => project.UpdateVPMPackage(package)); + _isUpdating = false; + Refresh(); + } + + } +} \ No newline at end of file diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver/ResolverWindow.cs.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver/ResolverWindow.cs.meta new file mode 100644 index 0000000..fbfb6ef --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Resolver/ResolverWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 32d2636186ee0834fa1dc2287750dd32 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Resources.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Resources.meta new file mode 100644 index 0000000..4474299 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8700b619eebc09545b4aaf4f69a2bf79 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Resources/PackageMakerWindowStyle.uss b/Packages/com.vrchat.core.vpm-resolver/Editor/Resources/PackageMakerWindowStyle.uss new file mode 100644 index 0000000..14ce0e7 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Resources/PackageMakerWindowStyle.uss @@ -0,0 +1,16 @@ +.unity-box { + margin: 10px; + padding:10px; +} + +.unity-box #description { + margin: 10px 0 10px 0; + white-space: normal; +} + +#action-button { + font-size: 20px; + -unity-font-style: bold; + padding: 10px; + margin:10px; +} \ No newline at end of file diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Resources/PackageMakerWindowStyle.uss.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Resources/PackageMakerWindowStyle.uss.meta new file mode 100644 index 0000000..80fa1a7 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Resources/PackageMakerWindowStyle.uss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8dfe8fb3b6d0f3e4693553ecc1cb23dd +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Resources/ResolverWindowStyle.uss b/Packages/com.vrchat.core.vpm-resolver/Editor/Resources/ResolverWindowStyle.uss new file mode 100644 index 0000000..443e2e9 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Resources/ResolverWindowStyle.uss @@ -0,0 +1,25 @@ +.unity-box { + margin:2px; + padding:10px; + border-width:0px; +} + +#package-box { + margin:2px; + padding:10px; + border-width:0px; + flex-direction:row; + max-height:20px; + min-height:20px; + height:20px; + padding-top:0px; + padding-bottom:0px; + margin-top:0px; + margin-bottom:0px; + align-items:center; +} + +#manifest-header { + font-size: 20px; + margin-bottom: 10px; +} \ No newline at end of file diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/Resources/ResolverWindowStyle.uss.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/Resources/ResolverWindowStyle.uss.meta new file mode 100644 index 0000000..042729b --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/Resources/ResolverWindowStyle.uss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 346f7a547766ecb4396d15f585a15133 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/com.vrchat.core.vpm-resolver.Editor.asmdef b/Packages/com.vrchat.core.vpm-resolver/Editor/com.vrchat.core.vpm-resolver.Editor.asmdef new file mode 100644 index 0000000..2dd9d94 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/com.vrchat.core.vpm-resolver.Editor.asmdef @@ -0,0 +1,15 @@ +{ + "name": "com.vrchat.core.vpm-resolver.Editor", + "references": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.vrchat.core.vpm-resolver/Editor/com.vrchat.core.vpm-resolver.Editor.asmdef.meta b/Packages/com.vrchat.core.vpm-resolver/Editor/com.vrchat.core.vpm-resolver.Editor.asmdef.meta new file mode 100644 index 0000000..7345680 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/Editor/com.vrchat.core.vpm-resolver.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d1e8c2ba944807d4a9213e2de6930a0b +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/License.md b/Packages/com.vrchat.core.vpm-resolver/License.md new file mode 100644 index 0000000..275530c --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/License.md @@ -0,0 +1,11 @@ +# VRCHAT INC. +### VRCHAT DISTRO LICENSE FILE +Version: February 24, 2022 + +**SUMMARY OF TERMS:** Any materials subject to this Distro Asset License may be distributed by you, with or without modifications, on a non-commercial basis (i.e., at no charge), in accordance with the full terms of the Materials License Agreement. + +This Distro License File is a "License File" as defined in the VRChat Materials License Agreement, found at https://hello.vrchat.com/legal/sdk (or any successor link designated by VRChat) (as may be revised from time to time, the "Materials License Agreement"). + +This Distro License File applies to all the files in the Folder containing this Distro License File and those in all Child Folders within that Folder (except with respect to files in any Child Folder that contains a different License File) (such files, other than this Distro License File, the "Covered Files"). All capitalized terms used but not otherwise defined in this Distro License File have the meanings provided in the Materials License Agreement. + +This Distro License File only provides a summary of the terms applicable to the Covered Files. To understand your rights and obligations and the full set of terms that apply to use of the Covered Files, please see the relevant sections of the Materials License Agreement, including terms applicable to Distro Materials. \ No newline at end of file diff --git a/Packages/com.vrchat.core.vpm-resolver/License.md.meta b/Packages/com.vrchat.core.vpm-resolver/License.md.meta new file mode 100644 index 0000000..20b9751 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/License.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7727f888edf4714448d5a0287deec6dd +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vrchat.core.vpm-resolver/package.json b/Packages/com.vrchat.core.vpm-resolver/package.json new file mode 100644 index 0000000..2e1a7d9 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/package.json @@ -0,0 +1,17 @@ +{ + "name" : "com.vrchat.core.vpm-resolver", + "displayName" : "VRChat Package Resolver Tool", + "version" : "0.1.27", + "unity" : "2022.3", + "description" : "Tool to Download VPM Packages", + "vrchatVersion" : "2022.3.3", + "author" : { + "name" : "VRChat", + "email" : "developer@vrchat.com", + "url" : "https://github.com/vrchat/packages" + }, + "url" : "", + "dependencies" : { + "com.unity.nuget.newtonsoft-json" : "3.0.2" + } +} diff --git a/Packages/com.vrchat.core.vpm-resolver/package.json.meta b/Packages/com.vrchat.core.vpm-resolver/package.json.meta new file mode 100644 index 0000000..b323585 --- /dev/null +++ b/Packages/com.vrchat.core.vpm-resolver/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6b02e2915ebf04e4ea94e503d73e7411 +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/manifest.json b/Packages/manifest.json new file mode 100644 index 0000000..0c78bbd --- /dev/null +++ b/Packages/manifest.json @@ -0,0 +1,44 @@ +{ + "dependencies": { + "com.unity.ai.navigation": "1.1.4", + "com.unity.ide.rider": "3.0.24", + "com.unity.ide.visualstudio": "2.0.18", + "com.unity.ide.vscode": "1.2.5", + "com.unity.test-framework": "1.1.33", + "com.unity.textmeshpro": "3.0.6", + "com.unity.timeline": "1.7.5", + "com.unity.toolchain.win-x86_64-linux-x86_64": "2.0.6", + "com.unity.ugui": "1.0.0", + "com.unity.modules.ai": "1.0.0", + "com.unity.modules.androidjni": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.cloth": "1.0.0", + "com.unity.modules.director": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.terrainphysics": "1.0.0", + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.uielements": "1.0.0", + "com.unity.modules.umbra": "1.0.0", + "com.unity.modules.unityanalytics": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.unitywebrequesttexture": "1.0.0", + "com.unity.modules.unitywebrequestwww": "1.0.0", + "com.unity.modules.vehicles": "1.0.0", + "com.unity.modules.video": "1.0.0", + "com.unity.modules.vr": "1.0.0", + "com.unity.modules.wind": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } +} diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json new file mode 100644 index 0000000..8cc8932 --- /dev/null +++ b/Packages/packages-lock.json @@ -0,0 +1,412 @@ +{ + "dependencies": { + "com.killers0992.awttersdk": { + "version": "file:com.killers0992.awttersdk", + "depth": 0, + "source": "embedded", + "dependencies": { + "com.unity.postprocessing": "3.1.1", + "com.unity.nuget.newtonsoft-json": "3.0.2", + "com.unity.editorcoroutines": "1.0.0", + "com.unity.sharp-zip-lib": "1.3.4-preview" + } + }, + "com.unity.ai.navigation": { + "version": "1.1.4", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.modules.ai": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.editorcoroutines": { + "version": "1.0.0", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.ext.nunit": { + "version": "1.0.6", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.ide.rider": { + "version": "3.0.24", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ext.nunit": "1.0.6" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ide.visualstudio": { + "version": "2.0.18", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.1.9" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ide.vscode": { + "version": "1.2.5", + "depth": 0, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.nuget.newtonsoft-json": { + "version": "3.2.1", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.postprocessing": { + "version": "3.2.2", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.modules.physics": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.sharp-zip-lib": { + "version": "1.3.4-preview", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.sysroot": { + "version": "2.0.7", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.sysroot.linux-x86_64": { + "version": "2.0.6", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.sysroot": "2.0.7" + }, + "url": "https://packages.unity.com" + }, + "com.unity.test-framework": { + "version": "1.1.33", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ext.nunit": "1.0.6", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.textmeshpro": { + "version": "3.0.6", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ugui": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.timeline": { + "version": "1.7.5", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.modules.director": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.toolchain.win-x86_64-linux-x86_64": { + "version": "2.0.6", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.sysroot": "2.0.7", + "com.unity.sysroot.linux-x86_64": "2.0.6" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ugui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.imgui": "1.0.0" + } + }, + "com.vrchat.core.bootstrap": { + "version": "file:com.vrchat.core.bootstrap", + "depth": 0, + "source": "embedded", + "dependencies": { + "com.unity.nuget.newtonsoft-json": "2.0.2" + } + }, + "com.vrchat.core.vpm-resolver": { + "version": "file:com.vrchat.core.vpm-resolver", + "depth": 0, + "source": "embedded", + "dependencies": { + "com.unity.nuget.newtonsoft-json": "3.0.2" + } + }, + "com.unity.modules.ai": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.androidjni": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.animation": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.assetbundle": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.audio": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.cloth": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0" + } + }, + "com.unity.modules.director": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.animation": "1.0.0" + } + }, + "com.unity.modules.imageconversion": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.imgui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.jsonserialize": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.particlesystem": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.physics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.physics2d": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.screencapture": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.subsystems": { + "version": "1.0.0", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.terrain": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.terrainphysics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.terrain": "1.0.0" + } + }, + "com.unity.modules.tilemap": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics2d": "1.0.0" + } + }, + "com.unity.modules.ui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.uielements": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.umbra": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.unityanalytics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.unitywebrequest": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.unitywebrequestassetbundle": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" + } + }, + "com.unity.modules.unitywebrequestaudio": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.audio": "1.0.0" + } + }, + "com.unity.modules.unitywebrequesttexture": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.unitywebrequestwww": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.vehicles": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0" + } + }, + "com.unity.modules.video": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" + } + }, + "com.unity.modules.vr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } + }, + "com.unity.modules.wind": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.xr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.subsystems": "1.0.0" + } + } + } +} diff --git a/Packages/vpm-manifest.json b/Packages/vpm-manifest.json new file mode 100644 index 0000000..9e8f163 --- /dev/null +++ b/Packages/vpm-manifest.json @@ -0,0 +1 @@ +{"dependencies": {}, "locked": {}} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..89059f7 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/Killers0992/AwtterSDK/total?label=Downloads&labelColor=2e343e&color=00FFFF&style=for-the-badge) +![License](https://img.shields.io/github/license/Ileriayo/markdown-badges?style=for-the-badge&labelColor=2e343e&color=00FFFF&) +# Awtter SDK + +

+Add to VCC +

\ No newline at end of file diff --git a/Website/app.js b/Website/app.js new file mode 100644 index 0000000..b15c8fe --- /dev/null +++ b/Website/app.js @@ -0,0 +1,231 @@ +import { baseLayerLuminance, StandardLuminance } from 'https://unpkg.com/@fluentui/web-components'; + +const LISTING_URL = "{{ listingInfo.Url }}"; + +const PACKAGES = { +{{~ for package in packages ~}} + "{{ package.Name }}": { + name: "{{ package.Name }}", + displayName: "{{ if package.DisplayName; package.DisplayName; end; }}", + description: "{{ if package.Description; package.Description; end; }}", + version: "{{ package.Version }}", + author: { + name: "{{ if package.Author.Name; package.Author.Name; end; }}", + url: "{{ if package.Author.Url; package.Author.Url; end; }}", + }, + dependencies: { + {{~ for dependency in package.Dependencies ~}} + "{{ dependency.Name }}": "{{ dependency.Version }}", + {{~ end ~}} + }, + keywords: [ + {{~ for keyword in package.Keywords ~}} + "{{ keyword }}", + {{~ end ~}} + ], + license: "{{ package.License }}", + licensesUrl: "{{ package.LicensesUrl }}", + }, +{{~ end ~}} +}; + +const setTheme = () => { + const isDarkTheme = () => window.matchMedia("(prefers-color-scheme: dark)").matches; + if (isDarkTheme()) { + baseLayerLuminance.setValueFor(document.documentElement, StandardLuminance.DarkMode); + } else { + baseLayerLuminance.setValueFor(document.documentElement, StandardLuminance.LightMode); + } +} + +(() => { + setTheme(); + + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { + setTheme(); + }); + + const packageGrid = document.getElementById('packageGrid'); + + const searchInput = document.getElementById('searchInput'); + searchInput.addEventListener('input', ({ target: { value = '' }}) => { + const items = packageGrid.querySelectorAll('fluent-data-grid-row[row-type="default"]'); + items.forEach(item => { + if (value === '') { + item.style.display = 'grid'; + return; + } + if ( + item.dataset?.packageName?.toLowerCase()?.includes(value.toLowerCase()) || + item.dataset?.packageId?.toLowerCase()?.includes(value.toLowerCase()) + ) { + item.style.display = 'grid'; + } else { + item.style.display = 'none'; + } + }); + }); + + const urlBarHelpButton = document.getElementById('urlBarHelp'); + const addListingToVccHelp = document.getElementById('addListingToVccHelp'); + urlBarHelpButton.addEventListener('click', () => { + addListingToVccHelp.hidden = false; + }); + const addListingToVccHelpClose = document.getElementById('addListingToVccHelpClose'); + addListingToVccHelpClose.addEventListener('click', () => { + addListingToVccHelp.hidden = true; + }); + + const vccListingInfoUrlFieldCopy = document.getElementById('vccListingInfoUrlFieldCopy'); + vccListingInfoUrlFieldCopy.addEventListener('click', () => { + const vccUrlField = document.getElementById('vccListingInfoUrlField'); + vccUrlField.select(); + navigator.clipboard.writeText(vccUrlField.value); + vccUrlFieldCopy.appearance = 'accent'; + setTimeout(() => { + vccUrlFieldCopy.appearance = 'neutral'; + }, 1000); + }); + + const vccAddRepoButton = document.getElementById('vccAddRepoButton'); + vccAddRepoButton.addEventListener('click', () => window.location.assign(`vcc://vpm/addRepo?url=${encodeURIComponent(LISTING_URL)}`)); + + const vccUrlFieldCopy = document.getElementById('vccUrlFieldCopy'); + vccUrlFieldCopy.addEventListener('click', () => { + const vccUrlField = document.getElementById('vccUrlField'); + vccUrlField.select(); + navigator.clipboard.writeText(vccUrlField.value); + vccUrlFieldCopy.appearance = 'accent'; + setTimeout(() => { + vccUrlFieldCopy.appearance = 'neutral'; + }, 1000); + }); + + const rowMoreMenu = document.getElementById('rowMoreMenu'); + const hideRowMoreMenu = e => { + if (rowMoreMenu.contains(e.target)) return; + document.removeEventListener('click', hideRowMoreMenu); + rowMoreMenu.hidden = true; + } + + const rowMenuButtons = document.querySelectorAll('.rowMenuButton'); + rowMenuButtons.forEach(button => { + button.addEventListener('click', e => { + if (rowMoreMenu?.hidden) { + rowMoreMenu.style.top = `${e.clientY + e.target.clientHeight}px`; + rowMoreMenu.style.left = `${e.clientX - 120}px`; + rowMoreMenu.hidden = false; + + const downloadLink = rowMoreMenu.querySelector('#rowMoreMenuDownload'); + const downloadListener = () => { + window.open(e?.target?.dataset?.packageUrl, '_blank'); + } + downloadLink.addEventListener('change', () => { + downloadListener(); + downloadLink.removeEventListener('change', downloadListener); + }); + + setTimeout(() => { + document.addEventListener('click', hideRowMoreMenu); + }, 1); + } + }); + }); + + const packageInfoModal = document.getElementById('packageInfoModal'); + const packageInfoModalClose = document.getElementById('packageInfoModalClose'); + packageInfoModalClose.addEventListener('click', () => { + packageInfoModal.hidden = true; + }); + + // Fluent dialogs use nested shadow-rooted elements, so we need to use JS to style them + const modalControl = packageInfoModal.shadowRoot.querySelector('.control'); + modalControl.style.maxHeight = "90%"; + modalControl.style.transition = 'height 0.2s ease-in-out'; + modalControl.style.overflowY = 'hidden'; + + const packageInfoName = document.getElementById('packageInfoName'); + const packageInfoId = document.getElementById('packageInfoId'); + const packageInfoVersion = document.getElementById('packageInfoVersion'); + const packageInfoDescription = document.getElementById('packageInfoDescription'); + const packageInfoAuthor = document.getElementById('packageInfoAuthor'); + const packageInfoDependencies = document.getElementById('packageInfoDependencies'); + const packageInfoKeywords = document.getElementById('packageInfoKeywords'); + const packageInfoLicense = document.getElementById('packageInfoLicense'); + + const rowAddToVccButtons = document.querySelectorAll('.rowAddToVccButton'); + rowAddToVccButtons.forEach((button) => { + button.addEventListener('click', () => window.location.assign(`vcc://vpm/addRepo?url=${encodeURIComponent(LISTING_URL)}`)); + }); + + const rowPackageInfoButton = document.querySelectorAll('.rowPackageInfoButton'); + rowPackageInfoButton.forEach((button) => { + button.addEventListener('click', e => { + const packageId = e.target.dataset?.packageId; + const packageInfo = PACKAGES?.[packageId]; + if (!packageInfo) { + console.error(`Did not find package ${packageId}. Packages available:`, PACKAGES); + return; + } + + packageInfoName.textContent = packageInfo.displayName; + packageInfoId.textContent = packageId; + packageInfoVersion.textContent = `v${packageInfo.version}`; + packageInfoDescription.textContent = packageInfo.description; + packageInfoAuthor.textContent = packageInfo.author.name; + packageInfoAuthor.href = packageInfo.author.url; + + if ((packageInfo.keywords?.length ?? 0) === 0) { + packageInfoKeywords.parentElement.classList.add('hidden'); + } else { + packageInfoKeywords.parentElement.classList.remove('hidden'); + packageInfoKeywords.innerHTML = null; + packageInfo.keywords.forEach(keyword => { + const keywordDiv = document.createElement('div'); + keywordDiv.classList.add('me-2', 'mb-2', 'badge'); + keywordDiv.textContent = keyword; + packageInfoKeywords.appendChild(keywordDiv); + }); + } + + if (!packageInfo.license?.length && !packageInfo.licensesUrl?.length) { + packageInfoLicense.parentElement.classList.add('hidden'); + } else { + packageInfoLicense.parentElement.classList.remove('hidden'); + packageInfoLicense.textContent = packageInfo.license ?? 'See License'; + packageInfoLicense.href = packageInfo.licensesUrl ?? '#'; + } + + packageInfoDependencies.innerHTML = null; + Object.entries(packageInfo.dependencies).forEach(([name, version]) => { + const depRow = document.createElement('li'); + depRow.classList.add('mb-2'); + depRow.textContent = `${name} @ v${version}`; + packageInfoDependencies.appendChild(depRow); + }); + + packageInfoModal.hidden = false; + + setTimeout(() => { + const height = packageInfoModal.querySelector('.col').clientHeight; + modalControl.style.setProperty('--dialog-height', `${height + 14}px`); + }, 1); + }); + }); + + const packageInfoVccUrlFieldCopy = document.getElementById('packageInfoVccUrlFieldCopy'); + packageInfoVccUrlFieldCopy.addEventListener('click', () => { + const vccUrlField = document.getElementById('packageInfoVccUrlField'); + vccUrlField.select(); + navigator.clipboard.writeText(vccUrlField.value); + vccUrlFieldCopy.appearance = 'accent'; + setTimeout(() => { + vccUrlFieldCopy.appearance = 'neutral'; + }, 1000); + }); + + const packageInfoListingHelp = document.getElementById('packageInfoListingHelp'); + packageInfoListingHelp.addEventListener('click', () => { + addListingToVccHelp.hidden = false; + }); +})(); \ No newline at end of file diff --git a/Website/banner.png b/Website/banner.png new file mode 100644 index 0000000..6609efc Binary files /dev/null and b/Website/banner.png differ diff --git a/Website/favicon.ico b/Website/favicon.ico new file mode 100644 index 0000000..a72240a Binary files /dev/null and b/Website/favicon.ico differ diff --git a/Website/index.html b/Website/index.html new file mode 100644 index 0000000..8bb119c --- /dev/null +++ b/Website/index.html @@ -0,0 +1,221 @@ + + + + + + VCC Listing + + + + + +
+
+ {{~ if listingInfo.BannerImage; ~}} +
+ {{~ end; ~}} +

+ {{~ listingInfo.Name ~}} +

+ {{~ if listingInfo.Description; ~}} +
{{ listingInfo.Description }}
+ {{~ end; ~}} +
+ {{~ if listingInfo.Author.Email; ~}} + + {{ listingInfo.Author.Email }} + + {{~ end; ~}} + + {{~ if listingInfo.InfoLink.Url ~}} + + {{~ end; ~}} +
+
+
+ + + Add to VCC + + + + + Copy + + + How to add a listing to your VCC + + + + + + +
+ +
+ +
+ + + + + + + Name + + + Type + + + + + {{~ for package in packages ~}} + + +
+
{{ package.DisplayName }}
+
{{ package.Description }}
+
{{ package.Name }}
+
+
+ + {{ package.Type }} + + + Add to VCC + + + + + + + + + + + +
+ {{~ end ~}} +
+
+ {{~ if listingInfo.InfoLink.Url ~}} + + {{~ end; ~}} +
+ + + diff --git a/Website/styles.css b/Website/styles.css new file mode 100644 index 0000000..ce999b0 --- /dev/null +++ b/Website/styles.css @@ -0,0 +1,356 @@ +:root { + color-scheme: light dark; +} + +* { + box-sizing: border-box; +} + +body { + padding: 0; + margin: 0; + min-width: 100vw; + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + color: var(--neutral-foreground-rest); +} + +.hidden { + display: none !important; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.content { + max-width: 1000px; + width: 100%; + margin: 0 auto; +} + +.align-items-center { + align-items: center; +} + +.justify-content-between { + justify-content: space-between; +} + +.justify-content-end { + justify-content: flex-end; +} + +h1 { + margin-bottom: 0.5rem; +} + +.caption1 { + font-size: 1rem; + color: var(--neutral-foreground-hover); +} + +.caption2 { + font-size: 0.8rem; + margin-top: 0.25rem; + color: var(--neutral-foreground-rest); +} + +.packages { + margin: 0.5rem 0 1rem 0; + max-width: 90%; + padding: 0.25rem; + display: flex; + flex: 1; +} + +#packageGrid { + overflow-y: auto; + width: 100%; + max-height: 40rem; +} + +.packages .packageName { + font-size: 1.1rem; + font-weight: 600; + margin: 0.25rem 0; +} + +.searchBlock { + margin-top: 1rem; + width: 100%; + max-width: 90%; +} + +.searchBlock .root { + width: 100%; +} + +#searchInput { + width: 100%; +} + +.vccUrlField { + min-width: 450px; + max-width: 90%; + flex-grow:1; +} + +#addListingToVccHelp { + z-index: 11; +} + +#packageInfoModal { + z-index: 10; +} + +#rowMoreMenu { + top: 0; + left: 0; + position: absolute; + z-index: 10; +} + +#rowMoreMenu a { + display: block; + text-decoration: none; + color: var(--neutral-foreground-rest); +} + +.bannerImage { + aspect-ratio: 5 / 1; + border-radius: 6px; + max-width: 90%; + width: 100%; + background-size: cover; + background-position: center; + background-repeat: no-repeat; + margin-bottom: 0.25rem; +} + +.badge { + border-radius: 4px; + padding: 0.25rem 0.5rem; + background-color: var(--neutral-fill-hover); +} + +.m-0 { + margin: 0; +} + +.m-1 { + margin: 0.25rem; +} + +.m-2 { + margin: 0.5rem; +} + +.m-3 { + margin: 0.75rem; +} + +.m-4 { + margin: 1rem; +} + +.m-5 { + margin: 2rem; +} + +.mt-1 { + margin-top: 0.25rem; +} + +.mt-2 { + margin-top: 0.5rem; +} + +.mt-3 { + margin-top: 0.75rem; +} + +.mt-4 { + margin-top: 1rem; +} + +.mt-5 { + margin-top: 2rem; +} + +.mb-1 { + margin-bottom: 0.25rem; +} + +.mb-2 { + margin-bottom: 0.5rem; +} + +.mb-3 { + margin-bottom: 0.75rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.mb-5 { + margin-bottom: 2rem; +} + +.ms-1 { + margin-left: 0.25rem; +} + +.ms-2 { + margin-left: 0.5rem; +} + +.ms-3 { + margin-left: 0.75rem; +} + +.ms-4 { + margin-left: 1rem; +} + +.ms-5 { + margin-left: 2rem; +} + +.me-1 { + margin-right: 0.25rem; +} + +.me-2 { + margin-right: 0.5rem; +} + +.me-3 { + margin-right: 0.75rem; +} + +.me-4 { + margin-right: 1rem; +} + +.me-5 { + margin-right: 2rem; +} + +.p-1 { + padding: 0.25rem; +} + +.p-2 { + padding: 0.5rem; +} + +.p-3 { + padding: 0.75rem; +} + +.p-4 { + padding: 1rem; +} + +.p-5 { + padding: 2rem; +} + +.pt-1 { + padding-top: 0.25rem; +} + +.pt-2 { + padding-top: 0.5rem; +} + +.pt-3 { + padding-top: 0.75rem; +} + +.pt-4 { + padding-top: 1rem; +} + +.pt-5 { + padding-top: 2rem; +} + +.pb-1 { + padding-bottom: 0.25rem; +} + +.pb-2 { + padding-bottom: 0.5rem; +} + +.pb-3 { + padding-bottom: 0.75rem; +} + +.pb-4 { + padding-bottom: 1rem; +} + +.pb-5 { + padding-bottom: 2rem; +} + +.ps-1 { + padding-left: 0.25rem; +} + +.ps-2 { + padding-left: 0.5rem; +} + +.ps-3 { + padding-left: 0.75rem; +} + +.ps-4 { + padding-left: 1rem; +} + +.ps-5 { + padding-left: 2rem; +} + +.pe-1 { + padding-right: 0.25rem; +} + +.pe-2 { + padding-right: 0.5rem; +} + +.pe-3 { + padding-right: 0.75rem; +} + +.pe-4 { + padding-right: 1rem; +} + +.pe-5 { + padding-right: 2rem; +} + +.w-100 { + width: 100%; +} + +.flex-1 { + flex: 1; +} \ No newline at end of file