Added Unity project files
This commit is contained in:
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f03ff36d4c069a242bd834fa910ceaa4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4580079e962030e448db94032dfc1559
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9d37276b77516a4884f2d78c5cfc710
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@ -0,0 +1,96 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8e4c8f12751f7c439bae4bb849c6166
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 1
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
: Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 0
|
||||
Exclude Editor: 1
|
||||
Exclude Linux: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude LinuxUniversal: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: ARMv7
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Facebook: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Facebook: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Linux
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: LinuxUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: None
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a6ae8ab64d58c944eac7b7257f9420d1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@ -0,0 +1,96 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a100aaac9551f649a8f4ff1280d16db
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 1
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
: Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 0
|
||||
Exclude Editor: 1
|
||||
Exclude Linux: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude LinuxUniversal: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: ARM64
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Facebook: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Facebook: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Linux
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: LinuxUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: None
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 883467ec1b9392b46a1549fac1d7f5dc
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 1
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e3c0e645ca81384a8624dcbf637dc13
|
||||
timeCreated: 1503014485
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,77 @@
|
||||
Copyright © Facebook Technologies, LLC and its affiliates. All rights reserved.
|
||||
|
||||
The Oculus SDK License Agreement became effective on June 1, 2020, and governs your use of all Oculus SDKs. The agreement below is no longer in effect.
|
||||
|
||||
***************************************************************
|
||||
|
||||
The text of this may be found at: https://developer.oculus.com/licenses/audio-3.2.2/
|
||||
|
||||
Human-Readable Summary*:
|
||||
You are Free to:
|
||||
Use, modify, and distribute the Oculus Audio SDK in source and binary form with your applications/software.
|
||||
|
||||
With the Following Restrictions:
|
||||
• Modifications to the Oculus Audio SDK in source or binary form must be shared with Oculus.
|
||||
* This human-readable Summary is not a license. It is simply a convenient reference for understanding the full Oculus Audio SDK License Agreement. The Summary is written as a user-friendly interface to the full Oculus Audio SDK License Agreement below. This Summary itself has no legal value, and its contents do not appear in the actual license.
|
||||
|
||||
Full-length Legal Copy:
|
||||
1. Subject to the terms and conditions of this License Agreement (the “License”), Facebook Technologies, LLC formerly known as Oculus VR, LLC (“Oculus”) hereby grants to you a perpetual, worldwide, non-exclusive, no-charge, royalty-free, sublicenseable copyright license to use, reproduce, redistribute (subject to restrictions below), modify, and improve the software contained in this Oculus Audio Software Development Kit (“AUDIO SDK”). This license is subject to the following terms and conditions:
|
||||
|
||||
1.1. This license includes the non-exclusive license and right to use (i) the AUDIO SDK to make applications, content, games and demos (collectively and generally referred to as “Developer Content”) which may incorporate the AUDIO SDK in whole or in part in binary or object code; and (ii) use the AUDIO SDK to create derivative works of the AUDIO SDK itself (“AUDIO SDK Derivatives”), whether in source, binary, or object form, in whole or in part, including third-party software unless otherwise noted.
|
||||
|
||||
1.2. AUDIO SDK Derivatives are further defined as source, binary or object code derived exclusively from the AUDIO SDK by you; provided, however, that AUDIO SDK Derivatives do not include the Developer Content (engines, utilities, applications, content, games or demos) which may be developed using the AUDIO SDK. By way of example an application or game or demo that is developed using the AUDIO SDK would not be an AUDIO SDK Derivative, nor would a utility or tool set in a pre-existing game engine that is adapted to work with the AUDIO SDK be a AUDIO SDK Derivative. By way of example, but not limitation, an AUDIO SDK Derivative is or would be: either (i) an adaptation of a utility or piece of code from the AUDIO SDK to improve efficiency; or (ii) an addition of code or improvement to the AUDIO SDK that adds functionality.
|
||||
|
||||
1.3 For the sake of clarification when you use the AUDIO SDK (including AUDIO SDK Derivatives) in or with Developer Content, you retain all rights to your Developer Content, and you have no obligations to share or license Developer Content (including your source and object code) to Oculus or any third parties; provided, however, Oculus retains all rights to the AUDIO SDK and the AUDIO SDK Derivatives that may be incorporated into your Developer Content.
|
||||
|
||||
2. You, the recipient and user of the AUDIO SDK, hereby agree and accept that Oculus hereby owns all right, title and interest to the intellectual property rights, including, but not limited to copyright, trademark and patent rights, to any AUDIO SDK Derivatives that you may create, and you hereby assign any and all such rights to such AUDIO SDK Derivatives to Oculus.
|
||||
|
||||
2.1 We hereby grant to you a fully paid up, no-charge, royalty-free, world-wide, in perpetuity, non-exclusive right and license back to use these AUDIO SDK Derivatives solely in conjunction with the AUDIO SDK (or any components of the AUDIO SDK) and/or Developer Content.
|
||||
|
||||
2.2 Furthermore, for the sake of clarification, Oculus and its assignees and licensees shall be free to use such AUDIO SDK Derivatives without any approval from you and without compensation or attribution to you.
|
||||
|
||||
2.3 You also agree upon Oculus’s request to provide the source and binary code of any AUDIO SDK Derivatives to Oculus. Failure to comply with this request is the basis for automatic termination of this License by Oculus.
|
||||
|
||||
3. Subject to the terms and conditions of this License, your license to redistribute and sublicense the AUDIO SDK and AUDIO SDK Derivatives is also expressly made subject to the following conditions:
|
||||
|
||||
3.1. You may sublicense and redistribute the source, binary, or object code of the AUDIO SDK in whole or in part by itself for no charge. If you license, sublicense or redistribute AUDIO SDK Derivatives in and of themselves (not as a part of a piece of Developer Content) then you may only do that solely with and in conjunction with the AUDIO SDK;
|
||||
|
||||
3.2. You must include with all such redistributed or sublicensed AUDIO SDK or AUDIO SDK Derivatives code the following copyright notice: “Copyright © Facebook Technologies, LLC and its affiliates. All rights reserved,” and include the list of conditions contained in this Section 3, including the full text of the disclaimer in Section 3.6 below;
|
||||
|
||||
3.3. Neither the names of Facebook Technologies, LLC, Oculus VR, LLC, Oculus, nor the names of Oculus’s contributors, licensors, employees, or contractors, may be used to endorse or promote products developed using the AUDIO SDK without specific prior written permission of Oculus;
|
||||
|
||||
3.4. You must give any other recipients of the AUDIO SDK or any elements thereof, including AUDIO SDK Derivatives, a copy of this License; and such recipients must agree to and enter into this License with Oculus. Recipients, licensees or sublicensees may only use the AUDIO SDK or any AUDIO SDK Derivatives or any elements thereof subject to the terms of this License. You must cause any modified files to carry prominent notices stating that you changed the files;
|
||||
|
||||
3.5. If the AUDIO SDK or a specific element thereof includes a “LICENSE” text file as part of its distribution (the “License Notice”), then any AUDIO SDK Derivatives that you distribute with the AUDIO SDK in whole or in part must include a readable copy of such attribution notices as are contained within the applicable License Notice file (excluding those notices that do not pertain to any part of the AUDIO SDK Derivatives), in at least one of the following places: within a License Notice text file distributed as part of the AUDIO SDK Derivatives; within the source form or documentation, if provided along with the AUDIO SDK Derivatives; or, within a display generated by the AUDIO SDK Derivatives, if and wherever such third-party notices normally appear. You must also include in the License Notice file for all AUDIO SDK Derivatives a copy of all notices (including any product liability notices). The contents of the License Notice file are for informational purposes only and do not modify the License. You may add your own attribution notices within AUDIO SDK Derivatives that you distribute, alongside or as an addendum to the License Notice text from the AUDIO SDK or any part thereof, provided that such additional attribution notices cannot be construed as modifying the License.
|
||||
|
||||
3.6. THIS AUDIO SDK AND ANY COMPONENT THEREOF IS PROVIDED BY OCULUS AND ITS CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OCULUS AS THE COPYRIGHT OWNER OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS AUDIO SDK OR THE AUDIO SDK DERIVATIVES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
4. This License does not grant permission to use the trade names, trademarks, service marks, or product names of Oculus, except as required for reasonable and customary use in describing the origin of the AUDIO SDK, or any element thereof, and reproducing the content of the License Notice file.
|
||||
|
||||
5. 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 Oculus or any contributor be liable to you or your licensees or sublicensees 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 AUDIO SDK, any element thereof or any AUDIO SDK Derivatives (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 you or such contributor has been advised of the possibility of such damages.
|
||||
|
||||
6. Your acceptance of the terms and conditions of this License in and of itself and for all Developer Content created as of March 2, 2015, may be evidenced by any of the following: your usage of the AUDIO SDK or any element thereof, or acceptance of the click-through agreement. As this License is updated for future releases of the AUDIO SDK, you agree to abide by and meet all requirements of future updates of this License for those future AUDIO SDK releases as evidenced by the same usage of the AUDIO SDK or any element thereof and the future updates of this License will apply for that future Developer Content that may be developed for or with that future AUDIO SDK or any element thereof (i.e., you cannot sidestep out of the requirements of future updates of the License by developing against an older release of the AUDIO SDK or License).
|
||||
|
||||
7. Oculus reserves the right to terminate this License and all your rights hereunder in the event you materially breach this License and fail to cure such breach within ten (10) business days after notice of breach from Oculus.
|
||||
|
||||
8. Furthermore, Oculus also reserves the right to cancel or terminate this License for any of the following reasons upon notice to you, subject to the appeal process set forth in Section 16 for a wrongful termination:
|
||||
|
||||
Intellectual property infringement by you with Developer Content or AUDIO SDK Derivatives created by you that is used with or by the AUDIO SDK or any part thereof, or any of the AUDIO SDK Derivatives;
|
||||
Developer Content that violates or infringes upon applicable law; and
|
||||
Failure to provide required notices or deliver source code and/or binary of AUDIO SDK Derivatives as set forth above.
|
||||
If you believe that your license has been wrongfully terminated under this Section 8 with respect to material breach or with respect to these above conditions, you have the right to appeal the termination of this License under Section 16.
|
||||
|
||||
9. This License may be amended by Oculus on a prospective basis, and your usage of the License after such amendments or changes signifies your consent to and acceptance of any such amendments or changes on a going forward basis.
|
||||
|
||||
10. In the event any provision of this License is determined to be invalid, prohibited or unenforceable by a court or other body of competent jurisdiction, this License shall be construed as if such invalid, prohibited or unenforceable provision has been more narrowly drawn so as not to be invalid, prohibited or unenforceable.
|
||||
|
||||
11. You may not assign any rights or obligations under this License without the advance written consent of Oculus, which may be withheld in its sole discretion. Oculus may assign its rights or obligations under this License in its sole discretion.
|
||||
|
||||
12. Failure of either party at any time to enforce any of the provisions of this License will not be construed as a waiver of such provisions or in any way affect the validity of this License or parts thereof.
|
||||
|
||||
13. Your remedies under this License shall be limited to the right to collect money damages, if any, and you hereby waive your right to injunctive or other equitable relief.
|
||||
|
||||
14. Your use of third-party materials included in the AUDIO SDK may be subject to other terms and conditions typically found in separate third-party license agreements or “READ ME” files included with such third-party materials. To the extent such other terms and conditions conflict with the terms and conditions of this License, the former will control with respect to the applicable third-party materials.
|
||||
|
||||
15. Oculus may include in the AUDIO SDK additional content (e.g., samples) for demonstration, references or other specific purposes. Such content will be clearly marked in the AUDIO SDK and is subject to any included terms and conditions.
|
||||
|
||||
16. This License shall be governed by the laws of the State of California, without giving effect to choice of law principles. Oculus reserves all rights not expressly granted in this License. All disputes relating to this License shall be resolved by binding non-appearance-based arbitration before a neutral arbitrator in San Mateo County, California. If your License has been terminated hereunder by Oculus, you may appeal your termination through this arbitration process on an expedited basis with an arbitration within thirty days of your giving Oculus notice of the appeal. The arbitration shall be conducted in accordance with the rules and procedures of JAMS then in effect, and the judgment of the arbitrator shall be final and capable of entry in any court of competent jurisdiction. You agree to submit to the personal jurisdiction of the courts located within San Mateo County, California in connection with any entrance of an arbitrator’s judgment or decision or any dispute with respect to the arbitration process or procedure or Oculus’s exercise of its equitable rights or remedies.
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9144e7615bfd5254e962fb05f2570bb0
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 888a622f2413c2d4abcc36028627cee1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@ -0,0 +1,27 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cab7645a5ae73dd4cbbe72983022cce7
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 1
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63d1839e71f01184eac940a6b93005a0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a3b976fcbb135046afbf6894a86382a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d8ee2f423f373f489148ca12b9a44ef
|
||||
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:
|
||||
@ -0,0 +1,17 @@
|
||||
namespace VRC.ExampleCentral.Types.Algolia
|
||||
{
|
||||
public class UnityPackage
|
||||
{
|
||||
public string AssetId { get; set; }
|
||||
public string AssetRevision { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string UnityPackageFile { get; set; }
|
||||
public string ThumbnailImage { get; set; }
|
||||
public string Author { get; set; }
|
||||
public string Description { get; set; }
|
||||
[Newtonsoft.Json.JsonProperty("_tags")]
|
||||
public string[] Tags { get; set; }
|
||||
public string DocsLink { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe2092d56e9eb434285274ef1583ecaa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73a1f0f944d9faf40905cd89382d8617
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,104 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
using System.IO;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace VRC.ExampleCentral.Window
|
||||
{
|
||||
public static class ExampleCentralSettings
|
||||
{
|
||||
public static readonly string customSettingsPath = "VRChat/Example Central";
|
||||
|
||||
[SettingsProvider]
|
||||
public static SettingsProvider CreateExampleCentralSettingsProvider()
|
||||
{
|
||||
var provider = new SettingsProvider(customSettingsPath, SettingsScope.Project)
|
||||
{
|
||||
label = "Example Central",
|
||||
|
||||
// This method will draw the UI for the settings
|
||||
activateHandler = (searchContext, rootElement) =>
|
||||
{
|
||||
var settings = Data.Instance;
|
||||
|
||||
var styleSheet = Resources.Load<StyleSheet>("ExampleCentralSettingsStyle");
|
||||
rootElement.styleSheets.Add(styleSheet);
|
||||
|
||||
var container = new VisualElement()
|
||||
{
|
||||
name = "container",
|
||||
};
|
||||
rootElement.Add(container);
|
||||
|
||||
var titleLabel = new Label("Example Central Settings")
|
||||
{
|
||||
name = "title-label"
|
||||
};
|
||||
|
||||
container.Add(titleLabel);
|
||||
|
||||
var showCEField = new Toggle("Show Creator Economy Examples")
|
||||
{
|
||||
value = settings.ShowEconomyPackages,
|
||||
name = "show-economy-packages-field"
|
||||
};
|
||||
showCEField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
settings.ShowEconomyPackages = evt.newValue;
|
||||
settings.Save();
|
||||
|
||||
var existingExampleCentralWindows = Resources.FindObjectsOfTypeAll<ExampleDownloaderPanel>();
|
||||
if (existingExampleCentralWindows.Length > 0)
|
||||
{
|
||||
var target = existingExampleCentralWindows[0];
|
||||
target.Refresh();
|
||||
}
|
||||
});
|
||||
container.Add(showCEField);
|
||||
},
|
||||
|
||||
// Populate the search keywords to enable smart search filtering and label highlighting
|
||||
keywords = new[] { "example", "central", "vrchat", "show creator economy examples" }
|
||||
};
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
public static void OpenSettings()
|
||||
{
|
||||
// Open the Project Settings window with these settings selected
|
||||
SettingsService.OpenProjectSettings(customSettingsPath);
|
||||
}
|
||||
|
||||
// Uses simple embedded Data class which saves and loads from EditorPrefs
|
||||
public class Data
|
||||
{
|
||||
public bool ShowEconomyPackages;
|
||||
|
||||
private static Data _data;
|
||||
|
||||
public static Data Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
// Create if needed
|
||||
if(_data == null)
|
||||
{
|
||||
_data = new Data();
|
||||
|
||||
// Set properties from EditorPrefs
|
||||
_data.ShowEconomyPackages = EditorPrefs.GetBool(nameof(ShowEconomyPackages));
|
||||
}
|
||||
return _data;
|
||||
}
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
EditorPrefs.SetBool(nameof(ShowEconomyPackages), ShowEconomyPackages);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76b1e1dae078236489b5d0c483ea0d69
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,370 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Algolia.Search.Clients;
|
||||
using Algolia.Search.Models.Search;
|
||||
using UnityEditor.UIElements;
|
||||
using VRC.Core;
|
||||
using AlgoliaPackage = VRC.ExampleCentral.Types.Algolia.UnityPackage;
|
||||
using Button = UnityEngine.UIElements.Button;
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
|
||||
namespace VRC.ExampleCentral.Window
|
||||
{
|
||||
|
||||
public class ExampleDownloaderPanel : EditorWindow
|
||||
{
|
||||
|
||||
[SerializeField] private VisualTreeAsset VisualTree;
|
||||
|
||||
// Visual Elements, cached after creation
|
||||
private VisualElement goToLoginView;
|
||||
private VisualElement mainView;
|
||||
private VisualElement previewThumbnail;
|
||||
private Label previewTitle;
|
||||
private Label previewTags;
|
||||
private Label previewVersion;
|
||||
private Label previewDescription;
|
||||
private Button previewDownloadButton;
|
||||
private Button previewDocsButtons;
|
||||
private ToolbarSearchField searchField;
|
||||
private VisualElement examplesScrollviewContainer;
|
||||
private Button settingsButton;
|
||||
|
||||
// Searching
|
||||
private CancellationTokenSource typingCancellation;
|
||||
private int searchDelayMs = 500;
|
||||
|
||||
private AlgoliaPackage selectedPackage;
|
||||
private PackageButton selectedButton;
|
||||
|
||||
// Algolia Info
|
||||
public const string AlgoliaSearchKey = "60b185254097bf630e913ceaf103822a";
|
||||
public const string AlgoliaAppKey = "P787M8AJR8";
|
||||
public const string AlgoliaIndexName = "unity-packages";
|
||||
|
||||
// Analytics rate-limiting
|
||||
private const int EVENT_LIMIT_EXAMPLE_PREVIEWED = 10;
|
||||
private const int TIME_LIMIT_EXAMPLE_PREVIEWED = 60;
|
||||
private int eventCounterExamplePreviewed;
|
||||
private DateTime lastResetTimeExamplePreviewed = DateTime.Now;
|
||||
|
||||
#region Setup and Basics
|
||||
|
||||
|
||||
[MenuItem("VRChat SDK/🏠 Example Central", false, 980)]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
ExampleDownloaderPanel window = GetWindow<ExampleDownloaderPanel>();
|
||||
window.titleContent = new GUIContent("VRChat Example Central");
|
||||
window.Show();
|
||||
|
||||
AnalyticsSDK.ExampleCentralOpened();
|
||||
}
|
||||
|
||||
private void CreateGUI()
|
||||
{
|
||||
// Set up base layout
|
||||
VisualTree.CloneTree(rootVisualElement);
|
||||
|
||||
// Get top-level UI containers
|
||||
goToLoginView = rootVisualElement.Query<VisualElement>("go-to-login");
|
||||
mainView = rootVisualElement.Query<VisualElement>("split-main");
|
||||
|
||||
// Get Auth View elements
|
||||
Button goToLoginButton = goToLoginView.Query<Button>("go-to-login-btn");
|
||||
|
||||
// If the user is already logged in, enable main view
|
||||
if (APIUser.IsLoggedIn)
|
||||
OnUserLoggedIn(null, null);
|
||||
|
||||
// Get Listing elements
|
||||
searchField = rootVisualElement.Query<ToolbarSearchField>("examples-search-field");
|
||||
searchField.RegisterValueChangedCallback(CheckSearch);
|
||||
|
||||
// Get Example elements
|
||||
examplesScrollviewContainer = rootVisualElement.Query<VisualElement>("examples-scrollview-container");
|
||||
examplesScrollviewContainer.Clear();
|
||||
|
||||
// Get Preview elements
|
||||
previewThumbnail = rootVisualElement.Query<VisualElement>("preview-thumbnail");
|
||||
previewTitle = rootVisualElement.Query<Label>("preview-title");
|
||||
previewTags = rootVisualElement.Query<Label>("preview-tags");
|
||||
previewVersion = rootVisualElement.Query<Label>("preview-version");
|
||||
previewDescription = rootVisualElement.Query<Label>("preview-description");
|
||||
previewDownloadButton = rootVisualElement.Query<Button>("preview-download");
|
||||
previewDocsButtons = rootVisualElement.Query<Button>("preview-documentation");
|
||||
|
||||
previewDownloadButton.clicked += DownloadSelectedPackage;
|
||||
previewDocsButtons.clicked += OpenSelectedPackageDocs;
|
||||
goToLoginButton.clicked += OpenControlPanel;
|
||||
|
||||
VRCSdkControlPanel.OnPanelLoggedIn += OnUserLoggedIn;
|
||||
VRCSdkControlPanel.OnPanelLoggedOut += OnUserLoggedOut;
|
||||
|
||||
settingsButton = rootVisualElement.Query<Button>("settings-button");
|
||||
var icon = Resources.Load<Texture2D>("gear");
|
||||
settingsButton.style.backgroundImage = new StyleBackground(icon);
|
||||
settingsButton.clicked += ExampleCentralSettings.OpenSettings;
|
||||
|
||||
// Set the default preview.
|
||||
DemoPreview();
|
||||
|
||||
// Fetch and display UnityPackages
|
||||
UpdatePackagesAsync();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
previewDownloadButton.clicked -= DownloadSelectedPackage;
|
||||
previewDocsButtons.clicked -= OpenSelectedPackageDocs;
|
||||
|
||||
VRCSdkControlPanel.OnPanelLoggedIn -= OnUserLoggedIn;
|
||||
VRCSdkControlPanel.OnPanelLoggedOut -= OnUserLoggedOut;
|
||||
}
|
||||
|
||||
private static void OpenControlPanel() => VRCSdkControlPanel.ShowControlPanel();
|
||||
private void OnUserLoggedIn(object _, APIUser __) => ToggleView(true);
|
||||
private void OnUserLoggedOut(object _, EventArgs __) => ToggleView(false);
|
||||
private void ToggleView(bool isUserLoggedIn)
|
||||
{
|
||||
goToLoginView.style.display = isUserLoggedIn ? DisplayStyle.None : DisplayStyle.Flex;
|
||||
mainView.style.display = isUserLoggedIn ? DisplayStyle.Flex : DisplayStyle.None;
|
||||
}
|
||||
|
||||
private void OpenSelectedPackageDocs()
|
||||
{
|
||||
if (selectedPackage == null) return;
|
||||
Application.OpenURL($"{selectedPackage.DocsLink}");
|
||||
}
|
||||
|
||||
private void DemoPreview()
|
||||
{
|
||||
previewTitle.text = "Select a package on the left to view and import.";
|
||||
previewVersion.text = "";
|
||||
previewTags.text = "";
|
||||
previewDescription.text = "";
|
||||
previewThumbnail.style.backgroundImage = new StyleBackground();
|
||||
}
|
||||
|
||||
private void AddPackageToList(AlgoliaPackage unityPackage)
|
||||
{
|
||||
PackageButton packageButton = new PackageButton();
|
||||
packageButton.name = unityPackage.Title;
|
||||
packageButton.PackageLabel.text = unityPackage.Title;
|
||||
packageButton.clicked += () =>
|
||||
{
|
||||
if (selectedButton != null) selectedButton.Select(false);
|
||||
selectedButton = packageButton;
|
||||
selectedButton.Select(true);
|
||||
|
||||
SelectExample(unityPackage);
|
||||
};
|
||||
|
||||
examplesScrollviewContainer.Add(packageButton);
|
||||
}
|
||||
|
||||
private void SelectExample(AlgoliaPackage unityPackage)
|
||||
{
|
||||
if (selectedPackage == unityPackage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
selectedPackage = unityPackage;
|
||||
|
||||
previewTitle.text = unityPackage.Title;
|
||||
previewVersion.text = $"Version: {unityPackage.Version}";
|
||||
previewTags.text = $"Tags: {string.Join(',', unityPackage.Tags)}";
|
||||
previewDescription.text = unityPackage.Description;
|
||||
|
||||
string thumbnailPath = DownloadThumbnail(unityPackage.ThumbnailImage);
|
||||
previewThumbnail.style.backgroundImage = new StyleBackground(LoadTextureFromDisk(thumbnailPath));
|
||||
|
||||
// rate-limit event tracking for previewing examples to at most 10 events per minute
|
||||
DateTime currentTime = DateTime.Now;
|
||||
TimeSpan elapsedTime = currentTime - lastResetTimeExamplePreviewed;
|
||||
if (elapsedTime.TotalSeconds > TIME_LIMIT_EXAMPLE_PREVIEWED)
|
||||
{
|
||||
eventCounterExamplePreviewed = 0;
|
||||
lastResetTimeExamplePreviewed = currentTime;
|
||||
}
|
||||
|
||||
if (eventCounterExamplePreviewed < EVENT_LIMIT_EXAMPLE_PREVIEWED)
|
||||
{
|
||||
eventCounterExamplePreviewed++;
|
||||
AnalyticsSDK.ExamplePreviewed(selectedPackage.Title, selectedPackage.Version);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Search the Index for Packages
|
||||
|
||||
private void UpdatePackagesAsync(string query = "")
|
||||
{
|
||||
ShowPackagesForQuery(query);
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
ShowPackagesForQuery(searchField.value);
|
||||
}
|
||||
|
||||
private void ToggleSearchedButtons(string searchKey)
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchKey) || string.IsNullOrWhiteSpace(searchKey))
|
||||
{
|
||||
foreach (VisualElement child in examplesScrollviewContainer.Children())
|
||||
{
|
||||
child.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (VisualElement child in examplesScrollviewContainer.Children())
|
||||
{
|
||||
bool shown = child.name.Contains(searchKey, StringComparison.InvariantCultureIgnoreCase);
|
||||
child.style.display = shown ? DisplayStyle.Flex : DisplayStyle.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckSearch(ChangeEvent<string> evt)
|
||||
{
|
||||
ToggleSearchedButtons(evt.newValue);
|
||||
|
||||
if (typingCancellation != null)
|
||||
{
|
||||
typingCancellation.Cancel();
|
||||
typingCancellation.Dispose();
|
||||
}
|
||||
|
||||
typingCancellation = new CancellationTokenSource();
|
||||
DebounceSearch(typingCancellation.Token, evt.newValue);
|
||||
}
|
||||
|
||||
private async Task DebounceSearch(CancellationToken token, string finalText)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Delay(searchDelayMs, cancellationToken: token);
|
||||
if (!token.IsCancellationRequested)
|
||||
{
|
||||
// User has finished typing
|
||||
UpdatePackagesAsync(finalText);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// This block is executed if the delay is cancelled
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<List<AlgoliaPackage>> FetchPackagesAlgolia(string query = "")
|
||||
{
|
||||
SearchClient algolia = new SearchClient(AlgoliaAppKey, AlgoliaSearchKey);
|
||||
SearchIndex index = algolia.InitIndex(AlgoliaIndexName);
|
||||
|
||||
// Construct the embedded list format needed for tag filters
|
||||
var tagFilters = new List<List<string>>();
|
||||
|
||||
if (!ExampleCentralSettings.Data.Instance.ShowEconomyPackages)
|
||||
{
|
||||
tagFilters.Add(new List<string>(){"-ce"});
|
||||
}
|
||||
|
||||
// Conduct the search, including tag filters from settings
|
||||
List<AlgoliaPackage> hits = (await index.SearchAsync<ExampleCentral.Types.Algolia.UnityPackage>(
|
||||
new Query(query)
|
||||
{
|
||||
TagFilters = tagFilters
|
||||
}
|
||||
)).Hits;
|
||||
|
||||
return hits;
|
||||
}
|
||||
|
||||
private async Task ShowPackagesForQuery(string query = "")
|
||||
{
|
||||
List<AlgoliaPackage> packages = await FetchPackagesAlgolia(query);
|
||||
// Clear the existing list
|
||||
examplesScrollviewContainer.Clear();
|
||||
|
||||
foreach (AlgoliaPackage unityPackage in packages)
|
||||
{
|
||||
// Add each package to the list
|
||||
AddPackageToList(unityPackage);
|
||||
}
|
||||
|
||||
ToggleSearchedButtons(query);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Downloads
|
||||
|
||||
private void DownloadSelectedPackage()
|
||||
{
|
||||
if (selectedPackage == null) return;
|
||||
AnalyticsSDK.ExampleDownloaded(selectedPackage.Title, selectedPackage.Version);
|
||||
DownloadUnityPackage(selectedPackage);
|
||||
}
|
||||
|
||||
private string DownloadThumbnail(string url)
|
||||
{
|
||||
// get or create path to store thumbnails, use Local App Data
|
||||
string thumbnailDir =
|
||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "VRChat",
|
||||
"Example Central", "Thumbnails");
|
||||
Directory.CreateDirectory(thumbnailDir);
|
||||
string thumbnailPath = Path.Combine(thumbnailDir, Path.GetFileName(url));
|
||||
// download thumbnail if it doesn't exist
|
||||
if (!File.Exists(thumbnailPath))
|
||||
{
|
||||
WebClient client = new System.Net.WebClient();
|
||||
client.DownloadFile(url, thumbnailPath);
|
||||
return thumbnailPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
return thumbnailPath;
|
||||
}
|
||||
}
|
||||
|
||||
private void DownloadUnityPackage(AlgoliaPackage unityPackage)
|
||||
{
|
||||
string packageDownloadDir =
|
||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "VRChat",
|
||||
"Example Central", "Packages");
|
||||
Directory.CreateDirectory(packageDownloadDir);
|
||||
string packageDownloadPath = Path.Combine(packageDownloadDir,
|
||||
$"{unityPackage.Title}-{unityPackage.Version}.unitypackage");
|
||||
// download file if it doesn't exist
|
||||
if (!File.Exists(packageDownloadPath))
|
||||
{
|
||||
WebClient client = new System.Net.WebClient();
|
||||
client.DownloadFile(unityPackage.UnityPackageFile, packageDownloadPath);
|
||||
}
|
||||
|
||||
// import the package
|
||||
AssetDatabase.ImportPackage(packageDownloadPath, true);
|
||||
}
|
||||
|
||||
private Texture2D LoadTextureFromDisk(string path)
|
||||
{
|
||||
Texture2D texture = new Texture2D(2, 2);
|
||||
byte[] fileData = File.ReadAllBytes(path);
|
||||
texture.LoadImage(fileData);
|
||||
return texture;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2dd19633aa70e484a94e884e201460a2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_ViewDataDictionary: {instanceID: 0}
|
||||
- VisualTree: {fileID: 9197481963319205126, guid: 850bbb1837d721e48a16d8567e3ecf7b,
|
||||
type: 3}
|
||||
- PackageTabButton: {fileID: 9197481963319205126, guid: f4f9892bd4d997b42923c93f4fb8519c,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b148a8f35d62fa647b4ba3e93b5a241c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,14 @@
|
||||
#container {
|
||||
margin: 2px 10px;
|
||||
}
|
||||
|
||||
#title-label {
|
||||
-unity-font-style: bold;
|
||||
font-size: 18px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#settings-button {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4433d9fd51eebc348aafa2130d7d546b
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
|
||||
disableValidation: 0
|
||||
@ -0,0 +1,40 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="True">
|
||||
<Style src="project://database/Packages/com.vrchat.base/Integrations/VRChat%20Example%20Central/Editor/Example%20Downloader%20Panel/Resources/ExampleDownloaderPanelStyle.uss?fileID=7433441132597879392&guid=2bbc5f61b79c52c4ebcb9fcf6a8a4487&type=3#ExampleDownloaderPanelStyle" />
|
||||
<ui:VisualElement name="container">
|
||||
<ui:VisualElement name="go-to-login">
|
||||
<ui:Button text="Log in to use Example Central" parse-escape-sequences="true" display-tooltip-when-elided="true" name="go-to-login-btn" tooltip="Opens the VRC Control Panel in order to log in and enable Example Central." />
|
||||
</ui:VisualElement>
|
||||
<VRC.ExampleCentral.Window.SplitView name="split-main" fixed-pane-index="1" fixed-pane-initial-dimension="500" view-data-key="ExamplePanel-MainView">
|
||||
<ui:VisualElement name="examples-container">
|
||||
<ui:VisualElement name="header-examples">
|
||||
<ui:Label tabindex="-1" text="Search" parse-escape-sequences="true" display-tooltip-when-elided="true" name="examples-label" />
|
||||
<uie:ToolbarSearchField focusable="true" name="examples-search-field" />
|
||||
<ui:Button parse-escape-sequences="true" display-tooltip-when-elided="true" name="settings-button" />
|
||||
</ui:VisualElement>
|
||||
<ui:ScrollView name="examples-scrollview" horizontal-scroller-visibility="Hidden" vertical-scroller-visibility="Auto">
|
||||
<ui:VisualElement name="examples-scrollview-container">
|
||||
<VRC.ExampleCentral.Window.PackageButton style="color: rgb(255, 255, 255);" />
|
||||
<VRC.ExampleCentral.Window.PackageButton style="color: rgb(255, 255, 255);" />
|
||||
<VRC.ExampleCentral.Window.PackageButton style="color: rgb(255, 255, 255);" />
|
||||
<VRC.ExampleCentral.Window.PackageButton style="color: rgb(255, 255, 255);" />
|
||||
</ui:VisualElement>
|
||||
</ui:ScrollView>
|
||||
</ui:VisualElement>
|
||||
<VRC.ExampleCentral.Window.SplitView name="split-details" orientation="Vertical" fixed-pane-index="0" view-data-key="ExamplePanel-DetailsView" fixed-pane-initial-dimension="200">
|
||||
<ui:VisualElement name="preview-thumbnail" />
|
||||
<ui:VisualElement name="preview-settings">
|
||||
<ui:Label tabindex="-1" text="Examples Thing" parse-escape-sequences="true" display-tooltip-when-elided="true" name="preview-title" />
|
||||
<ui:ScrollView name="preview-settings-scrollview" horizontal-scroller-visibility="Hidden">
|
||||
<ui:Label tabindex="-1" text="Version: " parse-escape-sequences="true" display-tooltip-when-elided="true" name="preview-version" />
|
||||
<ui:Label tabindex="-1" text="Tags: Used, Unused" parse-escape-sequences="true" display-tooltip-when-elided="true" name="preview-tags" />
|
||||
<ui:Label tabindex="-1" text="Description" parse-escape-sequences="true" display-tooltip-when-elided="true" name="preview-description" style="-unity-font-style: normal; margin-left: 0; margin-right: 0; margin-top: 4px; margin-bottom: 4px; overflow: visible; flex-wrap: nowrap; white-space: normal; text-overflow: ellipsis; color: rgb(255, 255, 255);" />
|
||||
</ui:ScrollView>
|
||||
<ui:VisualElement name="preview-options">
|
||||
<ui:Button text="Import" parse-escape-sequences="true" display-tooltip-when-elided="true" name="preview-download" />
|
||||
<ui:Button text="Docs" parse-escape-sequences="true" display-tooltip-when-elided="true" name="preview-documentation" />
|
||||
</ui:VisualElement>
|
||||
</ui:VisualElement>
|
||||
</VRC.ExampleCentral.Window.SplitView>
|
||||
</VRC.ExampleCentral.Window.SplitView>
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 850bbb1837d721e48a16d8567e3ecf7b
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
@ -0,0 +1,212 @@
|
||||
#container {
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
background-color: rgb(31, 31, 31);
|
||||
}
|
||||
|
||||
#go-to-login {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#split-main {
|
||||
display: none;
|
||||
margin-left: 16px;
|
||||
margin-right: 16px;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
#split-details {
|
||||
background-color: rgb(20, 20, 20);
|
||||
border-top-left-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
border-bottom-right-radius: 8px;
|
||||
margin-left: 16px;
|
||||
min-width: 155px;
|
||||
}
|
||||
|
||||
#examples-container {
|
||||
flex-grow: 0;
|
||||
min-width: 126px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
#header-examples {
|
||||
flex-direction: row;
|
||||
margin-bottom: 8px;
|
||||
height: 24px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
#examples-label {
|
||||
-unity-font-style: bold;
|
||||
font-size: 20px;
|
||||
margin-right: 16px;
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
#examples-search-field {
|
||||
flex-grow: 1;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
border-top-left-radius: 6px;
|
||||
border-bottom-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
width: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#packages-header {
|
||||
background-color: rgb(41, 41, 41);
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
height: 24px;
|
||||
flex-shrink: 0;
|
||||
border-left-color: rgb(82, 82, 82);
|
||||
border-right-color: rgb(82, 82, 82);
|
||||
border-top-color: rgb(82, 82, 82);
|
||||
border-bottom-color: rgb(82, 82, 82);
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
#packages-label {
|
||||
-unity-font-style: bold;
|
||||
padding-left: 16px;
|
||||
padding-right: 4px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
flex-grow: 1;
|
||||
-unity-text-align: middle-left;
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
#examples-scrollview {
|
||||
background-color: rgb(41, 41, 41);
|
||||
}
|
||||
|
||||
#examples-scrollview-container {
|
||||
background-color: rgb(82, 82, 82);
|
||||
}
|
||||
|
||||
#preview-thumbnail {
|
||||
height: 144px;
|
||||
background-color: rgba(89, 89, 89, 0);
|
||||
flex-shrink: 0;
|
||||
background-image: none;
|
||||
-unity-background-scale-mode: scale-to-fit;
|
||||
min-height: 64px;
|
||||
}
|
||||
|
||||
#preview-settings {
|
||||
flex-grow: 1;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
min-height: 164px;
|
||||
}
|
||||
|
||||
#preview-title {
|
||||
-unity-font-style: bold;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 2px;
|
||||
font-size: 20px;
|
||||
white-space: normal;
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
#preview-settings-scrollview {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#preview-version {
|
||||
-unity-font-style: normal;
|
||||
flex-grow: 0;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 4px;
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 10px;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
#preview-tags {
|
||||
-unity-font-style: normal;
|
||||
flex-grow: 0;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 4px;
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 10px;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
#preview-options {
|
||||
flex-direction: row;
|
||||
height: 32px;
|
||||
flex-shrink: 0;
|
||||
min-height: 32px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
#preview-download {
|
||||
flex-grow: 1;
|
||||
border-top-left-radius: 6px;
|
||||
border-bottom-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
width: auto;
|
||||
background-color: rgb(15, 145, 169);
|
||||
-unity-font-style: bold;
|
||||
font-size: 14px;
|
||||
border-left-color: rgb(48, 48, 48);
|
||||
border-right-color: rgb(48, 48, 48);
|
||||
border-top-color: rgb(48, 48, 48);
|
||||
border-bottom-color: rgb(36, 36, 36);
|
||||
color: rgb(238, 238, 238);
|
||||
}
|
||||
|
||||
#preview-documentation {
|
||||
border-top-left-radius: 6px;
|
||||
border-bottom-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
margin-left: 6px;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
flex-grow: 0;
|
||||
background-color: rgb(20, 20, 20);
|
||||
-unity-font-style: bold;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
font-size: 14px;
|
||||
color: rgb(255, 255, 255);
|
||||
border-left-color: rgb(48, 48, 48);
|
||||
border-right-color: rgb(48, 48, 48);
|
||||
border-top-color: rgb(48, 48, 48);
|
||||
border-bottom-color: rgb(36, 36, 36);
|
||||
}
|
||||
|
||||
#settings-button {
|
||||
background-image: none;
|
||||
flex-basis: 24px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
-unity-background-scale-mode: scale-to-fit;
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2bbc5f61b79c52c4ebcb9fcf6a8a4487
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
|
||||
disableValidation: 0
|
||||
@ -0,0 +1,7 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="True">
|
||||
<Style src="project://database/Packages/com.vrchat.base/Integrations/VRChat%20Sample%20Central/Editor/Sample%20Downloader%20Panel/Resources/PackageTabButtonStyle.uss?fileID=7433441132597879392&guid=7d25b279c57e51341bb553313ea74fc0&type=3#PackageTabButtonStyle" />
|
||||
<ui:VisualElement name="container">
|
||||
<ui:VisualElement name="selection-element" />
|
||||
<ui:Label tabindex="-1" text="Label" parse-escape-sequences="true" display-tooltip-when-elided="true" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4f9892bd4d997b42923c93f4fb8519c
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
@ -0,0 +1,28 @@
|
||||
|
||||
#container {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
height: 40px;
|
||||
background-color: rgb(41, 41, 41);
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
#selection-element {
|
||||
flex-grow: 1;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgb(56, 56, 56);
|
||||
display: none;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#container Label {
|
||||
flex-grow: 1;
|
||||
-unity-text-align: middle-left;
|
||||
margin-left: 16px;
|
||||
font-size: 14px;
|
||||
-unity-font-style: bold;
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d25b279c57e51341bb553313ea74fc0
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
|
||||
disableValidation: 0
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 387 B |
@ -0,0 +1,140 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d947179418dad34d9759416f16501d0
|
||||
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: 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: 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: iPhone
|
||||
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: Android
|
||||
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:
|
||||
@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace VRC.ExampleCentral.Window
|
||||
{
|
||||
|
||||
public class SplitView : TwoPaneSplitView
|
||||
{
|
||||
public new class UxmlFactory : UxmlFactory<SplitView, UxmlTraits> { }
|
||||
}
|
||||
|
||||
public class PackageButton : VisualElement
|
||||
{
|
||||
|
||||
public new class UxmlFactory : UxmlFactory<PackageButton, UxmlTraits> { }
|
||||
public Label PackageLabel;
|
||||
|
||||
private VisualElement selectionElement;
|
||||
private Clickable clickable;
|
||||
|
||||
/// <summary>
|
||||
/// Called when Package Button is clicked.
|
||||
/// </summary>
|
||||
public event Action clicked
|
||||
{
|
||||
add { if (clickable != null) clickable.clicked += value; }
|
||||
remove { if (clickable != null) clickable.clicked -= value; }
|
||||
}
|
||||
|
||||
public PackageButton()
|
||||
{
|
||||
VisualTreeAsset uxml = Resources.Load<VisualTreeAsset>("PackageTabButton");
|
||||
uxml.CloneTree(this);
|
||||
|
||||
PackageLabel = this.Query<Label>();
|
||||
selectionElement = this.Query<VisualElement>("selection-element");
|
||||
|
||||
clickable = new Clickable(OnClicked);
|
||||
this.AddManipulator(clickable);
|
||||
}
|
||||
|
||||
private void OnClicked(EventBase obj)
|
||||
{
|
||||
Select(true);
|
||||
}
|
||||
|
||||
public void Select(bool value)
|
||||
{
|
||||
selectionElement.style.display = value ? DisplayStyle.Flex : DisplayStyle.None;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67c2bdfc395e77b4abdc8b6e5c51653d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a183835343d1e7448143d7227e65054
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRC.ExampleCentral.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores the GUID and Hash for each Asset in an Example
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class AssetInfo
|
||||
{
|
||||
public string GUID { get; private set; }
|
||||
public string Hash { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AssetInfo"/> class with the specified GUID and hash.
|
||||
/// Used for deserialization, after the hash is computed.
|
||||
/// </summary>
|
||||
/// <param name="guid">The GUID of the asset.</param>
|
||||
/// <param name="hash">The hash of the asset.</param>
|
||||
public AssetInfo(string guid, string hash)
|
||||
{
|
||||
GUID = guid;
|
||||
Hash = hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AssetInfo"/> class with the specified GUID.
|
||||
/// The hash is computed based on the asset's content.
|
||||
/// </summary>
|
||||
/// <param name="guid">The GUID of the asset.</param>
|
||||
public AssetInfo(string guid)
|
||||
{
|
||||
GUID = guid;
|
||||
Hash = ComputeAssetHash(guid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the hash of the asset based on its content.
|
||||
/// </summary>
|
||||
/// <param name="guid">The GUID of the asset.</param>
|
||||
/// <returns>The computed hash of the asset.</returns>
|
||||
private string ComputeAssetHash(string guid)
|
||||
{
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
string fullPath = Path.Combine(Application.dataPath, assetPath.Substring("Assets/".Length));
|
||||
if (!File.Exists(fullPath))
|
||||
return "File Not Found";
|
||||
|
||||
try
|
||||
{
|
||||
using FileStream stream = File.OpenRead(fullPath);
|
||||
using SHA256 sha = SHA256.Create();
|
||||
byte[] hashBytes = sha.ComputeHash(stream);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (byte b in hashBytes)
|
||||
sb.Append(b.ToString("X2"));
|
||||
return sb.ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"Error computing hash for {assetPath}: {ex.Message}");
|
||||
return "Error";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the asset to a string, using a pipe character as a separator.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of the asset's guid and hash.</returns>
|
||||
public string Serialize()
|
||||
{
|
||||
return $"{GUID}|{Hash}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the asset information from a string.
|
||||
/// </summary>
|
||||
/// <param name="serializedData">The serialized data string.</param>
|
||||
/// <returns>An instance of <see cref="AssetInfo"/>.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown when the serialized data format is invalid.</exception>
|
||||
public static AssetInfo Deserialize(string serializedData)
|
||||
{
|
||||
var parts = serializedData.Split('|');
|
||||
if (parts.Length != 2)
|
||||
throw new ArgumentException("Invalid serialized data format");
|
||||
|
||||
return new AssetInfo(parts[0], parts[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d95aa121fc5f5848b1a4a6b1eae7299
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace VRC.ExampleCentral.Editor
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Stores a description of changes made to an Example
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class Changes
|
||||
{
|
||||
/// <summary>
|
||||
/// SemVer-compatible version number (SemVer not currently enforced anywhere)
|
||||
/// </summary>
|
||||
public string Version;
|
||||
/// <summary>
|
||||
/// Plain text description of changes
|
||||
/// </summary>
|
||||
public string Value;
|
||||
|
||||
public Changes(string version, string value)
|
||||
{
|
||||
Version = version;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 305cd65774c510c409011962a5752a51
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRC.ExampleCentral.Editor
|
||||
{
|
||||
public enum ExampleStatus
|
||||
{
|
||||
Local,
|
||||
Draft,
|
||||
Published
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ExampleData : ScriptableObject, ISerializationCallbackReceiver
|
||||
{
|
||||
[SerializeField]
|
||||
public string author;
|
||||
|
||||
[SerializeField]
|
||||
public string title;
|
||||
|
||||
[SerializeField]
|
||||
public Texture2D thumbnail;
|
||||
|
||||
[SerializeField]
|
||||
public string description;
|
||||
|
||||
[SerializeField]
|
||||
public string version;
|
||||
|
||||
[SerializeField]
|
||||
public string documentationLink;
|
||||
|
||||
[SerializeField]
|
||||
public string vrcWorldId;
|
||||
|
||||
[SerializeField]
|
||||
public List<string> tags = new();
|
||||
|
||||
[SerializeField]
|
||||
public SceneAsset exampleScene;
|
||||
|
||||
[SerializeField]
|
||||
private List<string> serializedAssets;
|
||||
public List<AssetInfo> assets = new();
|
||||
|
||||
[SerializeField]
|
||||
public string sanityId = $"drafts.{Guid.NewGuid().ToString()}";
|
||||
|
||||
[SerializeField]
|
||||
public ExampleStatus ExampleStatus = ExampleStatus.Local;
|
||||
|
||||
[SerializeField]
|
||||
public List<Changes> changes = new();
|
||||
|
||||
// Serialize the AssetInfo list to a list of strings
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
serializedAssets = assets.ConvertAll(asset => asset.Serialize());
|
||||
}
|
||||
|
||||
// Deserialize the List<string> back to the AssetInfo list
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
assets = serializedAssets.ConvertAll(AssetInfo.Deserialize);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02be9066d74f7884ab56988f40f56297
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "VRC.ExampleCentral.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"UniTask",
|
||||
"VRC.SDKBase.Editor"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0ff9a3db60cc184381fafd0c1e6b375
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user