restructure
This commit is contained in:
8
Unity/Assets/Ready Player Me/Avatars.meta
Normal file
8
Unity/Assets/Ready Player Me/Avatars.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 064f70a113e90b44d8d5726ef40dd72d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7acb87d51e82ae844a0144670bcacc19
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1 @@
|
||||
{"BodyType":"fullbodyxr","OutfitGender":2,"UpdatedAt":"2025-08-23T14:18:40.097Z","SkinTone":"#af5a35"}
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61a04ea0b8e39ca4085bfce76981f379
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5d14b36119dbbb4ab61704ce8109fc3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Unity/Assets/Ready Player Me/Avatars/68a9cd8660abed90567d4292/beabaa82737bd6837a3fe529c75ac82c/68a9cd8660abed90567d4292.glb
(Stored with Git LFS)
Normal file
BIN
Unity/Assets/Ready Player Me/Avatars/68a9cd8660abed90567d4292/beabaa82737bd6837a3fe529c75ac82c/68a9cd8660abed90567d4292.glb
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -0,0 +1,36 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c6841c0ea07df945bb638ec7442e32a
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 11500000, guid: 715df9372183c47e389bb6e19fbc3b52, type: 3}
|
||||
editorImportSettings:
|
||||
generateSecondaryUVSet: 0
|
||||
importSettings:
|
||||
nodeNameMethod: 1
|
||||
animationMethod: 2
|
||||
generateMipMaps: 1
|
||||
texturesReadable: 0
|
||||
defaultMinFilterMode: 9729
|
||||
defaultMagFilterMode: 9729
|
||||
anisotropicFilterLevel: 1
|
||||
instantiationSettings:
|
||||
mask: -1
|
||||
layer: 0
|
||||
skinUpdateWhenOffscreen: 1
|
||||
lightIntensityFactor: 1
|
||||
sceneObjectCreation: 2
|
||||
assetDependencies: []
|
||||
reportItems:
|
||||
- type: 2
|
||||
code: 20
|
||||
messages:
|
||||
- KHR_materials_ior
|
||||
- type: 2
|
||||
code: 20
|
||||
messages:
|
||||
- KHR_materials_specular
|
||||
BIN
Unity/Assets/Ready Player Me/Avatars/68a9cd8660abed90567d4292/beabaa82737bd6837a3fe529c75ac82c/68a9cd8660abed90567d4292.prefab
(Stored with Git LFS)
Normal file
BIN
Unity/Assets/Ready Player Me/Avatars/68a9cd8660abed90567d4292/beabaa82737bd6837a3fe529c75ac82c/68a9cd8660abed90567d4292.prefab
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4a09101afb8696a44a73b69130070969
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Unity/Assets/Ready Player Me/Core.meta
Normal file
8
Unity/Assets/Ready Player Me/Core.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: accc2378d3ac4f0448f2233c05d3e15a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
472
Unity/Assets/Ready Player Me/Core/CHANGELOG.md
Normal file
472
Unity/Assets/Ready Player Me/Core/CHANGELOG.md
Normal file
@ -0,0 +1,472 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [7.3.1] - 2024.10.30
|
||||
|
||||
## Updated
|
||||
- Re-exporting package for asset store with updated dependencies
|
||||
|
||||
## [7.3.0] - 2024.10.22
|
||||
|
||||
## Updated
|
||||
- auth-related requests now use auth-service endpoints [#317](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/317)
|
||||
- updated shader variants to fix issues various material issues
|
||||
|
||||
## Fixed
|
||||
- Fixed an issue causing Out of Bounds exception in WebGL voice handler [#322](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/322)
|
||||
|
||||
## Added
|
||||
- DestroyMesh class can be used to destroy manually destroy mesh, materials and textures to prevent memory leaks
|
||||
|
||||
## [7.2.0] - 2024.09.06
|
||||
|
||||
## Updated
|
||||
- Updated handling of response data to reduce garbage allocation [#314](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/314)
|
||||
## Fixed
|
||||
- Preserve AssetId property in IAssetData [#313](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/313)
|
||||
|
||||
## [7.1.1] - 2024.07.25
|
||||
|
||||
## Fixed
|
||||
- Fixed an issue causing json parsing to fail on iFrame events [#311](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/311/)
|
||||
|
||||
## [7.1.0] - 2024.07.16
|
||||
|
||||
## Updated
|
||||
- Reworked shader overrides to support mapping of other property types [#306](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/306)
|
||||
|
||||
## Fixed
|
||||
- Fixed an issue caused by missing bones on avatar template prefabs [#310](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/310/)
|
||||
|
||||
## [7.0.0] - 2024.07.01
|
||||
|
||||
## Updated
|
||||
|
||||
- Loading circle animation now using MMecanim animation [#302](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/302)
|
||||
- Removed unnecessary assets from Resources folder [#303](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/303)
|
||||
- Updated Template avatar assets [#300](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/300)
|
||||
- Avatar Body type now moved to CoreSettings [#290](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/290)
|
||||
|
||||
### Added
|
||||
|
||||
- Added support for hero customization assets (costumes) [#301](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/301)
|
||||
- Templates can now be filtered by Bodytype [#296](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/296)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed an issue causing invalid load settings in Avatar Loader window [#298](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/298)
|
||||
|
||||
## [6.3.1] - 2024.06.18
|
||||
|
||||
### Fixed
|
||||
|
||||
- Allow cache to be loaded from previous versions, where bodyType was stored as an integer [#293](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/293)
|
||||
|
||||
## [6.3.0] - 2024.06.11
|
||||
|
||||
### Updated
|
||||
|
||||
- XR animation avatars now have DOF enabled by default [#288](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/288)
|
||||
- Updated InCreatorAvatarLoader to use avatar config [#286](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/286)
|
||||
- Avatar Creator Icon categories updated [#272](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/272)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed an issue preventing LOD's from updating [#277](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/277)
|
||||
- An issue causing multiple signup requests [#275](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/275)
|
||||
|
||||
### Added
|
||||
- Avatar template type filter [#270](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/270)
|
||||
- Handle failed body shape requests [#281](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/281)
|
||||
- Option to filter Templates by gender [#273](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/273)
|
||||
|
||||
## [6.2.4] - 2024.05.03
|
||||
|
||||
### Fixed
|
||||
|
||||
- Updated XR template prefab meshes to prevent missing bone references to fix mesh transfer [#266](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/266)
|
||||
|
||||
## [6.2.3] - 2024.04.29
|
||||
|
||||
### Fixed
|
||||
|
||||
- Reverted update to GetMeshRenderer method [#264](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/264)
|
||||
|
||||
## [6.2.2] - 2024.04.29
|
||||
|
||||
### Updated
|
||||
|
||||
- Updated XR template avatar to have separated head mesh [#261](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/261)
|
||||
- Improved GetMeshRenderer() method to exclude invalid mesh renderers [#261](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/261)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed issue with XR animation avatars
|
||||
|
||||
## [6.2.1] - 2024.04.23
|
||||
|
||||
### Fixed
|
||||
|
||||
- An issue with gender and avatarID not to be set in AvatarManager [#260](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/260)
|
||||
|
||||
## [6.2.0] - 2024.04.22
|
||||
|
||||
### Added
|
||||
|
||||
- XR template avatar added to the Resources folder [#258](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/258)
|
||||
- Avatar Creator now supports body shapes [#252](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/252)
|
||||
- support for unknown exceptions [#251](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/251)
|
||||
- Simple PanelManager script
|
||||
- Optional define symbol to remove camera permissions from the Android manifest [#259](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/259)
|
||||
|
||||
## Updated
|
||||
|
||||
- Removed use of tuples and deprecated old methods [#257](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/257)
|
||||
|
||||
## [6.1.2] - 2024.04.03
|
||||
|
||||
### Updated
|
||||
|
||||
- XR animation avatars updated to support with latest xr avatar updates
|
||||
|
||||
## [6.1.1] - 2024.04.03
|
||||
|
||||
### Updated
|
||||
|
||||
- Avatars done with a photo are now added as a draft avatars [#254](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/254)
|
||||
|
||||
## [6.1.0] - 2024.03.04
|
||||
|
||||
### Updated
|
||||
- AvatarMeshHelper now supports multiple mesh and material transfer. [#241](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/241)
|
||||
|
||||
### Added
|
||||
- GetHeadMeshes method to AvatarMeshHelper to get head related meshes from an avatar. [#242](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/242)
|
||||
- Template avatar with all possible meshes is added to the Resources folder.
|
||||
|
||||
## [6.0.1] - 2024.02.26
|
||||
|
||||
### Updated
|
||||
|
||||
- Updated default render settings to fix an issue causing incorrect halfbody avatar renders [#238](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/238)
|
||||
|
||||
## [6.0.0] - 2024.02.19
|
||||
|
||||
### Updated
|
||||
|
||||
- **BREAKING: Renamed Avatar Create Samples** [#210](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/210) _This change
|
||||
may require updates to existing references in your projects._
|
||||
- Small fix for button icon resizing [#215](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/215)
|
||||
- LoginWithCode can now merge avatars into RPM account [#219](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/219)
|
||||
- Recover hair when headwear is removed [#224](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/224)
|
||||
- Added extra check to prevent settings override [#226](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/226)
|
||||
|
||||
### Added
|
||||
|
||||
- Logout Element for Avatar Creator [#216](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/216)
|
||||
- New iFrame Events to WebFrameHandler [#212](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/212)
|
||||
- Added support for XR Avatar skeleton [#217](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/217)
|
||||
- Added Avatar List element [#218](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/218)
|
||||
- Account creation and login elements in Avatar Creator sample [#230](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/230)
|
||||
|
||||
### Removed
|
||||
|
||||
- Quickstart Parameter from UrlConfig [#221](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/221)
|
||||
- Selfie to Avatar Element* [#220](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/220)
|
||||
- Removed WebView auto installation [#208](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/208)
|
||||
|
||||
## [5.0.0] - 2024.01.12
|
||||
|
||||
### Updated
|
||||
|
||||
- Refactor and extracted shared logic from network
|
||||
packages [#148](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/148)
|
||||
- Replaced api urls in samples with models urls [#152](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/152)
|
||||
- Added com.unity.cloud.gltfast as a dependency and removed auto install of gltfast from git
|
||||
url [#155](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/155)
|
||||
- Updated to GLTFast 6.0.1 [#157](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/157)
|
||||
- Replaced use of ienumerator coroutines with
|
||||
async/await [#172](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/172)
|
||||
- Request class names updated to be more uniform [#173](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/173)
|
||||
- Endpoint classes removed and refactored [#174](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/174)
|
||||
- Added avatar creator POC sample using new
|
||||
elements [#182](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/182)
|
||||
- Removed "I don't have an account" checkbox from setup
|
||||
guide [#184](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/184)
|
||||
- Restructure of avatar creator samples [#185](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/185)
|
||||
- Class and folder restructure to match Unity package
|
||||
standards [#190](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/190)
|
||||
- Namespaces added to some scripts to meet asset store
|
||||
requirements [#195](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/195)
|
||||
- Ready Player Me top toolbar menu is under `Tools/Ready Player Me` to comply with Asset Store
|
||||
requirements [#195](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/195)
|
||||
- Samples renamed for Asset Store version of package and paths updated
|
||||
accordingly [#198](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/198)
|
||||
- Quick start sample animations updated [#200](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/200)
|
||||
- Draco compression package version updated [#202](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/202)
|
||||
|
||||
### Added
|
||||
|
||||
- Add gender select element for Avatar Creator [#159](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/159)
|
||||
- Basic login element for Avatar Creator [#160](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/160)
|
||||
- Photo capture element for Avatar Creator [#162](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/162)
|
||||
- Avatar template element for Avatar Creator [#164](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/164)
|
||||
- Selfie element for Avatar Creator [#166](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/166)
|
||||
- Asset panel element for Avatar Creator [#175](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/175)
|
||||
- Account creation element for Avatar Creator [#178](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/178)
|
||||
- Avatar preview element for Avatar Creator [#181](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/181)
|
||||
|
||||
- Fixed some issues related to paths like in the Graphics Setting
|
||||
Utility [#195](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/195)
|
||||
- Shader override property added to avatar config [#199](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/199)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix for handling pasted url text in subdomain
|
||||
field [#183](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/183)
|
||||
- Added permission and orientation fix to photo capture
|
||||
element [#192](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/192)
|
||||
- Added Panel Switcher clear functionality to fix issues related to relaunching the
|
||||
Creator [#194](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/194)
|
||||
- Namespaces added to some scripts to meet asset store
|
||||
requirements [#195](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/195)
|
||||
|
||||
## [4.1.2] - 2023.12.20
|
||||
|
||||
### Fixed
|
||||
|
||||
- Add preserve attribute to CategoryConverter in
|
||||
AvatarCreator [#193](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/193)
|
||||
|
||||
## [4.1.1] - 2023.11.29
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed json converters in AvatarCreator getting stripped on android or webgl
|
||||
builds [#188](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/188)
|
||||
|
||||
## [4.1.0] - 2023.11.29
|
||||
|
||||
### Updated
|
||||
|
||||
- Replaced API URLs with model URLs for shortcodes [#152](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/152)
|
||||
- Updated render api and samples [#147](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/147)
|
||||
|
||||
### Added
|
||||
|
||||
- Added app id to setup guide [#145](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/145)
|
||||
|
||||
## [4.0.1] - 2023.11.14
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed an issue causing avatars to be stored locally even if caching was
|
||||
disabled [#150](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/150)
|
||||
|
||||
## [4.0.0] - 2023.11.01
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- Merge avatar creator into core [#135](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/135).
|
||||
- AvatarProcessor no longer searches and replaces existing
|
||||
avatar [#138](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/138)
|
||||
|
||||
### Added
|
||||
|
||||
- Show Avatar Creator sample button in guide [#141](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/141)
|
||||
|
||||
### Updated
|
||||
|
||||
- Merged related samples into single folders [#139](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/139)
|
||||
|
||||
## [3.4.0] - 2023.10.24
|
||||
|
||||
### Added
|
||||
|
||||
- Breaking change popup [#136](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/136)
|
||||
|
||||
### Updated
|
||||
|
||||
- Disable use demo toggle in setup guide [#131](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/131)
|
||||
- Refactor define symbol add and remove logic [#133](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/133)
|
||||
|
||||
## [3.3.0] - 2023.10.05
|
||||
|
||||
### Added
|
||||
|
||||
- Moved core iframe and url logic from WebView
|
||||
package [#125](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/125)
|
||||
|
||||
### Updated
|
||||
|
||||
- Refactored core settings handler [#124](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/124)
|
||||
- Centred all editor window content [#122](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/122)
|
||||
|
||||
## [3.2.4] - 2023.09.28
|
||||
|
||||
### Fixed
|
||||
|
||||
- An issue causing WebView to be auto imported if
|
||||
removed [#126](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/126)
|
||||
|
||||
## [3.2.3] - 2023.09.11
|
||||
|
||||
### Fixed
|
||||
|
||||
- An issue causing settings to be recreated when not
|
||||
needed [#123](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/123)
|
||||
|
||||
## [3.2.2] - 2023.09.07
|
||||
|
||||
### Fixed
|
||||
|
||||
- An issue with module installer causing errors when importing on some Windows
|
||||
machines [#117](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/117)
|
||||
|
||||
## [3.2.1] - 2023.08.28
|
||||
|
||||
### Fixed
|
||||
|
||||
-Issue of missing mesh references when prefabs were created by avatar loader
|
||||
window [#109](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/109)
|
||||
|
||||
## [3.2.0] - 2023.08.24
|
||||
|
||||
### Added
|
||||
|
||||
- App Id is added to header of all web requests
|
||||
|
||||
### Fixed
|
||||
|
||||
- GLTF scripting define symbol not getting assigned
|
||||
|
||||
## [3.1.1] - 2023.08.11
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed an issue causing analytics events being sent to development
|
||||
environment [#102](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/102)
|
||||
- Re-added RPM define symbol required for supporting
|
||||
packages [#102](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/102)
|
||||
|
||||
## [3.1.0] - 2023.08.08
|
||||
|
||||
### Added
|
||||
|
||||
* Personal avatar loading in quick start https://github.com/readyplayerme/rpm-unity-sdk-core/pull/97
|
||||
* Runtime analytics to quick start https://github.com/readyplayerme/rpm-unity-sdk-core/pull/98
|
||||
|
||||
## [3.0.0] - 2023.07.31
|
||||
|
||||
### Added
|
||||
|
||||
- **BREAKING: All scripts and assets from Avatar
|
||||
Loader** [#87](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/87)
|
||||
- Module installer now automatically removes Avatar Loader after
|
||||
update [#89](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/89)
|
||||
- New Integration guide editor window [#91](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/91)
|
||||
|
||||
### Removed
|
||||
|
||||
- **BREAKING: all references to ReadyPlayerMe.AvatarLoader namespace** [#87](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/87)
|
||||
|
||||
### Updated
|
||||
|
||||
- Moved GltFast dependent code behind scripting define
|
||||
symbol [#87](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/87)
|
||||
- Avatar config processor now uses new mesh LOD
|
||||
parameter [#90](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/90)
|
||||
- Setup guide window improvements [#91](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/91)
|
||||
|
||||
## [1.3.0] - 2023.05.29
|
||||
|
||||
### Added
|
||||
|
||||
- Import timeout to module installer [#70](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/70)
|
||||
- Add new setup guide window [#71](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/71)
|
||||
- Added function for folder size in MB [#72](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/72)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Various editor window layout fixes [#73](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/73)
|
||||
|
||||
## [1.2.0] - 2023.04.18
|
||||
|
||||
### Added
|
||||
|
||||
- Support for response codes [#62](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/62)
|
||||
|
||||
### Updated
|
||||
|
||||
- Refactor of WebRequestDispatcher [#59](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/59)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed an issue with the popup don't ask again pref was not updating
|
||||
correctly [#58](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/58)
|
||||
|
||||
## [1.1.0] - 2023.03.21
|
||||
|
||||
### Added
|
||||
|
||||
- Quick start sample popup
|
||||
- Added operation completed event
|
||||
- Discussion link to README.md
|
||||
|
||||
### Updated
|
||||
|
||||
- OpenUPM installation added to README.md
|
||||
|
||||
## [1.0.0] - 2023.02.20
|
||||
|
||||
### Added
|
||||
|
||||
- Optional sdk logging
|
||||
- Don't ask again option for update check
|
||||
|
||||
### Updated
|
||||
|
||||
- PartnerSubdomainSettings refactored to a CoreSettings scriptable object
|
||||
|
||||
### Fixed
|
||||
|
||||
- Core settings asset now automatically created if it is missing
|
||||
- Various bug fixes and improvements
|
||||
|
||||
## [0.2.0] - 2023.02.08
|
||||
|
||||
### Added
|
||||
|
||||
- Optional sdk logging
|
||||
|
||||
### Updated
|
||||
|
||||
- PartnerSubdomainSettings refactored to a CoreSettings scriptable object
|
||||
|
||||
### Fixed
|
||||
|
||||
- Various bug fixes and improvements
|
||||
|
||||
## [0.1.0] - 2023.01.22
|
||||
|
||||
### Updated
|
||||
|
||||
- Repository names in module list + version numbers
|
||||
|
||||
## [0.1.0] - 2023.01.12
|
||||
|
||||
### Added
|
||||
|
||||
- Inline code documentation
|
||||
- Contribution guide and code of conduct
|
||||
- Module installer and updater for handling package installation
|
||||
|
||||
### Updated
|
||||
|
||||
- A big refactor of code and classes
|
||||
|
||||
### Fixed
|
||||
|
||||
- Various bug fixes and improvements
|
||||
7
Unity/Assets/Ready Player Me/Core/CHANGELOG.md.meta
Normal file
7
Unity/Assets/Ready Player Me/Core/CHANGELOG.md.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a3e4746243f04549af24f9f9eca1f06
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
80
Unity/Assets/Ready Player Me/Core/CODE_OF_CONDUCT.md
Normal file
80
Unity/Assets/Ready Player Me/Core/CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,80 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email address, without their explicit permission
|
||||
* Contacting individual members, contributors, or leaders privately, outside designated community mechanisms, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at support@readyplayer.me. All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at <https://www.contributor-covenant.org/version/2/0/code_of_conduct.html>.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at <https://www.contributor-covenant.org/faq>. Translations are available at <https://www.contributor-covenant.org/translations>.
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7879103106cd18d47b36fbbd7faf0b2c
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
136
Unity/Assets/Ready Player Me/Core/CONTRIBUTING.md
Normal file
136
Unity/Assets/Ready Player Me/Core/CONTRIBUTING.md
Normal file
@ -0,0 +1,136 @@
|
||||
# Welcome to the Ready Player Me Unity SDK (Core) contributing guide
|
||||
|
||||
Thank you for investing your time in contributing to our project! Any contribution you make will be reflected on [https://github.com/readyplayerme/Unity-Core](https://github.com/readyplayerme/Unity-Core) :sparkles:.
|
||||
|
||||
Read our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectable.
|
||||
|
||||
In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR.
|
||||
|
||||
Use the table of contents icon on the top left corner of this document to get to a specific section of this guide quickly.
|
||||
|
||||
|
||||
## New contributor guide
|
||||
|
||||
To get an overview of the project, read the [README](README.md). Here are some resources to help you get started with open source contributions:
|
||||
|
||||
- [FAQ](#faq)
|
||||
- [Set up Git](https://docs.github.com/en/get-started/quickstart/set-up-git)
|
||||
- [GitHub flow](https://docs.github.com/en/get-started/quickstart/github-flow)
|
||||
- [Collaborating with pull requests](https://docs.github.com/en/github/collaborating-with-pull-requests)
|
||||
- [Code style guide](https://github.com/readyplayerme/rpm-unity-sdk-core/blob/main/style-guidelines.md)
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
#### **Did you find a bug?**
|
||||
|
||||
* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/readyplayerme/Unity-core/issues).
|
||||
|
||||
* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/readyplayerme/Unity-core/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring.
|
||||
|
||||
* If possible, use the relevant bug report templates to create the issue. Simply copy the content of the appropriate template into a .rb file, make the necessary changes to demonstrate the issue, and **paste the content into the issue description**:
|
||||
* [**Generic template** for other issues](https://github.com/readyplayerme/Unity-Core/blob/develop/.github/pull_request_template.md)
|
||||
|
||||
* If you would like to contact us directly to report an issue or for general support requests contact our Ready Player Me Support email [support@readyplayer.me](mailto:support@readyplayer.me).
|
||||
|
||||
#### **Did you write a patch that fixes a bug?**
|
||||
|
||||
* Open a new GitHub pull request with the patch.
|
||||
|
||||
* Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable.
|
||||
|
||||
* Before submitting, please read the [Contributing to Ready Player Me Unity SDK](#) guide to know more about our coding conventions and best practices.
|
||||
|
||||
#### **Did you fix whitespace, format code, or make a purely cosmetic patch?**
|
||||
|
||||
Changes that are cosmetic in nature and do not add anything substantial to the stability, functionality, or testability will generally not be accepted.
|
||||
|
||||
#### **Do you intend to add a new feature or change an existing one?**
|
||||
|
||||
* Suggest your change to the Ready Player Me support email [support@readyplayer.me](mailto:support@readyplayer.me) and start writing code.
|
||||
|
||||
* **Do not open an issue on GitHub** until you have collected positive feedback about the change. GitHub issues are primarily intended for bug reports and fixes.
|
||||
|
||||
#### **Do you have questions about the source code?**
|
||||
|
||||
* Ask any question about how to use the Ready Player Me Unity SDK in the [Ready Player Me support email](mailto:support@readyplayer.me).
|
||||
|
||||
## Issues
|
||||
|
||||
#### Create a new issue
|
||||
|
||||
If you spot a problem with the docs, [search if an issue already exists](https://docs.github.com/en/github/searching-for-information-on-github/searching-on-github/searching-issues-and-pull-requests#search-by-the-title-body-or-comments). If a related issue doesn't exist, you can open a new issue using a relevant [issue form](https://github.com/github/docs/issues/new/choose).
|
||||
|
||||
#### Solve an issue
|
||||
|
||||
Scan through our [existing issues](https://github.com/github/docs/issues) to find one that interests you. You can narrow down the search using `labels` as filters. See [Labels](/contributing/how-to-use-labels.md) for more information. As a general rule, we don’t assign issues to anyone. If you find an issue to work on, you are welcome to open a PR with a fix.
|
||||
|
||||
### Make Changes
|
||||
|
||||
#### Make changes locally
|
||||
|
||||
|
||||
1. [Install Git LFS](https://docs.github.com/en/github/managing-large-files/versioning-large-files/installing-git-large-file-storage).
|
||||
|
||||
2. Fork the repository.
|
||||
- Using GitHub Desktop:
|
||||
- [Getting started with GitHub Desktop](https://docs.github.com/en/desktop/installing-and-configuring-github-desktop/getting-started-with-github-desktop) will guide you through setting up Desktop.
|
||||
- Once Desktop is set up, you can use it to [fork the repo](https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/cloning-and-forking-repositories-from-github-desktop)!
|
||||
|
||||
- Using the command line:
|
||||
- [Fork the repo](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo#fork-an-example-repository) so that you can make your changes without affecting the original project until you're ready to merge them.
|
||||
|
||||
4. Create a working branch and start with your changes!
|
||||
|
||||
### Commit your update
|
||||
|
||||
We encourage following the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format when it comes to writing commit messages. Our package repositories come with a .githooks folder that has a commit-msg file that can enforce this.
|
||||
To set this up you just need to configure git's hookspath folder to point there.
|
||||
|
||||
You can do this by
|
||||
1. Open the terminal
|
||||
2. Navigate to the root folder of this repository
|
||||
3. Run the following command
|
||||
`git config core.hooksPath .githooks`
|
||||
|
||||
Commit the changes once you are happy with them. Don't forget to [self-review](#self-review) to speed up the review process:zap:.
|
||||
|
||||
### Self review
|
||||
|
||||
You should always review your own PR first.
|
||||
|
||||
For content changes, make sure that you:
|
||||
|
||||
- [ ] Confirm that the changes meet the user experience and goals outlined in the content design plan (if there is one).
|
||||
- [ ] Compare your pull request's source changes to staging to confirm that the output matches the source and that everything is rendering as expected. This helps spot issues like typos, content that doesn't follow the [style guide](https://github.com/readyplayerme/rpm-unity-sdk-core/blob/main/style-guidelines.md), or content that isn't rendering due to versioning problems. Remember that lists and tables can be tricky.
|
||||
- [ ] Review the content for technical accuracy.
|
||||
- [ ] Review the entire pull request using the [translations guide for writers](./translations/for-writers.md).
|
||||
- [ ] Copy-edit the changes for grammar, spelling, and adherence to the [style guide](https://github.com/readyplayerme/rpm-unity-sdk-core/blob/main/style-guidelines.md).
|
||||
- [ ] Check new or updated Liquid statements to confirm that versioning is correct.
|
||||
- [ ] If there are any failing checks in your PR, troubleshoot them until they're all passing.
|
||||
|
||||
|
||||
### Pull Request
|
||||
|
||||
When you're finished with the changes, create a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests).
|
||||
- Fill the "Ready for review" template so that we can review your PR. This template helps reviewers understand your changes as well as the purpose of your pull request.
|
||||
- Don't forget to [link PR to issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) if you are solving one.
|
||||
- Enable the checkbox to [allow maintainer edits](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork) so the branch can be updated for a merge.
|
||||
Once you submit your PR, a team member will review your proposal. We may ask questions or request additional information.
|
||||
- We may ask for changes to be made before a PR can be merged, either using [suggested changes](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request) or pull request comments. You can apply suggested changes directly through the UI. You can make any other changes in your fork, then commit them to your branch.
|
||||
- As you update your PR and apply changes, mark each conversation as [resolved](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request#resolving-conversations).
|
||||
- If you run into any merge issues, checkout this [git tutorial](https://github.com/skills/resolve-merge-conflicts) to help you resolve merge conflicts and other issues.
|
||||
|
||||
### Your PR is merged!
|
||||
|
||||
Congratulations :tada::tada: The GitHub team thanks you :sparkles:.
|
||||
|
||||
Once your PR is merged, your contributions will be publicly visible on the [GitHub docs](https://docs.github.com/en).
|
||||
|
||||
Now that you are part of the GitHub docs community, see how else you can [contribute to the docs](/contributing/types-of-contributions.md).
|
||||
|
||||
|
||||
|
||||
Thanks! :heart: :heart: :heart:
|
||||
|
||||
Ready Player Me Team
|
||||
7
Unity/Assets/Ready Player Me/Core/CONTRIBUTING.md.meta
Normal file
7
Unity/Assets/Ready Player Me/Core/CONTRIBUTING.md.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9911f547d3809f45a65e24379e1e2a0
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Unity/Assets/Ready Player Me/Core/Editor.meta
Normal file
8
Unity/Assets/Ready Player Me/Core/Editor.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 93849b2d974237746812c1d8407d660a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3cd7b15d18039474489020dd9d3daf34
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.AvatarCreator.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(AssetTypeFilterAttribute))]
|
||||
public class AssetTypeFilterDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
var assetTypeAttribute = attribute as AssetTypeFilterAttribute;
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.Enum)
|
||||
{
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
// Get the current enum value
|
||||
var currentEnumValue = (AssetType) property.enumValueIndex;
|
||||
|
||||
var filteredEnumNames = new List<string>();
|
||||
foreach (var enumName in Enum.GetNames(typeof(AssetType)))
|
||||
{
|
||||
var enumFieldInfo = typeof(AssetType).GetField(enumName);
|
||||
var enumAttribute = (AssetTypeFilterAttribute) Attribute.GetCustomAttribute(enumFieldInfo, typeof(AssetTypeFilterAttribute));
|
||||
if (enumAttribute == null) continue;
|
||||
|
||||
var filter = (AssetFilter) Enum.Parse(typeof(AssetFilter), enumAttribute.filter.ToString());
|
||||
if (filter == assetTypeAttribute?.filter)
|
||||
{
|
||||
filteredEnumNames.Add(enumName);
|
||||
}
|
||||
}
|
||||
|
||||
// Display the dropdown with filtered enum values
|
||||
var newIndex = EditorGUI.Popup(position, label.text, Array.IndexOf(filteredEnumNames.ToArray(), currentEnumValue.ToString()), filteredEnumNames.ToArray());
|
||||
|
||||
// Set the new enum value if it has changed
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
property.enumValueIndex = (int) Enum.Parse(typeof(AssetType), filteredEnumNames[newIndex]);
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUI.LabelField(position, label.text, "Use AssetType with Enum.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6add29e0a6c64d6786c6742dfbd87acf
|
||||
timeCreated: 1702392584
|
||||
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "ReadyPlayerMe.AvatarCreator.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"ReadyPlayerMe.Core",
|
||||
"ReadyPlayerMe.AvatarCreator"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ed01c010d356f94b99818818dbd9430
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Unity/Assets/Ready Player Me/Core/Editor/Core.meta
Normal file
8
Unity/Assets/Ready Player Me/Core/Editor/Core.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 17b21c922120b25458033294675f03ec
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15d9bb0049cd8b245900c3f74fc99cb0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Unity/Assets/Ready Player Me/Core/Editor/Core/Resources/Banner.png
(Stored with Git LFS)
Normal file
BIN
Unity/Assets/Ready Player Me/Core/Editor/Core/Resources/Banner.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -0,0 +1,120 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 97cb8e496ac634f4ba4c0a1bb899c8da
|
||||
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
|
||||
vTOnly: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
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
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 1024
|
||||
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: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 1024
|
||||
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:
|
||||
BIN
Unity/Assets/Ready Player Me/Core/Editor/Core/Resources/rpm_error_icon.png
(Stored with Git LFS)
Normal file
BIN
Unity/Assets/Ready Player Me/Core/Editor/Core/Resources/rpm_error_icon.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -0,0 +1,132 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38a8827f446904c4c802c5b7850e3ff0
|
||||
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
|
||||
vTOnly: 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: 1
|
||||
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
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 32
|
||||
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: 32
|
||||
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: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 32
|
||||
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:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05e3bb89ec0ad464c9a480276df7c651
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac1c518000284e8ea25dfdd1284e0f16
|
||||
timeCreated: 1657013631
|
||||
@ -0,0 +1,301 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ReadyPlayerMe.Core.Editor;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using static ReadyPlayerMe.Core.Analytics.Constants;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Analytics
|
||||
{
|
||||
public class AmplitudeEditorLogger : IAnalyticsEditorLogger
|
||||
{
|
||||
private const string SDK_TARGET = "Unity";
|
||||
|
||||
private readonly Dictionary<HelpSubject, string> helpDataMap = new()
|
||||
{
|
||||
{ HelpSubject.AvatarCaching, "avatar caching" },
|
||||
{ HelpSubject.Subdomain, "subdomain" },
|
||||
{ HelpSubject.AvatarConfig, "avatar config" },
|
||||
{ HelpSubject.GltfDeferAgent, "gltf defer agent" },
|
||||
{ HelpSubject.LoadingAvatars, "download avatar into scene" },
|
||||
{
|
||||
HelpSubject.Avatars, "avatars body type"
|
||||
}
|
||||
};
|
||||
|
||||
private bool isEnabled;
|
||||
private readonly AppData appData;
|
||||
|
||||
public AmplitudeEditorLogger(bool isEnabled)
|
||||
{
|
||||
this.isEnabled = isEnabled;
|
||||
appData = ApplicationData.GetData();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
isEnabled = true;
|
||||
if (!AmplitudeEventLogger.IsSessionIdSet())
|
||||
{
|
||||
GenerateSessionId();
|
||||
}
|
||||
ToggleAnalytics(true);
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
ToggleAnalytics(false);
|
||||
isEnabled = false;
|
||||
AmplitudeEventLogger.SetSessionId(0);
|
||||
}
|
||||
|
||||
public void IdentifyUser()
|
||||
{
|
||||
if (!isEnabled) return;
|
||||
if (!AmplitudeEventLogger.IsSessionIdSet())
|
||||
{
|
||||
GenerateSessionId();
|
||||
}
|
||||
SetUserProperties();
|
||||
}
|
||||
|
||||
public void LogOpenProject()
|
||||
{
|
||||
if (!isEnabled) return;
|
||||
GenerateSessionId();
|
||||
AmplitudeEventLogger.LogEvent(EventName.OPEN_PROJECT);
|
||||
}
|
||||
|
||||
public void LogCloseProject()
|
||||
{
|
||||
LogEvent(EventName.CLOSE_PROJECT);
|
||||
}
|
||||
|
||||
public void LogOpenDocumentation(string target)
|
||||
{
|
||||
LogEvent(EventName.OPEN_DOCUMENTATION, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.TARGET, target }
|
||||
});
|
||||
}
|
||||
|
||||
public void LogOpenFaq(string target)
|
||||
{
|
||||
LogEvent(EventName.OPEN_FAQ, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.TARGET, target }
|
||||
});
|
||||
}
|
||||
|
||||
public void LogOpenDiscord(string target)
|
||||
{
|
||||
LogEvent(EventName.OPEN_DISCORD, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.TARGET, target }
|
||||
});
|
||||
}
|
||||
|
||||
public void LogLoadAvatarFromDialog(string avatarUrl, bool eyeAnimation, bool voiceHandler)
|
||||
{
|
||||
LogEvent(EventName.LOAD_AVATAR_FROM_DIALOG, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.AVATAR_URL, avatarUrl },
|
||||
{ Properties.EYE_ANIMATION, eyeAnimation },
|
||||
{ Properties.VOICE_HANDLER, voiceHandler }
|
||||
});
|
||||
}
|
||||
|
||||
public void LogUpdatePartnerURL(string previousSubdomain, string newSubdomain)
|
||||
{
|
||||
LogEvent(EventName.UPDATED_PARTNER_URL, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.PREVIOUS_SUBDOMAIN, previousSubdomain },
|
||||
{ Properties.NEW_SUBDOMAIN, newSubdomain }
|
||||
}, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.SUBDOMAIN, newSubdomain }
|
||||
});
|
||||
}
|
||||
|
||||
public void LogOpenDialog(string dialog)
|
||||
{
|
||||
LogEvent(EventName.OPEN_DIALOG, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.DIALOG, dialog }
|
||||
});
|
||||
}
|
||||
|
||||
public void LogBuildApplication(string target, string appName, bool productionBuild)
|
||||
{
|
||||
LogEvent(EventName.BUILD_APPLICATION, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.TARGET, target },
|
||||
{ Properties.APP_NAME, appName },
|
||||
{ Properties.PRODUCTION_BUILD, productionBuild },
|
||||
{ Properties.APP_IDENTIFIER, Application.identifier }
|
||||
});
|
||||
}
|
||||
|
||||
public void LogMetadataDownloaded(double duration)
|
||||
{
|
||||
LogEvent(EventName.METADATA_DOWNLOADED, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.DURATION, duration }
|
||||
});
|
||||
}
|
||||
|
||||
public void LogAvatarLoaded(double duration)
|
||||
{
|
||||
LogEvent(EventName.AVATAR_LOADED, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.DURATION, duration }
|
||||
});
|
||||
}
|
||||
|
||||
public void LogCheckForUpdates()
|
||||
{
|
||||
LogEvent(EventName.CHECK_FOR_UPDATES);
|
||||
}
|
||||
|
||||
public void LogSetLoggingEnabled(bool isLoggingEnabled)
|
||||
{
|
||||
LogEvent(EventName.SET_LOGGING_ENABLED, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.LOGGING_ENABLED, isLoggingEnabled }
|
||||
});
|
||||
}
|
||||
|
||||
public void LogSetCachingEnabled(bool isCachingEnabled)
|
||||
{
|
||||
LogEvent(EventName.SET_CACHING_ENABLED, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.CACHING_ENABLED, isCachingEnabled }
|
||||
});
|
||||
}
|
||||
|
||||
public void LogClearLocalCache()
|
||||
{
|
||||
LogEvent(EventName.CLEAR_LOCAL_CACHE);
|
||||
}
|
||||
|
||||
public void LogViewPrivacyPolicy()
|
||||
{
|
||||
LogEvent(EventName.PRIVACY_POLICY);
|
||||
}
|
||||
|
||||
public void LogShowInExplorer()
|
||||
{
|
||||
LogEvent(EventName.SHOW_IN_EXPLORER);
|
||||
}
|
||||
|
||||
public void LogFindOutMore(HelpSubject subject)
|
||||
{
|
||||
LogEvent(EventName.FIND_OUT_MORE, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.CONTEXT, helpDataMap[subject] }
|
||||
});
|
||||
}
|
||||
|
||||
public void LogOpenSetupGuide()
|
||||
{
|
||||
LogEvent(EventName.OPEN_SETUP_GUIDE);
|
||||
}
|
||||
|
||||
public void LogOpenIntegrationGuide()
|
||||
{
|
||||
LogEvent(EventName.OPEN_INTEGRATION_GUIDE);
|
||||
}
|
||||
|
||||
public void LogLoadQuickStartScene()
|
||||
{
|
||||
LogEvent(EventName.LOAD_QUICK_START_SCENE);
|
||||
}
|
||||
|
||||
public void LogOpenAvatarDocumentation()
|
||||
{
|
||||
LogEvent(EventName.OPEN_AVATAR_DOCUMENTATION);
|
||||
}
|
||||
|
||||
public void LogOpenAnimationDocumentation()
|
||||
{
|
||||
LogEvent(EventName.OPEN_ANIMATION_DOCUMENTATION);
|
||||
}
|
||||
|
||||
public void LogOpenAvatarCreatorDocumentation()
|
||||
{
|
||||
LogEvent(EventName.OPEN_AVATAR_CREATOR_DOCUMENTATION);
|
||||
}
|
||||
|
||||
public void LogOpenOptimizationDocumentation()
|
||||
{
|
||||
LogEvent(EventName.OPEN_OPTIMIZATION_DOCUMENTATION);
|
||||
}
|
||||
|
||||
public void LogAvatarCreatorSampleImported()
|
||||
{
|
||||
LogEvent(EventName.AVATAR_CREATOR_SAMPLE_IMPORTED);
|
||||
}
|
||||
|
||||
public void LogPackageInstalled(string id, string name)
|
||||
{
|
||||
LogEvent(EventName.INSTALL_PACKAGE, new Dictionary<string, object>
|
||||
{
|
||||
{ "id", id },
|
||||
{ "name", name }
|
||||
});
|
||||
}
|
||||
|
||||
private void SetUserProperties()
|
||||
{
|
||||
var userProperties = new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.SDK_SOURCE_URL, PackageManagerHelper.GetSdkPackageSourceUrl() },
|
||||
{ Properties.ENGINE_VERSION, appData.UnityVersion },
|
||||
{ Properties.RENDER_PIPELINE, appData.RenderPipeline },
|
||||
{ Properties.SUBDOMAIN, appData.PartnerName },
|
||||
{ Properties.APP_NAME, PlayerSettings.productName },
|
||||
{ Properties.SDK_TARGET, SDK_TARGET },
|
||||
{ Properties.APP_IDENTIFIER, Application.identifier },
|
||||
{ Properties.ALLOW_ANALYTICS, true }
|
||||
};
|
||||
|
||||
var modules = ModuleList.GetInstalledModuleVersionDictionary();
|
||||
|
||||
foreach (var module in modules)
|
||||
{
|
||||
userProperties.Add(module.Key, module.Value);
|
||||
}
|
||||
|
||||
LogEvent(EventName.SET_USER_PROPERTIES, null, userProperties);
|
||||
}
|
||||
|
||||
private void GenerateSessionId()
|
||||
{
|
||||
AmplitudeEventLogger.SetSessionId(DateTimeOffset.Now.ToUnixTimeMilliseconds());
|
||||
}
|
||||
|
||||
private void ToggleAnalytics(bool allow)
|
||||
{
|
||||
LogEvent(EventName.ALLOW_ANALYTICS, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.ALLOW, allow }
|
||||
}, new Dictionary<string, object>
|
||||
{
|
||||
{ Properties.ENGINE_VERSION, appData.UnityVersion },
|
||||
{ Properties.RENDER_PIPELINE, appData.RenderPipeline },
|
||||
{ Properties.SUBDOMAIN, appData.PartnerName },
|
||||
{ Properties.APP_NAME, PlayerSettings.productName },
|
||||
{ Properties.SDK_TARGET, "Unity" },
|
||||
{ Properties.APP_IDENTIFIER, Application.identifier },
|
||||
{ Properties.ALLOW_ANALYTICS, allow }
|
||||
});
|
||||
}
|
||||
|
||||
private void LogEvent(string eventName, Dictionary<string, object> eventProperties = null, Dictionary<string, object> userProperties = null)
|
||||
{
|
||||
if (!isEnabled) return;
|
||||
|
||||
AmplitudeEventLogger.LogEvent(eventName, eventProperties, userProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed6804cd2c9d4b9bb873a4c1cd6af062
|
||||
timeCreated: 1657032252
|
||||
@ -0,0 +1,31 @@
|
||||
using ReadyPlayerMe.Core.Editor;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Analytics
|
||||
{
|
||||
public static class AnalyticsEditorLogger
|
||||
{
|
||||
public static readonly IAnalyticsEditorLogger EventLogger;
|
||||
|
||||
static AnalyticsEditorLogger()
|
||||
{
|
||||
IsEnabled = CoreSettingsHandler.CoreSettings.EnableAnalytics;
|
||||
EventLogger = new AmplitudeEditorLogger(IsEnabled);
|
||||
}
|
||||
|
||||
public static bool IsEnabled { get; private set; }
|
||||
|
||||
public static void Enable()
|
||||
{
|
||||
IsEnabled = true;
|
||||
EventLogger.Enable();
|
||||
CoreSettingsSetter.SetEnableAnalytics(true);
|
||||
}
|
||||
|
||||
public static void Disable()
|
||||
{
|
||||
EventLogger.Disable();
|
||||
IsEnabled = false;
|
||||
CoreSettingsSetter.SetEnableAnalytics(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc2862cbf129461eaa91ca136d9d045d
|
||||
timeCreated: 1658921992
|
||||
@ -0,0 +1,74 @@
|
||||
namespace ReadyPlayerMe.Core.Analytics
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
public static class EventName
|
||||
{
|
||||
public const string OPEN_PROJECT = "open project";
|
||||
public const string OPEN_DOCUMENTATION = "open documentation";
|
||||
public const string OPEN_FAQ = "open faq";
|
||||
public const string OPEN_DISCORD = "open discord";
|
||||
public const string LOAD_AVATAR_FROM_DIALOG = "load avatar from dialog";
|
||||
public const string UPDATED_PARTNER_URL = "updated partner url";
|
||||
public const string ALLOW_ANALYTICS = "allow analytics";
|
||||
public const string OPEN_DIALOG = "open dialog";
|
||||
public const string BUILD_APPLICATION = "build application";
|
||||
public const string CLOSE_PROJECT = "close project";
|
||||
public const string METADATA_DOWNLOADED = "metadata downloaded";
|
||||
public const string AVATAR_LOADED = "avatar loaded";
|
||||
public const string SET_USER_PROPERTIES = "set user properties";
|
||||
public const string CLEAR_LOCAL_CACHE = "clear local cache";
|
||||
public const string SHOW_IN_EXPLORER = "show in explorer";
|
||||
public const string SET_LOGGING_ENABLED = "set logging enabled";
|
||||
public const string SET_CACHING_ENABLED = "set caching enabled";
|
||||
public const string CHECK_FOR_UPDATES = "check for updates";
|
||||
public const string PRIVACY_POLICY = "view privacy policy";
|
||||
public const string FIND_OUT_MORE = "find out more";
|
||||
public const string OPEN_SETUP_GUIDE = "open setup guide";
|
||||
public const string OPEN_INTEGRATION_GUIDE = "open integration guide";
|
||||
public const string LOAD_QUICK_START_SCENE = "load quick start scene";
|
||||
public const string OPEN_AVATAR_DOCUMENTATION = "open avatar documentation";
|
||||
public const string OPEN_ANIMATION_DOCUMENTATION = "open animation documentation";
|
||||
public const string OPEN_AVATAR_CREATOR_DOCUMENTATION = "open avatar creator documentation";
|
||||
public const string OPEN_OPTIMIZATION_DOCUMENTATION = "open optimization documentation";
|
||||
public const string AVATAR_CREATOR_SAMPLE_IMPORTED = "Avatar creator sample imported";
|
||||
public const string INSTALL_PACKAGE = "install unity package";
|
||||
}
|
||||
|
||||
public static class Properties
|
||||
{
|
||||
public const string SDK_SOURCE_URL = "sdk source url";
|
||||
public const string ENGINE_VERSION = "engine version";
|
||||
public const string RENDER_PIPELINE = "render pipeline";
|
||||
public const string SUBDOMAIN = "subdomain";
|
||||
public const string APP_NAME = "app name";
|
||||
public const string SDK_TARGET = "sdk target";
|
||||
public const string TARGET = "target";
|
||||
public const string EYE_ANIMATION = "eye animation";
|
||||
public const string VOICE_HANDLER = "voice handler";
|
||||
public const string PREVIOUS_SUBDOMAIN = "previous subdomain";
|
||||
public const string NEW_SUBDOMAIN = "new subdomain";
|
||||
public const string ALLOW = "allow";
|
||||
public const string DIALOG = "dialog";
|
||||
public const string PRODUCTION_BUILD = "production build";
|
||||
public const string AVATAR_URL = "avatar url";
|
||||
public const string APP_IDENTIFIER = "app identifier";
|
||||
public const string ALLOW_ANALYTICS = "allow analytics";
|
||||
public const string DURATION = "duration";
|
||||
public const string LOGGING_ENABLED = "logging enabled";
|
||||
public const string CACHING_ENABLED = "caching enabled";
|
||||
public const string CONTEXT = "context";
|
||||
}
|
||||
|
||||
public static class Links
|
||||
{
|
||||
public const string DOCS_PARTNERS_LINK = "https://docs.readyplayer.me/ready-player-me/what-is-ready-player-me#url";
|
||||
public const string DOCS_DEFER_AGENT_LINK = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity/optimize/defer-agents";
|
||||
public const string DOCS_AVATAR_LOADER_WINDOW = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity/avatar-loader-window";
|
||||
public const string DOCS_AVATAR_CONFIG_LINK = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity/optimize/avatar-configuration";
|
||||
public const string DOCS_AVATAR_CACHING = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity/optimize/avatar-caching";
|
||||
public const string AVATARS = "https://docs.readyplayer.me/ready-player-me/api-reference/avatars";
|
||||
public const string APP_ID = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity/avatar-creator/custom-avatar-creator#prerequisites";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7e6b1c7b30a462e971d46dd09b38bdf
|
||||
timeCreated: 1657013679
|
||||
@ -0,0 +1,12 @@
|
||||
namespace ReadyPlayerMe.Core.Analytics
|
||||
{
|
||||
public enum HelpSubject
|
||||
{
|
||||
AvatarCaching,
|
||||
Subdomain,
|
||||
AvatarConfig,
|
||||
GltfDeferAgent,
|
||||
LoadingAvatars,
|
||||
Avatars
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38767189f66d5bc4d8dfe76b552103f5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,36 @@
|
||||
namespace ReadyPlayerMe.Core.Analytics
|
||||
{
|
||||
public interface IAnalyticsEditorLogger
|
||||
{
|
||||
void Enable();
|
||||
void Disable();
|
||||
void IdentifyUser();
|
||||
void LogOpenProject();
|
||||
void LogCloseProject();
|
||||
void LogOpenDocumentation(string target);
|
||||
void LogOpenFaq(string target);
|
||||
void LogOpenDiscord(string target);
|
||||
void LogLoadAvatarFromDialog(string avatarUrl, bool eyeAnimation, bool voiceHandler);
|
||||
void LogUpdatePartnerURL(string previousSubdomain, string newSubdomain);
|
||||
void LogOpenDialog(string dialog);
|
||||
void LogBuildApplication(string target, string appName, bool productionBuild);
|
||||
void LogMetadataDownloaded(double duration);
|
||||
void LogAvatarLoaded(double duration);
|
||||
void LogCheckForUpdates();
|
||||
void LogSetLoggingEnabled(bool isLoggingEnabled);
|
||||
void LogSetCachingEnabled(bool isCachingEnabled);
|
||||
void LogClearLocalCache();
|
||||
void LogViewPrivacyPolicy();
|
||||
void LogShowInExplorer();
|
||||
void LogFindOutMore(HelpSubject subject);
|
||||
void LogOpenSetupGuide();
|
||||
void LogOpenIntegrationGuide();
|
||||
void LogLoadQuickStartScene();
|
||||
void LogOpenAvatarDocumentation();
|
||||
void LogOpenAnimationDocumentation();
|
||||
void LogOpenAvatarCreatorDocumentation();
|
||||
void LogOpenOptimizationDocumentation();
|
||||
void LogAvatarCreatorSampleImported();
|
||||
void LogPackageInstalled(string id, string name);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a73e3153ee348d199f878b693a5e1f7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56a89e876009bc043b3211c63f594371
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
public static class StringExtensions
|
||||
{
|
||||
private const string SHORT_CODE_REGEX = "^[A-Z0-9]{6}$";
|
||||
|
||||
public static bool IsUrlShortcodeValid(this string urlString)
|
||||
{
|
||||
return !string.IsNullOrEmpty(urlString) &&
|
||||
(Regex.Match(urlString, SHORT_CODE_REGEX).Length > 0 || Uri.IsWellFormedUriString(urlString, UriKind.Absolute) && urlString.EndsWith(".glb"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d58d3d8f33d435f4aa8b5b0b6625bcbb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c882a7949df662b428444bc798c7ebb8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using ReadyPlayerMe.Core.Analytics;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// This class serves as a way of tracking when the Unity project (editor) is initially opened so that functions can be run at this point.
|
||||
/// </summary>
|
||||
[InitializeOnLoad]
|
||||
public static class EntryPoint
|
||||
{
|
||||
private const string SESSION_STARTED_KEY = "SessionStarted";
|
||||
|
||||
/// Event for when package is imported or when project with package is opened.
|
||||
public static Action Startup;
|
||||
|
||||
/// <summary>
|
||||
/// This constructor is used to subscribe to the <see cref="EditorApplication.update"/> event.
|
||||
/// </summary>
|
||||
static EntryPoint()
|
||||
{
|
||||
if (!SessionState.GetBool(SESSION_STARTED_KEY, false))
|
||||
{
|
||||
SessionState.SetBool(SESSION_STARTED_KEY, true);
|
||||
EditorApplication.update += Update;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is called on every Editor <see cref="EditorApplication.update"/>.
|
||||
/// It is used to trigger moduleUpdater to check for updates when the Unity Project launches.
|
||||
/// </summary>
|
||||
private static void Update()
|
||||
{
|
||||
EditorApplication.update -= Update;
|
||||
AnalyticsEditorLogger.EventLogger.LogOpenProject();
|
||||
AnalyticsEditorLogger.EventLogger.IdentifyUser();
|
||||
Startup?.Invoke();
|
||||
EditorApplication.quitting += OnQuit;
|
||||
}
|
||||
|
||||
private static void OnQuit()
|
||||
{
|
||||
AnalyticsEditorLogger.EventLogger.LogCloseProject();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71bde74e39624415805f1552261fd75e
|
||||
timeCreated: 1657016805
|
||||
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Structure <c>ModuleInfo</c> describes a Ready Player Me Module or Unity package.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public struct ModuleInfo
|
||||
{
|
||||
public string name;
|
||||
public string gitUrl;
|
||||
public string branch;
|
||||
public string version;
|
||||
|
||||
/// <summary>
|
||||
/// Get the Unity package identifier.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <c>string</c> representing the Unity packages Git Url including branch if specified. Returns module name if
|
||||
/// gitUrl is not set.
|
||||
/// </returns>
|
||||
public string Identifier
|
||||
{
|
||||
get
|
||||
{
|
||||
if (gitUrl == string.Empty)
|
||||
{
|
||||
return name;
|
||||
}
|
||||
// if branch not set, default to the version in ModuleList
|
||||
return gitUrl + (string.IsNullOrEmpty(branch) ? $"#v{version}" : $"#{branch}");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f14ac780c523d32408d7ea9c6f78e692
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Compilation;
|
||||
using UnityEditor.PackageManager;
|
||||
using UnityEditor.PackageManager.Requests;
|
||||
using UnityEngine;
|
||||
using PackageInfo = UnityEditor.PackageManager.PackageInfo;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Class <c>ModuleInstaller</c> is responsible for checking and installing all modules (Unity packages) required for
|
||||
/// the Ready Player Me Unity SDK from their Git URL's.
|
||||
/// </summary>
|
||||
[InitializeOnLoad]
|
||||
public static class ModuleInstaller
|
||||
{
|
||||
private const string TAG = nameof(ModuleInstaller);
|
||||
private const int THREAD_SLEEP_TIME = 100;
|
||||
private const float TIMEOUT_FOR_MODULE_INSTALLATION = 20f;
|
||||
|
||||
static ModuleInstaller()
|
||||
{
|
||||
Events.registeringPackages -= OnRegisteringPackages;
|
||||
Events.registeringPackages += OnRegisteringPackages;
|
||||
|
||||
#if !READY_PLAYER_ME
|
||||
EditorApplication.delayCall += DelayCreateCoreSettings;
|
||||
DefineSymbolHelper.AddSymbols();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a package is about to be added, removed or changed.
|
||||
/// </summary>
|
||||
/// <param name="args">Describes the <c>PackageInfo</c> entries of packages currently registering.</param>
|
||||
private static void OnRegisteringPackages(PackageRegistrationEventArgs args)
|
||||
{
|
||||
// Core module uninstalled
|
||||
if (args.removed != null && args.removed.Any(p => p.name == ModuleList.Core.name))
|
||||
{
|
||||
DefineSymbolHelper.RemoveSymbols();
|
||||
ProjectPrefs.SetBool(ProjectPrefs.FIRST_TIME_SETUP_DONE, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DelayCreateCoreSettings()
|
||||
{
|
||||
EditorApplication.delayCall -= DelayCreateCoreSettings;
|
||||
CoreSettingsLoader.EnsureSettingsExist();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Request UPM to install the given module with the identifier.
|
||||
/// </summary>
|
||||
/// <param name="identifier">The Unity package identifier of the module to be installed.</param>
|
||||
public static void AddModuleRequest(string identifier)
|
||||
{
|
||||
var startTime = Time.realtimeSinceStartup;
|
||||
AddRequest addRequest = Client.Add(identifier);
|
||||
while (!addRequest.IsCompleted && Time.realtimeSinceStartup - startTime < TIMEOUT_FOR_MODULE_INSTALLATION)
|
||||
Thread.Sleep(THREAD_SLEEP_TIME);
|
||||
|
||||
if (Time.realtimeSinceStartup - startTime >= TIMEOUT_FOR_MODULE_INSTALLATION)
|
||||
{
|
||||
Debug.LogError($"Package installation timed out for {identifier}. Please try again.");
|
||||
}
|
||||
if (addRequest.Error != null)
|
||||
{
|
||||
Debug.LogError("Error: " + addRequest.Error.message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the given module with the name is currently installed.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the module.</param>
|
||||
/// <returns>A boolean <c>true</c> if the module is installed.</returns>
|
||||
public static bool IsModuleInstalled(string name)
|
||||
{
|
||||
return GetPackageList().Any(info => info.name == name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the list of unity packages installed in the current project.
|
||||
/// </summary>
|
||||
/// <returns>An array of <c>PackageInfo</c>.</returns>
|
||||
public static PackageInfo[] GetPackageList()
|
||||
{
|
||||
ListRequest listRequest = Client.List(true);
|
||||
while (!listRequest.IsCompleted)
|
||||
Thread.Sleep(THREAD_SLEEP_TIME);
|
||||
|
||||
if (listRequest.Error != null)
|
||||
{
|
||||
SDKLogger.Log(TAG, "Error: " + listRequest.Error.message);
|
||||
return Array.Empty<PackageInfo>();
|
||||
}
|
||||
|
||||
return listRequest.Result.ToArray();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5201abe9c7e36574d90cd052f0e8cda3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,72 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.PackageManager;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Class <c>ModuleList</c> is a static class that can be referenced to get the latest module version.
|
||||
/// </summary>
|
||||
public static class ModuleList
|
||||
{
|
||||
public static ModuleInfo Core = new ModuleInfo
|
||||
{
|
||||
name = "com.readyplayerme.core",
|
||||
gitUrl = "https://github.com/readyplayerme/rpm-unity-sdk-core.git",
|
||||
branch = "",
|
||||
version = "5.0.0"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A static list of all the required modules represented in an array of <c>ModuleInfo</c>.
|
||||
/// </summary>
|
||||
public static readonly ModuleInfo[] Modules =
|
||||
{
|
||||
new ModuleInfo
|
||||
{
|
||||
name = "com.readyplayerme.webview",
|
||||
gitUrl = "https://github.com/readyplayerme/rpm-unity-sdk-webview.git",
|
||||
branch = "",
|
||||
version = "2.1.3"
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Unity Module that adds support for gltf files that use DracoCompression.
|
||||
/// </summary>
|
||||
public static ModuleInfo DracoCompression = new ModuleInfo
|
||||
{
|
||||
name = "com.atteneder.draco",
|
||||
gitUrl = "https://github.com/atteneder/DracoUnity.git",
|
||||
branch = "",
|
||||
version = "4.1.0"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Get installed modules from Modules list.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Dictionary"/> of installed Unity Module information in the format of <c>Dictionary<string: name, string: version></c>. </returns>
|
||||
public static Dictionary<string, string> GetInstalledModuleVersionDictionary()
|
||||
{
|
||||
PackageInfo[] packageList = ModuleInstaller.GetPackageList();
|
||||
|
||||
var installedModules = new Dictionary<string, string>();
|
||||
installedModules.Add(Core.name, Core.version);
|
||||
|
||||
foreach (ModuleInfo module in Modules)
|
||||
{
|
||||
if (packageList.Any(x => x.name == module.name))
|
||||
{
|
||||
installedModules.Add(module.name, module.version);
|
||||
}
|
||||
}
|
||||
|
||||
if (packageList.Any(x => x.name == DracoCompression.name))
|
||||
{
|
||||
installedModules.Add(DracoCompression.name, DracoCompression.version);
|
||||
}
|
||||
|
||||
return installedModules;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 725bcc26dc146374c8f0d96d3928d7ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,211 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using ReadyPlayerMe.Core.Analytics;
|
||||
using UnityEditor;
|
||||
using UnityEditor.PackageManager;
|
||||
using UnityEditor.PackageManager.Requests;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
using PackageInfo = UnityEditor.PackageManager.PackageInfo;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// It is responsible for checking and updating the Ready Player Me SDK modules.
|
||||
/// </summary>
|
||||
[InitializeOnLoad]
|
||||
public class ModuleUpdater
|
||||
{
|
||||
|
||||
private class Release
|
||||
{
|
||||
[JsonProperty("tag_name")]
|
||||
public string Tag;
|
||||
}
|
||||
|
||||
private const string PACKAGE_JSON = "package.json";
|
||||
private const string PACKAGE_DOMAIN = "com.readyplayerme";
|
||||
|
||||
private const string GITHUB_WEBSITE = "https://github.com";
|
||||
private const string GITHUB_API_URL = "https://api.github.com/repos";
|
||||
|
||||
private const int MILLISECONDS_TIMEOUT = 20;
|
||||
private const string ASSET_FILTER = "package";
|
||||
|
||||
private const string DONT_ASK = "Dont Ask";
|
||||
private const string UPDATE_PACKAGES_WINDOW_TITLE = "Update Packages";
|
||||
private const string UPDATE_BUTTON_TEXT = "Update";
|
||||
private const string CANCEL_BUTTON_TEXT = "Cancel";
|
||||
private const string DONT_ASK_TEXT = "Don't ask";
|
||||
|
||||
private const string AVATAR_LOADER_PACKAGE = "com.readyplayerme.avatarloader";
|
||||
|
||||
static ModuleUpdater()
|
||||
{
|
||||
EntryPoint.Startup += () => Check(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check for Ready Player Me package updates.
|
||||
/// </summary>
|
||||
[MenuItem("Tools/Ready Player Me/Check For Updates", priority = 23)]
|
||||
public static void CheckForUpdates()
|
||||
{
|
||||
AnalyticsEditorLogger.EventLogger.LogCheckForUpdates();
|
||||
Check();
|
||||
}
|
||||
|
||||
private static void Check(bool isStartup = false)
|
||||
{
|
||||
// Get PackageInfo array from RPM Module package.json files
|
||||
PackageInfo[] packages = AssetDatabase.FindAssets(ASSET_FILTER)
|
||||
.Select(AssetDatabase.GUIDToAssetPath)
|
||||
.Where(x => x.Contains(PACKAGE_JSON) && x.Contains(PACKAGE_DOMAIN))
|
||||
.Select(PackageInfo.FindForAssetPath)
|
||||
.ToArray();
|
||||
|
||||
if (packages.Length == 0)
|
||||
{
|
||||
Debug.Log("No rpm package found");
|
||||
}
|
||||
|
||||
// Turn package_name@repo_url#branch_name into https://api.github.com/repos/readyplayerme/repo_name/releases
|
||||
foreach (PackageInfo package in packages)
|
||||
{
|
||||
var repoUrl = package.packageId.Split('@')[1];
|
||||
var releasesUrl = repoUrl
|
||||
.Split(new[] { ".git" }, StringSplitOptions.None)[0]
|
||||
.Replace(GITHUB_WEBSITE, GITHUB_API_URL) + "/releases";
|
||||
|
||||
var packageUrl = repoUrl.Split('#')[0];
|
||||
|
||||
// Experimental or prerelease packages might look like 0.1.0-exp.1, remove after dash to parse with Version
|
||||
var version = package.version.Split('-')[0];
|
||||
|
||||
if (isStartup && EditorPrefs.GetBool(DONT_ASK + "-" + package.name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FetchReleases(package.name, packageUrl, releasesUrl, new Version(version));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetch latest release for each module and prompt for update if available.
|
||||
/// </summary>
|
||||
/// <param name="packageName">The name of the Unity package.</param>
|
||||
/// <param name="packageUrl">The Git URL of the Unity package.</param>
|
||||
/// <param name="releasesUrl">The Git URL of the Unity package.</param>
|
||||
/// <param name="currentVersion">The current version of the package.</param>
|
||||
private static async void FetchReleases(string packageName, string packageUrl, string releasesUrl,
|
||||
Version currentVersion)
|
||||
{
|
||||
UnityWebRequest request = UnityWebRequest.Get(releasesUrl);
|
||||
UnityWebRequestAsyncOperation op = request.SendWebRequest();
|
||||
while (!op.isDone) await Task.Yield();
|
||||
|
||||
if (request.result == UnityWebRequest.Result.Success)
|
||||
{
|
||||
var response = request.downloadHandler.text;
|
||||
Release[] releases = JsonConvert.DeserializeObject<Release[]>(response);
|
||||
Version[] versions = releases!.Select(r => new Version(r.Tag.Substring(1).Split('-')[0])).ToArray();
|
||||
|
||||
Version latestVersion = versions.Max();
|
||||
|
||||
if (latestVersion > currentVersion)
|
||||
{
|
||||
DisplayUpdateDialog(packageName, currentVersion, latestVersion, packageUrl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"Failed to fetch {packageName} releases. Error: {request.error} ");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a Unity popup with notification about available package updates with buttons to update or skip.
|
||||
/// </summary>
|
||||
/// <param name="packageName">The name of the Unity package.</param>
|
||||
/// <param name="currentVersion">The current version of the package.</param>
|
||||
/// <param name="latestVersion">The new version of the package.</param>
|
||||
/// <param name="packageUrl">The Git URL of the Unity package.</param>
|
||||
private static void DisplayUpdateDialog(string packageName, Version currentVersion, Version latestVersion,
|
||||
string packageUrl)
|
||||
{
|
||||
var shouldUpdate = EditorUtility.DisplayDialogComplex(UPDATE_PACKAGES_WINDOW_TITLE,
|
||||
$"New update available for {packageName}\nCurrent version: {currentVersion}\nLatest version: {latestVersion}",
|
||||
UPDATE_BUTTON_TEXT,
|
||||
CANCEL_BUTTON_TEXT,
|
||||
DONT_ASK_TEXT);
|
||||
|
||||
switch (shouldUpdate)
|
||||
{
|
||||
// Update
|
||||
case 0:
|
||||
CheckIfMajorRelease(packageName, currentVersion, latestVersion, packageUrl);
|
||||
break;
|
||||
// Cancel
|
||||
case 1:
|
||||
// Do nothing
|
||||
break;
|
||||
// Don't ask
|
||||
case 2:
|
||||
EditorPrefs.SetBool(DONT_ASK + "-" + packageName, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckIfMajorRelease(string packageName, Version currentVersion, Version latestVersion,
|
||||
string packageUrl)
|
||||
{
|
||||
if (latestVersion.Major > currentVersion.Major)
|
||||
{
|
||||
BreakingChangeDialog.ShowDialog(() =>
|
||||
{
|
||||
UpdateModule(packageName, packageUrl, currentVersion, latestVersion);
|
||||
});
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateModule(packageName, packageUrl, currentVersion, latestVersion);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the specified module by removing the current version and then adding the specified version.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the Unity package.</param>
|
||||
/// <param name="url">The Git URL of the Unity package.</param>
|
||||
/// <param name="current">The current version of the package.</param>
|
||||
/// <param name="latest">The new version of the package.</param>
|
||||
private static void UpdateModule(string name, string url, Version current, Version latest)
|
||||
{
|
||||
url += "#v" + latest;
|
||||
CleanRedundantAvatarLoader();
|
||||
RemoveRequest removeRequest = Client.Remove(name);
|
||||
while (!removeRequest.IsCompleted) Thread.Sleep(MILLISECONDS_TIMEOUT);
|
||||
|
||||
AddRequest addRequest = Client.Add(url);
|
||||
while (!addRequest.IsCompleted) Thread.Sleep(MILLISECONDS_TIMEOUT);
|
||||
|
||||
Debug.Log($"Updated {name} from v{current} to v{latest}");
|
||||
}
|
||||
|
||||
private static void CleanRedundantAvatarLoader()
|
||||
{
|
||||
if (!ModuleInstaller.IsModuleInstalled(AVATAR_LOADER_PACKAGE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveRequest removeRequest = Client.Remove(AVATAR_LOADER_PACKAGE);
|
||||
while (!removeRequest.IsCompleted) Thread.Sleep(MILLISECONDS_TIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 40c5062ebf8390443a66ccca5f9d4507
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ac2b39cc7ef4a5988d6ac77077db307
|
||||
timeCreated: 1699344120
|
||||
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using ReadyPlayerMe.Core.Analytics;
|
||||
using UnityEditor;
|
||||
using UnityEditor.PackageManager;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
public abstract class PackageManagerEventListener
|
||||
{
|
||||
public static event Action<string> OnPackageImported;
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
static void Initialize()
|
||||
{
|
||||
Events.registeredPackages += OnPackagesInstalled;
|
||||
}
|
||||
|
||||
~PackageManagerEventListener()
|
||||
{
|
||||
Events.registeredPackages -= OnPackagesInstalled;
|
||||
}
|
||||
|
||||
static void OnPackagesInstalled(PackageRegistrationEventArgs packageRegistrationEventArgs)
|
||||
{
|
||||
packageRegistrationEventArgs.added
|
||||
.ToList()
|
||||
.ForEach(packageInfo =>
|
||||
{
|
||||
OnPackageImported?.Invoke(packageInfo.name);
|
||||
AnalyticsEditorLogger.EventLogger.LogPackageInstalled(packageInfo.name, packageInfo.packageId);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a08c3f9ac3c142dc9ea5d854a1bc3af1
|
||||
timeCreated: 1699344135
|
||||
@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using UnityEditor.PackageManager;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
public abstract class PackageManagerHelper
|
||||
{
|
||||
private const string TAG = nameof(PackageManagerHelper);
|
||||
private const int THREAD_SLEEP_TIME = 100;
|
||||
private const float TIMEOUT_FOR_PACKAGE_INSTALLATION = 20f;
|
||||
private const string READY_PLAYER_ME_PACKAGE_PATH = "Packages/com.readyplayerme.core";
|
||||
|
||||
public static bool IsPackageInstalled(string name)
|
||||
{
|
||||
return GetPackageList().Any(info => info.name == name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the list of unity packages installed in the current project.
|
||||
/// </summary>
|
||||
/// <returns>An array of <c>PackageInfo</c>.</returns>
|
||||
public static PackageInfo[] GetPackageList()
|
||||
{
|
||||
var listRequest = Client.List(true);
|
||||
while (!listRequest.IsCompleted)
|
||||
Thread.Sleep(THREAD_SLEEP_TIME);
|
||||
|
||||
if (listRequest.Error == null)
|
||||
{
|
||||
return listRequest.Result.ToArray();
|
||||
}
|
||||
|
||||
SDKLogger.Log(TAG, "Error: " + listRequest.Error.message);
|
||||
return Array.Empty<PackageInfo>();
|
||||
|
||||
}
|
||||
|
||||
public static string GetSdkPackageSourceUrl()
|
||||
{
|
||||
var sdkPackageInfo = PackageInfo.FindForAssetPath(READY_PLAYER_ME_PACKAGE_PATH);
|
||||
|
||||
return sdkPackageInfo?.packageId
|
||||
.Split(new[] { '@' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.LastOrDefault();
|
||||
}
|
||||
|
||||
public static void AddPackage(string identifier)
|
||||
{
|
||||
var startTime = Time.realtimeSinceStartup;
|
||||
var addRequest = Client.Add(identifier);
|
||||
|
||||
while (!addRequest.IsCompleted && Time.realtimeSinceStartup - startTime < TIMEOUT_FOR_PACKAGE_INSTALLATION)
|
||||
Thread.Sleep(THREAD_SLEEP_TIME);
|
||||
|
||||
if (Time.realtimeSinceStartup - startTime >= TIMEOUT_FOR_PACKAGE_INSTALLATION)
|
||||
{
|
||||
Debug.LogError($"Package installation timed out for {identifier}. Please try again.");
|
||||
}
|
||||
if (addRequest.Error != null)
|
||||
{
|
||||
Debug.LogError("Error: " + addRequest.Error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c12b21e35214e19a1c3dfe7148a3fda
|
||||
timeCreated: 1698851420
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc95a31f3c977d74d95cba569605dbf1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,19 @@
|
||||
using ReadyPlayerMe.Core.Analytics;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Callbacks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
public static class BuildPostProcessor
|
||||
{
|
||||
[PostProcessBuild(1)]
|
||||
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
|
||||
{
|
||||
// create asset if it has been deleted
|
||||
CoreSettingsLoader.EnsureSettingsExist();
|
||||
AppData appData = ApplicationData.GetData();
|
||||
AnalyticsEditorLogger.EventLogger.LogBuildApplication(appData.BuildTarget, PlayerSettings.productName, !Debug.isDebugBuild);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9efa9adc0c4948579b226dac039a2e85
|
||||
timeCreated: 1657013212
|
||||
@ -0,0 +1,40 @@
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
public class BuildPreprocessor : IPreprocessBuildWithReport
|
||||
{
|
||||
private const string TAG = nameof(BuildPreprocessor);
|
||||
private const string ADD_SHADER_VARIANTS = "Add and Build";
|
||||
private const string BUILD_WARNING = "Build Warning";
|
||||
private const string SUBDOMAIN_WARNING =
|
||||
@"It looks like the glTFast Shader Variants are missing from the Graphics Settings/Preloaded Shader list list. This can cause errors when loading Ready Player Me avatars at runtime. Would you like to add them now before building?";
|
||||
private const string CONTINUE_WITH_DEMO = "Build without Variants";
|
||||
private const string WARNING_BUILD_WITHOUT_VARIANTS = "Building without adding glTFast Shader Variants";
|
||||
|
||||
public int callbackOrder { get; }
|
||||
|
||||
public void OnPreprocessBuild(BuildReport report)
|
||||
{
|
||||
if (!Application.isBatchMode && GraphicsSettingsUtility.IsMissingVariants())
|
||||
{
|
||||
var addShaderVariants = EditorUtility.DisplayDialog(BUILD_WARNING,
|
||||
SUBDOMAIN_WARNING,
|
||||
ADD_SHADER_VARIANTS,
|
||||
CONTINUE_WITH_DEMO);
|
||||
|
||||
if (addShaderVariants)
|
||||
{
|
||||
GraphicsSettingsUtility.AddPreloadShaderVariants();
|
||||
}
|
||||
else
|
||||
{
|
||||
SDKLogger.LogWarning(TAG, WARNING_BUILD_WITHOUT_VARIANTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d1731ba78624114ba8112a23e3033a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,30 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
public class ModelAssetProcessor : AssetPostprocessor
|
||||
{
|
||||
private const string ANIMATION_ASSET_PATH = "Assets/Ready Player Me/Animations";
|
||||
|
||||
private void OnPreprocessModel()
|
||||
{
|
||||
var modelImporter = assetImporter as ModelImporter;
|
||||
UpdateAnimationFileSettings(modelImporter);
|
||||
}
|
||||
|
||||
private void UpdateAnimationFileSettings(ModelImporter modelImporter)
|
||||
{
|
||||
void SetModelImportData()
|
||||
{
|
||||
if (modelImporter is null) return;
|
||||
modelImporter.useFileScale = false;
|
||||
modelImporter.animationType = ModelImporterAnimationType.Human;
|
||||
}
|
||||
|
||||
if (assetPath.Contains(ANIMATION_ASSET_PATH))
|
||||
{
|
||||
SetModelImportData();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42dc49b3ab05c424a80c14e9bfae17e6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "ReadyPlayerMe.Core.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"ReadyPlayerMe.Core",
|
||||
"ReadyPlayerMe.AvatarCreator"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36f486ff968bbf4439cd840e8fca87ea
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52273617608987047a79eb2417aab281
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,44 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public class AvatarLoaderSettingsCreator
|
||||
{
|
||||
private const string SETTINGS_SAVE_FOLDER = "Ready Player Me/Resources/Settings";
|
||||
private const string AVATAR_LOADER_ASSET_NAME = "AvatarLoaderSettings.asset";
|
||||
|
||||
static AvatarLoaderSettingsCreator()
|
||||
{
|
||||
EditorApplication.delayCall += CreateSettingsAssets;
|
||||
}
|
||||
|
||||
~AvatarLoaderSettingsCreator()
|
||||
{
|
||||
EditorApplication.delayCall -= CreateSettingsAssets;
|
||||
}
|
||||
|
||||
private static void CreateSettingsAssets()
|
||||
{
|
||||
if (AvatarLoaderSettings.LoadSettings() != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
DirectoryUtility.ValidateDirectory($"{Application.dataPath}/{SETTINGS_SAVE_FOLDER}");
|
||||
AssetDatabase.Refresh();
|
||||
CreateAvatarLoaderSettings();
|
||||
}
|
||||
|
||||
private static void CreateAvatarLoaderSettings()
|
||||
{
|
||||
var newSettings = ScriptableObject.CreateInstance<AvatarLoaderSettings>();
|
||||
newSettings.AvatarConfig = null;
|
||||
newSettings.GLTFDeferAgent = null;
|
||||
newSettings.AvatarCachingEnabled = true;
|
||||
|
||||
AssetDatabase.CreateAsset(newSettings, $"Assets/{SETTINGS_SAVE_FOLDER}/{AVATAR_LOADER_ASSET_NAME}");
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ea257c9bde84481a358e3685eef8646
|
||||
timeCreated: 1670940169
|
||||
@ -0,0 +1,36 @@
|
||||
using System.IO;
|
||||
using ReadyPlayerMe.Core.Data;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public static class CoreSettingsLoader
|
||||
{
|
||||
private const string PROJECT_RELATIVE_ASSET_PATH = "Assets/Ready Player Me/Resources/Settings/CoreSettings.asset";
|
||||
private const string SETTINGS_SAVE_FOLDER = "Ready Player Me/Resources/Settings";
|
||||
|
||||
static CoreSettingsLoader()
|
||||
{
|
||||
EnsureSettingsExist();
|
||||
}
|
||||
|
||||
public static void EnsureSettingsExist()
|
||||
{
|
||||
if (CoreSettingsHandler.CoreSettings == null && !File.Exists($"{Application.dataPath}/Ready Player Me/Resources/Settings/CoreSettings.asset"))
|
||||
{
|
||||
CreateSettings();
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateSettings()
|
||||
{
|
||||
DirectoryUtility.ValidateDirectory($"{Application.dataPath}/{SETTINGS_SAVE_FOLDER}");
|
||||
var newSettings = ScriptableObject.CreateInstance<CoreSettings>();
|
||||
AssetDatabase.CreateAsset(newSettings, PROJECT_RELATIVE_ASSET_PATH);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da717eefac74935459a3f995092c5463
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,44 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
public static class CoreSettingsSetter
|
||||
{
|
||||
public static void SetEnableAnalytics(bool isEnabled)
|
||||
{
|
||||
CoreSettingsHandler.CoreSettings.EnableAnalytics = isEnabled;
|
||||
Save();
|
||||
}
|
||||
|
||||
public static void SetEnableLogging(bool isEnabled)
|
||||
{
|
||||
CoreSettingsHandler.CoreSettings.EnableLogging = isEnabled;
|
||||
Save();
|
||||
}
|
||||
|
||||
public static void SaveSubDomain(string subDomain)
|
||||
{
|
||||
if (string.IsNullOrEmpty(subDomain) || CoreSettingsHandler.CoreSettings.Subdomain == subDomain) return;
|
||||
CoreSettingsHandler.CoreSettings.Subdomain = subDomain;
|
||||
Save();
|
||||
}
|
||||
|
||||
public static void SaveAppId(string appId)
|
||||
{
|
||||
CoreSettingsHandler.CoreSettings.AppId = appId;
|
||||
Save();
|
||||
}
|
||||
|
||||
public static void SaveBodyType(BodyType bodyType)
|
||||
{
|
||||
CoreSettingsHandler.CoreSettings.BodyType = bodyType;
|
||||
Save();
|
||||
}
|
||||
|
||||
public static void Save()
|
||||
{
|
||||
EditorUtility.SetDirty(CoreSettingsHandler.CoreSettings);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79be5f9e434a00b46bacd5a47871b69a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,138 @@
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
public enum RenderPipeline { Standard, URP, HDRP }
|
||||
public static class GraphicsSettingsUtility
|
||||
{
|
||||
private const string TAG = nameof(GraphicsSettingsUtility);
|
||||
private const string PRELOADED_SHADER_PROPERTY = "m_PreloadedShaders";
|
||||
private const string GRAPHICS_SETTING_PATH = "ProjectSettings/GraphicsSettings.asset";
|
||||
|
||||
private const string SHADER_VARIANT_ASSETS_FOLDER = "Assets/Ready Player Me/Core/Runtime/Core/Shaders";
|
||||
private const string SHADER_VARIANT_PACKAGES_FOLDER = "Packages/com.readyplayerme.core/Runtime/Core/Shaders";
|
||||
|
||||
private const string SHADER_VARIANTS_STANDARD = "glTFastShaderVariants";
|
||||
private const string SHADER_VARIANTS_URP = "glTFastShaderVariantsURP";
|
||||
private const string SHADER_VARIANTS_HDRP = "glTFastShaderVariantsHDRP";
|
||||
|
||||
private const string HDRP_TYPE_NAME = "HDRenderPipelineAsset";
|
||||
private const string URP_TYPE_NAME = "UniversalRenderPipelineAsset";
|
||||
private const string SHADER_SESSION_CHECK = "SHADER_SESSION_CHECK";
|
||||
private const string VARIANTS_FOUND_LOG = "glTFast shader variants found in Graphics Settings->Preloaded Shaders";
|
||||
private const string SHADER_VARIANTS_EXTENSION = ".shadervariants";
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
private static void InitializeOnLoad()
|
||||
{
|
||||
if (SessionState.GetBool(SHADER_SESSION_CHECK, false)) return;
|
||||
SessionState.SetBool(SHADER_SESSION_CHECK, true);
|
||||
|
||||
EditorApplication.update += CheckAndUpdatePreloadShaders;
|
||||
}
|
||||
|
||||
private static void CheckAndUpdatePreloadShaders()
|
||||
{
|
||||
EditorApplication.update -= CheckAndUpdatePreloadShaders;
|
||||
AddPreloadShaderVariants(true);
|
||||
}
|
||||
|
||||
public static void AddPreloadShaderVariants(bool checkForMissingVariants = false)
|
||||
{
|
||||
var graphicsSettings = AssetDatabase.LoadAssetAtPath<GraphicsSettings>(GRAPHICS_SETTING_PATH);
|
||||
var serializedGraphicsObject = new SerializedObject(graphicsSettings);
|
||||
SerializedProperty shaderPreloadArray = serializedGraphicsObject.FindProperty(PRELOADED_SHADER_PROPERTY);
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
var newArrayIndex = shaderPreloadArray.arraySize;
|
||||
var shaderVariants = AssetDatabase.LoadAssetAtPath<ShaderVariantCollection>(GetTargetShaderPath());
|
||||
if (shaderVariants == null)
|
||||
{
|
||||
Debug.LogWarning($"Shader variants not found at {GetTargetShaderPath()}");
|
||||
return;
|
||||
}
|
||||
if (checkForMissingVariants)
|
||||
{
|
||||
var shadersMissing = true;
|
||||
var serializedVariants = new SerializedObject(shaderVariants);
|
||||
|
||||
foreach (SerializedProperty shaderInclude in shaderPreloadArray)
|
||||
{
|
||||
if (shaderInclude.objectReferenceValue.name == serializedVariants.targetObject.name)
|
||||
{
|
||||
SDKLogger.Log(TAG, VARIANTS_FOUND_LOG);
|
||||
shadersMissing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!shadersMissing) return;
|
||||
}
|
||||
|
||||
shaderPreloadArray.InsertArrayElementAtIndex(newArrayIndex);
|
||||
SerializedProperty shaderInArray = shaderPreloadArray.GetArrayElementAtIndex(newArrayIndex);
|
||||
shaderInArray.objectReferenceValue = shaderVariants;
|
||||
|
||||
serializedGraphicsObject.ApplyModifiedProperties();
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
|
||||
public static bool IsMissingVariants()
|
||||
{
|
||||
var graphicsSettings = AssetDatabase.LoadAssetAtPath<GraphicsSettings>(GRAPHICS_SETTING_PATH);
|
||||
var serializedGraphicsObject = new SerializedObject(graphicsSettings);
|
||||
|
||||
SerializedProperty shaderPreloadArray = serializedGraphicsObject.FindProperty(PRELOADED_SHADER_PROPERTY);
|
||||
|
||||
var shaderVariants = AssetDatabase.LoadAssetAtPath<ShaderVariantCollection>(GetTargetShaderPath());
|
||||
var shadersMissing = true;
|
||||
var serializedVariants = new SerializedObject(shaderVariants);
|
||||
|
||||
foreach (SerializedProperty shaderInclude in shaderPreloadArray)
|
||||
{
|
||||
if (shaderInclude.objectReferenceValue.name == serializedVariants.targetObject.name)
|
||||
{
|
||||
SDKLogger.Log(TAG, VARIANTS_FOUND_LOG);
|
||||
|
||||
shadersMissing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return shadersMissing;
|
||||
}
|
||||
|
||||
private static string GetTargetShaderPath()
|
||||
{
|
||||
var shaderFolderPath = SHADER_VARIANT_PACKAGES_FOLDER;
|
||||
if (!Directory.Exists(shaderFolderPath))
|
||||
{
|
||||
shaderFolderPath = SHADER_VARIANT_ASSETS_FOLDER;
|
||||
}
|
||||
return GetCurrentRenderPipeline() switch
|
||||
{
|
||||
RenderPipeline.URP => $"{shaderFolderPath}/{SHADER_VARIANTS_URP}{SHADER_VARIANTS_EXTENSION}",
|
||||
RenderPipeline.HDRP => $"{shaderFolderPath}/{SHADER_VARIANTS_HDRP}{SHADER_VARIANTS_EXTENSION}",
|
||||
_ => $"{shaderFolderPath}/{SHADER_VARIANTS_STANDARD}{SHADER_VARIANTS_EXTENSION}"
|
||||
};
|
||||
}
|
||||
|
||||
private static RenderPipeline GetCurrentRenderPipeline()
|
||||
{
|
||||
if (GraphicsSettings.defaultRenderPipeline != null)
|
||||
{
|
||||
var renderPipelineType = GraphicsSettings.defaultRenderPipeline.GetType().ToString();
|
||||
if (renderPipelineType.Contains(HDRP_TYPE_NAME))
|
||||
{
|
||||
return RenderPipeline.HDRP;
|
||||
}
|
||||
if (renderPipelineType.Contains(URP_TYPE_NAME))
|
||||
{
|
||||
return RenderPipeline.URP;
|
||||
}
|
||||
}
|
||||
return RenderPipeline.Standard;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d2fbb1ef6a68bc4b9c0c99be430c64d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18404e155f36da7408078998b6470ce2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 669755add08ba044d9ffb4e764476d9d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,430 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
[CustomEditor(typeof(AvatarConfig))]
|
||||
public class AvatarConfigEditor : UnityEditor.Editor
|
||||
{
|
||||
private const string DIALOG_TITLE = "Read Player Me";
|
||||
private const string DIALOG_MESSAGE = "Do you want to install {0} Unity Package: {1} ?";
|
||||
private const string DIALOG_OK = "Ok";
|
||||
private const string DIALOG_CANCEL = "Cancel";
|
||||
private const string ADD_MORPH_TARGET = "Add Morph Target";
|
||||
private const string DELETE_MORPH_TARGET = "Delete Morph Target";
|
||||
private const string REMOVE_BUTTON_TEXT = "Remove";
|
||||
private const string MESH_OPT_PACKAGE_NAME = "com.unity.meshopt.decompress";
|
||||
|
||||
[SerializeField] private VisualTreeAsset visualTreeAsset;
|
||||
|
||||
private AvatarConfig avatarConfigTarget;
|
||||
private List<Label> morphTargetLabels;
|
||||
|
||||
private Dictionary<VisualElement, string> morphTargetsParentVisualElement;
|
||||
|
||||
private VisualElement selectedMorphTargets;
|
||||
|
||||
private SerializedProperty useDracoCompressionField;
|
||||
private bool previousDracoCompressionValue;
|
||||
|
||||
private SerializedProperty useMeshOptCompressionField;
|
||||
private bool previousMeshOptCompressionValue;
|
||||
|
||||
private VisualElement root;
|
||||
private Action textureChannelChanged;
|
||||
|
||||
private SerializedProperty shaderPropertyMappingList;
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
root = new VisualElement();
|
||||
visualTreeAsset.CloneTree(root);
|
||||
avatarConfigTarget = (AvatarConfig) target;
|
||||
shaderPropertyMappingList = serializedObject.FindProperty("ShaderPropertyMapping");
|
||||
SetupLod();
|
||||
SetupPose();
|
||||
SetupTextureAtlas();
|
||||
SetupTextureSizeLimit();
|
||||
SetupUseHands();
|
||||
SetupCompressionPackages();
|
||||
SetupTextureChannel();
|
||||
SetupMorphTargets();
|
||||
SetupShader();
|
||||
return root;
|
||||
}
|
||||
|
||||
private void SetupLod()
|
||||
{
|
||||
var lod = root.Q<EnumField>("Lod");
|
||||
lod.SetValueWithoutNotify(avatarConfigTarget.Lod);
|
||||
lod.RegisterValueChangedCallback(x =>
|
||||
{
|
||||
avatarConfigTarget.Lod = (Lod) x.newValue;
|
||||
Save();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void SetupPose()
|
||||
{
|
||||
var pose = root.Q<EnumField>("Pose");
|
||||
pose.SetValueWithoutNotify(avatarConfigTarget.Pose);
|
||||
pose.RegisterValueChangedCallback(x =>
|
||||
{
|
||||
avatarConfigTarget.Pose = (Pose) x.newValue;
|
||||
Save();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void Save()
|
||||
{
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
EditorUtility.SetDirty(serializedObject.targetObject);
|
||||
}
|
||||
|
||||
private void SetupTextureAtlas()
|
||||
{
|
||||
var textureAtlas = root.Q<EnumField>("TextureAtlas");
|
||||
textureAtlas.SetValueWithoutNotify(avatarConfigTarget.TextureAtlas);
|
||||
textureAtlas.RegisterValueChangedCallback(x =>
|
||||
{
|
||||
avatarConfigTarget.TextureAtlas = (TextureAtlas) x.newValue;
|
||||
Save();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void SetupTextureSizeLimit()
|
||||
{
|
||||
var textureSizeLimit = root.Q<SliderInt>("TextureSizeLimit");
|
||||
textureSizeLimit.SetValueWithoutNotify(avatarConfigTarget.TextureSizeLimit);
|
||||
textureSizeLimit.RegisterValueChangedCallback(x =>
|
||||
{
|
||||
avatarConfigTarget.TextureSizeLimit = x.newValue;
|
||||
Save();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void SetupUseHands()
|
||||
{
|
||||
var useHands = root.Q<Toggle>("UseHands");
|
||||
useHands.SetValueWithoutNotify(avatarConfigTarget.UseHands);
|
||||
useHands.RegisterValueChangedCallback(x =>
|
||||
{
|
||||
avatarConfigTarget.UseHands = x.newValue;
|
||||
Save();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void SetupCompressionPackages()
|
||||
{
|
||||
var useDracoCompression = root.Q<Toggle>("UseDracoCompression");
|
||||
var useMeshOptCompression = root.Q<Toggle>("UseMeshOptCompression");
|
||||
var optimizationPackages = root.Q<Foldout>("OptimizationPackages");
|
||||
optimizationPackages.RegisterValueChangedCallback(x =>
|
||||
{
|
||||
useDracoCompression.SetValueWithoutNotify(avatarConfigTarget.UseDracoCompression);
|
||||
useMeshOptCompression.SetValueWithoutNotify(avatarConfigTarget.UseMeshOptCompression);
|
||||
});
|
||||
|
||||
useDracoCompression.RegisterValueChangedCallback(x =>
|
||||
{
|
||||
if (avatarConfigTarget.UseDracoCompression == x.newValue) return;
|
||||
avatarConfigTarget.UseDracoCompression = x.newValue;
|
||||
if (!ModuleInstaller.IsModuleInstalled(ModuleList.DracoCompression.name))
|
||||
{
|
||||
if (EditorUtility.DisplayDialog(
|
||||
DIALOG_TITLE,
|
||||
string.Format(DIALOG_MESSAGE, "Draco compression", ModuleList.DracoCompression.name),
|
||||
DIALOG_OK,
|
||||
DIALOG_CANCEL))
|
||||
{
|
||||
ModuleInstaller.AddModuleRequest(ModuleList.DracoCompression.Identifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
avatarConfigTarget.UseDracoCompression = false;
|
||||
}
|
||||
}
|
||||
useDracoCompression.SetValueWithoutNotify(avatarConfigTarget.UseDracoCompression);
|
||||
if (avatarConfigTarget.UseDracoCompression && avatarConfigTarget.UseMeshOptCompression)
|
||||
{
|
||||
Debug.LogWarning("Draco compression is not compatible with Mesh Optimization compression. Mesh Optimization compression will be disabled.");
|
||||
avatarConfigTarget.UseMeshOptCompression = false;
|
||||
useMeshOptCompression.SetValueWithoutNotify(false);
|
||||
}
|
||||
Save();
|
||||
}
|
||||
);
|
||||
|
||||
useMeshOptCompression.RegisterValueChangedCallback(x =>
|
||||
{
|
||||
if (avatarConfigTarget.UseMeshOptCompression == x.newValue) return;
|
||||
avatarConfigTarget.UseMeshOptCompression = x.newValue;
|
||||
if (!PackageManagerHelper.IsPackageInstalled(MESH_OPT_PACKAGE_NAME))
|
||||
{
|
||||
if (EditorUtility.DisplayDialog(
|
||||
DIALOG_TITLE,
|
||||
string.Format(DIALOG_MESSAGE, "Mesh opt compression", MESH_OPT_PACKAGE_NAME),
|
||||
DIALOG_OK,
|
||||
DIALOG_CANCEL))
|
||||
{
|
||||
PackageManagerHelper.AddPackage(MESH_OPT_PACKAGE_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
avatarConfigTarget.UseMeshOptCompression = false;
|
||||
}
|
||||
}
|
||||
useMeshOptCompression.SetValueWithoutNotify(avatarConfigTarget.UseMeshOptCompression);
|
||||
if (avatarConfigTarget.UseMeshOptCompression && avatarConfigTarget.UseDracoCompression)
|
||||
{
|
||||
Debug.LogWarning("Mesh Optimization compression is not compatible with Draco compression. Draco compression will be disabled.");
|
||||
avatarConfigTarget.UseDracoCompression = false;
|
||||
useDracoCompression.SetValueWithoutNotify(false);
|
||||
}
|
||||
Save();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void SetupTextureChannel()
|
||||
{
|
||||
var items = new List<string>();
|
||||
foreach (TextureChannel textureChannel in Enum.GetValues(typeof(TextureChannel)))
|
||||
{
|
||||
items.Add(textureChannel.ToString());
|
||||
}
|
||||
|
||||
VisualElement MakeItem()
|
||||
{
|
||||
var toggle = new Toggle();
|
||||
toggle.style.alignItems = Align.Center;
|
||||
return toggle;
|
||||
}
|
||||
|
||||
void BindItem(VisualElement e, int i)
|
||||
{
|
||||
var toggle = (Toggle) e;
|
||||
toggle.label = items[i];
|
||||
if (avatarConfigTarget.TextureChannel.Contains((TextureChannel) i))
|
||||
{
|
||||
toggle.SetValueWithoutNotify(true);
|
||||
}
|
||||
|
||||
toggle.RegisterValueChangedCallback(x =>
|
||||
{
|
||||
if (x.newValue)
|
||||
{
|
||||
var textureChannels = avatarConfigTarget.TextureChannel.ToList();
|
||||
textureChannels.Add((TextureChannel) i);
|
||||
avatarConfigTarget.TextureChannel = textureChannels.ToArray();
|
||||
textureChannelChanged?.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
var textureChannels = avatarConfigTarget.TextureChannel.ToList();
|
||||
textureChannels.Remove((TextureChannel) i);
|
||||
avatarConfigTarget.TextureChannel = textureChannels.ToArray();
|
||||
textureChannelChanged?.Invoke();
|
||||
}
|
||||
Save();
|
||||
});
|
||||
}
|
||||
|
||||
var listView = root.Q<ListView>();
|
||||
listView.style.height = 30 * Enum.GetValues(typeof(TextureChannel)).Length + 2;
|
||||
listView.makeItem = MakeItem;
|
||||
listView.bindItem = BindItem;
|
||||
listView.itemsSource = items;
|
||||
listView.selectionType = SelectionType.Multiple;
|
||||
|
||||
listView.onItemsChosen += Debug.Log;
|
||||
listView.onSelectionChange += Debug.Log;
|
||||
}
|
||||
|
||||
private void SetupShader()
|
||||
{
|
||||
var shader = root.Q<ObjectField>("ShaderOverride");
|
||||
shader.SetValueWithoutNotify(avatarConfigTarget.Shader);
|
||||
|
||||
shader.RegisterValueChangedCallback(x =>
|
||||
{
|
||||
avatarConfigTarget.Shader = (Shader) x.newValue;
|
||||
Save();
|
||||
SetupShader();
|
||||
}
|
||||
);
|
||||
var shaderPropertiesContainer = root.Q<VisualElement>("ShaderProperties");
|
||||
shaderPropertiesContainer.Clear();
|
||||
shaderPropertiesContainer.style.display = DisplayStyle.Flex;
|
||||
shaderPropertiesContainer.style.flexDirection = FlexDirection.Column;
|
||||
if (avatarConfigTarget.Shader == null)
|
||||
{
|
||||
shaderPropertiesContainer.style.display = DisplayStyle.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
shaderPropertiesContainer.style.display = DisplayStyle.Flex;
|
||||
shaderPropertiesContainer.style.marginTop = 10;
|
||||
shaderPropertiesContainer.style.left = 10;
|
||||
shaderPropertiesContainer.style.right = 10;
|
||||
var titleRowContainer = new VisualElement();
|
||||
titleRowContainer.style.flexDirection = FlexDirection.Row;
|
||||
titleRowContainer.style.marginBottom = 7;
|
||||
titleRowContainer.style.marginTop = 7;
|
||||
titleRowContainer.style.left = 10;
|
||||
titleRowContainer.style.right = 10;
|
||||
var sourceTitleField = new Label("Source Property")
|
||||
{
|
||||
style =
|
||||
{
|
||||
width = 200, unityFontStyleAndWeight = FontStyle.Bold, // Make the text bold
|
||||
unityTextAlign = TextAnchor.MiddleLeft
|
||||
}
|
||||
};
|
||||
titleRowContainer.Add(sourceTitleField);
|
||||
var targetTitleField = new Label("Target Property")
|
||||
{
|
||||
style = { width = 200, marginRight = 10, flexGrow = 0.8f, unityFontStyleAndWeight = FontStyle.Bold, }
|
||||
};
|
||||
titleRowContainer.Add(targetTitleField);
|
||||
var typeTitleField = new Label("Type")
|
||||
{
|
||||
style = { width = 70, alignSelf = Align.FlexEnd, unityFontStyleAndWeight = FontStyle.Bold, }
|
||||
};
|
||||
titleRowContainer.Add(typeTitleField);
|
||||
shaderPropertiesContainer.Add(titleRowContainer);
|
||||
for (int i = 0; i < shaderPropertyMappingList.arraySize; i++)
|
||||
{
|
||||
SerializedProperty mapping = shaderPropertyMappingList.GetArrayElementAtIndex(i);
|
||||
|
||||
var propertyContainer = new VisualElement();
|
||||
propertyContainer.style.flexDirection = FlexDirection.Column;
|
||||
//propertyContainer.style.marginBottom = 10;
|
||||
|
||||
var horizontalContainer = new VisualElement();
|
||||
horizontalContainer.style.flexDirection = FlexDirection.Row;
|
||||
horizontalContainer.style.marginBottom = 7;
|
||||
horizontalContainer.style.marginTop = 7;
|
||||
horizontalContainer.style.left = 10;
|
||||
horizontalContainer.style.right = 10;
|
||||
// Alternating background colors
|
||||
propertyContainer.style.backgroundColor = i % 2 == 0 ? new StyleColor(new Color(0.25f, 0.25f, 0.25f)) : new StyleColor(new Color(0.3f, 0.3f, 0.3f));
|
||||
|
||||
var sourcePropertyField = new Label(mapping.FindPropertyRelative("SourceProperty").stringValue)
|
||||
{
|
||||
style =
|
||||
{
|
||||
width = 200, unityFontStyleAndWeight = FontStyle.Bold, // Make the text bold
|
||||
unityTextAlign = TextAnchor.MiddleLeft
|
||||
}
|
||||
};
|
||||
horizontalContainer.Add(sourcePropertyField);
|
||||
|
||||
var targetPropertyField = new TextField
|
||||
{
|
||||
value = mapping.FindPropertyRelative("TargetProperty").stringValue,
|
||||
//style = { flexGrow = 1, marginTop = 5 }
|
||||
style = { width = 200, marginRight = 10, flexGrow = 0.8f }
|
||||
};
|
||||
targetPropertyField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
mapping.FindPropertyRelative("TargetProperty").stringValue = evt.newValue;
|
||||
Save();
|
||||
});
|
||||
horizontalContainer.Add(targetPropertyField);
|
||||
|
||||
var propertyTypeField = new EnumField((ShaderPropertyType) mapping.FindPropertyRelative("Type").enumValueIndex)
|
||||
{
|
||||
style = { width = 70, alignSelf = Align.FlexEnd }
|
||||
};
|
||||
propertyTypeField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
mapping.FindPropertyRelative("Type").enumValueIndex = (int) (ShaderPropertyType) evt.newValue;
|
||||
Save();
|
||||
});
|
||||
horizontalContainer.Add(propertyTypeField);
|
||||
propertyContainer.Add(horizontalContainer);
|
||||
shaderPropertiesContainer.Add(propertyContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupMorphTargets()
|
||||
{
|
||||
morphTargetLabels = AvatarMorphTarget.MorphTargetAvatarAPI.Select(x => new Label(x)).ToList();
|
||||
morphTargetsParentVisualElement = new Dictionary<VisualElement, string>();
|
||||
selectedMorphTargets = root.Q<VisualElement>("SelectedMorphTargets");
|
||||
|
||||
for (var i = 0; i < avatarConfigTarget.MorphTargets.Count; i++)
|
||||
{
|
||||
var defaultIndex = AvatarMorphTarget.MorphTargetAvatarAPI.IndexOf(avatarConfigTarget.MorphTargets[i]);
|
||||
CreateNewElement(defaultIndex);
|
||||
}
|
||||
|
||||
var addButton = root.Q<Button>("AddButton");
|
||||
addButton.clicked += OnAddButtonClicked;
|
||||
}
|
||||
|
||||
private void OnAddButtonClicked()
|
||||
{
|
||||
Undo.RecordObject(avatarConfigTarget, ADD_MORPH_TARGET);
|
||||
avatarConfigTarget.MorphTargets.Add(AvatarMorphTarget.MorphTargetAvatarAPI[0]);
|
||||
EditorUtility.SetDirty(avatarConfigTarget);
|
||||
CreateNewElement(0);
|
||||
}
|
||||
|
||||
private void CreateNewElement(int popFieldDefaultIndex)
|
||||
{
|
||||
var parent = new VisualElement();
|
||||
parent.style.flexDirection = new StyleEnum<FlexDirection>(FlexDirection.Row);
|
||||
parent.style.justifyContent = new StyleEnum<Justify>(Justify.SpaceBetween);
|
||||
|
||||
morphTargetsParentVisualElement.Add(parent, AvatarMorphTarget.MorphTargetAvatarAPI[popFieldDefaultIndex]);
|
||||
parent.Add(CreatePopupField(popFieldDefaultIndex, parent));
|
||||
parent.Add(CreateRemoveButton(parent));
|
||||
selectedMorphTargets.Add(parent);
|
||||
}
|
||||
|
||||
private PopupField<Label> CreatePopupField(int defaultIndex, VisualElement parent)
|
||||
{
|
||||
return new PopupField<Label>(string.Empty,
|
||||
morphTargetLabels,
|
||||
defaultIndex,
|
||||
x =>
|
||||
{
|
||||
avatarConfigTarget.MorphTargets[GetIndex(morphTargetsParentVisualElement[parent])] = x.text;
|
||||
morphTargetsParentVisualElement[parent] = x.text;
|
||||
return x.text;
|
||||
},
|
||||
x => x.text);
|
||||
}
|
||||
|
||||
private VisualElement CreateRemoveButton(VisualElement parent)
|
||||
{
|
||||
var removeButton = new Button(() =>
|
||||
{
|
||||
Undo.RecordObject(avatarConfigTarget, DELETE_MORPH_TARGET);
|
||||
avatarConfigTarget.MorphTargets.RemoveAt(GetIndex(morphTargetsParentVisualElement[parent]));
|
||||
selectedMorphTargets.Remove(parent);
|
||||
EditorUtility.SetDirty(avatarConfigTarget);
|
||||
});
|
||||
removeButton.text = REMOVE_BUTTON_TEXT;
|
||||
return removeButton;
|
||||
}
|
||||
|
||||
private int GetIndex(string morphTarget)
|
||||
{
|
||||
return avatarConfigTarget.MorphTargets.FindIndex(x => x == morphTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd70400e8b2b4c20bfe2f9bc47844cff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- visualTreeAsset: {fileID: 9197481963319205126, guid: 166ba78a57a90ca4abc5779ed8901042,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,22 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
|
||||
<uie:EnumField label="Lod" value="High" type="ReadyPlayerMe.Core.Lod, ReadyPlayerMe.Core" name="Lod" />
|
||||
<uie:EnumField label="Pose" value="APose" type="ReadyPlayerMe.Core.Pose, ReadyPlayerMe.Core" name="Pose" />
|
||||
<ui:Toggle label="Use Hands" name="UseHands" value="false" style="margin-left: 3px; height: 16px; margin-top: 3px;" />
|
||||
<uie:EnumField label="TextureAtlas" value="High" type="ReadyPlayerMe.Core.TextureAtlas, ReadyPlayerMe.Core" name="TextureAtlas" />
|
||||
<ui:SliderInt picking-mode="Ignore" label="TextureSizeLimit" value="0" high-value="1024" low-value="256" show-input-field="true" name="TextureSizeLimit" />
|
||||
<ui:Foldout text="Texture Channel" name="TextureChannel" value="false" style="flex-direction: column; margin-left: 4px; flex-grow: 0; margin-right: 4px; margin-top: 4px; align-items: stretch; justify-content: space-between; flex-shrink: 0;">
|
||||
<ui:ListView focusable="true" reorderable="true" show-border="true" show-alternating-row-backgrounds="All" style="height: auto; flex-shrink: 0; flex-grow: 0; justify-content: flex-start; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px;" />
|
||||
</ui:Foldout>
|
||||
<ui:VisualElement name="CustomShader" style="border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgba(113, 109, 109, 255); border-right-color: rgba(113, 109, 109, 255); border-top-color: rgba(113, 109, 109, 255); border-bottom-color: rgba(113, 109, 109, 255);">
|
||||
<uie:ObjectField label="Shader Override" type="UnityEngine.Shader, UnityEngine.CoreModule" name="ShaderOverride" />
|
||||
<ui:VisualElement name="ShaderProperties" style="flex-grow: 1; margin-left: 5px;" />
|
||||
</ui:VisualElement>
|
||||
<ui:Foldout text="Optimization Packages" name="OptimizationPackages" value="false" style="flex-shrink: 0; margin-top: 4px; margin-left: 4px; margin-right: 4px;">
|
||||
<ui:Toggle label="Use Draco Compression" name="UseDracoCompression" style="flex-direction: row; align-items: center; justify-content: flex-start; margin-left: 3px; margin-top: 3px;" />
|
||||
<ui:Toggle label="Use Mesh Opt Compression" name="UseMeshOptCompression" style="margin-left: 3px; margin-top: 3px; align-items: center; flex-direction: row; flex-grow: 0; flex-shrink: 0; flex-wrap: nowrap; position: relative; overflow: hidden; opacity: 1;" />
|
||||
</ui:Foldout>
|
||||
<ui:Foldout text="Morph Targets" name="MorphTargets" value="false" style="margin-left: 4px; margin-right: 4px; margin-top: 4px; margin-bottom: 1px;">
|
||||
<ui:VisualElement name="SelectedMorphTargets" style="flex-grow: 0; margin-top: 5px; -unity-text-outline-width: 0;" />
|
||||
<ui:Button text="Add" display-tooltip-when-elided="true" name="AddButton" style="margin-top: 5px;" />
|
||||
</ui:Foldout>
|
||||
</ui:UXML>
|
||||
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 166ba78a57a90ca4abc5779ed8901042
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
@ -0,0 +1,27 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
[CustomEditor(typeof(AvatarData))]
|
||||
public class AvatarDataEditor : UnityEditor.Editor
|
||||
{
|
||||
private SerializedProperty avatarIdProperty;
|
||||
private SerializedProperty avatarMetadataProperty;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
var avatarData = (AvatarData) target;
|
||||
|
||||
avatarIdProperty = serializedObject.FindProperty(nameof(avatarData.AvatarId));
|
||||
avatarMetadataProperty = serializedObject.FindProperty(nameof(avatarData.AvatarMetadata));
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.PropertyField(avatarIdProperty);
|
||||
EditorGUILayout.PropertyField(avatarMetadataProperty);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30e5b5d4cbc84b689f1b98490cc2a57b
|
||||
timeCreated: 1676906312
|
||||
@ -0,0 +1,46 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
[CustomEditor(typeof(EyeAnimationHandler))]
|
||||
public class EyeAnimationHandlerEditor : UnityEditor.Editor
|
||||
{
|
||||
private const string BLINK_DURATION = "blinkDuration";
|
||||
private const string BLINK_INTERVAL = "blinkInterval";
|
||||
private readonly GUIContent blinkSpeedLabel =
|
||||
new GUIContent("Blink Duration", "Effects the duration of the avatar blink animation in seconds.");
|
||||
|
||||
private readonly GUIContent blinkIntervalLabel =
|
||||
new GUIContent("Blink Interval", "Effects the amount of time in between each blink in seconds..");
|
||||
|
||||
private SerializedProperty blinkDuration;
|
||||
private SerializedProperty blinkInterval;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
DrawPropertyField(blinkDuration, blinkSpeedLabel);
|
||||
DrawPropertyField(blinkInterval, blinkIntervalLabel);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
blinkDuration = serializedObject.FindProperty(BLINK_DURATION);
|
||||
blinkInterval = serializedObject.FindProperty(BLINK_INTERVAL);
|
||||
}
|
||||
|
||||
private void DrawPropertyField(SerializedProperty property, GUIContent content)
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(property, content);
|
||||
if (EditorGUI.EndChangeCheck() && Application.isPlaying)
|
||||
{
|
||||
(target as EyeAnimationHandler)?.Initialize();
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02b38ee26065cb443adf628c0b8ded61
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,73 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
[CustomEditor(typeof(VoiceHandler))]
|
||||
public class VoiceHandlerEditor : UnityEditor.Editor
|
||||
{
|
||||
private const string AUDIO_CLIP = "AudioClip";
|
||||
private const string PROPERTY_PATH = "AudioSource";
|
||||
private const string AUDIO_SOURCE = PROPERTY_PATH;
|
||||
private const string AUDIO_PROVIDER = "AudioProvider";
|
||||
private const string MICROPHONE_IS_NOT_SUPPORTED_IN_WEBGL = "Microphone is not supported in WebGL.";
|
||||
private const string TEST_AUDIO_CLIP_PLAY_MODE = "Test Audio Clip [Play Mode]";
|
||||
private readonly GUIContent audioClipLabel = new GUIContent(AUDIO_CLIP, "AudioClip to play.");
|
||||
|
||||
private readonly GUIContent audioSourceLabel = new GUIContent(AUDIO_SOURCE,
|
||||
"AudioSource that will play the audio. If not assigned spawns on the avatar root object.");
|
||||
|
||||
private readonly GUIContent audioProviderLabel =
|
||||
new GUIContent(AUDIO_PROVIDER, "Selection for source of the audio.");
|
||||
|
||||
private SerializedProperty audioClip;
|
||||
private SerializedProperty audioSource;
|
||||
private SerializedProperty audioProvider;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
DrawPropertyField(audioProvider, audioProviderLabel);
|
||||
DrawPropertyField(audioSource, audioSourceLabel);
|
||||
|
||||
if (audioProvider.intValue == (int) AudioProviderType.AudioClip)
|
||||
{
|
||||
DrawPropertyField(audioClip, audioClipLabel);
|
||||
|
||||
GUI.enabled = Application.isPlaying;
|
||||
if (GUILayout.Button(TEST_AUDIO_CLIP_PLAY_MODE))
|
||||
{
|
||||
((VoiceHandler) target).PlayCurrentAudioClip();
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
#if UNITY_WEBGL
|
||||
if (audioProvider.intValue == (int) AudioProviderType.Microphone)
|
||||
{
|
||||
EditorGUILayout.HelpBox(MICROPHONE_IS_NOT_SUPPORTED_IN_WEBGL, MessageType.Warning);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
audioClip = serializedObject.FindProperty(AUDIO_CLIP);
|
||||
audioSource = serializedObject.FindProperty(AUDIO_SOURCE);
|
||||
audioProvider = serializedObject.FindProperty(AUDIO_PROVIDER);
|
||||
}
|
||||
|
||||
private void DrawPropertyField(SerializedProperty property, GUIContent content)
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(property, content);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
((VoiceHandler) target).InitializeAudio();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56f2c5f87e6c33748843fd099b9e2242
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd8d777b90a04f7ab091ca8efd1b0b63
|
||||
timeCreated: 1673349421
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bd53f8c2f141b74393738962a77da0f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,135 @@
|
||||
using ReadyPlayerMe.Core.Analytics;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
public class AvatarLoaderEditor : EditorWindow
|
||||
{
|
||||
private const string TAG = nameof(AvatarLoaderEditor);
|
||||
private const string AVATAR_LOADER = "Avatar Loader";
|
||||
private const string LOAD_AVATAR_BUTTON = "LoadAvatarButton";
|
||||
private const string HEADER_LABEL = "HeaderLabel";
|
||||
private const string USE_EYE_ANIMATIONS_TOGGLE = "UseEyeAnimationsToggle";
|
||||
private const string USE_VOICE_TO_ANIMATION_TOGGLE = "UseVoiceToAnimationToggle";
|
||||
|
||||
private const string VOICE_TO_ANIM_SAVE_KEY = "VoiceToAnimSaveKey";
|
||||
private const string EYE_ANIMATION_SAVE_KEY = "EyeAnimationSaveKey";
|
||||
private const string MODEL_CACHING_SAVE_KEY = "ModelCachingSaveKey";
|
||||
|
||||
[SerializeField] private VisualTreeAsset visualTreeAsset;
|
||||
|
||||
private double startTime;
|
||||
private AvatarLoaderSettings avatarLoaderSettings;
|
||||
|
||||
private bool useEyeAnimations;
|
||||
private bool useVoiceToAnim;
|
||||
|
||||
[MenuItem("Tools/Ready Player Me/Avatar Loader", priority = 1)]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
var window = GetWindow<AvatarLoaderEditor>();
|
||||
window.titleContent = new GUIContent(AVATAR_LOADER);
|
||||
window.minSize = new Vector2(500, 300);
|
||||
}
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
visualTreeAsset.CloneTree(rootVisualElement);
|
||||
|
||||
if (EditorPrefs.GetBool(MODEL_CACHING_SAVE_KEY)) EditorPrefs.SetBool(MODEL_CACHING_SAVE_KEY, false);
|
||||
|
||||
var headerLabel = rootVisualElement.Q<Label>(HEADER_LABEL);
|
||||
headerLabel.text = AVATAR_LOADER;
|
||||
|
||||
var useEyeAnimationsToggle = rootVisualElement.Q<Toggle>(USE_EYE_ANIMATIONS_TOGGLE);
|
||||
useEyeAnimations = EditorPrefs.GetBool(EYE_ANIMATION_SAVE_KEY);
|
||||
useEyeAnimationsToggle.value = useEyeAnimations;
|
||||
useEyeAnimationsToggle.RegisterCallback<ChangeEvent<bool>>(evt =>
|
||||
{
|
||||
useEyeAnimations = evt.newValue;
|
||||
EditorPrefs.SetBool(EYE_ANIMATION_SAVE_KEY, useEyeAnimations);
|
||||
});
|
||||
|
||||
var useVoiceToAnimToggle = rootVisualElement.Q<Toggle>(USE_VOICE_TO_ANIMATION_TOGGLE);
|
||||
useVoiceToAnim = EditorPrefs.GetBool(VOICE_TO_ANIM_SAVE_KEY);
|
||||
useVoiceToAnimToggle.value = useVoiceToAnim;
|
||||
useVoiceToAnimToggle.RegisterCallback<ChangeEvent<bool>>(evt =>
|
||||
{
|
||||
useVoiceToAnim = evt.newValue;
|
||||
EditorPrefs.SetBool(VOICE_TO_ANIM_SAVE_KEY, useVoiceToAnim);
|
||||
});
|
||||
|
||||
var avatarLoader = rootVisualElement.Q<Button>(LOAD_AVATAR_BUTTON);
|
||||
var urlField = rootVisualElement.Q<AvatarUrlTemplate>();
|
||||
|
||||
avatarLoader.clicked += () =>
|
||||
{
|
||||
if (urlField.TryGetUrl(out var url))
|
||||
{
|
||||
LoadAvatar(url);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void LoadAvatar(string url)
|
||||
{
|
||||
startTime = EditorApplication.timeSinceStartup;
|
||||
|
||||
AnalyticsEditorLogger.EventLogger.LogLoadAvatarFromDialog(url, useEyeAnimations, useVoiceToAnim);
|
||||
if (avatarLoaderSettings == null)
|
||||
{
|
||||
avatarLoaderSettings = AvatarLoaderSettings.LoadSettings();
|
||||
}
|
||||
var avatarLoader = new AvatarObjectLoader();
|
||||
avatarLoader.OnFailed += Failed;
|
||||
avatarLoader.OnCompleted += Completed;
|
||||
avatarLoader.OperationCompleted += OnOperationCompleted;
|
||||
if (avatarLoaderSettings != null)
|
||||
{
|
||||
avatarLoader.AvatarConfig = avatarLoaderSettings.AvatarConfig;
|
||||
if (avatarLoaderSettings.GLTFDeferAgent != null)
|
||||
{
|
||||
avatarLoader.GLTFDeferAgent = avatarLoaderSettings.GLTFDeferAgent;
|
||||
}
|
||||
}
|
||||
avatarLoader.LoadAvatar(url);
|
||||
}
|
||||
|
||||
private void OnOperationCompleted(object sender, IOperation<AvatarContext> e)
|
||||
{
|
||||
if (e.GetType() == typeof(MetadataDownloader))
|
||||
{
|
||||
AnalyticsEditorLogger.EventLogger.LogMetadataDownloaded(EditorApplication.timeSinceStartup - startTime);
|
||||
}
|
||||
}
|
||||
|
||||
private void Failed(object sender, FailureEventArgs args)
|
||||
{
|
||||
Debug.LogError($"{args.Type} - {args.Message}");
|
||||
}
|
||||
|
||||
private void Completed(object sender, CompletionEventArgs args)
|
||||
{
|
||||
AnalyticsEditorLogger.EventLogger.LogAvatarLoaded(EditorApplication.timeSinceStartup - startTime);
|
||||
|
||||
if (avatarLoaderSettings == null)
|
||||
{
|
||||
avatarLoaderSettings = AvatarLoaderSettings.LoadSettings();
|
||||
}
|
||||
var paramHash = AvatarCache.GetAvatarConfigurationHash(avatarLoaderSettings.AvatarConfig);
|
||||
var path = $"{DirectoryUtility.GetRelativeProjectPath(args.Avatar.name, paramHash)}/{args.Avatar.name}";
|
||||
if (!avatarLoaderSettings.AvatarCachingEnabled)
|
||||
{
|
||||
SDKLogger.LogWarning(TAG, "Enable Avatar Caching to generate a prefab in the project folder.");
|
||||
return;
|
||||
}
|
||||
var avatar = PrefabHelper.CreateAvatarPrefab(args.Metadata, path, avatarConfig: avatarLoaderSettings.AvatarConfig);
|
||||
if (useEyeAnimations) avatar.AddComponent<EyeAnimationHandler>();
|
||||
if (useVoiceToAnim) avatar.AddComponent<VoiceHandler>();
|
||||
DestroyImmediate(args.Avatar, true);
|
||||
Selection.activeObject = avatar;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42d4f7af0c237ce4b962a3966fcde2ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_ViewDataDictionary: {instanceID: 0}
|
||||
- visualTreeAsset: {fileID: 9197481963319205126, guid: 9c9fb1a8c3e120d42b59955126dc5cc1,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,14 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
||||
<ui:Template name="HeaderTemplate" src="../Templates/HeaderTemplate.uxml" />
|
||||
<Style src="../CommonStyle.uss" />
|
||||
<ui:VisualElement name="ContentWrapper" style="align-items: center; width: 500px; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: auto;">
|
||||
<ui:Instance template="HeaderTemplate" name="HeaderTemplate" style="flex-shrink: 0;" />
|
||||
<ReadyPlayerMe.Core.Editor.AvatarUrlTemplate style="flex-shrink: 0; width: 500px;" />
|
||||
<ui:VisualElement name="Extras" style="flex-shrink: 0; flex-direction: column; align-items: flex-start; justify-content: flex-start; align-self: stretch;">
|
||||
<ui:Label text="Extras" display-tooltip-when-elided="true" class="headingText" />
|
||||
<ui:Toggle label="Use Eye Animations" name="UseEyeAnimationsToggle" style="flex-direction: row-reverse; margin-left: 15px; margin-top: 10px;" />
|
||||
<ui:Toggle label="Use Voice To Animation" name="UseVoiceToAnimationToggle" style="flex-direction: row-reverse; margin-left: 15px; margin-top: 10px;" />
|
||||
</ui:VisualElement>
|
||||
<ui:Button text="Load Avatar into the Current Scene" display-tooltip-when-elided="true" name="LoadAvatarButton" style="margin-top: 10px; margin-left: 15px; margin-right: 15px; font-size: 16px; -unity-font-style: bold; height: 30px; -unity-text-align: middle-center; white-space: nowrap; margin-bottom: 10px; width: 470px;" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c9fb1a8c3e120d42b59955126dc5cc1
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
@ -0,0 +1,56 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
public static class AvatarLoaderSettingsHelper
|
||||
{
|
||||
public static AvatarLoaderSettings AvatarLoaderSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
if (avatarLoaderSettings == null)
|
||||
{
|
||||
avatarLoaderSettings = AvatarLoaderSettings.LoadSettings();
|
||||
}
|
||||
|
||||
return avatarLoaderSettings;
|
||||
}
|
||||
}
|
||||
|
||||
private static AvatarLoaderSettings avatarLoaderSettings;
|
||||
|
||||
public static void SaveAvatarConfig(AvatarConfig avatarConfig)
|
||||
{
|
||||
if (avatarLoaderSettings != null && avatarLoaderSettings.AvatarConfig != avatarConfig)
|
||||
{
|
||||
avatarLoaderSettings.AvatarConfig = avatarConfig;
|
||||
SaveAvatarLoaderSettings();
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveDeferAgent(GLTFDeferAgent deferAgent)
|
||||
{
|
||||
if (avatarLoaderSettings != null && avatarLoaderSettings.GLTFDeferAgent != deferAgent)
|
||||
{
|
||||
avatarLoaderSettings.GLTFDeferAgent = deferAgent;
|
||||
SaveAvatarLoaderSettings();
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetAvatarCaching(bool enable)
|
||||
{
|
||||
if (avatarLoaderSettings != null)
|
||||
{
|
||||
avatarLoaderSettings.AvatarCachingEnabled = enable;
|
||||
SaveAvatarLoaderSettings();
|
||||
}
|
||||
}
|
||||
|
||||
private static void SaveAvatarLoaderSettings()
|
||||
{
|
||||
EditorUtility.SetDirty(avatarLoaderSettings);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e9df9df699f4bb09c162c7948503583
|
||||
timeCreated: 1686078044
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e97a78112f684e40ad730948b73896b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace ReadyPlayerMe.Core.Editor
|
||||
{
|
||||
public class BreakingChangeDialog : EditorWindow
|
||||
{
|
||||
private const string MIGRATION_GUIDE_URL = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity/troubleshooting/updating-from-earlier-versions";
|
||||
private const string TITLE = "Update Packages";
|
||||
|
||||
[SerializeField] private VisualTreeAsset visualTreeAsset;
|
||||
|
||||
private static Action updateClicked;
|
||||
|
||||
public static void ShowDialog(Action onUpdate)
|
||||
{
|
||||
updateClicked = onUpdate;
|
||||
|
||||
var window = GetWindow<BreakingChangeDialog>();
|
||||
window.titleContent = new GUIContent(TITLE);
|
||||
window.minSize = new Vector2(500, 140);
|
||||
window.maxSize = new Vector2(500, 140);
|
||||
window.ShowModalUtility();
|
||||
}
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
visualTreeAsset.CloneTree(rootVisualElement);
|
||||
|
||||
var migrationLink = rootVisualElement.Q<Label>("MigrationLink");
|
||||
migrationLink.RegisterCallback<MouseUpEvent>(x =>
|
||||
{
|
||||
Application.OpenURL(MIGRATION_GUIDE_URL);
|
||||
});
|
||||
|
||||
rootVisualElement.Q<Button>("UpdateButton").clicked += () =>
|
||||
{
|
||||
updateClicked?.Invoke();
|
||||
Close();
|
||||
};
|
||||
|
||||
rootVisualElement.Q<Button>("CancelButton").clicked += Close;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a33436e71dc6be2449976c3e84fa2b80
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_ViewDataDictionary: {instanceID: 0}
|
||||
- visualTreeAsset: {fileID: 9197481963319205126, guid: 26fd6ad3d3a5b8b40b21885331e8c518,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user