fileFormatVersion: 2 | |||||
guid: 7232873a97408ef4fbf8e655841e61ed | |||||
folderAsset: yes | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 9ceea87507dde1e4e9f4d2f9b3218898 | |||||
folderAsset: yes | |||||
timeCreated: 1521506758 | |||||
licenseType: Pro | |||||
DefaultImporter: | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: c3215fde7fc71504fb3b192b10dbf263 | |||||
folderAsset: yes | |||||
timeCreated: 1521506802 | |||||
licenseType: Pro | |||||
DefaultImporter: | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 3bb6d22e89000724b90fb830af69384b | |||||
timeCreated: 1480638879 | |||||
licenseType: Free | |||||
PluginImporter: | |||||
serializedVersion: 2 | |||||
iconMap: {} | |||||
executionOrder: {} | |||||
isPreloaded: 0 | |||||
isOverridable: 0 | |||||
platformData: | |||||
data: | |||||
first: | |||||
'': Any | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
Exclude Android: 1 | |||||
Exclude Editor: 0 | |||||
Exclude Linux: 0 | |||||
Exclude Linux64: 0 | |||||
Exclude LinuxUniversal: 0 | |||||
Exclude OSXIntel: 0 | |||||
Exclude OSXIntel64: 0 | |||||
Exclude OSXUniversal: 0 | |||||
Exclude Tizen: 1 | |||||
Exclude WebGL: 1 | |||||
Exclude Win: 1 | |||||
Exclude Win64: 0 | |||||
data: | |||||
first: | |||||
'': Editor | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: AnyCPU | |||||
OS: AnyOS | |||||
data: | |||||
first: | |||||
Android: Android | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: ARMv7 | |||||
data: | |||||
first: | |||||
Any: | |||||
second: | |||||
enabled: 0 | |||||
settings: {} | |||||
data: | |||||
first: | |||||
Editor: Editor | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: x86_64 | |||||
DefaultValueInitialized: true | |||||
data: | |||||
first: | |||||
Facebook: Win | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: None | |||||
data: | |||||
first: | |||||
Facebook: Win64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Standalone: Linux | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: None | |||||
data: | |||||
first: | |||||
Standalone: Linux64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: x86_64 | |||||
data: | |||||
first: | |||||
Standalone: LinuxUniversal | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Standalone: OSXIntel | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: None | |||||
data: | |||||
first: | |||||
Standalone: OSXIntel64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Standalone: OSXUniversal | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Standalone: Win | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: None | |||||
data: | |||||
first: | |||||
Standalone: Win64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Tizen: Tizen | |||||
second: | |||||
enabled: 0 | |||||
settings: {} | |||||
data: | |||||
first: | |||||
WebGL: WebGL | |||||
second: | |||||
enabled: 0 | |||||
settings: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 40895a3d0d3ec475c8ff555d0c40f7cb | |||||
folderAsset: yes | |||||
DefaultImporter: | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 23868bd667cf64b479fbd8d1039e2cd2 | |||||
folderAsset: yes | |||||
timeCreated: 1448340266 | |||||
licenseType: Free | |||||
DefaultImporter: | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 1d2c94db16e356840a089b257eb5d536 | |||||
folderAsset: yes | |||||
timeCreated: 1480638868 | |||||
licenseType: Free | |||||
DefaultImporter: | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 820ee6e459999be418b410c7af108bc3 | |||||
timeCreated: 1480638870 | |||||
licenseType: Free | |||||
PluginImporter: | |||||
serializedVersion: 1 | |||||
iconMap: {} | |||||
executionOrder: {} | |||||
isPreloaded: 0 | |||||
platformData: | |||||
Any: | |||||
enabled: 1 | |||||
settings: {} | |||||
Editor: | |||||
enabled: 0 | |||||
settings: | |||||
DefaultValueInitialized: true | |||||
WindowsStoreApps: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: AnyCPU | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: aecaffc7454b52e448fc0ea1aef2dd1d | |||||
timeCreated: 1480638874 | |||||
licenseType: Free | |||||
PluginImporter: | |||||
serializedVersion: 1 | |||||
iconMap: {} | |||||
executionOrder: {} | |||||
isPreloaded: 0 | |||||
platformData: | |||||
Any: | |||||
enabled: 1 | |||||
settings: {} | |||||
Editor: | |||||
enabled: 0 | |||||
settings: | |||||
DefaultValueInitialized: true | |||||
WindowsStoreApps: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: AnyCPU | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: d4055bfc0cd67d642a7eceaf547c4901 | |||||
timeCreated: 1480638876 | |||||
licenseType: Free | |||||
PluginImporter: | |||||
serializedVersion: 1 | |||||
iconMap: {} | |||||
executionOrder: {} | |||||
isPreloaded: 0 | |||||
platformData: | |||||
Any: | |||||
enabled: 1 | |||||
settings: {} | |||||
Editor: | |||||
enabled: 0 | |||||
settings: | |||||
DefaultValueInitialized: true | |||||
WindowsStoreApps: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: AnyCPU | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 625a50dd0dd525a49a41cb3e3117fa15 | |||||
timeCreated: 1480638869 | |||||
licenseType: Free | |||||
PluginImporter: | |||||
serializedVersion: 1 | |||||
iconMap: {} | |||||
executionOrder: {} | |||||
isPreloaded: 0 | |||||
platformData: | |||||
Any: | |||||
enabled: 1 | |||||
settings: {} | |||||
Editor: | |||||
enabled: 0 | |||||
settings: | |||||
DefaultValueInitialized: true | |||||
WindowsStoreApps: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: AnyCPU | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 3a71aca790a5f774e9b2c6802399180d | |||||
folderAsset: yes | |||||
timeCreated: 1499820116 | |||||
licenseType: Free | |||||
DefaultImporter: | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 34b0990e1522a284b9666d6821cd601c | |||||
timeCreated: 1499845244 | |||||
licenseType: Free | |||||
PluginImporter: | |||||
serializedVersion: 2 | |||||
iconMap: {} | |||||
executionOrder: {} | |||||
isPreloaded: 0 | |||||
isOverridable: 0 | |||||
platformData: | |||||
data: | |||||
first: | |||||
'': Any | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
Exclude Android: 1 | |||||
Exclude Editor: 0 | |||||
Exclude Linux: 0 | |||||
Exclude Linux64: 0 | |||||
Exclude LinuxUniversal: 0 | |||||
Exclude OSXIntel: 0 | |||||
Exclude OSXIntel64: 0 | |||||
Exclude OSXUniversal: 0 | |||||
Exclude Win: 0 | |||||
Exclude Win64: 0 | |||||
data: | |||||
first: | |||||
'': Editor | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: AnyCPU | |||||
OS: AnyOS | |||||
data: | |||||
first: | |||||
Android: Android | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: ARMv7 | |||||
data: | |||||
first: | |||||
Any: | |||||
second: | |||||
enabled: 1 | |||||
settings: {} | |||||
data: | |||||
first: | |||||
Editor: Editor | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
DefaultValueInitialized: true | |||||
data: | |||||
first: | |||||
Facebook: Win | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Facebook: Win64 | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Standalone: Linux | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: x86 | |||||
data: | |||||
first: | |||||
Standalone: Linux64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: x86_64 | |||||
data: | |||||
first: | |||||
Standalone: LinuxUniversal | |||||
second: | |||||
enabled: 1 | |||||
settings: {} | |||||
data: | |||||
first: | |||||
Standalone: OSXIntel | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Standalone: OSXIntel64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Standalone: OSXUniversal | |||||
second: | |||||
enabled: 1 | |||||
settings: {} | |||||
data: | |||||
first: | |||||
Standalone: Win | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Standalone: Win64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Windows Store Apps: WindowsStoreApps | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: AnyCPU | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: ecaca62aaec760a4dbd18ddd39d3d81b | |||||
folderAsset: yes | |||||
timeCreated: 1499820171 | |||||
licenseType: Free | |||||
DefaultImporter: | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 94693a1781c168a47a2a3ef863992cd8 | |||||
folderAsset: yes | |||||
timeCreated: 1499820184 | |||||
licenseType: Free | |||||
DefaultImporter: | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: b609c54f9d3581e4fa22b3e389fd8d33 | |||||
timeCreated: 1499820240 | |||||
licenseType: Free | |||||
PluginImporter: | |||||
serializedVersion: 2 | |||||
iconMap: {} | |||||
executionOrder: {} | |||||
isPreloaded: 0 | |||||
isOverridable: 0 | |||||
platformData: | |||||
data: | |||||
first: | |||||
'': Any | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
Exclude Android: 1 | |||||
Exclude Editor: 0 | |||||
Exclude Linux: 0 | |||||
Exclude Linux64: 0 | |||||
Exclude LinuxUniversal: 0 | |||||
Exclude OSXIntel: 0 | |||||
Exclude OSXIntel64: 0 | |||||
Exclude OSXUniversal: 0 | |||||
Exclude Win: 0 | |||||
Exclude Win64: 0 | |||||
data: | |||||
first: | |||||
Any: | |||||
second: | |||||
enabled: 1 | |||||
settings: {} | |||||
data: | |||||
first: | |||||
Editor: Editor | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: x86 | |||||
DefaultValueInitialized: true | |||||
data: | |||||
first: | |||||
Facebook: Win | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Facebook: Win64 | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: None | |||||
data: | |||||
first: | |||||
Standalone: Linux | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: x86 | |||||
data: | |||||
first: | |||||
Standalone: Linux64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: None | |||||
data: | |||||
first: | |||||
Standalone: LinuxUniversal | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: x86 | |||||
data: | |||||
first: | |||||
Standalone: OSXIntel | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Standalone: OSXIntel64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: None | |||||
data: | |||||
first: | |||||
Standalone: OSXUniversal | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: x86 | |||||
data: | |||||
first: | |||||
Standalone: Win | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Standalone: Win64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: None | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 318c96e9cf64fb44a8aeb0f088e53f96 | |||||
folderAsset: yes | |||||
timeCreated: 1499820192 | |||||
licenseType: Free | |||||
DefaultImporter: | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 54f59547b5261e64f8256d6daaa01b17 | |||||
timeCreated: 1499820211 | |||||
licenseType: Free | |||||
PluginImporter: | |||||
serializedVersion: 2 | |||||
iconMap: {} | |||||
executionOrder: {} | |||||
isPreloaded: 0 | |||||
isOverridable: 0 | |||||
platformData: | |||||
data: | |||||
first: | |||||
'': Any | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
Exclude Android: 1 | |||||
Exclude Editor: 0 | |||||
Exclude Linux: 0 | |||||
Exclude Linux64: 0 | |||||
Exclude LinuxUniversal: 0 | |||||
Exclude OSXIntel: 0 | |||||
Exclude OSXIntel64: 0 | |||||
Exclude OSXUniversal: 0 | |||||
Exclude Win: 0 | |||||
Exclude Win64: 0 | |||||
data: | |||||
first: | |||||
Any: | |||||
second: | |||||
enabled: 1 | |||||
settings: {} | |||||
data: | |||||
first: | |||||
Editor: Editor | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: x86_64 | |||||
DefaultValueInitialized: true | |||||
data: | |||||
first: | |||||
Facebook: Win | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: None | |||||
data: | |||||
first: | |||||
Facebook: Win64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Standalone: Linux | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: None | |||||
data: | |||||
first: | |||||
Standalone: Linux64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: x86_64 | |||||
data: | |||||
first: | |||||
Standalone: LinuxUniversal | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: x86_64 | |||||
data: | |||||
first: | |||||
Standalone: OSXIntel | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: None | |||||
data: | |||||
first: | |||||
Standalone: OSXIntel64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
data: | |||||
first: | |||||
Standalone: OSXUniversal | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: x86_64 | |||||
data: | |||||
first: | |||||
Standalone: Win | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: None | |||||
data: | |||||
first: | |||||
Standalone: Win64 | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
CPU: AnyCPU | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 99a3cc965a6419644b54113eb9983bd0 | |||||
folderAsset: yes | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 63a46438a8152c74c980a66bfaf7b61c | |||||
folderAsset: yes | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 574563b688a5ed54b978ae8718c2194d | |||||
folderAsset: yes | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
/************************************************************************************ | |||||
Filename : ONSPAudioSourceEditor.cs | |||||
Content : This script adds editor functionality to OculusSpatializerUserParams script. | |||||
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved. | |||||
Licensed under the Oculus SDK Version 3.5 (the "License"); | |||||
you may not use the Oculus SDK except in compliance with the License, | |||||
which is provided at the time of installation or download, or which | |||||
otherwise accompanies this software in either electronic or hard copy form. | |||||
You may obtain a copy of the License at | |||||
https://developer.oculus.com/licenses/sdk-3.5/ | |||||
Unless required by applicable law or agreed to in writing, the Oculus SDK | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
************************************************************************************/ | |||||
#define CUSTOM_LAYOUT | |||||
using UnityEditor; | |||||
using UnityEngine; | |||||
using System.Collections.Generic; | |||||
[CustomEditor(typeof(ONSPAudioSource))] | |||||
public class OculusSpatializerUserParamsEditor : Editor | |||||
{ | |||||
// target component | |||||
private ONSPAudioSource m_Component; | |||||
// OnEnable | |||||
void OnEnable() | |||||
{ | |||||
m_Component = (ONSPAudioSource)target; | |||||
} | |||||
// OnInspectorGUI | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
GUI.color = Color.white; | |||||
Undo.RecordObject(m_Component, "OculusSpatializerUserParams"); | |||||
{ | |||||
EditorGUILayout.HelpBox("Please use a VRC_SpatialAudioSource in the future.", MessageType.Error); | |||||
#if CUSTOM_LAYOUT | |||||
m_Component.EnableSpatialization = EditorGUILayout.Toggle("Spatialization Enabled", m_Component.EnableSpatialization); | |||||
m_Component.EnableRfl = EditorGUILayout.Toggle("Reflections Enabled", m_Component.EnableRfl); | |||||
m_Component.Gain = EditorGUILayout.FloatField("Gain", m_Component.Gain); | |||||
Separator(); | |||||
Label ("OCULUS ATTENUATION"); | |||||
m_Component.UseInvSqr = EditorGUILayout.Toggle("Enabled", m_Component.UseInvSqr); | |||||
Label (""); | |||||
Label("RANGE (0.0 - 1000000.0 meters)"); | |||||
m_Component.Near = EditorGUILayout.FloatField("Minimum", m_Component.Near); | |||||
m_Component.Far = EditorGUILayout.FloatField("Maximum", m_Component.Far); | |||||
Label(""); | |||||
Label("VOLUMETRIC RADIUS (0.0 - 1000.0 meters)"); | |||||
m_Component.VolumetricRadius = EditorGUILayout.FloatField("Radius", m_Component.VolumetricRadius); | |||||
Separator(); | |||||
Label("REVERB SEND LEVEL (-60.0 - 20.0 decibels)"); | |||||
m_Component.ReverbSend = EditorGUILayout.FloatField(" ", m_Component.ReverbSend); | |||||
Separator(); | |||||
#else | |||||
DrawDefaultInspector (); | |||||
#endif | |||||
} | |||||
if (GUI.changed) | |||||
{ | |||||
EditorUtility.SetDirty(m_Component); | |||||
} | |||||
} | |||||
// Utilities, move out of here (or copy over to other editor script) | |||||
// Separator | |||||
void Separator() | |||||
{ | |||||
GUI.color = new Color(1, 1, 1, 0.25f); | |||||
GUILayout.Box("", "HorizontalSlider", GUILayout.Height(16)); | |||||
GUI.color = Color.white; | |||||
} | |||||
// Label | |||||
void Label(string label) | |||||
{ | |||||
EditorGUILayout.LabelField (label); | |||||
} | |||||
} | |||||
fileFormatVersion: 2 | |||||
guid: cb850b86de9091d4db4595959c56f954 | |||||
timeCreated: 1442269815 | |||||
licenseType: Pro | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: d082e53096d08f441bc71078ece58e73 | |||||
folderAsset: yes | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
/************************************************************************************ | |||||
Filename : ONSPAudioSource.cs | |||||
Content : Interface into the Oculus Native Spatializer Plugin | |||||
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved. | |||||
Licensed under the Oculus SDK Version 3.5 (the "License"); | |||||
you may not use the Oculus SDK except in compliance with the License, | |||||
which is provided at the time of installation or download, or which | |||||
otherwise accompanies this software in either electronic or hard copy form. | |||||
You may obtain a copy of the License at | |||||
https://developer.oculus.com/licenses/sdk-3.5/ | |||||
Unless required by applicable law or agreed to in writing, the Oculus SDK | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
************************************************************************************/ | |||||
// Uncomment below to test access of read-only spatializer parameters | |||||
//#define TEST_READONLY_PARAMETERS | |||||
using UnityEngine; | |||||
using System; | |||||
using System.Collections; | |||||
using System.Runtime.InteropServices; | |||||
public class ONSPAudioSource : MonoBehaviour | |||||
{ | |||||
#if TEST_READONLY_PARAMETERS | |||||
// Spatializer read-only system parameters (global) | |||||
static int readOnly_GlobalRelectionOn = 8; | |||||
static int readOnly_NumberOfUsedSpatializedVoices = 9; | |||||
#endif | |||||
// Import functions | |||||
public const string strONSPS = "AudioPluginOculusSpatializer"; | |||||
[DllImport(strONSPS)] | |||||
private static extern void ONSP_GetGlobalRoomReflectionValues(ref bool reflOn, ref bool reverbOn, | |||||
ref float width, ref float height, ref float length); | |||||
// Public | |||||
[SerializeField] | |||||
private bool enableSpatialization = true; | |||||
public bool EnableSpatialization | |||||
{ | |||||
get | |||||
{ | |||||
return enableSpatialization; | |||||
} | |||||
set | |||||
{ | |||||
enableSpatialization = value; | |||||
} | |||||
} | |||||
[SerializeField] | |||||
private float gain = 0.0f; | |||||
public float Gain | |||||
{ | |||||
get | |||||
{ | |||||
return gain; | |||||
} | |||||
set | |||||
{ | |||||
gain = Mathf.Clamp(value, 0.0f, 24.0f); | |||||
} | |||||
} | |||||
[SerializeField] | |||||
private bool useInvSqr = false; | |||||
public bool UseInvSqr | |||||
{ | |||||
get | |||||
{ | |||||
return useInvSqr; | |||||
} | |||||
set | |||||
{ | |||||
useInvSqr = value; | |||||
} | |||||
} | |||||
[SerializeField] | |||||
private float near = 0.25f; | |||||
public float Near | |||||
{ | |||||
get | |||||
{ | |||||
return near; | |||||
} | |||||
set | |||||
{ | |||||
near = Mathf.Clamp(value, 0.0f, 1000000.0f); | |||||
} | |||||
} | |||||
[SerializeField] | |||||
private float far = 250.0f; | |||||
public float Far | |||||
{ | |||||
get | |||||
{ | |||||
return far; | |||||
} | |||||
set | |||||
{ | |||||
far = Mathf.Clamp(value, 0.0f, 1000000.0f); | |||||
} | |||||
} | |||||
[SerializeField] | |||||
private float volumetricRadius = 0.0f; | |||||
public float VolumetricRadius | |||||
{ | |||||
get | |||||
{ | |||||
return volumetricRadius; | |||||
} | |||||
set | |||||
{ | |||||
volumetricRadius = Mathf.Clamp(value, 0.0f, 1000.0f); | |||||
} | |||||
} | |||||
[SerializeField] | |||||
private float reverbSend = 0.0f; | |||||
public float ReverbSend | |||||
{ | |||||
get | |||||
{ | |||||
return reverbSend; | |||||
} | |||||
set | |||||
{ | |||||
reverbSend = Mathf.Clamp(value, -60.0f, 20.0f); | |||||
} | |||||
} | |||||
[SerializeField] | |||||
private bool enableRfl = false; | |||||
public bool EnableRfl | |||||
{ | |||||
get | |||||
{ | |||||
return enableRfl; | |||||
} | |||||
set | |||||
{ | |||||
enableRfl = value; | |||||
} | |||||
} | |||||
/// VRCHAT: We need to reset the params after avatar loading and viseme setup | |||||
public void Reset() | |||||
{ | |||||
var source = GetComponent<AudioSource>(); | |||||
if(source == null) | |||||
{ | |||||
enabled = false; | |||||
return; | |||||
} | |||||
SetParameters(ref source); | |||||
} | |||||
/// <summary> | |||||
/// Awake this instance. | |||||
/// </summary> | |||||
void Awake() | |||||
{ | |||||
Reset(); | |||||
} | |||||
/// <summary> | |||||
/// Start this instance. | |||||
/// </summary> | |||||
void Start() | |||||
{ | |||||
#if VRC_CLIENT | |||||
var source = GetComponent<AudioSource>(); | |||||
if(source != null && source.outputAudioMixerGroup != VRCAudioManager.GetAvatarGroup()) | |||||
VRCAudioManager.ApplyGameAudioMixerSettings(source); | |||||
#endif | |||||
} | |||||
/// <summary> | |||||
/// Update this instance. | |||||
/// </summary> | |||||
void LateUpdate() | |||||
{ | |||||
// We might iterate through multiple sources / game object | |||||
var source = GetComponent<AudioSource>(); | |||||
if(source == null) | |||||
{ | |||||
enabled = false; | |||||
return; | |||||
} | |||||
// READ-ONLY PARAMETER TEST | |||||
#if TEST_READONLY_PARAMETERS | |||||
float rfl_enabled = 0.0f; | |||||
source.GetSpatializerFloat(readOnly_GlobalRelectionOn, out rfl_enabled); | |||||
float num_voices = 0.0f; | |||||
source.GetSpatializerFloat(readOnly_NumberOfUsedSpatializedVoices, out num_voices); | |||||
String readOnly = System.String.Format | |||||
("Read only values: refl enabled: {0:F0} num voices: {1:F0}", rfl_enabled, num_voices); | |||||
Debug.Log(readOnly); | |||||
#endif | |||||
// Check to see if we should disable spatializion | |||||
if ((Application.isPlaying == false) || | |||||
(AudioListener.pause == true) || | |||||
(source.isPlaying == false) || | |||||
(source.isActiveAndEnabled == false) | |||||
) | |||||
{ | |||||
source.spatialize = false; | |||||
return; | |||||
} | |||||
else | |||||
{ | |||||
SetParameters(ref source); | |||||
} | |||||
} | |||||
enum Parameters : int | |||||
{ | |||||
P_GAIN = 0, | |||||
P_USEINVSQR, | |||||
P_NEAR, | |||||
P_FAR, | |||||
P_RADIUS, | |||||
P_DISABLE_RFL, | |||||
P_VSPEAKERMODE, | |||||
P_AMBISTAT, | |||||
P_READONLY_GLOBAL_RFL_ENABLED, // READ-ONLY | |||||
P_READONLY_NUM_VOICES, // READ-ONLY | |||||
P_SENDLEVEL, | |||||
P_NUM | |||||
}; | |||||
/// <summary> | |||||
/// Sets the parameters. | |||||
/// </summary> | |||||
/// <param name="source">Source.</param> | |||||
public void SetParameters(ref AudioSource source) | |||||
{ | |||||
// VRCHAT: indentation is weird intentionally, for easier diff | |||||
// jnuccio: added try here to catch unknown exception reported in analytics | |||||
try | |||||
{ | |||||
if (source == null) | |||||
return; | |||||
// See if we should enable spatialization | |||||
source.spatialize = enableSpatialization; | |||||
source.SetSpatializerFloat((int)Parameters.P_GAIN, gain); | |||||
// All inputs are floats; convert bool to 0.0 and 1.0 | |||||
if(useInvSqr == true) | |||||
source.SetSpatializerFloat((int)Parameters.P_USEINVSQR, 1.0f); | |||||
else | |||||
source.SetSpatializerFloat((int)Parameters.P_USEINVSQR, 0.0f); | |||||
source.SetSpatializerFloat((int)Parameters.P_NEAR, near); | |||||
source.SetSpatializerFloat((int)Parameters.P_FAR, far); | |||||
source.SetSpatializerFloat((int)Parameters.P_RADIUS, volumetricRadius); | |||||
if(enableRfl == true) | |||||
source.SetSpatializerFloat((int)Parameters.P_DISABLE_RFL, 0.0f); | |||||
else | |||||
source.SetSpatializerFloat((int)Parameters.P_DISABLE_RFL, 1.0f); | |||||
source.SetSpatializerFloat((int)Parameters.P_SENDLEVEL, reverbSend); | |||||
// VRCHAT: indentation is weird intentionally, for easier diff | |||||
} | |||||
catch (Exception) | |||||
{ | |||||
// not sure why this throws sometimes | |||||
} | |||||
} | |||||
private static ONSPAudioSource RoomReflectionGizmoAS = null; | |||||
/// <summary> | |||||
/// | |||||
/// </summary> | |||||
void OnDrawGizmos() | |||||
{ | |||||
// Are we the first one created? make sure to set our static ONSPAudioSource | |||||
// for drawing out room parameters once | |||||
if(RoomReflectionGizmoAS == null) | |||||
{ | |||||
RoomReflectionGizmoAS = this; | |||||
} | |||||
Color c; | |||||
const float colorSolidAlpha = 0.1f; | |||||
// Draw the near/far spheres | |||||
// Near (orange) | |||||
c.r = 1.0f; | |||||
c.g = 0.5f; | |||||
c.b = 0.0f; | |||||
c.a = 1.0f; | |||||
Gizmos.color = c; | |||||
Gizmos.DrawWireSphere(transform.position, Near); | |||||
c.a = colorSolidAlpha; | |||||
Gizmos.color = c; | |||||
Gizmos.DrawSphere(transform.position, Near); | |||||
// Far (red) | |||||
c.r = 1.0f; | |||||
c.g = 0.0f; | |||||
c.b = 0.0f; | |||||
c.a = 1.0f; | |||||
Gizmos.color = Color.red; | |||||
Gizmos.DrawWireSphere(transform.position, Far); | |||||
c.a = colorSolidAlpha; | |||||
Gizmos.color = c; | |||||
Gizmos.DrawSphere(transform.position, Far); | |||||
// VolumetricRadius (purple) | |||||
c.r = 1.0f; | |||||
c.g = 0.0f; | |||||
c.b = 1.0f; | |||||
c.a = 1.0f; | |||||
Gizmos.color = c; | |||||
Gizmos.DrawWireSphere(transform.position, VolumetricRadius); | |||||
c.a = colorSolidAlpha; | |||||
Gizmos.color = c; | |||||
Gizmos.DrawSphere(transform.position, VolumetricRadius); | |||||
// Draw room parameters ONCE only, provided reflection engine is on | |||||
if (RoomReflectionGizmoAS == this) | |||||
{ | |||||
// Get global room parameters (write new C api to get reflection values) | |||||
bool reflOn = false; | |||||
bool reverbOn = false; | |||||
float width = 1.0f; | |||||
float height = 1.0f; | |||||
float length = 1.0f; | |||||
ONSP_GetGlobalRoomReflectionValues(ref reflOn, ref reverbOn, ref width, ref height, ref length); | |||||
// TO DO: Get the room reflection values and render those out as well (like we do in the VST) | |||||
if((Camera.main != null) && (reflOn == true)) | |||||
{ | |||||
// Set color of cube (cyan is early reflections only, white is with reverb on) | |||||
if(reverbOn == true) | |||||
c = Color.white; | |||||
else | |||||
c = Color.cyan; | |||||
Gizmos.color = c; | |||||
Gizmos.DrawWireCube(Camera.main.transform.position, new Vector3(width, height, length)); | |||||
c.a = colorSolidAlpha; | |||||
Gizmos.color = c; | |||||
Gizmos.DrawCube(Camera.main.transform.position, new Vector3(width, height, length)); | |||||
} | |||||
} | |||||
} | |||||
/// <summary> | |||||
/// | |||||
/// </summary> | |||||
void OnDestroy() | |||||
{ | |||||
// We will null out single pointer instance | |||||
// of the room reflection gizmo since we are being destroyed. | |||||
// Any ONSPAS that is alive or born will re-set this pointer | |||||
// so that we only draw it once | |||||
if(RoomReflectionGizmoAS == this) | |||||
{ | |||||
RoomReflectionGizmoAS = null; | |||||
} | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: e503ea6418d27594caa33b93cac1b06a | |||||
MonoImporter: | |||||
externalObjects: {} | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 1 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: e86b1ecf748c17744a6a94f8ee6f50ba | |||||
folderAsset: yes | |||||
timeCreated: 1500596137 | |||||
licenseType: Free | |||||
DefaultImporter: | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 5a8cc42eaba7a2a41b6ca3be3c40b315 | |||||
timeCreated: 1500596155 | |||||
licenseType: Free | |||||
PluginImporter: | |||||
serializedVersion: 2 | |||||
iconMap: {} | |||||
executionOrder: {} | |||||
isPreloaded: 0 | |||||
isOverridable: 0 | |||||
platformData: | |||||
data: | |||||
first: | |||||
Any: | |||||
second: | |||||
enabled: 1 | |||||
settings: {} | |||||
data: | |||||
first: | |||||
Editor: Editor | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
DefaultValueInitialized: true | |||||
data: | |||||
first: | |||||
Windows Store Apps: WindowsStoreApps | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: AnyCPU | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 534760d5f8b40420d8dbff996c9060a8 | |||||
folderAsset: yes | |||||
timeCreated: 1449532728 | |||||
licenseType: Free | |||||
DefaultImporter: | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: f3c17e56945504a4eaf427a9ae38ad3a | |||||
folderAsset: yes | |||||
DefaultImporter: | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: a45642ab77cf9604887c9bcb222c596f | |||||
folderAsset: yes | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
// | |||||
// Copyright 2014-2015 Amazon.com, | |||||
// Inc. or its affiliates. All Rights Reserved. | |||||
// | |||||
// Licensed under the AWS Mobile SDK For Unity | |||||
// Sample Application License Agreement (the "License"). | |||||
// You may not use this file except in compliance with the | |||||
// License. A copy of the License is located | |||||
// in the "license" file accompanying this file. This file is | |||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR | |||||
// CONDITIONS OF ANY KIND, express or implied. See the License | |||||
// for the specific language governing permissions and | |||||
// limitations under the License. | |||||
// | |||||
using UnityEngine; | |||||
using System.Collections; | |||||
using UnityEngine.UI; | |||||
using Amazon.S3; | |||||
using Amazon.S3.Model; | |||||
using Amazon.Runtime; | |||||
using System.IO; | |||||
using System; | |||||
using Amazon.S3.Util; | |||||
using System.Collections.Generic; | |||||
using Amazon.CognitoIdentity; | |||||
using Amazon; | |||||
public class S3Manager : MonoBehaviour | |||||
{ | |||||
public string IdentityPoolId = "us-east-1:066cd25b-b249-4394-a267-7a49247aa8f9"; // vrchat identity pool id | |||||
public string CognitoIdentityRegion = RegionEndpoint.USEast1.SystemName; | |||||
private RegionEndpoint _CognitoIdentityRegion | |||||
{ | |||||
get { return RegionEndpoint.GetBySystemName(CognitoIdentityRegion); } | |||||
} | |||||
public string S3Region = RegionEndpoint.USEast1.SystemName; | |||||
private RegionEndpoint _S3Region | |||||
{ | |||||
get { return RegionEndpoint.GetBySystemName(S3Region); } | |||||
} | |||||
public string S3BucketName = "vrc-uploads"; // vrchat | |||||
private IAmazonS3 _s3Client; | |||||
private AWSCredentials _credentials; | |||||
private AWSCredentials Credentials | |||||
{ | |||||
get | |||||
{ | |||||
if (_credentials == null) | |||||
_credentials = new CognitoAWSCredentials(IdentityPoolId, _CognitoIdentityRegion); | |||||
return _credentials; | |||||
} | |||||
} | |||||
private IAmazonS3 Client | |||||
{ | |||||
get | |||||
{ | |||||
if (_s3Client == null) | |||||
{ | |||||
_s3Client = new AmazonS3Client(Credentials, _S3Region); | |||||
} | |||||
//test comment | |||||
return _s3Client; | |||||
} | |||||
} | |||||
void Start() | |||||
{ | |||||
UnityInitializer.AttachToGameObject(this.gameObject); | |||||
} | |||||
/// <summary> | |||||
/// Post Object to S3 Bucket. | |||||
/// </summary> | |||||
public PostObjectRequest PostObject(string filePath, string s3FolderName, Action<string> onSuccess = null) | |||||
{ | |||||
string fileName = s3FolderName + "/" + System.IO.Path.GetFileName(filePath); | |||||
VRC.Core.Logger.Log ("uploading " + fileName, VRC.Core.DebugLevel.All); | |||||
AWSConfigs.LoggingConfig.LogTo = LoggingOptions.None; | |||||
var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); | |||||
VRC.Core.Logger.Log ("Creating request object", VRC.Core.DebugLevel.All); | |||||
var request = new PostObjectRequest() | |||||
{ | |||||
Bucket = S3BucketName, | |||||
Key = fileName, | |||||
InputStream = stream, | |||||
CannedACL = S3CannedACL.Private | |||||
}; | |||||
VRC.Core.Logger.Log ("Making HTTP post call", VRC.Core.DebugLevel.All); | |||||
StartCoroutine(PostObjectRoutine(request, onSuccess)); | |||||
return request; | |||||
} | |||||
IEnumerator PostObjectRoutine(PostObjectRequest request, Action<string> onSuccess) | |||||
{ | |||||
// make sure UnityInitializer call has time to initialize | |||||
yield return null; | |||||
yield return null; | |||||
Client.PostObjectAsync(request, (responseObj) => | |||||
{ | |||||
if (responseObj.Exception == null) | |||||
{ | |||||
VRC.Core.Logger.Log("object " + responseObj.Request.Key + " posted to bucket " + responseObj.Request.Bucket, VRC.Core.DebugLevel.All); | |||||
string s3Url = string.Format("https://s3-us-west-2.amazonaws.com/{0}/{1}", responseObj.Request.Bucket, responseObj.Request.Key); | |||||
if(onSuccess != null) | |||||
onSuccess(s3Url); | |||||
} | |||||
else | |||||
{ | |||||
VRC.Core.Logger.Log ("Exception while posting the result object"); | |||||
VRC.Core.Logger.Log("receieved error " + responseObj.Response.HttpStatusCode.ToString()); | |||||
} | |||||
}); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 3d6a1d7b0624f414ba6fb922687a06da | |||||
timeCreated: 1480975716 | |||||
licenseType: Free | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 027731dadc7571046abaf43e4f52e9ae | |||||
folderAsset: yes | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using UnityEditor; | |||||
using VRC.Core; | |||||
[CustomEditor(typeof(ApiCache))] | |||||
public class ApiCacheEditor : Editor { | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
foreach (System.Type type in ApiCache.cache.Keys) | |||||
{ | |||||
Dictionary<string, ApiCache.CacheEntry> typeCache = ApiCache.cache[type]; | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.PrefixLabel(type.Name); | |||||
EditorGUILayout.LabelField(typeCache.Count.ToString()); | |||||
EditorGUILayout.EndHorizontal(); | |||||
} | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 39cdf3092ab81be4b9e623cb5a8819d8 | |||||
timeCreated: 1509575680 | |||||
licenseType: Pro | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
#define SUPPORT_DEPRECATED_ONSP | |||||
using UnityEngine; | |||||
using System.Collections; | |||||
using UnityEditor; | |||||
using VRCSDK2; | |||||
[InitializeOnLoad] | |||||
public class AutoAddSpatialAudioComponents | |||||
{ | |||||
public static bool Enabled = true; | |||||
static AutoAddSpatialAudioComponents() | |||||
{ | |||||
EditorApplication.hierarchyWindowChanged += OnHierarchyWindowChanged; | |||||
EditorApplication.projectWindowChanged += OnProjectWindowChanged; | |||||
RegisterCallbacks(); | |||||
} | |||||
static void OnHierarchyWindowChanged() | |||||
{ | |||||
if (!Enabled) | |||||
{ | |||||
EditorApplication.hierarchyWindowChanged -= OnHierarchyWindowChanged; | |||||
return; | |||||
} | |||||
// check for proper use of VRCSP, and warn | |||||
//TryToAddSpatializationToAllAudioSources(true, false); | |||||
} | |||||
static void OnProjectWindowChanged() | |||||
{ | |||||
RegisterCallbacks(); | |||||
} | |||||
static void RegisterCallbacks() | |||||
{ | |||||
VRCSdkControlPanel._EnableSpatialization = VRCSDKControlPanel_EnableSpatialization; | |||||
} | |||||
// callback from VrcSdkControlPanel in dll | |||||
public static void VRCSDKControlPanel_EnableSpatialization() | |||||
{ | |||||
Debug.Log("Enabling spatialization on 3D AudioSources..."); | |||||
TryToAddSpatializationToAllAudioSources(false, true); | |||||
} | |||||
static bool ApplyDefaultSpatializationToAudioSource(AudioSource audioSrc, bool force = false) | |||||
{ | |||||
if (audioSrc == null) | |||||
return false; | |||||
var vrcsp = audioSrc.gameObject.GetComponent<VRCSDK2.VRC_SpatialAudioSource>(); | |||||
// don't make changes if we already have a vrcsp and we aren't forcing | |||||
if (vrcsp != null && !force) | |||||
return false; | |||||
if (force) | |||||
audioSrc.spatialBlend = 1; | |||||
bool initValues = force; | |||||
// is audio source set to be 2D? | |||||
bool is2D = audioSrc.spatialBlend == 0; | |||||
#if SUPPORT_DEPRECATED_ONSP | |||||
var onsp = audioSrc.GetComponent<ONSPAudioSource>(); | |||||
if (onsp != null) | |||||
{ | |||||
if (vrcsp == null) | |||||
{ | |||||
// copy the values from deprecated component | |||||
vrcsp = audioSrc.gameObject.AddComponent<VRCSDK2.VRC_SpatialAudioSource>(); | |||||
vrcsp.Gain = onsp.Gain; | |||||
vrcsp.Near = onsp.Near; | |||||
vrcsp.Far = onsp.Far; | |||||
vrcsp.UseAudioSourceVolumeCurve = !onsp.UseInvSqr; | |||||
vrcsp.EnableSpatialization = onsp.EnableSpatialization; | |||||
} | |||||
// remove deprecated component | |||||
Component.DestroyImmediate(onsp); | |||||
} | |||||
#endif | |||||
if (vrcsp == null) | |||||
{ | |||||
// no onsp and no vrcsp, so add | |||||
vrcsp = audioSrc.gameObject.AddComponent<VRCSDK2.VRC_SpatialAudioSource>(); | |||||
if (is2D) | |||||
{ | |||||
// this audio source was marked as 2D, leave the vrcsp disabled | |||||
vrcsp.EnableSpatialization = false; | |||||
} | |||||
initValues = true; | |||||
} | |||||
audioSrc.spatialize = vrcsp.EnableSpatialization; | |||||
vrcsp.enabled = true; | |||||
if (initValues) | |||||
{ | |||||
bool isAvatar = audioSrc.GetComponentInParent<VRCSDK2.VRC_AvatarDescriptor>(); | |||||
vrcsp.Gain = isAvatar ? VRCSDK2.AudioManagerSettings.AvatarAudioMaxGain : VRCSDK2.AudioManagerSettings.RoomAudioGain; | |||||
vrcsp.Near = 0; | |||||
vrcsp.Far = isAvatar ? VRCSDK2.AudioManagerSettings.AvatarAudioMaxRange : VRCSDK2.AudioManagerSettings.RoomAudioMaxRange; | |||||
vrcsp.UseAudioSourceVolumeCurve = false; | |||||
} | |||||
return true; | |||||
} | |||||
public static void TryToAddSpatializationToAllAudioSources(bool newAudioSourcesOnly, bool includeInactive) | |||||
{ | |||||
AudioSource[] allAudioSources = includeInactive ? Resources.FindObjectsOfTypeAll<AudioSource>() : Object.FindObjectsOfType<AudioSource>(); | |||||
foreach (AudioSource src in allAudioSources) | |||||
{ | |||||
if (src == null || src.gameObject == null || src.gameObject.scene != UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene()) | |||||
{ | |||||
continue; | |||||
} | |||||
if (newAudioSourcesOnly) | |||||
{ | |||||
if (!IsNewAudioSource(src)) | |||||
continue; | |||||
UnityEngine.Audio.AudioMixerGroup mixer = AssetDatabase.LoadAssetAtPath<UnityEngine.Audio.AudioMixerGroup>("Assets/VRCSDK/Dependencies/OSPNative/scenes/mixers/SpatializerMixer.mixer"); | |||||
if (mixer != null) | |||||
{ | |||||
src.outputAudioMixerGroup = mixer; | |||||
} | |||||
} | |||||
if (ApplyDefaultSpatializationToAudioSource(src, false)) | |||||
{ | |||||
Debug.Log("Automatically added VRC_SpatialAudioSource component to " + GetGameObjectPath(src.gameObject) + "!"); | |||||
} | |||||
} | |||||
} | |||||
static bool IsNewAudioSource(AudioSource src) | |||||
{ | |||||
var vrcsp = src.GetComponent<VRC_SpatialAudioSource>(); | |||||
if (vrcsp != null) | |||||
return false; | |||||
if (src.clip != null) | |||||
return false; | |||||
if (src.outputAudioMixerGroup != null) | |||||
return false; | |||||
if (src.mute || src.bypassEffects || src.bypassReverbZones || !src.playOnAwake || src.loop) | |||||
return false; | |||||
if (src.priority != 128 || | |||||
!Mathf.Approximately(src.volume, 1.0f) || | |||||
!Mathf.Approximately(src.pitch, 1.0f) || | |||||
!Mathf.Approximately(src.panStereo, 0.0f) || | |||||
!Mathf.Approximately(src.spatialBlend, 0.0f) || | |||||
!Mathf.Approximately(src.reverbZoneMix, 1.0f)) | |||||
{ | |||||
return false; | |||||
} | |||||
if (!Mathf.Approximately(src.dopplerLevel, 1.0f) || | |||||
!Mathf.Approximately(src.spread, 0.0f) || | |||||
src.rolloffMode != AudioRolloffMode.Logarithmic || | |||||
!Mathf.Approximately(src.minDistance, 1.0f) || | |||||
!Mathf.Approximately(src.maxDistance, 500.0f)) | |||||
{ | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
static string GetGameObjectPath(GameObject obj) | |||||
{ | |||||
string path = "/" + obj.name; | |||||
while (obj.transform.parent != null) | |||||
{ | |||||
obj = obj.transform.parent.gameObject; | |||||
path = "/" + obj.name + path; | |||||
} | |||||
return path; | |||||
} | |||||
public static void ConvertONSPAudioSource(AudioSource src) | |||||
{ | |||||
if (src == null) return; | |||||
var onsp = src.GetComponent<ONSPAudioSource>(); | |||||
if (onsp != null) | |||||
{ | |||||
var vrcsp = src.gameObject.GetComponent<VRCSDK2.VRC_SpatialAudioSource>(); | |||||
if (vrcsp == null) | |||||
{ | |||||
// copy the values from deprecated component | |||||
vrcsp = src.gameObject.AddComponent<VRCSDK2.VRC_SpatialAudioSource>(); | |||||
vrcsp.Gain = onsp.Gain; | |||||
vrcsp.Near = onsp.Near; | |||||
vrcsp.Far = onsp.Far; | |||||
vrcsp.UseAudioSourceVolumeCurve = !onsp.UseInvSqr; | |||||
vrcsp.EnableSpatialization = onsp.EnableSpatialization; | |||||
} | |||||
// remove deprecated component | |||||
Component.DestroyImmediate(onsp); | |||||
} | |||||
} | |||||
public static void AddVRCSpatialToBareAudioSource(AudioSource src) | |||||
{ | |||||
if (src == null) return; | |||||
var vrcsp = src.gameObject.GetComponent<VRCSDK2.VRC_SpatialAudioSource>(); | |||||
if (vrcsp != null) return; | |||||
vrcsp = src.gameObject.AddComponent<VRCSDK2.VRC_SpatialAudioSource>(); | |||||
// add default values | |||||
bool isAvatar = src.gameObject.GetComponentInParent<VRCSDK2.VRC_AvatarDescriptor>(); | |||||
vrcsp.Gain = isAvatar ? VRCSDK2.AudioManagerSettings.AvatarAudioMaxGain : VRCSDK2.AudioManagerSettings.RoomAudioGain; | |||||
vrcsp.Near = 0; | |||||
vrcsp.Far = isAvatar ? VRCSDK2.AudioManagerSettings.AvatarAudioMaxRange : VRCSDK2.AudioManagerSettings.RoomAudioMaxRange; | |||||
vrcsp.UseAudioSourceVolumeCurve = false; | |||||
// enable spatialization if src is not 2D | |||||
AnimationCurve curve = src.GetCustomCurve(AudioSourceCurveType.SpatialBlend); | |||||
if (src.spatialBlend == 0 || (curve == null || curve.keys.Length <= 1)) | |||||
vrcsp.EnableSpatialization = false; | |||||
else | |||||
vrcsp.EnableSpatialization = true; | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 0a364ece829b6234888c59987a305a00 | |||||
MonoImporter: | |||||
externalObjects: {} | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using System; | |||||
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using UnityEditor; | |||||
using UnityEngine; | |||||
using Object = UnityEngine.Object; | |||||
public class EditorCoroutine | |||||
{ | |||||
public static EditorCoroutine Start( IEnumerator _routine ) | |||||
{ | |||||
EditorCoroutine coroutine = new EditorCoroutine(_routine); | |||||
coroutine.start(); | |||||
return coroutine; | |||||
} | |||||
public static EditorCoroutine Start(System.Action _action) | |||||
{ | |||||
EditorCoroutine coroutine = new EditorCoroutine(_action); | |||||
coroutine.start(); | |||||
return coroutine; | |||||
} | |||||
readonly IEnumerator routine; | |||||
EditorCoroutine( IEnumerator _routine ) | |||||
{ | |||||
routine = _routine; | |||||
} | |||||
readonly System.Action action; | |||||
EditorCoroutine(System.Action _action) | |||||
{ | |||||
action = _action; | |||||
} | |||||
void start() | |||||
{ | |||||
EditorApplication.update += update; | |||||
} | |||||
public void stop() | |||||
{ | |||||
EditorApplication.update -= update; | |||||
} | |||||
void update() | |||||
{ | |||||
if (routine != null) | |||||
{ | |||||
if (!routine.MoveNext()) | |||||
stop(); | |||||
} | |||||
else if (action != null) | |||||
{ | |||||
action(); | |||||
stop(); | |||||
} | |||||
else | |||||
stop(); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 89005ebc9543e0a4284893c09ca19b1d | |||||
timeCreated: 1473271738 | |||||
licenseType: Pro | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using UnityEditor; | |||||
using UnityEngine.SceneManagement; | |||||
[InitializeOnLoad] | |||||
public static class EditorHandling | |||||
{ | |||||
static EditorHandling() | |||||
{ | |||||
UnityEditor.SceneManagement.EditorSceneManager.sceneOpened += SceneOpenedCallback; | |||||
} | |||||
static void SceneOpenedCallback( Scene scene, UnityEditor.SceneManagement.OpenSceneMode mode) | |||||
{ | |||||
// refresh window when scene is opened to display content images correctly | |||||
if (null != VRCSdkControlPanel.window) VRCSdkControlPanel.window.Reset(); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 3d6c2e367eaa9564ebf6267ec163cfbd | |||||
MonoImporter: | |||||
externalObjects: {} | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
#if UNITY_EDITOR | |||||
#pragma warning disable 0618 | |||||
using UnityEditor; | |||||
using System.Collections; | |||||
namespace VRCSDK2 | |||||
{ | |||||
[CustomEditor(typeof(VRCSDK2.VRC_KeyEvents))] | |||||
public class VRC_KeyEventsEditor : Editor | |||||
{ | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
EditorGUILayout.HelpBox("Obsolete. Please use a VRC_Trigger instead.", MessageType.Error); | |||||
} | |||||
} | |||||
[CustomEditor(typeof(VRCSDK2.VRC_UseEvents))] | |||||
public class VRC_UseEventsEditor : Editor | |||||
{ | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
EditorGUILayout.HelpBox("Obsolete. Please use a VRC_Trigger instead.", MessageType.Error); | |||||
} | |||||
} | |||||
[CustomEditor(typeof(VRCSDK2.VRC_TriggerColliderEventTrigger))] | |||||
public class VRC_TriggerColliderEventTriggerEditor : Editor | |||||
{ | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
EditorGUILayout.HelpBox("Obsolete. Please use a VRC_Trigger instead.", MessageType.Error); | |||||
} | |||||
} | |||||
[CustomEditor(typeof(VRCSDK2.VRC_TimedEvents))] | |||||
public class VRC_TimedEventsEditor : Editor | |||||
{ | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
EditorGUILayout.HelpBox("Obsolete. Please use a VRC_Trigger instead.", MessageType.Error); | |||||
} | |||||
} | |||||
} | |||||
#pragma warning restore 0618 | |||||
#endif |
fileFormatVersion: 2 | |||||
guid: 482185bf29f12074dada194ffef6a682 | |||||
timeCreated: 1475877803 | |||||
licenseType: Free | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using UnityEngine; | |||||
using UnityEditor; | |||||
using System.Collections; | |||||
using System.Collections.Generic; | |||||
[CustomEditor(typeof(VRCSDK2.VRC_AvatarDescriptor))] | |||||
public class AvatarDescriptorEditor : Editor | |||||
{ | |||||
VRCSDK2.VRC_AvatarDescriptor avatarDescriptor; | |||||
VRC.Core.PipelineManager pipelineManager; | |||||
SkinnedMeshRenderer selectedMesh; | |||||
List<string> blendShapeNames = null; | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
if (avatarDescriptor == null) | |||||
avatarDescriptor = (VRCSDK2.VRC_AvatarDescriptor)target; | |||||
if (pipelineManager == null) | |||||
{ | |||||
pipelineManager = avatarDescriptor.GetComponent<VRC.Core.PipelineManager>(); | |||||
if (pipelineManager == null) | |||||
avatarDescriptor.gameObject.AddComponent<VRC.Core.PipelineManager>(); | |||||
} | |||||
// DrawDefaultInspector(); | |||||
if(VRCSdkControlPanel.window != null) | |||||
{ | |||||
if( GUILayout.Button( "Select this avatar in the SDK control panel" ) ) | |||||
VRCSdkControlPanel.SelectAvatar(avatarDescriptor); | |||||
} | |||||
avatarDescriptor.ViewPosition = EditorGUILayout.Vector3Field("View Position", avatarDescriptor.ViewPosition); | |||||
//avatarDescriptor.Name = EditorGUILayout.TextField("Avatar Name", avatarDescriptor.Name); | |||||
avatarDescriptor.Animations = (VRCSDK2.VRC_AvatarDescriptor.AnimationSet)EditorGUILayout.EnumPopup("Default Animation Set", avatarDescriptor.Animations); | |||||
avatarDescriptor.CustomStandingAnims = (AnimatorOverrideController)EditorGUILayout.ObjectField("Custom Standing Anims", avatarDescriptor.CustomStandingAnims, typeof(AnimatorOverrideController), true, null); | |||||
avatarDescriptor.CustomSittingAnims = (AnimatorOverrideController)EditorGUILayout.ObjectField("Custom Sitting Anims", avatarDescriptor.CustomSittingAnims, typeof(AnimatorOverrideController), true, null); | |||||
avatarDescriptor.ScaleIPD = EditorGUILayout.Toggle("Scale IPD", avatarDescriptor.ScaleIPD); | |||||
avatarDescriptor.lipSync = (VRCSDK2.VRC_AvatarDescriptor.LipSyncStyle)EditorGUILayout.EnumPopup("Lip Sync", avatarDescriptor.lipSync); | |||||
switch (avatarDescriptor.lipSync) | |||||
{ | |||||
case VRCSDK2.VRC_AvatarDescriptor.LipSyncStyle.Default: | |||||
if (GUILayout.Button("Auto Detect!")) | |||||
AutoDetectLipSync(); | |||||
break; | |||||
case VRCSDK2.VRC_AvatarDescriptor.LipSyncStyle.JawFlapBlendShape: | |||||
avatarDescriptor.VisemeSkinnedMesh = (SkinnedMeshRenderer)EditorGUILayout.ObjectField("Face Mesh", avatarDescriptor.VisemeSkinnedMesh, typeof(SkinnedMeshRenderer), true); | |||||
if (avatarDescriptor.VisemeSkinnedMesh != null) | |||||
{ | |||||
DetermineBlendShapeNames(); | |||||
int current = -1; | |||||
for (int b = 0; b < blendShapeNames.Count; ++b) | |||||
if (avatarDescriptor.MouthOpenBlendShapeName == blendShapeNames[b]) | |||||
current = b; | |||||
string title = "Jaw Flap Blend Shape"; | |||||
int next = EditorGUILayout.Popup(title, current, blendShapeNames.ToArray()); | |||||
if (next >= 0) | |||||
avatarDescriptor.MouthOpenBlendShapeName = blendShapeNames[next]; | |||||
} | |||||
break; | |||||
case VRCSDK2.VRC_AvatarDescriptor.LipSyncStyle.JawFlapBone: | |||||
avatarDescriptor.lipSyncJawBone = (Transform)EditorGUILayout.ObjectField("Jaw Bone", avatarDescriptor.lipSyncJawBone, typeof(Transform), true); | |||||
break; | |||||
case VRCSDK2.VRC_AvatarDescriptor.LipSyncStyle.VisemeBlendShape: | |||||
avatarDescriptor.VisemeSkinnedMesh = (SkinnedMeshRenderer)EditorGUILayout.ObjectField("Face Mesh", avatarDescriptor.VisemeSkinnedMesh, typeof(SkinnedMeshRenderer), true); | |||||
if (avatarDescriptor.VisemeSkinnedMesh != null) | |||||
{ | |||||
DetermineBlendShapeNames(); | |||||
if (avatarDescriptor.VisemeBlendShapes == null || avatarDescriptor.VisemeBlendShapes.Length != (int)VRCSDK2.VRC_AvatarDescriptor.Viseme.Count) | |||||
avatarDescriptor.VisemeBlendShapes = new string[(int)VRCSDK2.VRC_AvatarDescriptor.Viseme.Count]; | |||||
for (int i = 0; i < (int)VRCSDK2.VRC_AvatarDescriptor.Viseme.Count; ++i) | |||||
{ | |||||
int current = -1; | |||||
for (int b = 0; b < blendShapeNames.Count; ++b) | |||||
if (avatarDescriptor.VisemeBlendShapes[i] == blendShapeNames[b]) | |||||
current = b; | |||||
string title = "Viseme: " + ((VRCSDK2.VRC_AvatarDescriptor.Viseme)i).ToString(); | |||||
int next = EditorGUILayout.Popup(title, current, blendShapeNames.ToArray()); | |||||
if (next >= 0) | |||||
avatarDescriptor.VisemeBlendShapes[i] = blendShapeNames[next]; | |||||
} | |||||
} | |||||
break; | |||||
} | |||||
EditorGUILayout.LabelField("Unity Version", avatarDescriptor.unityVersion); | |||||
} | |||||
void DetermineBlendShapeNames() | |||||
{ | |||||
if (avatarDescriptor.VisemeSkinnedMesh != null && | |||||
avatarDescriptor.VisemeSkinnedMesh != selectedMesh) | |||||
{ | |||||
blendShapeNames = new List<string>(); | |||||
blendShapeNames.Add("-none-"); | |||||
selectedMesh = avatarDescriptor.VisemeSkinnedMesh; | |||||
for (int i = 0; i < selectedMesh.sharedMesh.blendShapeCount; ++i) | |||||
blendShapeNames.Add(selectedMesh.sharedMesh.GetBlendShapeName(i)); | |||||
} | |||||
} | |||||
void AutoDetectLipSync() | |||||
{ | |||||
var smrs = avatarDescriptor.GetComponentsInChildren<SkinnedMeshRenderer>(); | |||||
foreach (var smr in smrs) | |||||
{ | |||||
if (smr.sharedMesh.blendShapeCount > 0) | |||||
{ | |||||
avatarDescriptor.lipSync = VRCSDK2.VRC_AvatarDescriptor.LipSyncStyle.JawFlapBlendShape; | |||||
avatarDescriptor.VisemeSkinnedMesh = null; | |||||
avatarDescriptor.lipSyncJawBone = null; | |||||
return; | |||||
} | |||||
} | |||||
if (avatarDescriptor.GetComponent<Animator>().GetBoneTransform(HumanBodyBones.Jaw) != null) | |||||
{ | |||||
avatarDescriptor.lipSync = VRCSDK2.VRC_AvatarDescriptor.LipSyncStyle.JawFlapBone; | |||||
avatarDescriptor.lipSyncJawBone = avatarDescriptor.GetComponent<Animator>().GetBoneTransform(HumanBodyBones.Jaw); | |||||
avatarDescriptor.VisemeSkinnedMesh = null; | |||||
return; | |||||
} | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 5e83254bb97e84795ac882692ae124ba | |||||
timeCreated: 1450462624 | |||||
licenseType: Free | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using UnityEngine; | |||||
using System.Collections; | |||||
using UnityEditor; | |||||
using System; | |||||
[CustomEditor(typeof(VRCSDK2.VRC_ObjectSpawn))] | |||||
public class VRCObjectSpawnEditor : Editor | |||||
{ | |||||
VRCSDK2.VRC_ObjectSpawn spawn; | |||||
void OnEnable() | |||||
{ | |||||
if (spawn == null) | |||||
spawn = (VRCSDK2.VRC_ObjectSpawn)target; | |||||
} | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
DrawDefaultInspector(); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 26a75599848adb449b7aceed5090e35c | |||||
timeCreated: 1463516633 | |||||
licenseType: Free | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using UnityEngine; | |||||
using System.Collections; | |||||
using UnityEditor; | |||||
using System; | |||||
[CustomEditor(typeof(VRCSDK2.VRC_ObjectSync))] | |||||
public class VRCObjectSyncEditor : Editor | |||||
{ | |||||
VRCSDK2.VRC_ObjectSync sync; | |||||
void OnEnable() | |||||
{ | |||||
if (sync == null) | |||||
sync = (VRCSDK2.VRC_ObjectSync)target; | |||||
} | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
sync.SynchronizePhysics = EditorGUILayout.Toggle("Synchronize Physics",sync.SynchronizePhysics); | |||||
sync.AllowCollisionTransfer = EditorGUILayout.Toggle("Allow Collision Transfer", sync.AllowCollisionTransfer); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: ed4aad2698d3b62408e69b57c7748791 | |||||
timeCreated: 1463516212 | |||||
licenseType: Free | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
// C# example: | |||||
using UnityEngine; | |||||
using UnityEditor; | |||||
public class VRCPlayerModEditorWindow : EditorWindow { | |||||
public delegate void AddModCallback(); | |||||
public static AddModCallback addModCallback; | |||||
private static VRCSDK2.VRC_PlayerMods myTarget; | |||||
private static VRCSDK2.VRCPlayerModFactory.PlayerModType type; | |||||
public static void Init (VRCSDK2.VRC_PlayerMods target, AddModCallback callback) | |||||
{ | |||||
// Get existing open window or if none, make a new one: | |||||
EditorWindow.GetWindow (typeof (VRCPlayerModEditorWindow)); | |||||
addModCallback = callback; | |||||
myTarget = target; | |||||
type = VRCSDK2.VRCPlayerModFactory.PlayerModType.Jump; | |||||
} | |||||
void OnGUI () | |||||
{ | |||||
type = (VRCSDK2.VRCPlayerModFactory.PlayerModType)EditorGUILayout.EnumPopup("Mods", type); | |||||
if(GUILayout.Button("Add Mod")) | |||||
{ | |||||
VRCSDK2.VRCPlayerMod mod = VRCSDK2.VRCPlayerModFactory.Create(type); | |||||
myTarget.AddMod(mod); | |||||
addModCallback(); | |||||
} | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 8986a640e24a0754ea0aded12234b808 | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using UnityEngine; | |||||
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using UnityEditor; | |||||
using System; | |||||
namespace VRCSDK2 | |||||
{ | |||||
[CustomEditor(typeof(VRCSDK2.VRC_PlayerMods))] | |||||
public class VRCPlayerModsEditor : Editor | |||||
{ | |||||
VRCSDK2.VRC_PlayerMods myTarget; | |||||
void OnEnable() | |||||
{ | |||||
if(myTarget == null) | |||||
myTarget = (VRCSDK2.VRC_PlayerMods)target; | |||||
} | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
myTarget.isRoomPlayerMods = EditorGUILayout.Toggle("isRoomPlayerMods", myTarget.isRoomPlayerMods); | |||||
List<VRCPlayerMod> playerMods = myTarget.playerMods; | |||||
for(int i=0; i<playerMods.Count; ++i) | |||||
{ | |||||
VRCSDK2.VRCPlayerMod mod = playerMods[i]; | |||||
EditorGUILayout.BeginVertical("box"); | |||||
EditorGUILayout.LabelField(mod.name, EditorStyles.boldLabel); | |||||
if( mod.allowNameEdit ) | |||||
mod.name = EditorGUILayout.TextField( "Mod Name: ", mod.name ); | |||||
for(int j=0; j<mod.properties.Count; ++j) | |||||
{ | |||||
VRCSDK2.VRCPlayerModProperty prop = mod.properties[j]; | |||||
myTarget.playerMods[i].properties[j] = DrawFieldForProp(prop); | |||||
} | |||||
if(GUILayout.Button ("Remove Mod")) | |||||
{ | |||||
myTarget.RemoveMod(mod); | |||||
break; | |||||
} | |||||
EditorGUILayout.EndVertical(); | |||||
} | |||||
if(GUILayout.Button("Add Mods")) | |||||
{ | |||||
VRCPlayerModEditorWindow.AddModCallback adcb = OnInspectorGUI; | |||||
VRCPlayerModEditorWindow.Init(myTarget, adcb); | |||||
} | |||||
} | |||||
VRCSDK2.VRCPlayerModProperty DrawFieldForProp(VRCSDK2.VRCPlayerModProperty property) | |||||
{ | |||||
if(property.type.SystemType == typeof(int)) | |||||
{ | |||||
property.intValue = EditorGUILayout.IntField(property.name, property.intValue); | |||||
} | |||||
else if(property.type.SystemType == typeof(float)) | |||||
{ | |||||
property.floatValue = EditorGUILayout.FloatField(property.name, property.floatValue); | |||||
} | |||||
else if(property.type.SystemType == typeof(string)) | |||||
{ | |||||
property.stringValue = EditorGUILayout.TextField(property.name, property.stringValue); | |||||
} | |||||
else if(property.type.SystemType == typeof(bool)) | |||||
{ | |||||
property.boolValue = EditorGUILayout.Toggle(property.name, property.boolValue); | |||||
} | |||||
else if(property.type.SystemType == typeof(GameObject)) | |||||
{ | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField( property.name ); | |||||
property.gameObjectValue = (GameObject) EditorGUILayout.ObjectField( property.gameObjectValue, typeof( GameObject ), true ); | |||||
EditorGUILayout.EndHorizontal(); | |||||
} | |||||
else if(property.type.SystemType == typeof(KeyCode)) | |||||
{ | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField( property.name ); | |||||
property.keyCodeValue = (KeyCode) EditorGUILayout.EnumPopup( property.keyCodeValue ); | |||||
EditorGUILayout.EndHorizontal(); | |||||
} | |||||
else if(property.type.SystemType == typeof(VRCSDK2.VRC_EventHandler.VrcBroadcastType)) | |||||
{ | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField( property.name ); | |||||
property.broadcastValue = (VRCSDK2.VRC_EventHandler.VrcBroadcastType) EditorGUILayout.EnumPopup( property.broadcastValue ); | |||||
EditorGUILayout.EndHorizontal(); | |||||
} | |||||
else if(property.type.SystemType == typeof(VRCSDK2.VRCPlayerModFactory.HealthOnDeathAction)) | |||||
{ | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField( property.name ); | |||||
property.onDeathActionValue = (VRCSDK2.VRCPlayerModFactory.HealthOnDeathAction) EditorGUILayout.EnumPopup( property.onDeathActionValue); | |||||
EditorGUILayout.EndHorizontal(); | |||||
} | |||||
else if(property.type.SystemType == typeof(RuntimeAnimatorController)) | |||||
{ | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField( property.name ); | |||||
property.animationController = (RuntimeAnimatorController) EditorGUILayout.ObjectField( property.animationController, typeof( RuntimeAnimatorController ), false ); | |||||
EditorGUILayout.EndHorizontal(); | |||||
} | |||||
return property; | |||||
} | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 792e7964a56e51f4188e1221751642e9 | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using UnityEngine; | |||||
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using UnityEditor; | |||||
using System; | |||||
[CustomEditor(typeof(VRCSDK2.VRC_Station))] | |||||
public class VRCPlayerStationEditor : Editor | |||||
{ | |||||
VRCSDK2.VRC_Station myTarget; | |||||
void OnEnable() | |||||
{ | |||||
if(myTarget == null) | |||||
myTarget = (VRCSDK2.VRC_Station)target; | |||||
} | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
DrawDefaultInspector(); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 5262a02c32e41e047bdfdfc3b63db8ff | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using UnityEngine; | |||||
using UnityEditor; | |||||
using System.Collections; | |||||
[CustomEditor (typeof(VRCSDK2.VRC_SceneDescriptor))] | |||||
public class VRCSceneDescriptorEditor : Editor | |||||
{ | |||||
VRCSDK2.VRC_SceneDescriptor sceneDescriptor; | |||||
VRC.Core.PipelineManager pipelineManager; | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
if(sceneDescriptor == null) | |||||
sceneDescriptor = (VRCSDK2.VRC_SceneDescriptor)target; | |||||
if(pipelineManager == null) | |||||
{ | |||||
pipelineManager = sceneDescriptor.GetComponent<VRC.Core.PipelineManager>(); | |||||
if(pipelineManager == null) | |||||
sceneDescriptor.gameObject.AddComponent<VRC.Core.PipelineManager>(); | |||||
} | |||||
DrawDefaultInspector(); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: e9cbc493bbbc443fb92898aa84d221ec | |||||
timeCreated: 1450463561 | |||||
licenseType: Free | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using UnityEngine; | |||||
using UnityEditor; | |||||
namespace VRCSDK2 | |||||
{ | |||||
//[CustomPropertyDrawer(typeof(VRC_AvatarVariations.VariationCategory))] | |||||
//public class PropertyDrawer_AvatarVariation_VariationCategory : PropertyDrawer | |||||
//{ | |||||
// public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label) | |||||
// { | |||||
// //EditorGUILayout.Label("blah"); | |||||
// if (property == null) | |||||
// return; | |||||
// SerializedProperty nameProperty = property.FindPropertyRelative("name"); | |||||
// //SerializedProperty mirrorProperty = property.FindPropertyRelative("mirror"); | |||||
// //SerializedProperty typeProperty = property.FindPropertyRelative("type"); | |||||
// //SerializedProperty valueProperty = null; | |||||
// //switch (typeProperty.enumValueIndex) | |||||
// //{ | |||||
// // case (int)VRC_DataStorage.VrcDataType.Bool: | |||||
// // valueProperty = property.FindPropertyRelative("valueBool"); | |||||
// // break; | |||||
// // case (int)VRC_DataStorage.VrcDataType.Float: | |||||
// // valueProperty = property.FindPropertyRelative("valueFloat"); | |||||
// // break; | |||||
// // case (int)VRC_DataStorage.VrcDataType.Int: | |||||
// // valueProperty = property.FindPropertyRelative("valueInt"); | |||||
// // break; | |||||
// // case (int)VRC_DataStorage.VrcDataType.String: | |||||
// // valueProperty = property.FindPropertyRelative("valueString"); | |||||
// // break; | |||||
// // case (int)VRC_DataStorage.VrcDataType.SerializeObject: | |||||
// // valueProperty = property.FindPropertyRelative("serializeComponent"); | |||||
// // break; | |||||
// // case (int)VRC_DataStorage.VrcDataType.None: | |||||
// // case (int)VRC_DataStorage.VrcDataType.SerializeBytes: | |||||
// // break; | |||||
// //} | |||||
// EditorGUI.BeginProperty(rect, label, property); | |||||
// int baseWidth = (int)(rect.width / 4); | |||||
// Rect nameRect = new Rect(rect.x, rect.y, baseWidth, rect.height); | |||||
// //Rect mirrorRect = new Rect(rect.x + baseWidth, rect.y, baseWidth, rect.height); | |||||
// //Rect typeRect = new Rect(rect.x + baseWidth * 2, rect.y, baseWidth, rect.height); | |||||
// //Rect valueRect = new Rect(rect.x + baseWidth * 3, rect.y, baseWidth, rect.height); | |||||
// //Rect typeValueRect = new Rect(rect.x + baseWidth * 2, rect.y, baseWidth * 2, rect.height); | |||||
// EditorGUI.PropertyField(nameRect, nameProperty, GUIContent.none); | |||||
// //EditorGUI.PropertyField(mirrorRect, mirrorProperty, GUIContent.none); | |||||
// //switch (mirrorProperty.enumValueIndex) | |||||
// //{ | |||||
// // case (int)VRC_DataStorage.VrcDataMirror.None: | |||||
// // if (valueProperty == null) | |||||
// // VRC_EditorTools.FilteredEnumPopup<VRC_DataStorage.VrcDataType>(typeValueRect, typeProperty, t => true); | |||||
// // else | |||||
// // { | |||||
// // VRC_EditorTools.FilteredEnumPopup<VRC_DataStorage.VrcDataType>(typeRect, typeProperty, t => true); | |||||
// // EditorGUI.PropertyField(valueRect, valueProperty, GUIContent.none); | |||||
// // } | |||||
// // break; | |||||
// // case (int)VRC_DataStorage.VrcDataMirror.SerializeComponent: | |||||
// // typeProperty.enumValueIndex = (int)VRC_DataStorage.VrcDataType.SerializeObject; | |||||
// // EditorGUI.PropertyField(typeValueRect, valueProperty, GUIContent.none); | |||||
// // break; | |||||
// // default: | |||||
// // VRC_EditorTools.FilteredEnumPopup<VRC_DataStorage.VrcDataType>(typeValueRect, typeProperty, t => true); | |||||
// // break; | |||||
// //} | |||||
// EditorGUI.EndProperty(); | |||||
// } | |||||
//} | |||||
//[CustomEditor(typeof(VRC_AvatarVariations))] | |||||
//public class VRC_AvatarVariationsEditor : Editor | |||||
//{ | |||||
// SerializedProperty categories; | |||||
// void OnEnable() | |||||
// { | |||||
// categories = serializedObject.FindProperty("categories"); | |||||
// } | |||||
// public override void OnInspectorGUI() | |||||
// { | |||||
// //serializedObject.Update(); | |||||
// // EditorGUILayout.PropertyField(categories); | |||||
// //serializedObject.ApplyModifiedProperties(); | |||||
// //if (target == null) | |||||
// // return; | |||||
// ////var prop = serializedObject.FindProperty("root"); | |||||
// ////EditorGUILayout.PropertyField(prop, new GUIContent("Show Help")); | |||||
// //VRCSDK2.VRC_AvatarVariations variations = target as VRCSDK2.VRC_AvatarVariations; | |||||
// //if (variations.categories == null) | |||||
// // variations.categories = new VRC_AvatarVariations.VariationCategory[0]; | |||||
// //foreach ( var vc in variations.categories ) | |||||
// //{ | |||||
// // vc.name = EditorGUILayout.TextField("Variation Name", vc.name); | |||||
// //// SerializedProperty triggers = triggersProperty.Copy(); | |||||
// //// int triggersLength = triggers.arraySize; | |||||
// //// List<int> to_remove = new List<int>(); | |||||
// //// for (int idx = 0; idx < triggersLength; ++idx) | |||||
// //// { | |||||
// //// SerializedProperty triggerProperty = triggers.GetArrayElementAtIndex(idx); | |||||
// //// } | |||||
// //// EditorGUILayout.LabelField(""); | |||||
// ////// helpProperty = serializedObject.FindProperty("ShowHelp"); | |||||
// ////// EditorGUILayout.PropertyField(helpProperty, new GUIContent("Show Help")); | |||||
// //} | |||||
// ////EditorGUILayout. | |||||
// DrawDefaultInspector(); | |||||
// } | |||||
//} | |||||
} |
fileFormatVersion: 2 | |||||
guid: eeda995d0ceac6443a54716996eab52e | |||||
timeCreated: 1511373338 | |||||
licenseType: Pro | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
#if UNITY_EDITOR | |||||
using UnityEditor; | |||||
using UnityEngine; | |||||
using System.Linq; | |||||
namespace VRCSDK2 | |||||
{ | |||||
[CustomPropertyDrawer(typeof(VRCSDK2.VRC_DataStorage.VrcDataElement))] | |||||
public class CustomDataElementDrawer : PropertyDrawer | |||||
{ | |||||
public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label) | |||||
{ | |||||
if (property == null) | |||||
return; | |||||
SerializedProperty nameProperty = property.FindPropertyRelative("name"); | |||||
SerializedProperty mirrorProperty = property.FindPropertyRelative("mirror"); | |||||
SerializedProperty typeProperty = property.FindPropertyRelative("type"); | |||||
SerializedProperty valueProperty = null; | |||||
switch (typeProperty.enumValueIndex) | |||||
{ | |||||
case (int)VRC_DataStorage.VrcDataType.Bool: | |||||
valueProperty = property.FindPropertyRelative("valueBool"); | |||||
break; | |||||
case (int)VRC_DataStorage.VrcDataType.Float: | |||||
valueProperty = property.FindPropertyRelative("valueFloat"); | |||||
break; | |||||
case (int)VRC_DataStorage.VrcDataType.Int: | |||||
valueProperty = property.FindPropertyRelative("valueInt"); | |||||
break; | |||||
case (int)VRC_DataStorage.VrcDataType.String: | |||||
valueProperty = property.FindPropertyRelative("valueString"); | |||||
break; | |||||
case (int)VRC_DataStorage.VrcDataType.SerializeObject: | |||||
valueProperty = property.FindPropertyRelative("serializeComponent"); | |||||
break; | |||||
case (int)VRC_DataStorage.VrcDataType.None: | |||||
case (int)VRC_DataStorage.VrcDataType.SerializeBytes: | |||||
break; | |||||
} | |||||
EditorGUI.BeginProperty(rect, label, property); | |||||
int baseWidth = (int)(rect.width / 4); | |||||
Rect nameRect = new Rect(rect.x, rect.y, baseWidth, rect.height); | |||||
Rect mirrorRect = new Rect(rect.x + baseWidth, rect.y, baseWidth, rect.height); | |||||
Rect typeRect = new Rect(rect.x + baseWidth * 2, rect.y, baseWidth, rect.height); | |||||
Rect valueRect = new Rect(rect.x + baseWidth * 3, rect.y, baseWidth, rect.height); | |||||
Rect typeValueRect = new Rect(rect.x + baseWidth * 2, rect.y, baseWidth * 2, rect.height); | |||||
EditorGUI.PropertyField(nameRect, nameProperty, GUIContent.none); | |||||
EditorGUI.PropertyField(mirrorRect, mirrorProperty, GUIContent.none); | |||||
switch (mirrorProperty.enumValueIndex) | |||||
{ | |||||
case (int)VRC_DataStorage.VrcDataMirror.None: | |||||
if (valueProperty == null) | |||||
VRC_EditorTools.FilteredEnumPopup<VRC_DataStorage.VrcDataType>(typeValueRect, typeProperty, t => true); | |||||
else | |||||
{ | |||||
VRC_EditorTools.FilteredEnumPopup<VRC_DataStorage.VrcDataType>(typeRect, typeProperty, t => true); | |||||
EditorGUI.PropertyField(valueRect, valueProperty, GUIContent.none); | |||||
} | |||||
break; | |||||
case (int)VRC_DataStorage.VrcDataMirror.SerializeComponent: | |||||
typeProperty.enumValueIndex = (int)VRC_DataStorage.VrcDataType.SerializeObject; | |||||
EditorGUI.PropertyField(typeValueRect, valueProperty, GUIContent.none); | |||||
break; | |||||
default: | |||||
VRC_EditorTools.FilteredEnumPopup<VRC_DataStorage.VrcDataType>(typeValueRect, typeProperty, t => true); | |||||
break; | |||||
} | |||||
EditorGUI.EndProperty(); | |||||
} | |||||
} | |||||
[CustomEditor(typeof(VRCSDK2.VRC_DataStorage)), CanEditMultipleObjects] | |||||
public class VRC_DataStorageEditor : Editor | |||||
{ | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
VRCSDK2.VRC_ObjectSync os = ((VRCSDK2.VRC_DataStorage)target).GetComponent<VRCSDK2.VRC_ObjectSync>(); | |||||
if (os != null && os.SynchronizePhysics) | |||||
EditorGUILayout.HelpBox("Consider either removing the VRC_ObjectSync or disabling SynchronizePhysics.", MessageType.Warning); | |||||
DrawDefaultInspector(); | |||||
} | |||||
} | |||||
} | |||||
#endif |
fileFormatVersion: 2 | |||||
guid: 0ac7998a36f085844847acbc046d4e27 | |||||
timeCreated: 1478191469 | |||||
licenseType: Free | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using UnityEngine; | |||||
using System.Collections; | |||||
using UnityEditor; | |||||
using VRCSDK2; | |||||
[CustomEditor(typeof(VRC_DestructibleStandard))] | |||||
[CanEditMultipleObjects] | |||||
public class VRC_DestructibleStandardEditor : Editor | |||||
{ | |||||
VRC_DestructibleStandard ds; | |||||
SerializedProperty maxHealth; | |||||
SerializedProperty currentHealth; | |||||
SerializedProperty healable; | |||||
SerializedProperty onDamagedTrigger; | |||||
SerializedProperty onDestroyedTrigger; | |||||
SerializedProperty onHealedTrigger; | |||||
SerializedProperty onFullHealedTrigger; | |||||
void OnEnable() | |||||
{ | |||||
maxHealth = serializedObject.FindProperty("maxHealth"); | |||||
currentHealth = serializedObject.FindProperty("currentHealth"); | |||||
healable = serializedObject.FindProperty("healable"); | |||||
onDamagedTrigger = serializedObject.FindProperty("onDamagedTrigger"); | |||||
onDestroyedTrigger = serializedObject.FindProperty("onDestructedTrigger"); | |||||
onHealedTrigger = serializedObject.FindProperty("onHealedTrigger"); | |||||
onFullHealedTrigger = serializedObject.FindProperty("onFullHealedTrigger"); | |||||
} | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
ds = (VRC_DestructibleStandard)target; | |||||
// Update the serializedProperty - always do this in the beginning of OnInspectorGUI. | |||||
serializedObject.Update (); | |||||
EditorGUILayout.PropertyField(maxHealth, new GUIContent("Max Health")); | |||||
EditorGUILayout.PropertyField(currentHealth, new GUIContent("Current Health")); | |||||
EditorGUILayout.PropertyField(healable, new GUIContent("Is Healable")); | |||||
EditorGUILayout.PropertyField(onDamagedTrigger, new GUIContent("On Damaged Trigger")); | |||||
VRC_EditorTools.DrawTriggerActionCallback("On Damaged Action", ds.onDamagedTrigger, ds.onDamagedEvent); | |||||
EditorGUILayout.PropertyField(onDestroyedTrigger, new GUIContent("On Destructed Trigger")); | |||||
VRC_EditorTools.DrawTriggerActionCallback("On Destructed Action", ds.onDestructedTrigger, ds.onDestructedEvent); | |||||
EditorGUILayout.PropertyField(onHealedTrigger, new GUIContent("On Healed Trigger")); | |||||
VRC_EditorTools.DrawTriggerActionCallback("On Healed Action", ds.onHealedTrigger, ds.onHealedEvent); | |||||
EditorGUILayout.PropertyField(onFullHealedTrigger, new GUIContent("On Full Healed Trigger")); | |||||
VRC_EditorTools.DrawTriggerActionCallback("On Full Healed Action", ds.onFullHealedTrigger, ds.onFullHealedEvent); | |||||
// Apply changes to the serializedProperty - always do this in the end of OnInspectorGUI. | |||||
serializedObject.ApplyModifiedProperties (); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 3b63b118c0591b548ba1797e6be4292e | |||||
timeCreated: 1477161996 | |||||
licenseType: Pro | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using UnityEditor; | |||||
using UnityEngine; | |||||
[CustomEditor(typeof(VRCSDK2.VRC_ObjectSync))] | |||||
public class VRC_ObjectSyncEditor : Editor { | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
VRCSDK2.VRC_ObjectSync c = ((VRCSDK2.VRC_ObjectSync)target); | |||||
if ((c.gameObject.GetComponent<Animator>() != null || c.gameObject.GetComponent<Animation>() != null) && c.SynchronizePhysics) | |||||
EditorGUILayout.HelpBox("If the Animator or Animation moves the root position of this object then it will conflict with physics synchronization.", MessageType.Warning); | |||||
if (c.GetComponent<VRCSDK2.VRC_DataStorage>() != null && c.SynchronizePhysics) | |||||
EditorGUILayout.HelpBox("Consider either removing the VRC_DataStorage or disabling SynchronizePhysics.", MessageType.Warning); | |||||
DrawDefaultInspector(); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: e19a7147a2386554a8e4d6e414f190a2 | |||||
timeCreated: 1504908295 | |||||
licenseType: Free | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using UnityEngine; | |||||
using UnityEditor; | |||||
using UnityEditorInternal; | |||||
[CustomPropertyDrawer(typeof(VRCSDK2.VRC_SyncVideoPlayer.VideoEntry))] | |||||
public class CustomVideoEntryDrawer : PropertyDrawer | |||||
{ | |||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) | |||||
{ | |||||
SerializedProperty source = property.FindPropertyRelative("Source"); | |||||
SerializedProperty ratio = property.FindPropertyRelative("AspectRatio"); | |||||
SerializedProperty speed = property.FindPropertyRelative("PlaybackSpeed"); | |||||
SerializedProperty clip = property.FindPropertyRelative("VideoClip"); | |||||
SerializedProperty url = property.FindPropertyRelative("URL"); | |||||
return EditorGUI.GetPropertyHeight(source, new GUIContent("Source"), true) + EditorGUIUtility.standardVerticalSpacing | |||||
+ EditorGUI.GetPropertyHeight(ratio, new GUIContent("Aspect Ratio"), true) + EditorGUIUtility.standardVerticalSpacing | |||||
+ EditorGUI.GetPropertyHeight(speed, new GUIContent("Playback Speed"), true) + EditorGUIUtility.standardVerticalSpacing | |||||
+ Mathf.Max(EditorGUI.GetPropertyHeight(clip, new GUIContent("VideoClip"), true), EditorGUI.GetPropertyHeight(url, new GUIContent("URL"), true)) + EditorGUIUtility.standardVerticalSpacing; | |||||
} | |||||
public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label) | |||||
{ | |||||
SerializedProperty source = property.FindPropertyRelative("Source"); | |||||
SerializedProperty ratio = property.FindPropertyRelative("AspectRatio"); | |||||
SerializedProperty speed = property.FindPropertyRelative("PlaybackSpeed"); | |||||
SerializedProperty clip = property.FindPropertyRelative("VideoClip"); | |||||
SerializedProperty url = property.FindPropertyRelative("URL"); | |||||
EditorGUI.BeginProperty(rect, label, property); | |||||
float x = rect.x; | |||||
float y = rect.y; | |||||
float w = rect.width; | |||||
float h = EditorGUI.GetPropertyHeight(source, new GUIContent("Source"), true) + EditorGUIUtility.standardVerticalSpacing; | |||||
VRCSDK2.VRC_EditorTools.FilteredEnumPopup<UnityEngine.Video.VideoSource>(new Rect(x, y, w, h), source, (e) => e == UnityEngine.Video.VideoSource.Url); | |||||
y += h; | |||||
if (source.enumValueIndex == (int)UnityEngine.Video.VideoSource.Url) | |||||
{ | |||||
h = EditorGUI.GetPropertyHeight(url, new GUIContent("URL"), true) + EditorGUIUtility.standardVerticalSpacing; | |||||
EditorGUI.PropertyField(new Rect(x, y, w, h), url); | |||||
y += h; | |||||
} | |||||
else | |||||
{ | |||||
h = EditorGUI.GetPropertyHeight(clip, new GUIContent("VideoClip"), true) + EditorGUIUtility.standardVerticalSpacing; | |||||
EditorGUI.PropertyField(new Rect(x, y, w, h), clip); | |||||
y += h; | |||||
} | |||||
h = EditorGUI.GetPropertyHeight(ratio, new GUIContent("AspectRatio"), true) + EditorGUIUtility.standardVerticalSpacing; | |||||
EditorGUI.PropertyField(new Rect(x, y, w, h), ratio); | |||||
y += h; | |||||
h = EditorGUI.GetPropertyHeight(ratio, new GUIContent("Playback Speed"), true) + EditorGUIUtility.standardVerticalSpacing; | |||||
EditorGUI.PropertyField(new Rect(x, y, w, h), speed); | |||||
if (speed.floatValue == 0f) | |||||
speed.floatValue = 1f; | |||||
y += h; | |||||
EditorGUI.EndProperty(); | |||||
} | |||||
} | |||||
[CustomEditor(typeof(VRCSDK2.VRC_SyncVideoPlayer))] | |||||
public class SyncVideoPlayerEditor : Editor | |||||
{ | |||||
ReorderableList sourceList; | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
SerializedProperty searchRoot = serializedObject.FindProperty("VideoSearchRoot"); | |||||
EditorGUILayout.PropertyField(searchRoot); | |||||
SerializedProperty maxQual = serializedObject.FindProperty("MaxStreamQuality"); | |||||
EditorGUILayout.PropertyField(maxQual); | |||||
EditorGUILayout.Space(); | |||||
sourceList.DoLayoutList(); | |||||
serializedObject.ApplyModifiedProperties(); | |||||
} | |||||
private void OnEnable() | |||||
{ | |||||
SerializedProperty videos = serializedObject.FindProperty("Videos"); | |||||
sourceList = new ReorderableList(serializedObject, videos); | |||||
sourceList.drawElementCallback += (Rect rect, int index, bool active, bool focused) => | |||||
{ | |||||
EditorGUI.PropertyField(rect, serializedObject.FindProperty("Videos").GetArrayElementAtIndex(index)); | |||||
}; | |||||
sourceList.elementHeightCallback += (int index) => | |||||
{ | |||||
SerializedProperty element = serializedObject.FindProperty("Videos").GetArrayElementAtIndex(index); | |||||
return EditorGUI.GetPropertyHeight(element); | |||||
}; | |||||
sourceList.drawHeaderCallback = (Rect rect) => EditorGUI.LabelField(rect, "Videos"); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: ae0e74693b7899f47bd98864f94b9311 | |||||
timeCreated: 1499468412 | |||||
licenseType: Free | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using UnityEngine; | |||||
using UnityEditor; | |||||
using UnityEditorInternal; | |||||
[CustomPropertyDrawer(typeof(VRCSDK2.VRC_SyncVideoStream.VideoEntry))] | |||||
public class CustomVideoStreamEntryDrawer : PropertyDrawer | |||||
{ | |||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) | |||||
{ | |||||
SerializedProperty source = property.FindPropertyRelative("Source"); | |||||
SerializedProperty speed = property.FindPropertyRelative("PlaybackSpeed"); | |||||
SerializedProperty clip = property.FindPropertyRelative("VideoClip"); | |||||
SerializedProperty url = property.FindPropertyRelative("URL"); | |||||
SerializedProperty live = property.FindPropertyRelative("SyncType"); | |||||
SerializedProperty sync = property.FindPropertyRelative("SyncMinutes"); | |||||
return EditorGUI.GetPropertyHeight(source, new GUIContent("Source"), true) + EditorGUIUtility.standardVerticalSpacing | |||||
+ EditorGUI.GetPropertyHeight(speed, new GUIContent("Playback Speed"), true) + EditorGUIUtility.standardVerticalSpacing | |||||
+ Mathf.Max(EditorGUI.GetPropertyHeight(clip, new GUIContent("VideoClip"), true), EditorGUI.GetPropertyHeight(url, new GUIContent("URL"), true)) + EditorGUIUtility.standardVerticalSpacing | |||||
+ EditorGUI.GetPropertyHeight(speed, new GUIContent("SyncType"), true) + EditorGUIUtility.standardVerticalSpacing | |||||
+ EditorGUI.GetPropertyHeight(speed, new GUIContent("SyncMinutes"), true) + EditorGUIUtility.standardVerticalSpacing; | |||||
} | |||||
public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label) | |||||
{ | |||||
SerializedProperty source = property.FindPropertyRelative("Source"); | |||||
SerializedProperty speed = property.FindPropertyRelative("PlaybackSpeed"); | |||||
SerializedProperty clip = property.FindPropertyRelative("VideoClip"); | |||||
SerializedProperty url = property.FindPropertyRelative("URL"); | |||||
SerializedProperty live = property.FindPropertyRelative("SyncType"); | |||||
SerializedProperty sync = property.FindPropertyRelative("SyncMinutes"); | |||||
EditorGUI.BeginProperty(rect, label, property); | |||||
float x = rect.x; | |||||
float y = rect.y; | |||||
float w = rect.width; | |||||
float h = EditorGUI.GetPropertyHeight(source, new GUIContent("Source"), true) + EditorGUIUtility.standardVerticalSpacing; | |||||
VRCSDK2.VRC_EditorTools.FilteredEnumPopup<UnityEngine.Video.VideoSource>(new Rect(x, y, w, h), source, (e) => e == UnityEngine.Video.VideoSource.Url); | |||||
y += h; | |||||
if (source.enumValueIndex == (int)UnityEngine.Video.VideoSource.Url) | |||||
{ | |||||
h = EditorGUI.GetPropertyHeight(url, new GUIContent("URL"), true) + EditorGUIUtility.standardVerticalSpacing; | |||||
EditorGUI.PropertyField(new Rect(x, y, w, h), url); | |||||
y += h; | |||||
} | |||||
else | |||||
{ | |||||
h = EditorGUI.GetPropertyHeight(clip, new GUIContent("VideoClip"), true) + EditorGUIUtility.standardVerticalSpacing; | |||||
EditorGUI.PropertyField(new Rect(x, y, w, h), clip); | |||||
y += h; | |||||
} | |||||
h = EditorGUI.GetPropertyHeight(speed, new GUIContent("Playback Speed"), true) + EditorGUIUtility.standardVerticalSpacing; | |||||
EditorGUI.PropertyField(new Rect(x, y, w, h), speed); | |||||
if (speed.floatValue == 0f) | |||||
speed.floatValue = 1f; | |||||
y += h; | |||||
h = EditorGUI.GetPropertyHeight(live, new GUIContent("SyncType"), true) + EditorGUIUtility.standardVerticalSpacing; | |||||
EditorGUI.PropertyField(new Rect(x, y, w, h), live); | |||||
y += h; | |||||
h = EditorGUI.GetPropertyHeight(sync, new GUIContent("SyncMinutes"), true) + EditorGUIUtility.standardVerticalSpacing; | |||||
EditorGUI.PropertyField(new Rect(x, y, w, h), sync); | |||||
if (sync.floatValue < 1f) | |||||
sync.floatValue = 0; | |||||
y += h; | |||||
EditorGUI.EndProperty(); | |||||
} | |||||
} | |||||
[CustomEditor(typeof(VRCSDK2.VRC_SyncVideoStream))] | |||||
public class SyncVideoStreamEditor : Editor | |||||
{ | |||||
ReorderableList sourceList; | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
SerializedProperty searchRoot = serializedObject.FindProperty("VideoSearchRoot"); | |||||
EditorGUILayout.PropertyField(searchRoot); | |||||
SerializedProperty maxQual = serializedObject.FindProperty("MaxStreamQuality"); | |||||
EditorGUILayout.PropertyField(maxQual); | |||||
SerializedProperty texFmt = serializedObject.FindProperty("videoTextureFormat"); | |||||
EditorGUILayout.PropertyField(texFmt); | |||||
SerializedProperty autoStart = serializedObject.FindProperty("AutoStart"); | |||||
EditorGUILayout.PropertyField(autoStart); | |||||
EditorGUILayout.Space(); | |||||
sourceList.DoLayoutList(); | |||||
serializedObject.ApplyModifiedProperties(); | |||||
} | |||||
private void OnEnable() | |||||
{ | |||||
SerializedProperty videos = serializedObject.FindProperty("Videos"); | |||||
sourceList = new ReorderableList(serializedObject, videos); | |||||
sourceList.drawElementCallback += (Rect rect, int index, bool active, bool focused) => | |||||
{ | |||||
EditorGUI.PropertyField(rect, serializedObject.FindProperty("Videos").GetArrayElementAtIndex(index)); | |||||
}; | |||||
sourceList.elementHeightCallback += (int index) => | |||||
{ | |||||
SerializedProperty element = serializedObject.FindProperty("Videos").GetArrayElementAtIndex(index); | |||||
return EditorGUI.GetPropertyHeight(element); | |||||
}; | |||||
sourceList.drawHeaderCallback = (Rect rect) => EditorGUI.LabelField(rect, "Videos"); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 3f9dccfed0b072f49a307b3f20a7e768 | |||||
timeCreated: 1528745185 | |||||
licenseType: Pro | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 3aecd666943878944a811acb9db2ace7 | |||||
timeCreated: 1474315179 | |||||
licenseType: Free | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
#if UNITY_EDITOR | |||||
using System.IO; | |||||
using UnityEditor; | |||||
using UnityEngine; | |||||
using UnityEditor.Build; | |||||
using System; | |||||
using System.Linq; | |||||
namespace VRCSDK2 | |||||
{ | |||||
[CustomEditor(typeof(VRC_WebPanel))] | |||||
public class VRC_WebPanelEditor : Editor | |||||
{ | |||||
private void InspectorField(string propertyName, string humanName) | |||||
{ | |||||
SerializedProperty propertyField = serializedObject.FindProperty(propertyName); | |||||
EditorGUILayout.PropertyField(propertyField, new GUIContent(humanName), true); | |||||
} | |||||
bool showFiles = false; | |||||
bool showHelp = true; | |||||
System.Collections.Generic.List<string> directories = null; | |||||
System.Collections.Generic.List<string> files = null; | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
serializedObject.Update(); | |||||
EditorGUI.BeginChangeCheck(); | |||||
EditorGUILayout.BeginVertical(); | |||||
EditorGUILayout.HelpBox("Do not play any videos with Web Panels, use VRC_VideoPlayerSync instead!", MessageType.Error); | |||||
showHelp = EditorGUILayout.Toggle("Show Help", showHelp); | |||||
EditorGUILayout.Space(); | |||||
InspectorField("proximity", "Proximity for Interactivity"); | |||||
EditorGUILayout.Space(); | |||||
VRC_WebPanel web = (VRC_WebPanel)target; | |||||
if (Application.isPlaying) | |||||
{ | |||||
InspectorField("webRoot", "Web Root"); | |||||
InspectorField("defaultUrl", "URI"); | |||||
showFiles = web.webData != null && EditorGUILayout.Foldout(showFiles, web.webData.Count.ToString() + " files imported"); | |||||
if (showFiles) | |||||
foreach (var file in web.webData) | |||||
{ | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.PrefixLabel(file.path); | |||||
EditorGUILayout.LabelField(file.data.Length.ToString()); | |||||
EditorGUILayout.EndHorizontal(); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
SerializedProperty webRoot = serializedObject.FindProperty("webRoot"); | |||||
RenderDirectoryList(serializedObject, "webRoot", "Path To Web Content"); | |||||
if (string.IsNullOrEmpty(webRoot.stringValue)) | |||||
{ | |||||
InspectorField("defaultUrl", "Start URI"); | |||||
} | |||||
else | |||||
{ | |||||
RenderWebRootSelector(serializedObject, "defaultUrl", "Start Page"); | |||||
if (showHelp) | |||||
{ | |||||
EditorGUILayout.HelpBox("Javascript API bindings are called with engine.call('methodName', ...), which returns a promise-like object.", MessageType.Info); | |||||
EditorGUILayout.HelpBox("Javascript may call ListBindings() to discover available API bindings.", MessageType.Info); | |||||
EditorGUILayout.HelpBox("Javascript may listen for the 'onBindingsReady' event to execute script when the page is fully loaded and API bindings are available.", MessageType.Info); | |||||
} | |||||
} | |||||
} | |||||
EditorGUILayout.Space(); | |||||
InspectorField("cookiesEnabled", "Enable Cookies"); | |||||
InspectorField("interactive", "Is Interactive"); | |||||
InspectorField("localOnly", "Only Visible Locally"); | |||||
if (!web.localOnly) | |||||
{ | |||||
InspectorField("syncURI", "Synchronize URI"); | |||||
InspectorField("syncInput", "Synchronize Mouse Position"); | |||||
} | |||||
InspectorField("transparent", "Transparent Background"); | |||||
InspectorField("autoFormSubmit", "Input should Submit Forms"); | |||||
EditorGUILayout.Space(); | |||||
InspectorField("station", "Interaction Station"); | |||||
EditorGUILayout.Space(); | |||||
InspectorField("cursor", "Mouse Cursor Object"); | |||||
EditorGUILayout.Space(); | |||||
InspectorField("resolutionWidth", "Resolution Width"); | |||||
InspectorField("resolutionHeight", "Resolution Height"); | |||||
InspectorField("displayRegion", "Display Region"); | |||||
EditorGUILayout.Space(); | |||||
InspectorField("extraVideoScreens", "Duplicate Screens"); | |||||
EditorGUILayout.EndVertical(); | |||||
if (EditorGUI.EndChangeCheck()) | |||||
serializedObject.ApplyModifiedProperties(); | |||||
} | |||||
private void AddSubDirectories(ref System.Collections.Generic.List<string> l, string root) | |||||
{ | |||||
if (!Directory.Exists(root)) | |||||
{ | |||||
return; | |||||
} | |||||
if (!root.StartsWith(Application.dataPath + Path.DirectorySeparatorChar + "VRCSDK") | |||||
|| root == Application.dataPath + Path.DirectorySeparatorChar + "VRCSDK" + Path.DirectorySeparatorChar + "Examples" + Path.DirectorySeparatorChar + "Sample Assets" + Path.DirectorySeparatorChar + "WebRoot") | |||||
l.Add(root.Substring(Application.dataPath.Length)); | |||||
string[] subdirectories = Directory.GetDirectories(root); | |||||
foreach (string dir in subdirectories) | |||||
AddSubDirectories(ref l, dir); | |||||
} | |||||
private void RenderDirectoryList(SerializedObject obj, string propertyName, string humanName) | |||||
{ | |||||
if (directories == null) | |||||
{ | |||||
directories = new System.Collections.Generic.List<string>(); | |||||
directories.Add("No Web Content Directory"); | |||||
AddSubDirectories(ref directories, Application.dataPath + Path.DirectorySeparatorChar); | |||||
} | |||||
SerializedProperty target = serializedObject.FindProperty(propertyName); | |||||
int selectedIdx = target.stringValue == null ? 0 : directories.IndexOf(target.stringValue); | |||||
if (selectedIdx < 0 || selectedIdx >= directories.Count) | |||||
selectedIdx = 0; | |||||
selectedIdx = EditorGUILayout.Popup(humanName, selectedIdx, directories.ToArray()); | |||||
if (selectedIdx > 0 && selectedIdx < directories.Count) | |||||
target.stringValue = directories[selectedIdx]; | |||||
else | |||||
target.stringValue = null; | |||||
} | |||||
private void AddSubDirectoryFiles(ref System.Collections.Generic.List<string> l, string root) | |||||
{ | |||||
if (!Directory.Exists(root)) | |||||
return; | |||||
string[] files = Directory.GetFiles(root); | |||||
foreach (string file in files.Where(f => f.ToLower().EndsWith(".html") || f.ToLower().EndsWith(".htm"))) | |||||
l.Add(file.Substring(Application.dataPath.Length)); | |||||
string[] subdirectories = Directory.GetDirectories(root); | |||||
foreach (string dir in subdirectories) | |||||
AddSubDirectoryFiles(ref l, dir); | |||||
} | |||||
private void RenderWebRootSelector(SerializedObject obj, string propertyName, string humanName) | |||||
{ | |||||
SerializedProperty webRoot = obj.FindProperty("webRoot"); | |||||
SerializedProperty target = serializedObject.FindProperty(propertyName); | |||||
if (files == null) | |||||
{ | |||||
files = new System.Collections.Generic.List<string>(); | |||||
AddSubDirectoryFiles(ref files, Application.dataPath + webRoot.stringValue); | |||||
if (files.Count == 0) | |||||
{ | |||||
EditorGUILayout.HelpBox("No suitable html files found in Web Content path.", MessageType.Error); | |||||
return; | |||||
} | |||||
} | |||||
int selectedIdx = 0; | |||||
try | |||||
{ | |||||
System.Uri uri = string.IsNullOrEmpty(target.stringValue) ? null : new Uri(target.stringValue); | |||||
selectedIdx = uri == null ? 0 : files.IndexOf(uri.AbsolutePath.Replace('/', System.IO.Path.DirectorySeparatorChar)); | |||||
if (selectedIdx < 0 || selectedIdx >= files.Count) | |||||
selectedIdx = 0; | |||||
} | |||||
catch { } | |||||
selectedIdx = EditorGUILayout.Popup(humanName, selectedIdx, files.ToArray()); | |||||
if (selectedIdx >= 0 && selectedIdx < files.Count) | |||||
{ | |||||
System.UriBuilder builder = new UriBuilder() | |||||
{ | |||||
Scheme = "file", | |||||
Path = files[selectedIdx].Replace(System.IO.Path.DirectorySeparatorChar, '/'), | |||||
Host = "" | |||||
}; | |||||
target.stringValue = builder.Uri.ToString(); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
#endif |
fileFormatVersion: 2 | |||||
guid: d09b36020f697be4d9a0f5a6a48cfa83 | |||||
timeCreated: 1457992191 | |||||
licenseType: Free | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
#if UNITY_EDITOR | |||||
using UnityEngine; | |||||
using UnityEditor; | |||||
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.IO; | |||||
namespace VRCSDK2 | |||||
{ | |||||
[CustomEditor(typeof(VRC_YouTubeSync))] | |||||
public class VRC_YouTubeSyncEditor : Editor | |||||
{ | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
EditorGUILayout.HelpBox("This component is deprecated, please use the VRC_SyncVideoPlayer component instead.", MessageType.Error); | |||||
} | |||||
} | |||||
} | |||||
#endif |
fileFormatVersion: 2 | |||||
guid: 764e26c1ca28e2e45a30c778c1955a47 | |||||
timeCreated: 1474675311 | |||||
licenseType: Pro | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: e751dcaa3656a324f91244e7b795d83a | |||||
folderAsset: yes | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using UnityEditor; | |||||
using UnityEngine; | |||||
using VRC.Core; | |||||
[ExecuteInEditMode] | |||||
public partial class VRCSdkControlPanel : EditorWindow | |||||
{ | |||||
public static VRCSdkControlPanel window; | |||||
[MenuItem("VRChat SDK/Show Control Panel", false, 600)] | |||||
static void ShowControlPanel() | |||||
{ | |||||
if (!RemoteConfig.IsInitialized()) | |||||
{ | |||||
VRC.Core.API.SetOnlineMode(true, "vrchat"); | |||||
RemoteConfig.Init(() => ShowControlPanel()); | |||||
return; | |||||
} | |||||
window = (VRCSdkControlPanel)EditorWindow.GetWindow(typeof(VRCSdkControlPanel)); | |||||
window.titleContent.text = "VRChat SDK"; | |||||
window.minSize = new Vector2(SdkWindowWidth + 4, 600); | |||||
window.maxSize = new Vector2(SdkWindowWidth + 4, 2000); | |||||
window.Init(); | |||||
window.Show(); | |||||
} | |||||
void Update() | |||||
{ | |||||
Repaint(); | |||||
} | |||||
static GUIStyle titleGuiStyle; | |||||
static GUIStyle boxGuiStyle; | |||||
static GUIStyle infoGuiStyle; | |||||
static GUIStyle listButtonStyleEven; | |||||
static GUIStyle listButtonStyleOdd; | |||||
static GUIStyle listButtonStyleSelected; | |||||
void InitializeStyles() | |||||
{ | |||||
titleGuiStyle = new GUIStyle(); | |||||
titleGuiStyle.fontSize = 15; | |||||
titleGuiStyle.fontStyle = FontStyle.BoldAndItalic; | |||||
titleGuiStyle.alignment = TextAnchor.MiddleCenter; | |||||
titleGuiStyle.wordWrap = true; | |||||
if (EditorGUIUtility.isProSkin) | |||||
titleGuiStyle.normal.textColor = Color.white; | |||||
else | |||||
titleGuiStyle.normal.textColor = Color.black; | |||||
boxGuiStyle = new GUIStyle(); | |||||
if (EditorGUIUtility.isProSkin) | |||||
{ | |||||
boxGuiStyle.normal.background = CreateBackgroundColorImage(new Color(0.6f, 0.6f, 0.6f)); | |||||
boxGuiStyle.normal.textColor = Color.white; | |||||
} | |||||
else | |||||
{ | |||||
boxGuiStyle.normal.background = CreateBackgroundColorImage(new Color(0.85f, 0.85f, 0.85f)); | |||||
boxGuiStyle.normal.textColor = Color.black; | |||||
} | |||||
infoGuiStyle = new GUIStyle(); | |||||
infoGuiStyle.wordWrap = true; ; | |||||
if (EditorGUIUtility.isProSkin) | |||||
infoGuiStyle.normal.textColor = Color.white; | |||||
else | |||||
infoGuiStyle.normal.textColor = Color.black; | |||||
infoGuiStyle.margin = new RectOffset(10, 10, 10, 10); | |||||
listButtonStyleEven = new GUIStyle(); | |||||
listButtonStyleEven.margin = new RectOffset(0, 0, 0, 0); | |||||
listButtonStyleEven.border = new RectOffset(0, 0, 0, 0); | |||||
if (EditorGUIUtility.isProSkin) | |||||
{ | |||||
listButtonStyleEven.normal.textColor = new Color(0.8f, 0.8f, 0.8f); | |||||
listButtonStyleEven.normal.background = CreateBackgroundColorImage(new Color(0.540f, 0.540f, 0.54f)); | |||||
} | |||||
else | |||||
{ | |||||
listButtonStyleEven.normal.textColor = Color.black; | |||||
listButtonStyleEven.normal.background = CreateBackgroundColorImage(new Color(0.85f, 0.85f, 0.85f)); | |||||
} | |||||
listButtonStyleOdd = new GUIStyle(); | |||||
listButtonStyleOdd.margin = new RectOffset(0, 0, 0, 0); | |||||
listButtonStyleOdd.border = new RectOffset(0, 0, 0, 0); | |||||
if (EditorGUIUtility.isProSkin) | |||||
{ | |||||
listButtonStyleOdd.normal.textColor = new Color(0.8f, 0.8f, 0.8f); | |||||
//listButtonStyleOdd.normal.background = CreateBackgroundColorImage(new Color(0.50f, 0.50f, 0.50f)); | |||||
} | |||||
else | |||||
{ | |||||
listButtonStyleOdd.normal.textColor = Color.black; | |||||
listButtonStyleOdd.normal.background = CreateBackgroundColorImage(new Color(0.90f, 0.90f, 0.90f)); | |||||
} | |||||
listButtonStyleSelected = new GUIStyle(); | |||||
listButtonStyleSelected.normal.textColor = Color.white; | |||||
listButtonStyleSelected.margin = new RectOffset(0, 0, 0, 0); | |||||
if (EditorGUIUtility.isProSkin) | |||||
{ | |||||
listButtonStyleSelected.normal.textColor = new Color(0.8f, 0.8f, 0.8f); | |||||
listButtonStyleSelected.normal.background = CreateBackgroundColorImage(new Color(0.4f, 0.4f, 0.4f)); | |||||
} | |||||
else | |||||
{ | |||||
listButtonStyleSelected.normal.textColor = Color.black; | |||||
listButtonStyleSelected.normal.background = CreateBackgroundColorImage(new Color(0.75f, 0.75f, 0.75f)); | |||||
} | |||||
} | |||||
void Init() | |||||
{ | |||||
InitializeStyles(); | |||||
ResetIssues(); | |||||
InitAccount(); | |||||
} | |||||
void OnEnable() | |||||
{ | |||||
OnEnableAccount(); | |||||
AssemblyReloadEvents.afterAssemblyReload += BuilderAssemblyReload; | |||||
} | |||||
void OnDisable() | |||||
{ | |||||
AssemblyReloadEvents.afterAssemblyReload -= BuilderAssemblyReload; | |||||
} | |||||
void OnDestroy() | |||||
{ | |||||
AccountDestroy(); | |||||
} | |||||
const int SdkWindowWidth = 518; | |||||
void OnGUI() | |||||
{ | |||||
if (window == null) | |||||
{ | |||||
window = (VRCSdkControlPanel)EditorWindow.GetWindow(typeof(VRCSdkControlPanel)); | |||||
InitializeStyles(); | |||||
} | |||||
if (_bannerImage == null) | |||||
_bannerImage = AssetDatabase.LoadAssetAtPath("Assets/VRCSDK/Dependencies/VRChat/SdkGraphics/SDK_Panel_Banner.png", typeof(Texture2D)) as Texture2D; | |||||
GUILayout.Box(_bannerImage); | |||||
if (Application.isPlaying) | |||||
{ | |||||
EditorGUILayout.LabelField("You cannot edit your VRChat data while the Unity Application is running"); | |||||
return; | |||||
} | |||||
EditorGUILayout.Space(); | |||||
VRCSettings.Get().activeWindowPanel = GUILayout.Toolbar(VRCSettings.Get().activeWindowPanel, new string[] { "Authentication", "Builder", "Content Manager", "Settings" }, GUILayout.Width(SdkWindowWidth)); | |||||
int showPanel = VRCSettings.Get().activeWindowPanel; | |||||
if (APIUser.IsLoggedInWithCredentials == false && showPanel != 3) | |||||
showPanel = 0; | |||||
switch (showPanel) | |||||
{ | |||||
case 1: | |||||
ShowBuilder(); | |||||
break; | |||||
case 2: | |||||
ShowContent(); | |||||
break; | |||||
case 3: | |||||
ShowSettings(); | |||||
break; | |||||
case 0: | |||||
default: | |||||
ShowAccount(); | |||||
break; | |||||
} | |||||
} | |||||
[UnityEditor.Callbacks.PostProcessScene] | |||||
static void OnPostProcessScene() | |||||
{ | |||||
if (window != null) | |||||
window.Reset(); | |||||
} | |||||
private void OnFocus() | |||||
{ | |||||
Reset(); | |||||
} | |||||
public void Reset() | |||||
{ | |||||
ResetIssues(); | |||||
} | |||||
[UnityEditor.Callbacks.DidReloadScripts(int.MaxValue)] | |||||
static void DidReloadScripts() | |||||
{ | |||||
RefreshApiUrlSetting(); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 20b4cdbdda9655947aab6f8f2c90690f | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using UnityEngine; | |||||
using UnityEditor; | |||||
using VRC.Core; | |||||
using System.Text.RegularExpressions; | |||||
public partial class VRCSdkControlPanel : EditorWindow | |||||
{ | |||||
static bool isInitialized = false; | |||||
static string clientInstallPath; | |||||
static bool signingIn = false; | |||||
static string error = null; | |||||
public static bool FutureProofPublishEnabled { get { return UnityEditor.EditorPrefs.GetBool("futureProofPublish", DefaultFutureProofPublishEnabled); } } | |||||
public static bool DefaultFutureProofPublishEnabled { get { return !SDKClientUtilities.IsInternalSDK(); } } | |||||
static string storedUsername | |||||
{ | |||||
get | |||||
{ | |||||
if (EditorPrefs.HasKey("sdk#username")) | |||||
return EditorPrefs.GetString("sdk#username"); | |||||
return null; | |||||
} | |||||
set | |||||
{ | |||||
EditorPrefs.SetString("sdk#username", value); | |||||
if (string.IsNullOrEmpty(value)) | |||||
EditorPrefs.DeleteKey("sdk#username"); | |||||
} | |||||
} | |||||
static string storedPassword | |||||
{ | |||||
get | |||||
{ | |||||
if (EditorPrefs.HasKey("sdk#password")) | |||||
return EditorPrefs.GetString("sdk#password"); | |||||
return null; | |||||
} | |||||
set | |||||
{ | |||||
EditorPrefs.SetString("sdk#password", value); | |||||
if (string.IsNullOrEmpty(value)) | |||||
EditorPrefs.DeleteKey("sdk#password"); | |||||
} | |||||
} | |||||
static string _username = null; | |||||
static string _password = null; | |||||
static string username | |||||
{ | |||||
get | |||||
{ | |||||
if (!string.IsNullOrEmpty(_username)) | |||||
return _username; | |||||
else | |||||
_username = storedUsername; | |||||
return _username; | |||||
} | |||||
set | |||||
{ | |||||
_username = value; | |||||
} | |||||
} | |||||
static string password | |||||
{ | |||||
get | |||||
{ | |||||
if (!string.IsNullOrEmpty(_password)) | |||||
return _password; | |||||
else | |||||
_password = storedPassword; | |||||
return _password; | |||||
} | |||||
set | |||||
{ | |||||
_password = value; | |||||
} | |||||
} | |||||
static ApiServerEnvironment serverEnvironment | |||||
{ | |||||
get | |||||
{ | |||||
ApiServerEnvironment env = ApiServerEnvironment.Release; | |||||
try | |||||
{ | |||||
env = (ApiServerEnvironment)System.Enum.Parse(typeof(ApiServerEnvironment), UnityEditor.EditorPrefs.GetString("VRC_ApiServerEnvironment", env.ToString())); | |||||
} | |||||
catch (System.Exception e) | |||||
{ | |||||
Debug.LogError("Invalid server environment name - " + e.ToString()); | |||||
} | |||||
return env; | |||||
} | |||||
set | |||||
{ | |||||
UnityEditor.EditorPrefs.SetString("VRC_ApiServerEnvironment", value.ToString()); | |||||
API.SetApiUrlFromEnvironment(value); | |||||
} | |||||
} | |||||
private void OnEnableAccount() | |||||
{ | |||||
entered2faCodeIsInvalid = false; | |||||
warningIconGraphic = Resources.Load("2FAIcons/SDK_Warning_Triangle_icon") as Texture2D; | |||||
} | |||||
public static void RefreshApiUrlSetting() | |||||
{ | |||||
// this forces the static api url variable to be reset from the server environment set in editor prefs. | |||||
// needed because the static variable states get cleared when entering / exiting play mode | |||||
ApiServerEnvironment env = serverEnvironment; | |||||
serverEnvironment = env; | |||||
} | |||||
public static void InitAccount() | |||||
{ | |||||
if (isInitialized) | |||||
return; | |||||
if (!APIUser.IsLoggedInWithCredentials && ApiCredentials.Load()) | |||||
APIUser.FetchCurrentUser((c) => AnalyticsSDK.LoggedInUserChanged(c.Model as APIUser), null); | |||||
clientInstallPath = SDKClientUtilities.GetSavedVRCInstallPath(); | |||||
if (string.IsNullOrEmpty(clientInstallPath)) | |||||
clientInstallPath = SDKClientUtilities.LoadRegistryVRCInstallPath(); | |||||
signingIn = false; | |||||
isInitialized = true; | |||||
ClearContent(); | |||||
} | |||||
public static bool OnShowStatus() | |||||
{ | |||||
API.SetOnlineMode(true); | |||||
SignIn(false); | |||||
EditorGUILayout.BeginVertical(); | |||||
if (APIUser.IsLoggedInWithCredentials) | |||||
{ | |||||
OnCreatorStatusGUI(); | |||||
} | |||||
EditorGUILayout.EndVertical(); | |||||
return APIUser.IsLoggedInWithCredentials; | |||||
} | |||||
static bool OnAccountGUI() | |||||
{ | |||||
const int ACCOUNT_LOGIN_BORDER_SPACING = 20; | |||||
EditorGUILayout.Separator(); | |||||
EditorGUILayout.Separator(); | |||||
EditorGUILayout.Separator(); | |||||
EditorGUILayout.Separator(); | |||||
GUILayout.BeginHorizontal(); | |||||
GUILayout.FlexibleSpace(); | |||||
GUILayout.Space(ACCOUNT_LOGIN_BORDER_SPACING); | |||||
GUILayout.BeginVertical("Account", "window", GUILayout.Height(150), GUILayout.Width(340)); | |||||
if (signingIn) | |||||
{ | |||||
EditorGUILayout.LabelField("Signing in as " + username + "."); | |||||
} | |||||
else if (APIUser.IsLoggedInWithCredentials) | |||||
{ | |||||
if (Status != "Connected") | |||||
EditorGUILayout.LabelField(Status); | |||||
OnCreatorStatusGUI(); | |||||
GUILayout.BeginHorizontal(); | |||||
GUILayout.Label(""); | |||||
if (GUILayout.Button("Logout")) | |||||
{ | |||||
storedUsername = username = null; | |||||
storedPassword = password = null; | |||||
VRC.Tools.ClearCookies(); | |||||
APIUser.Logout(); | |||||
ClearContent(); | |||||
} | |||||
GUILayout.EndHorizontal(); | |||||
} | |||||
else | |||||
{ | |||||
InitAccount(); | |||||
ApiServerEnvironment newEnv = ApiServerEnvironment.Release; | |||||
if (VRCSettings.Get().DisplayAdvancedSettings) | |||||
newEnv = (ApiServerEnvironment)EditorGUILayout.EnumPopup("Use API", serverEnvironment); | |||||
if (serverEnvironment != newEnv) | |||||
serverEnvironment = newEnv; | |||||
username = EditorGUILayout.TextField("Username", username); | |||||
password = EditorGUILayout.PasswordField("Password", password); | |||||
if (GUILayout.Button("Sign In")) | |||||
SignIn(true); | |||||
if (GUILayout.Button("Sign up")) | |||||
Application.OpenURL("http://vrchat.com/register"); | |||||
} | |||||
if (showTwoFactorAuthenticationEntry) | |||||
{ | |||||
OnTwoFactorAuthenticationGUI(); | |||||
} | |||||
GUILayout.EndVertical(); | |||||
GUILayout.Space(ACCOUNT_LOGIN_BORDER_SPACING); | |||||
GUILayout.FlexibleSpace(); | |||||
GUILayout.EndHorizontal(); | |||||
return !signingIn; | |||||
} | |||||
static void OnCreatorStatusGUI() | |||||
{ | |||||
EditorGUILayout.LabelField("Logged in as:", APIUser.CurrentUser.displayName); | |||||
if (SDKClientUtilities.IsInternalSDK()) | |||||
EditorGUILayout.LabelField("Developer Status: ", APIUser.CurrentUser.developerType.ToString()); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.BeginVertical(); | |||||
EditorGUILayout.LabelField("World Creator Status: ", APIUser.CurrentUser.canPublishWorlds ? "Allowed to publish worlds" : "Not yet allowed to publish worlds"); | |||||
EditorGUILayout.LabelField("Avatar Creator Status: ", APIUser.CurrentUser.canPublishAvatars ? "Allowed to publish avatars" : "Not yet allowed to publish avatars"); | |||||
EditorGUILayout.EndVertical(); | |||||
if (!APIUser.CurrentUser.canPublishAllContent) | |||||
{ | |||||
if (GUILayout.Button("More Info...")) | |||||
{ | |||||
VRCSdkControlPanel.ShowContentPublishPermissionsDialog(); | |||||
} | |||||
} | |||||
EditorGUILayout.EndHorizontal(); | |||||
} | |||||
void ShowAccount() | |||||
{ | |||||
if (VRC.Core.RemoteConfig.IsInitialized()) | |||||
{ | |||||
if (VRC.Core.RemoteConfig.HasKey("sdkUnityVersion")) | |||||
{ | |||||
string sdkUnityVersion = VRC.Core.RemoteConfig.GetString("sdkUnityVersion"); | |||||
if (string.IsNullOrEmpty(sdkUnityVersion)) | |||||
EditorGUILayout.LabelField("Could not fetch remote config."); | |||||
else if (Application.unityVersion != sdkUnityVersion) | |||||
{ | |||||
EditorGUILayout.LabelField("Unity Version", EditorStyles.boldLabel); | |||||
EditorGUILayout.LabelField("Wrong Unity version. Please use " + sdkUnityVersion); | |||||
} | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
VRC.Core.API.SetOnlineMode(true, "vrchat"); | |||||
VRC.Core.RemoteConfig.Init(); | |||||
} | |||||
OnAccountGUI(); | |||||
} | |||||
private const string TWO_FACTOR_AUTHENTICATION_HELP_URL = "https://docs.vrchat.com/docs/setup-2fa"; | |||||
private const string ENTER_2FA_CODE_TITLE_STRING = "Enter a numeric code from your authenticator app (or one of your saved recovery codes)."; | |||||
private const string ENTER_2FA_CODE_LABEL_STRING = "Code:"; | |||||
private const string CHECKING_2FA_CODE_STRING = "Checking code..."; | |||||
private const string ENTER_2FA_CODE_INVALID_CODE_STRING = "Invalid Code"; | |||||
private const string ENTER_2FA_CODE_VERIFY_STRING = "Verify"; | |||||
private const string ENTER_2FA_CODE_CANCEL_STRING = "Cancel"; | |||||
private const string ENTER_2FA_CODE_HELP_STRING = "Help"; | |||||
private const int WARNING_ICON_SIZE = 60; | |||||
private const int WARNING_FONT_HEIGHT = 18; | |||||
static private Texture2D warningIconGraphic; | |||||
static bool entered2faCodeIsInvalid; | |||||
static bool authorizationCodeWasVerified; | |||||
static private int previousAuthenticationCodeLength = 0; | |||||
static bool checkingCode; | |||||
static string authenticationCode = ""; | |||||
static System.Action onAuthenticationVerifiedAction; | |||||
static bool _showTwoFactorAuthenticationEntry = false; | |||||
static bool showTwoFactorAuthenticationEntry | |||||
{ | |||||
get | |||||
{ | |||||
return _showTwoFactorAuthenticationEntry; | |||||
} | |||||
set | |||||
{ | |||||
_showTwoFactorAuthenticationEntry = value; | |||||
authenticationCode = ""; | |||||
if (!_showTwoFactorAuthenticationEntry && !authorizationCodeWasVerified) | |||||
Logout(); | |||||
} | |||||
} | |||||
static bool IsValidAuthenticationCodeFormat() | |||||
{ | |||||
bool isValid2faAuthenticationCode = false; | |||||
if (!string.IsNullOrEmpty(authenticationCode)) | |||||
{ | |||||
// check if the input is a valid 6-digit numberic code (ignoring spaces) | |||||
Regex rx = new Regex(@"^(\s*\d\s*){6}$", RegexOptions.Compiled); | |||||
MatchCollection matches6DigitCode = rx.Matches(authenticationCode); | |||||
isValid2faAuthenticationCode = (matches6DigitCode.Count == 1); | |||||
} | |||||
return isValid2faAuthenticationCode; | |||||
} | |||||
static bool IsValidRecoveryCodeFormat() | |||||
{ | |||||
bool isValid2faRecoveryCode = false; | |||||
if (!string.IsNullOrEmpty(authenticationCode)) | |||||
{ | |||||
// check if the input is a valid 8-digit alpha-numberic code (format xxxx-xxxx) "-" is optional & ignore any spaces | |||||
// OTP codes also exclude the letters i,l,o and the digit 1 to prevent any confusion | |||||
Regex rx = new Regex(@"^(\s*[a-hj-km-np-zA-HJ-KM-NP-Z02-9]\s*){4}-?(\s*[a-hj-km-np-zA-HJ-KM-NP-Z02-9]\s*){4}$", RegexOptions.Compiled); | |||||
MatchCollection matchesRecoveryCode = rx.Matches(authenticationCode); | |||||
isValid2faRecoveryCode = (matchesRecoveryCode.Count == 1); | |||||
} | |||||
return isValid2faRecoveryCode; | |||||
} | |||||
static void OnTwoFactorAuthenticationGUI() | |||||
{ | |||||
const int ENTER_2FA_CODE_BORDER_SIZE = 20; | |||||
const int ENTER_2FA_CODE_BUTTON_WIDTH = 260; | |||||
const int ENTER_2FA_CODE_VERIFY_BUTTON_WIDTH = ENTER_2FA_CODE_BUTTON_WIDTH / 2; | |||||
const int ENTER_2FA_CODE_ENTRY_REGION_WIDTH = 130; | |||||
const int ENTER_2FA_CODE_MIN_WINDOW_WIDTH = ENTER_2FA_CODE_VERIFY_BUTTON_WIDTH + ENTER_2FA_CODE_ENTRY_REGION_WIDTH + (ENTER_2FA_CODE_BORDER_SIZE * 3); | |||||
bool isValidAuthenticationCode = IsValidAuthenticationCodeFormat(); | |||||
bool isValidRecoveryCode = IsValidRecoveryCodeFormat(); | |||||
// Invalid code text | |||||
if (entered2faCodeIsInvalid) | |||||
{ | |||||
GUIStyle s = new GUIStyle(EditorStyles.label); | |||||
s.alignment = TextAnchor.UpperLeft; | |||||
s.normal.textColor = Color.red; | |||||
s.fontSize = WARNING_FONT_HEIGHT; | |||||
s.padding = new RectOffset(0, 0, (WARNING_ICON_SIZE - s.fontSize) / 2, 0); | |||||
s.fixedHeight = WARNING_ICON_SIZE; | |||||
EditorGUILayout.BeginHorizontal(); | |||||
GUILayout.FlexibleSpace(); | |||||
EditorGUILayout.BeginVertical(); | |||||
GUILayout.FlexibleSpace(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
var textDimensions = s.CalcSize(new GUIContent(ENTER_2FA_CODE_INVALID_CODE_STRING)); | |||||
GUILayout.Label(new GUIContent(warningIconGraphic), GUILayout.Width(WARNING_ICON_SIZE), GUILayout.Height(WARNING_ICON_SIZE)); | |||||
EditorGUILayout.LabelField(ENTER_2FA_CODE_INVALID_CODE_STRING, s, GUILayout.Width(textDimensions.x)); | |||||
EditorGUILayout.EndHorizontal(); | |||||
GUILayout.FlexibleSpace(); | |||||
EditorGUILayout.EndVertical(); | |||||
GUILayout.FlexibleSpace(); | |||||
EditorGUILayout.EndHorizontal(); | |||||
} | |||||
else if (checkingCode) | |||||
{ | |||||
// Display checking code message | |||||
EditorGUILayout.BeginVertical(); | |||||
GUILayout.FlexibleSpace(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
GUIStyle s = new GUIStyle(EditorStyles.label); | |||||
s.alignment = TextAnchor.MiddleCenter; | |||||
s.fixedHeight = WARNING_ICON_SIZE; | |||||
EditorGUILayout.LabelField(CHECKING_2FA_CODE_STRING, s, GUILayout.Height(WARNING_ICON_SIZE)); | |||||
EditorGUILayout.EndHorizontal(); | |||||
GUILayout.FlexibleSpace(); | |||||
EditorGUILayout.EndVertical(); | |||||
} | |||||
else | |||||
{ | |||||
EditorGUILayout.BeginHorizontal(); | |||||
GUILayout.Space(ENTER_2FA_CODE_BORDER_SIZE); | |||||
GUILayout.FlexibleSpace(); | |||||
GUIStyle titleStyle = new GUIStyle(EditorStyles.label); | |||||
titleStyle.alignment = TextAnchor.MiddleCenter; | |||||
titleStyle.wordWrap = true; | |||||
EditorGUILayout.LabelField(ENTER_2FA_CODE_TITLE_STRING, titleStyle, GUILayout.Width(ENTER_2FA_CODE_MIN_WINDOW_WIDTH - (2 * ENTER_2FA_CODE_BORDER_SIZE)), GUILayout.Height(WARNING_ICON_SIZE), GUILayout.ExpandHeight(true)); | |||||
GUILayout.FlexibleSpace(); | |||||
GUILayout.Space(ENTER_2FA_CODE_BORDER_SIZE); | |||||
EditorGUILayout.EndHorizontal(); | |||||
} | |||||
EditorGUILayout.BeginHorizontal(); | |||||
GUILayout.Space(ENTER_2FA_CODE_BORDER_SIZE); | |||||
GUILayout.FlexibleSpace(); | |||||
Vector2 size = EditorStyles.boldLabel.CalcSize(new GUIContent(ENTER_2FA_CODE_LABEL_STRING)); | |||||
EditorGUILayout.LabelField(ENTER_2FA_CODE_LABEL_STRING, EditorStyles.boldLabel, GUILayout.MaxWidth(size.x)); | |||||
authenticationCode = EditorGUILayout.TextField(authenticationCode); | |||||
// Verify 2FA code button | |||||
if (GUILayout.Button(ENTER_2FA_CODE_VERIFY_STRING, GUILayout.Width(ENTER_2FA_CODE_VERIFY_BUTTON_WIDTH))) | |||||
{ | |||||
checkingCode = true; | |||||
APIUser.VerifyTwoFactorAuthCode(authenticationCode, isValidAuthenticationCode ? API2FA.TIME_BASED_ONE_TIME_PASSWORD_AUTHENTICATION : API2FA.ONE_TIME_PASSWORD_AUTHENTICATION, username, password, | |||||
delegate | |||||
{ | |||||
// valid 2FA code submitted | |||||
entered2faCodeIsInvalid = false; | |||||
authorizationCodeWasVerified = true; | |||||
checkingCode = false; | |||||
showTwoFactorAuthenticationEntry = false; | |||||
if (null != onAuthenticationVerifiedAction) | |||||
onAuthenticationVerifiedAction(); | |||||
}, | |||||
delegate | |||||
{ | |||||
entered2faCodeIsInvalid = true; | |||||
checkingCode = false; | |||||
} | |||||
); | |||||
} | |||||
GUILayout.FlexibleSpace(); | |||||
GUILayout.Space(ENTER_2FA_CODE_BORDER_SIZE); | |||||
EditorGUILayout.EndHorizontal(); | |||||
GUILayout.FlexibleSpace(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
GUILayout.FlexibleSpace(); | |||||
// after user has entered an invalid code causing the invalid code message to be displayed, | |||||
// edit the code will change it's length meaning it is invalid format, so we can clear the invalid code setting until they resubmit | |||||
if (previousAuthenticationCodeLength != authenticationCode.Length) | |||||
{ | |||||
previousAuthenticationCodeLength = authenticationCode.Length; | |||||
entered2faCodeIsInvalid = false; | |||||
} | |||||
GUI.enabled = true; | |||||
GUILayout.FlexibleSpace(); | |||||
GUILayout.Space(ENTER_2FA_CODE_BORDER_SIZE); | |||||
EditorGUILayout.EndHorizontal(); | |||||
GUILayout.FlexibleSpace(); | |||||
// Two-Factor Authentication Help button | |||||
EditorGUILayout.BeginHorizontal(); | |||||
if (GUILayout.Button(ENTER_2FA_CODE_HELP_STRING)) | |||||
{ | |||||
Application.OpenURL(TWO_FACTOR_AUTHENTICATION_HELP_URL); | |||||
} | |||||
EditorGUILayout.EndHorizontal(); | |||||
// Cancel button | |||||
EditorGUILayout.BeginHorizontal(); | |||||
if (GUILayout.Button(ENTER_2FA_CODE_CANCEL_STRING)) | |||||
{ | |||||
showTwoFactorAuthenticationEntry = false; | |||||
Logout(); | |||||
} | |||||
EditorGUILayout.EndHorizontal(); | |||||
} | |||||
private static string Status | |||||
{ | |||||
get | |||||
{ | |||||
if (!APIUser.IsLoggedInWithCredentials) | |||||
return error == null ? "Please log in." : "Error in authenticating: " + error; | |||||
if (signingIn) | |||||
return "Logging in."; | |||||
else | |||||
{ | |||||
if( serverEnvironment == ApiServerEnvironment.Dev ) | |||||
return "Connected to " + serverEnvironment.ToString(); | |||||
return "Connected"; | |||||
} | |||||
} | |||||
} | |||||
private static void OnAuthenticationCompleted() | |||||
{ | |||||
AttemptLogin(); | |||||
} | |||||
private static void AttemptLogin() | |||||
{ | |||||
APIUser.Login(username, password, | |||||
delegate (ApiModelContainer<APIUser> c) | |||||
{ | |||||
APIUser user = c.Model as APIUser; | |||||
if (c.Cookies.ContainsKey("auth")) | |||||
ApiCredentials.Set(user.username, username, "vrchat", c.Cookies["auth"]); | |||||
else | |||||
ApiCredentials.SetHumanName(user.username); | |||||
signingIn = false; | |||||
error = null; | |||||
storedUsername = username; | |||||
storedPassword = password; | |||||
AnalyticsSDK.LoggedInUserChanged(user); | |||||
if (!APIUser.CurrentUser.canPublishAllContent) | |||||
{ | |||||
if (UnityEditor.SessionState.GetString("HasShownContentPublishPermissionsDialogForUser", "") != user.id) | |||||
{ | |||||
UnityEditor.SessionState.SetString("HasShownContentPublishPermissionsDialogForUser", user.id); | |||||
VRCSdkControlPanel.ShowContentPublishPermissionsDialog(); | |||||
} | |||||
} | |||||
}, | |||||
delegate (ApiModelContainer<APIUser> c) | |||||
{ | |||||
Logout(); | |||||
error = c.Error; | |||||
VRC.Core.Logger.Log("Error logging in: " + error); | |||||
}, | |||||
delegate (ApiModelContainer<API2FA> c) | |||||
{ | |||||
API2FA model2FA = c.Model as API2FA; | |||||
if (c.Cookies.ContainsKey("auth")) | |||||
ApiCredentials.Set(username, username, "vrchat", c.Cookies["auth"]); | |||||
showTwoFactorAuthenticationEntry = true; | |||||
onAuthenticationVerifiedAction = OnAuthenticationCompleted; | |||||
} | |||||
); | |||||
} | |||||
private static object syncObject = new object(); | |||||
private static void SignIn(bool explicitAttempt) | |||||
{ | |||||
lock (syncObject) | |||||
{ | |||||
if (signingIn | |||||
|| APIUser.IsLoggedInWithCredentials | |||||
|| (!explicitAttempt && string.IsNullOrEmpty(storedUsername)) | |||||
|| (!explicitAttempt && string.IsNullOrEmpty(storedPassword))) | |||||
return; | |||||
signingIn = true; | |||||
} | |||||
InitAccount(); | |||||
AttemptLogin(); | |||||
} | |||||
public static void Logout() | |||||
{ | |||||
signingIn = false; | |||||
storedUsername = null; | |||||
storedPassword = null; | |||||
VRC.Tools.ClearCookies(); | |||||
APIUser.Logout(); | |||||
} | |||||
private void AccountDestroy() | |||||
{ | |||||
signingIn = false; | |||||
isInitialized = false; | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 5066cd5c1cc208143a1253cac821714a | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: 4c73e735ee0380241b186a8993fa56bf | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using UnityEngine; | |||||
using UnityEditor; | |||||
using VRC.Core; | |||||
public partial class VRCSdkControlPanel : EditorWindow | |||||
{ | |||||
const int PageLimit = 20; | |||||
static List<ApiAvatar> uploadedAvatars = null; | |||||
static List<ApiWorld> uploadedWorlds = null; | |||||
public static Dictionary<string, Texture2D> ImageCache = new Dictionary<string, Texture2D>(); | |||||
static List<string> justDeletedContents; | |||||
static List<ApiAvatar> justUpdatedAvatars; | |||||
static EditorCoroutine fetchingAvatars = null, fetchingWorlds = null; | |||||
private static string searchString = ""; | |||||
private static bool WorldsToggle = true; | |||||
private static bool AvatarsToggle = true; | |||||
const int SCROLLBAR_RESERVED_REGION_WIDTH = 50; | |||||
const int WORLD_DESCRIPTION_FIELD_WIDTH = 140; | |||||
const int WORLD_IMAGE_BUTTON_WIDTH = 100; | |||||
const int WORLD_IMAGE_BUTTON_HEIGHT = 100; | |||||
const int WORLD_RELEASE_STATUS_FIELD_WIDTH = 150; | |||||
const int COPY_WORLD_ID_BUTTON_WIDTH = 75; | |||||
const int DELETE_WORLD_BUTTON_WIDTH = 75; | |||||
const int WORLD_ALL_INFORMATION_MAX_WIDTH = WORLD_DESCRIPTION_FIELD_WIDTH + WORLD_IMAGE_BUTTON_WIDTH + WORLD_RELEASE_STATUS_FIELD_WIDTH + COPY_WORLD_ID_BUTTON_WIDTH + DELETE_WORLD_BUTTON_WIDTH + SCROLLBAR_RESERVED_REGION_WIDTH; | |||||
const int WORLD_REDUCED_INFORMATION_MAX_WIDTH = WORLD_DESCRIPTION_FIELD_WIDTH + WORLD_IMAGE_BUTTON_WIDTH + WORLD_RELEASE_STATUS_FIELD_WIDTH + SCROLLBAR_RESERVED_REGION_WIDTH; | |||||
const int AVATAR_DESCRIPTION_FIELD_WIDTH = 140; | |||||
const int AVATAR_IMAGE_BUTTON_WIDTH = WORLD_IMAGE_BUTTON_WIDTH; | |||||
const int AVATAR_IMAGE_BUTTON_HEIGHT = WORLD_IMAGE_BUTTON_HEIGHT; | |||||
const int AVATAR_RELEASE_STATUS_FIELD_WIDTH = 150; | |||||
const int SET_AVATAR_STATUS_BUTTON_WIDTH = 100; | |||||
const int COPY_AVATAR_ID_BUTTON_WIDTH = COPY_WORLD_ID_BUTTON_WIDTH; | |||||
const int DELETE_AVATAR_BUTTON_WIDTH = DELETE_WORLD_BUTTON_WIDTH; | |||||
const int AVATAR_ALL_INFORMATION_MAX_WIDTH = AVATAR_DESCRIPTION_FIELD_WIDTH + AVATAR_IMAGE_BUTTON_WIDTH + AVATAR_RELEASE_STATUS_FIELD_WIDTH + SET_AVATAR_STATUS_BUTTON_WIDTH + COPY_AVATAR_ID_BUTTON_WIDTH + DELETE_AVATAR_BUTTON_WIDTH + SCROLLBAR_RESERVED_REGION_WIDTH; | |||||
const int AVATAR_REDUCED_INFORMATION_MAX_WIDTH = AVATAR_DESCRIPTION_FIELD_WIDTH + AVATAR_IMAGE_BUTTON_WIDTH + AVATAR_RELEASE_STATUS_FIELD_WIDTH + SCROLLBAR_RESERVED_REGION_WIDTH; | |||||
const int MAX_ALL_INFORMATION_WIDTH = WORLD_ALL_INFORMATION_MAX_WIDTH > AVATAR_ALL_INFORMATION_MAX_WIDTH ? WORLD_ALL_INFORMATION_MAX_WIDTH : AVATAR_ALL_INFORMATION_MAX_WIDTH; | |||||
const int MAX_REDUCED_INFORMATION_WIDTH = WORLD_REDUCED_INFORMATION_MAX_WIDTH > AVATAR_REDUCED_INFORMATION_MAX_WIDTH ? WORLD_REDUCED_INFORMATION_MAX_WIDTH : AVATAR_REDUCED_INFORMATION_MAX_WIDTH; | |||||
public static void ClearContent() | |||||
{ | |||||
if (uploadedWorlds != null) | |||||
uploadedWorlds = null; | |||||
if (uploadedAvatars != null) | |||||
uploadedAvatars = null; | |||||
ImageCache.Clear(); | |||||
} | |||||
IEnumerator FetchUploadedData() | |||||
{ | |||||
if (!RemoteConfig.IsInitialized()) | |||||
RemoteConfig.Init(); | |||||
if (!APIUser.IsLoggedInWithCredentials) | |||||
yield break; | |||||
ApiCache.ClearResponseCache(); | |||||
VRCCachedWWW.ClearOld(); | |||||
if (fetchingAvatars == null) | |||||
fetchingAvatars = EditorCoroutine.Start(() => FetchAvatars()); | |||||
if (fetchingWorlds == null) | |||||
fetchingWorlds = EditorCoroutine.Start(() => FetchWorlds()); | |||||
} | |||||
static void FetchAvatars(int offset = 0) | |||||
{ | |||||
ApiAvatar.FetchList( | |||||
delegate (IEnumerable<ApiAvatar> obj) | |||||
{ | |||||
Debug.LogFormat("<color=yellow>Fetching Avatar Bucket {0}</color>", offset); | |||||
if (obj.FirstOrDefault() != null) | |||||
fetchingAvatars = EditorCoroutine.Start(() => | |||||
{ | |||||
var l = obj.ToList(); | |||||
int count = l.Count; | |||||
SetupAvatarData(l); | |||||
FetchAvatars(offset + count); | |||||
}); | |||||
else | |||||
{ | |||||
fetchingAvatars = null; | |||||
foreach (ApiAvatar a in uploadedAvatars) | |||||
DownloadImage(a.id, a.thumbnailImageUrl); | |||||
} | |||||
}, | |||||
delegate (string obj) | |||||
{ | |||||
Debug.LogError("Error fetching your uploaded avatars:\n" + obj); | |||||
fetchingAvatars = null; | |||||
}, | |||||
ApiAvatar.Owner.Mine, | |||||
ApiAvatar.ReleaseStatus.All, | |||||
null, | |||||
PageLimit, | |||||
offset, | |||||
ApiAvatar.SortHeading.None, | |||||
ApiAvatar.SortOrder.Descending, | |||||
null, | |||||
null, | |||||
true, | |||||
false, | |||||
null, | |||||
false | |||||
); | |||||
} | |||||
static void FetchWorlds(int offset = 0) | |||||
{ | |||||
ApiWorld.FetchList( | |||||
delegate (IEnumerable<ApiWorld> obj) | |||||
{ | |||||
Debug.LogFormat("<color=yellow>Fetching World Bucket {0}</color>", offset); | |||||
if (obj.FirstOrDefault() != null) | |||||
fetchingWorlds = EditorCoroutine.Start(() => | |||||
{ | |||||
var l = obj.ToList(); | |||||
int count = l.Count; | |||||
SetupWorldData(l); | |||||
FetchWorlds(offset + count); | |||||
}); | |||||
else | |||||
{ | |||||
fetchingWorlds = null; | |||||
foreach (ApiWorld w in uploadedWorlds) | |||||
DownloadImage(w.id, w.thumbnailImageUrl); | |||||
} | |||||
}, | |||||
delegate (string obj) | |||||
{ | |||||
Debug.LogError("Error fetching your uploaded worlds:\n" + obj); | |||||
fetchingWorlds = null; | |||||
}, | |||||
ApiWorld.SortHeading.Updated, | |||||
ApiWorld.SortOwnership.Mine, | |||||
ApiWorld.SortOrder.Descending, | |||||
offset, | |||||
PageLimit, | |||||
"", | |||||
null, | |||||
null, | |||||
null, | |||||
"", | |||||
ApiWorld.ReleaseStatus.All, | |||||
null, | |||||
null, | |||||
true, | |||||
false); | |||||
} | |||||
static void SetupWorldData(List<ApiWorld> worlds) | |||||
{ | |||||
if (worlds == null || uploadedWorlds == null) | |||||
return; | |||||
worlds.RemoveAll(w => w == null || w.name == null || uploadedWorlds.Any(w2 => w2.id == w.id)); | |||||
if (worlds.Count > 0) | |||||
{ | |||||
uploadedWorlds.AddRange(worlds); | |||||
uploadedWorlds.Sort((w1, w2) => w1.name.CompareTo(w2.name)); | |||||
} | |||||
} | |||||
static void SetupAvatarData(List<ApiAvatar> avatars) | |||||
{ | |||||
if (avatars == null || uploadedAvatars == null ) | |||||
return; | |||||
avatars.RemoveAll(a => a == null || a.name == null || uploadedAvatars.Any(a2 => a2.id == a.id)); | |||||
if (avatars.Count > 0) | |||||
{ | |||||
uploadedAvatars.AddRange(avatars); | |||||
uploadedAvatars.Sort((w1, w2) => w1.name.CompareTo(w2.name)); | |||||
} | |||||
} | |||||
static void DownloadImage(string id, string url) | |||||
{ | |||||
if (ImageCache.ContainsKey(id) && ImageCache[id] != null) | |||||
return; | |||||
System.Action<WWW> onDone = (www) => | |||||
{ | |||||
if (string.IsNullOrEmpty(www.error)) | |||||
{ | |||||
try | |||||
{ // converting Texture2D to use linear color space fixes issue with SDK world & avatar thumbnails appearing too dark (also enables mipmaps to improve appearance of thumbnails) | |||||
Texture2D newTexture2DWithLinearEnabled; | |||||
newTexture2DWithLinearEnabled = new Texture2D(4, 4, TextureFormat.DXT1, true, true); | |||||
www.LoadImageIntoTexture(newTexture2DWithLinearEnabled); | |||||
ImageCache[id] = newTexture2DWithLinearEnabled; | |||||
} | |||||
catch (System.Exception e) | |||||
{ | |||||
Debug.LogException(e); | |||||
} | |||||
} | |||||
else if (ImageCache.ContainsKey(id)) | |||||
ImageCache.Remove(id); | |||||
}; | |||||
EditorCoroutine.Start(VRCCachedWWW.Get(url, onDone)); | |||||
} | |||||
Vector2 contentScrollPos; | |||||
bool OnGUIUserInfo() | |||||
{ | |||||
bool updatedContent = false; | |||||
if (!RemoteConfig.IsInitialized()) | |||||
RemoteConfig.Init(); | |||||
if (APIUser.IsLoggedInWithCredentials && uploadedWorlds != null && uploadedAvatars != null) | |||||
{ | |||||
contentScrollPos = EditorGUILayout.BeginScrollView(contentScrollPos); | |||||
GUIStyle descriptionStyle = new GUIStyle(EditorStyles.wordWrappedLabel); | |||||
descriptionStyle.wordWrap = true; | |||||
bool expandedLayout = (position.width > MAX_ALL_INFORMATION_WIDTH); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
searchString = EditorGUILayout.TextField(searchString, GUI.skin.FindStyle("SearchTextField")); | |||||
GUIStyle searchButtonStyle = searchString == string.Empty | |||||
? GUI.skin.FindStyle("SearchCancelButtonEmpty") | |||||
: GUI.skin.FindStyle("SearchCancelButton"); | |||||
if (GUILayout.Button(string.Empty, searchButtonStyle)) | |||||
{ | |||||
searchString = string.Empty; | |||||
GUI.FocusControl(null); | |||||
} | |||||
EditorGUILayout.EndHorizontal(); | |||||
if (uploadedWorlds.Count > 0) | |||||
{ | |||||
EditorGUILayout.Space(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("WORLDS", EditorStyles.boldLabel, GUILayout.ExpandWidth(false), GUILayout.Width(58)); | |||||
WorldsToggle = EditorGUILayout.Foldout(WorldsToggle, new GUIContent("")); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.Space(); | |||||
if (WorldsToggle) | |||||
{ | |||||
List<ApiWorld> tmpWorlds = new List<ApiWorld>(); | |||||
if (uploadedWorlds.Count > 0) | |||||
tmpWorlds = new List<ApiWorld>(uploadedWorlds); | |||||
foreach (ApiWorld w in tmpWorlds) | |||||
{ | |||||
if (justDeletedContents != null && justDeletedContents.Contains(w.id)) | |||||
{ | |||||
uploadedWorlds.Remove(w); | |||||
continue; | |||||
} | |||||
if (!w.name.ToLowerInvariant().Contains(searchString.ToLowerInvariant())) | |||||
{ | |||||
continue; | |||||
} | |||||
EditorGUILayout.BeginHorizontal(EditorStyles.helpBox); | |||||
EditorGUILayout.BeginHorizontal(GUILayout.Width(WORLD_IMAGE_BUTTON_WIDTH)); | |||||
if (ImageCache.ContainsKey(w.id)) | |||||
{ | |||||
if (GUILayout.Button(ImageCache[w.id], GUILayout.Height(WORLD_IMAGE_BUTTON_HEIGHT), | |||||
GUILayout.Width(WORLD_IMAGE_BUTTON_WIDTH))) | |||||
{ | |||||
Application.OpenURL(w.imageUrl); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
if (GUILayout.Button("", GUILayout.Height(WORLD_IMAGE_BUTTON_HEIGHT), | |||||
GUILayout.Width(WORLD_IMAGE_BUTTON_WIDTH))) | |||||
{ | |||||
Application.OpenURL(w.imageUrl); | |||||
} | |||||
} | |||||
if (expandedLayout) | |||||
{ | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField(w.name, descriptionStyle, | |||||
GUILayout.Width(position.width - MAX_ALL_INFORMATION_WIDTH + | |||||
WORLD_DESCRIPTION_FIELD_WIDTH)); | |||||
} | |||||
else | |||||
{ | |||||
EditorGUILayout.BeginVertical(); | |||||
EditorGUILayout.LabelField(w.name, descriptionStyle); | |||||
} | |||||
EditorGUILayout.LabelField("Release Status: " + w.releaseStatus, | |||||
GUILayout.Width(WORLD_RELEASE_STATUS_FIELD_WIDTH)); | |||||
if (GUILayout.Button("Copy ID", GUILayout.Width(COPY_WORLD_ID_BUTTON_WIDTH))) | |||||
{ | |||||
TextEditor te = new TextEditor(); | |||||
te.text = w.id; | |||||
te.SelectAll(); | |||||
te.Copy(); | |||||
} | |||||
if (GUILayout.Button("Delete", GUILayout.Width(DELETE_WORLD_BUTTON_WIDTH))) | |||||
{ | |||||
if (EditorUtility.DisplayDialog("Delete " + w.name + "?", | |||||
"Are you sure you want to delete " + w.name + "? This cannot be undone.", "Delete", | |||||
"Cancel")) | |||||
{ | |||||
foreach (VRC.Core.PipelineManager pm in FindObjectsOfType<VRC.Core.PipelineManager>() | |||||
.Where(pm => pm.blueprintId == w.id)) | |||||
{ | |||||
pm.blueprintId = ""; | |||||
pm.completedSDKPipeline = false; | |||||
UnityEditor.EditorUtility.SetDirty(pm); | |||||
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(pm.gameObject.scene); | |||||
UnityEditor.SceneManagement.EditorSceneManager.SaveScene(pm.gameObject.scene); | |||||
} | |||||
API.Delete<ApiWorld>(w.id); | |||||
uploadedWorlds.RemoveAll(world => world.id == w.id); | |||||
if (ImageCache.ContainsKey(w.id)) | |||||
ImageCache.Remove(w.id); | |||||
if (justDeletedContents == null) justDeletedContents = new List<string>(); | |||||
justDeletedContents.Add(w.id); | |||||
updatedContent = true; | |||||
} | |||||
} | |||||
if (expandedLayout) | |||||
EditorGUILayout.EndHorizontal(); | |||||
else | |||||
EditorGUILayout.EndVertical(); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.Space(); | |||||
} | |||||
} | |||||
} | |||||
if (uploadedAvatars.Count > 0) | |||||
{ | |||||
EditorGUILayout.Space(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("AVATARS", EditorStyles.boldLabel, GUILayout.ExpandWidth(false), GUILayout.Width(65)); | |||||
AvatarsToggle = EditorGUILayout.Foldout(AvatarsToggle, new GUIContent("")); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.Space(); | |||||
if (AvatarsToggle) | |||||
{ | |||||
List<ApiAvatar> tmpAvatars = new List<ApiAvatar>(); | |||||
if (uploadedAvatars.Count > 0) | |||||
tmpAvatars = new List<ApiAvatar>(uploadedAvatars); | |||||
if (justUpdatedAvatars != null) | |||||
{ | |||||
foreach (ApiAvatar a in justUpdatedAvatars) | |||||
{ | |||||
int index = tmpAvatars.FindIndex((av) => av.id == a.id); | |||||
if (index != -1) | |||||
tmpAvatars[index] = a; | |||||
} | |||||
} | |||||
foreach (ApiAvatar a in tmpAvatars) | |||||
{ | |||||
if (justDeletedContents != null && justDeletedContents.Contains(a.id)) | |||||
{ | |||||
uploadedAvatars.Remove(a); | |||||
continue; | |||||
} | |||||
if (!a.name.ToLowerInvariant().Contains(searchString.ToLowerInvariant())) | |||||
{ | |||||
continue; | |||||
} | |||||
EditorGUILayout.BeginHorizontal(EditorStyles.helpBox); | |||||
EditorGUILayout.BeginHorizontal(GUILayout.Width(AVATAR_DESCRIPTION_FIELD_WIDTH)); | |||||
if (ImageCache.ContainsKey(a.id)) | |||||
{ | |||||
if (GUILayout.Button(ImageCache[a.id], GUILayout.Height(AVATAR_IMAGE_BUTTON_HEIGHT), | |||||
GUILayout.Width(AVATAR_IMAGE_BUTTON_WIDTH))) | |||||
{ | |||||
Application.OpenURL(a.imageUrl); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
if (GUILayout.Button("", GUILayout.Height(AVATAR_IMAGE_BUTTON_HEIGHT), | |||||
GUILayout.Width(AVATAR_IMAGE_BUTTON_WIDTH))) | |||||
{ | |||||
Application.OpenURL(a.imageUrl); | |||||
} | |||||
} | |||||
if (expandedLayout) | |||||
EditorGUILayout.BeginHorizontal(); | |||||
else | |||||
EditorGUILayout.BeginVertical(); | |||||
EditorGUILayout.LabelField(a.name, descriptionStyle, | |||||
GUILayout.Width(expandedLayout | |||||
? position.width - MAX_ALL_INFORMATION_WIDTH + AVATAR_DESCRIPTION_FIELD_WIDTH | |||||
: AVATAR_DESCRIPTION_FIELD_WIDTH)); | |||||
EditorGUILayout.LabelField("Release Status: " + a.releaseStatus, | |||||
GUILayout.Width(AVATAR_RELEASE_STATUS_FIELD_WIDTH)); | |||||
string oppositeReleaseStatus = a.releaseStatus == "public" ? "private" : "public"; | |||||
if (GUILayout.Button("Make " + oppositeReleaseStatus, | |||||
GUILayout.Width(SET_AVATAR_STATUS_BUTTON_WIDTH))) | |||||
{ | |||||
a.releaseStatus = oppositeReleaseStatus; | |||||
a.SaveReleaseStatus((c) => | |||||
{ | |||||
ApiAvatar savedBP = (ApiAvatar) c.Model; | |||||
if (justUpdatedAvatars == null) justUpdatedAvatars = new List<ApiAvatar>(); | |||||
justUpdatedAvatars.Add(savedBP); | |||||
}, | |||||
(c) => | |||||
{ | |||||
Debug.LogError(c.Error); | |||||
EditorUtility.DisplayDialog("Avatar Updated", | |||||
"Failed to change avatar release status", "OK"); | |||||
}); | |||||
} | |||||
if (GUILayout.Button("Copy ID", GUILayout.Width(COPY_AVATAR_ID_BUTTON_WIDTH))) | |||||
{ | |||||
TextEditor te = new TextEditor(); | |||||
te.text = a.id; | |||||
te.SelectAll(); | |||||
te.Copy(); | |||||
} | |||||
if (GUILayout.Button("Delete", GUILayout.Width(DELETE_AVATAR_BUTTON_WIDTH))) | |||||
{ | |||||
if (EditorUtility.DisplayDialog("Delete " + a.name + "?", | |||||
"Are you sure you want to delete " + a.name + "? This cannot be undone.", "Delete", | |||||
"Cancel")) | |||||
{ | |||||
foreach (VRC.Core.PipelineManager pm in FindObjectsOfType<VRC.Core.PipelineManager>() | |||||
.Where(pm => pm.blueprintId == a.id)) | |||||
{ | |||||
pm.blueprintId = ""; | |||||
pm.completedSDKPipeline = false; | |||||
UnityEditor.EditorUtility.SetDirty(pm); | |||||
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(pm.gameObject.scene); | |||||
UnityEditor.SceneManagement.EditorSceneManager.SaveScene(pm.gameObject.scene); | |||||
} | |||||
API.Delete<ApiAvatar>(a.id); | |||||
uploadedAvatars.RemoveAll(avatar => avatar.id == a.id); | |||||
if (ImageCache.ContainsKey(a.id)) | |||||
ImageCache.Remove(a.id); | |||||
if (justDeletedContents == null) justDeletedContents = new List<string>(); | |||||
justDeletedContents.Add(a.id); | |||||
updatedContent = true; | |||||
} | |||||
} | |||||
if (expandedLayout) | |||||
EditorGUILayout.EndHorizontal(); | |||||
else | |||||
EditorGUILayout.EndVertical(); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.Space(); | |||||
} | |||||
} | |||||
} | |||||
EditorGUILayout.EndScrollView(); | |||||
if ((updatedContent) && (null != window)) window.Reset(); | |||||
return true; | |||||
} | |||||
else | |||||
{ | |||||
return false; | |||||
} | |||||
} | |||||
void ShowContent() | |||||
{ | |||||
if (uploadedWorlds == null || uploadedAvatars == null) | |||||
{ | |||||
if (uploadedWorlds == null) | |||||
uploadedWorlds = new List<ApiWorld>(); | |||||
if (uploadedAvatars == null) | |||||
uploadedAvatars = new List<ApiAvatar>(); | |||||
EditorCoroutine.Start(FetchUploadedData()); | |||||
} | |||||
if( fetchingWorlds != null || fetchingAvatars != null ) | |||||
{ | |||||
GUILayout.BeginVertical(boxGuiStyle, GUILayout.Width(SdkWindowWidth)); | |||||
EditorGUILayout.Space(); | |||||
EditorGUILayout.LabelField("Fetching Records", titleGuiStyle); | |||||
EditorGUILayout.Space(); | |||||
GUILayout.EndVertical(); | |||||
} | |||||
else | |||||
{ | |||||
GUILayout.BeginVertical(boxGuiStyle, GUILayout.Width(SdkWindowWidth)); | |||||
EditorGUILayout.Space(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
GUILayout.Label("Fetch updated records from the VRChat server"); | |||||
if( GUILayout.Button("Fetch") ) | |||||
{ | |||||
ClearContent(); | |||||
} | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.Space(); | |||||
GUILayout.EndVertical(); | |||||
} | |||||
OnGUIUserInfo(); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: c7333cdb3df19724b84b4a1b05093fe0 | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using System.Collections.Generic; | |||||
using System.IO; | |||||
using System.Linq; | |||||
using UnityEditor; | |||||
using UnityEngine; | |||||
using VRC; | |||||
using VRC.Core; | |||||
using VRCSDK2; | |||||
public partial class VRCSdkControlPanel : EditorWindow | |||||
{ | |||||
[MenuItem("VRChat SDK/Help/Developer FAQ")] | |||||
public static void ShowDeveloperFAQ() | |||||
{ | |||||
if (!RemoteConfig.IsInitialized()) | |||||
{ | |||||
RemoteConfig.Init(() => ShowDeveloperFAQ()); | |||||
return; | |||||
} | |||||
Application.OpenURL(RemoteConfig.GetString("sdkDeveloperFaqUrl")); | |||||
} | |||||
[MenuItem("VRChat SDK/Help/VRChat Discord")] | |||||
public static void ShowVRChatDiscord() | |||||
{ | |||||
if (!RemoteConfig.IsInitialized()) | |||||
{ | |||||
RemoteConfig.Init(() => ShowVRChatDiscord()); | |||||
return; | |||||
} | |||||
Application.OpenURL(RemoteConfig.GetString("sdkDiscordUrl")); | |||||
} | |||||
[MenuItem("VRChat SDK/Help/Avatar Optimization Tips")] | |||||
public static void ShowAvatarOptimizationTips() | |||||
{ | |||||
if (!RemoteConfig.IsInitialized()) | |||||
{ | |||||
RemoteConfig.Init(() => ShowAvatarOptimizationTips()); | |||||
return; | |||||
} | |||||
Application.OpenURL(kAvatarOptimizationTipsURL); | |||||
} | |||||
[MenuItem("VRChat SDK/Help/Avatar Rig Requirements")] | |||||
public static void ShowAvatarRigRequirements() | |||||
{ | |||||
if (!RemoteConfig.IsInitialized()) | |||||
{ | |||||
RemoteConfig.Init(() => ShowAvatarRigRequirements()); | |||||
return; | |||||
} | |||||
Application.OpenURL(kAvatarRigRequirementsURL); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: f3507a74e4b8cfd469afac127fa5f4e5 | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using UnityEngine; | |||||
using UnityEditor; | |||||
using VRC.Core; | |||||
public partial class VRCSdkControlPanel : EditorWindow | |||||
{ | |||||
bool UseDevApi | |||||
{ | |||||
get | |||||
{ | |||||
return VRC.Core.API.GetApiUrl() == VRC.Core.API.devApiUrl; | |||||
} | |||||
} | |||||
string clientVersionDate; | |||||
string sdkVersionDate; | |||||
Vector2 settingsScroll; | |||||
private void Awake() | |||||
{ | |||||
GetClientSdkVersionInformation(); | |||||
} | |||||
public void GetClientSdkVersionInformation() | |||||
{ | |||||
clientVersionDate = VRC.Core.SDKClientUtilities.GetTestClientVersionDate(); | |||||
sdkVersionDate = VRC.Core.SDKClientUtilities.GetSDKVersionDate(); | |||||
} | |||||
public void OnConfigurationChanged() | |||||
{ | |||||
GetClientSdkVersionInformation(); | |||||
} | |||||
void ShowSettings() | |||||
{ | |||||
settingsScroll = EditorGUILayout.BeginScrollView( settingsScroll, GUILayout.Width(SdkWindowWidth) ); | |||||
EditorGUILayout.BeginVertical(boxGuiStyle); | |||||
EditorGUILayout.LabelField("Developer", EditorStyles.boldLabel); | |||||
VRCSettings.Get().DisplayAdvancedSettings = EditorGUILayout.ToggleLeft("Show Extra Options on build page and account page",VRCSettings.Get().DisplayAdvancedSettings ); | |||||
EditorGUILayout.EndVertical(); | |||||
EditorGUILayout.Separator(); | |||||
EditorGUILayout.BeginVertical(boxGuiStyle); | |||||
GUILayout.Label("Avatar Options", EditorStyles.boldLabel); | |||||
bool prevShowPerfDetails = showAvatarPerformanceDetails; | |||||
bool showPerfDetails = EditorGUILayout.ToggleLeft("Show All Avatar Performance Details", prevShowPerfDetails); | |||||
if (showPerfDetails != prevShowPerfDetails) | |||||
{ | |||||
showAvatarPerformanceDetails = showPerfDetails; | |||||
ResetIssues(); | |||||
} | |||||
EditorGUILayout.EndVertical(); | |||||
// debugging | |||||
if (APIUser.CurrentUser != null && APIUser.CurrentUser.hasSuperPowers) | |||||
{ | |||||
EditorGUILayout.Separator(); | |||||
EditorGUILayout.BeginVertical(boxGuiStyle); | |||||
EditorGUILayout.LabelField("Logging", EditorStyles.boldLabel); | |||||
// API logging | |||||
{ | |||||
bool isLoggingEnabled = UnityEditor.EditorPrefs.GetBool("apiLoggingEnabled"); | |||||
bool enableLogging = EditorGUILayout.ToggleLeft("API Logging Enabled", isLoggingEnabled); | |||||
if (enableLogging != isLoggingEnabled) | |||||
{ | |||||
if (enableLogging) | |||||
VRC.Core.Logger.AddDebugLevel(DebugLevel.API); | |||||
else | |||||
VRC.Core.Logger.RemoveDebugLevel(DebugLevel.API); | |||||
UnityEditor.EditorPrefs.SetBool("apiLoggingEnabled", enableLogging); | |||||
} | |||||
} | |||||
// All logging | |||||
{ | |||||
bool isLoggingEnabled = UnityEditor.EditorPrefs.GetBool("allLoggingEnabled"); | |||||
bool enableLogging = EditorGUILayout.ToggleLeft("All Logging Enabled", isLoggingEnabled); | |||||
if (enableLogging != isLoggingEnabled) | |||||
{ | |||||
if (enableLogging) | |||||
VRC.Core.Logger.AddDebugLevel(DebugLevel.All); | |||||
else | |||||
VRC.Core.Logger.RemoveDebugLevel(DebugLevel.All); | |||||
UnityEditor.EditorPrefs.SetBool("allLoggingEnabled", enableLogging); | |||||
} | |||||
} | |||||
EditorGUILayout.EndVertical(); | |||||
} | |||||
else | |||||
{ | |||||
if (UnityEditor.EditorPrefs.GetBool("apiLoggingEnabled")) | |||||
UnityEditor.EditorPrefs.SetBool("apiLoggingEnabled", false); | |||||
if (UnityEditor.EditorPrefs.GetBool("allLoggingEnabled")) | |||||
UnityEditor.EditorPrefs.SetBool("allLoggingEnabled", false); | |||||
} | |||||
// Future proof upload | |||||
{ | |||||
EditorGUILayout.Separator(); | |||||
EditorGUILayout.BeginVertical(boxGuiStyle); | |||||
EditorGUILayout.LabelField("Publish", EditorStyles.boldLabel); | |||||
bool futureProofPublish = UnityEditor.EditorPrefs.GetBool("futureProofPublish", DefaultFutureProofPublishEnabled); | |||||
futureProofPublish = EditorGUILayout.ToggleLeft("Future Proof Publish", futureProofPublish); | |||||
if (UnityEditor.EditorPrefs.GetBool("futureProofPublish", DefaultFutureProofPublishEnabled) != futureProofPublish) | |||||
{ | |||||
UnityEditor.EditorPrefs.SetBool("futureProofPublish", futureProofPublish); | |||||
} | |||||
EditorGUILayout.LabelField("Client Version Date", clientVersionDate); | |||||
EditorGUILayout.LabelField("SDK Version Date", sdkVersionDate); | |||||
EditorGUILayout.EndVertical(); | |||||
} | |||||
if (APIUser.CurrentUser != null) | |||||
{ | |||||
EditorGUILayout.Separator(); | |||||
EditorGUILayout.BeginVertical(boxGuiStyle); | |||||
// custom vrchat install location | |||||
OnVRCInstallPathGUI(); | |||||
EditorGUILayout.EndVertical(); | |||||
} | |||||
EditorGUILayout.EndScrollView(); | |||||
} | |||||
static void OnVRCInstallPathGUI() | |||||
{ | |||||
EditorGUILayout.LabelField("VRChat Client", EditorStyles.boldLabel); | |||||
EditorGUILayout.LabelField("Installed Client Path: ", clientInstallPath); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
GUILayout.Label(""); | |||||
if (GUILayout.Button("Edit")) | |||||
{ | |||||
string initPath = ""; | |||||
if (!string.IsNullOrEmpty(clientInstallPath)) | |||||
initPath = clientInstallPath; | |||||
clientInstallPath = EditorUtility.OpenFilePanel("Choose VRC Client Exe", initPath, "exe"); | |||||
SDKClientUtilities.SetVRCInstallPath(clientInstallPath); | |||||
window.OnConfigurationChanged(); | |||||
} | |||||
if (GUILayout.Button("Revert to Default")) | |||||
{ | |||||
clientInstallPath = SDKClientUtilities.LoadRegistryVRCInstallPath(); | |||||
window.OnConfigurationChanged(); | |||||
} | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.Separator(); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 8357b9b7ef2416946ae86f465a64c0e0 | |||||
DefaultImporter: | |||||
externalObjects: {} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
fileFormatVersion: 2 | |||||
guid: f262853fc6bbe904faa6fa7ac7b0e570 | |||||
PluginImporter: | |||||
externalObjects: {} | |||||
serializedVersion: 2 | |||||
iconMap: {} | |||||
executionOrder: {} | |||||
isPreloaded: 0 | |||||
isOverridable: 0 | |||||
platformData: | |||||
- first: | |||||
Any: | |||||
second: | |||||
enabled: 0 | |||||
settings: {} | |||||
- first: | |||||
Editor: Editor | |||||
second: | |||||
enabled: 1 | |||||
settings: | |||||
DefaultValueInitialized: true | |||||
- first: | |||||
Windows Store Apps: WindowsStoreApps | |||||
second: | |||||
enabled: 0 | |||||
settings: | |||||
CPU: AnyCPU | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
#define ENV_SET_INCLUDED_SHADERS | |||||
using UnityEngine; | |||||
using UnityEditor; | |||||
using System.Collections; | |||||
using System; | |||||
using System.Linq; | |||||
using UnityEngine.Rendering; | |||||
using VRCSDK2.Validation.Performance.Stats; | |||||
/// <summary> | |||||
/// Setup up SDK env on editor launch | |||||
/// </summary> | |||||
[InitializeOnLoad] | |||||
public class EnvConfig | |||||
{ | |||||
static BuildTarget[] relevantBuildTargets = new BuildTarget[] { | |||||
BuildTarget.Android, BuildTarget.iOS, | |||||
BuildTarget.StandaloneLinux, BuildTarget.StandaloneLinux64, BuildTarget.StandaloneLinuxUniversal, | |||||
BuildTarget.StandaloneWindows, BuildTarget.StandaloneWindows64, | |||||
BuildTarget.StandaloneOSX | |||||
}; | |||||
#if !VRC_CLIENT | |||||
static BuildTarget[] allowedBuildtargets = new BuildTarget[] | |||||
{ | |||||
BuildTarget.StandaloneWindows64, | |||||
BuildTarget.Android | |||||
}; | |||||
#endif | |||||
static System.Collections.Generic.Dictionary<BuildTarget, UnityEngine.Rendering.GraphicsDeviceType[]> allowedGraphicsAPIs = new System.Collections.Generic.Dictionary<BuildTarget, UnityEngine.Rendering.GraphicsDeviceType[]>() | |||||
{ | |||||
{ BuildTarget.Android, new [] { GraphicsDeviceType.OpenGLES3, /* GraphicsDeviceType.Vulkan */ }}, | |||||
{ BuildTarget.iOS, null }, | |||||
{ BuildTarget.StandaloneLinux, null }, | |||||
{ BuildTarget.StandaloneLinux64, null }, | |||||
{ BuildTarget.StandaloneLinuxUniversal, null }, | |||||
{ BuildTarget.StandaloneWindows, new UnityEngine.Rendering.GraphicsDeviceType[] { UnityEngine.Rendering.GraphicsDeviceType.Direct3D11 } }, | |||||
{ BuildTarget.StandaloneWindows64, new UnityEngine.Rendering.GraphicsDeviceType[] { UnityEngine.Rendering.GraphicsDeviceType.Direct3D11 } }, | |||||
{ BuildTarget.StandaloneOSX, null } | |||||
}; | |||||
static string[] ensureTheseShadersAreAvailable = new string[] | |||||
{ | |||||
#if VRC_CLIENT | |||||
"Hidden/CubeBlend", | |||||
"Hidden/CubeBlur", | |||||
"Hidden/CubeCopy", | |||||
"Hidden/VideoDecode", | |||||
"Legacy Shaders/Bumped Diffuse", | |||||
"Legacy Shaders/Bumped Specular", | |||||
"Legacy Shaders/Decal", | |||||
"Legacy Shaders/Diffuse Detail", | |||||
"Legacy Shaders/Diffuse Fast", | |||||
"Legacy Shaders/Diffuse", | |||||
"Legacy Shaders/Diffuse", | |||||
"Legacy Shaders/Lightmapped/Diffuse", | |||||
"Legacy Shaders/Lightmapped/Specular", | |||||
"Legacy Shaders/Lightmapped/VertexLit", | |||||
"Legacy Shaders/Parallax Diffuse", | |||||
"Legacy Shaders/Parallax Specular", | |||||
"Legacy Shaders/Reflective/Bumped Diffuse", | |||||
"Legacy Shaders/Reflective/Bumped Specular", | |||||
"Legacy Shaders/Reflective/Bumped Unlit", | |||||
"Legacy Shaders/Reflective/Bumped VertexLit", | |||||
"Legacy Shaders/Reflective/Diffuse", | |||||
"Legacy Shaders/Reflective/Parallax Diffuse", | |||||
"Legacy Shaders/Reflective/Parallax Specular", | |||||
"Legacy Shaders/Reflective/Specular", | |||||
"Legacy Shaders/Reflective/VertexLit", | |||||
"Legacy Shaders/Self-Illumin/Bumped Diffuse", | |||||
"Legacy Shaders/Self-Illumin/Bumped Specular", | |||||
"Legacy Shaders/Self-Illumin/Diffuse", | |||||
"Legacy Shaders/Self-Illumin/Parallax Diffuse", | |||||
"Legacy Shaders/Self-Illumin/Parallax Specular", | |||||
"Legacy Shaders/Self-Illumin/Specular", | |||||
"Legacy Shaders/Self-Illumin/VertexLit", | |||||
"Legacy Shaders/Specular", | |||||
"Legacy Shaders/Transparent/Bumped Diffuse", | |||||
"Legacy Shaders/Transparent/Bumped Specular", | |||||
"Legacy Shaders/Transparent/Cutout/Bumped Diffuse", | |||||
"Legacy Shaders/Transparent/Cutout/Bumped Specular", | |||||
"Legacy Shaders/Transparent/Cutout/Diffuse", | |||||
"Legacy Shaders/Transparent/Cutout/Soft Edge Unlit", | |||||
"Legacy Shaders/Transparent/Cutout/Specular", | |||||
"Legacy Shaders/Transparent/Cutout/VertexLit", | |||||
"Legacy Shaders/Transparent/Diffuse", | |||||
"Legacy Shaders/Transparent/Parallax Diffuse", | |||||
"Legacy Shaders/Transparent/Parallax Specular", | |||||
"Legacy Shaders/Transparent/Specular", | |||||
"Legacy Shaders/Transparent/VertexLit", | |||||
"Legacy Shaders/VertexLit", | |||||
"Mobile/Particles/Additive", | |||||
"Mobile/Particles/Alpha Blended", | |||||
"Mobile/Particles/Multiply", | |||||
"Mobile/Particles/VertexLit Blended", | |||||
"Mobile/Skybox", | |||||
"Nature/Terrain/Diffuse", | |||||
"Nature/Terrain/Specular", | |||||
"Nature/Terrain/Standard", | |||||
"Particles/Additive (Soft)", | |||||
"Particles/Additive", | |||||
"Particles/Alpha Blended Premultiply", | |||||
"Particles/Alpha Blended", | |||||
"Particles/Anim Alpha Blended", | |||||
"Particles/Multiply (Double)", | |||||
"Particles/Multiply", | |||||
"Particles/VertexLit Blended", | |||||
"Particles/~Additive-Multiply", | |||||
"Skybox/Cubemap", | |||||
"Skybox/Procedural", | |||||
"Skybox/6 Sided", | |||||
"Sprites/Default", | |||||
"Sprites/Diffuse", | |||||
"UI/Default", | |||||
"VRChat/UI/Unlit/WebPanelTransparent", | |||||
"Toon/Lit", | |||||
"Toon/Lit (Double)", | |||||
"Toon/Lit Cutout", | |||||
"Toon/Lit Cutout (Double)", | |||||
"Toon/Lit Outline", | |||||
"VRChat/Mobile/Diffuse", | |||||
"VRChat/Mobile/Bumped Uniform Diffuse", | |||||
"VRChat/Mobile/Bumped Uniform Specular", | |||||
"VRChat/Mobile/Toon Lit", | |||||
"VRChat/Mobile/MatCap Lit", | |||||
"VRChat/Mobile/Skybox", | |||||
"VRChat/Mobile/Lightmapped", | |||||
"VRChat/PC/Toon Lit", | |||||
"VRChat/PC/Toon Lit (Double)", | |||||
"VRChat/PC/Toon Lit Cutout", | |||||
"VRChat/PC/Toon Lit Cutout (Double)", | |||||
"Unlit/Color", | |||||
"Unlit/Transparent", | |||||
"Unlit/Transparent Cutout", | |||||
"Unlit/Texture", | |||||
"MatCap/Vertex/Textured Lit", | |||||
#endif | |||||
}; | |||||
private static bool _requestConfigureSettings = true; | |||||
static EnvConfig() | |||||
{ | |||||
EditorApplication.update += EditorUpdate; | |||||
} | |||||
static void EditorUpdate() | |||||
{ | |||||
if (_requestConfigureSettings) | |||||
{ | |||||
if (ConfigureSettings()) | |||||
{ | |||||
_requestConfigureSettings = false; | |||||
} | |||||
} | |||||
} | |||||
public static void RequestConfigureSettings() | |||||
{ | |||||
_requestConfigureSettings = true; | |||||
} | |||||
[UnityEditor.Callbacks.DidReloadScripts(int.MaxValue)] | |||||
static void DidReloadScripts() | |||||
{ | |||||
RequestConfigureSettings(); | |||||
} | |||||
public static bool ConfigureSettings() | |||||
{ | |||||
CustomDLLMaker.CreateDirectories(); | |||||
if (CheckForFirstInit()) | |||||
VRC.AssetExporter.CleanupTmpFiles(); | |||||
if (EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isUpdating) | |||||
return false; | |||||
ConfigurePlayerSettings(); | |||||
if (!VRC.Core.RemoteConfig.IsInitialized()) | |||||
{ | |||||
VRC.Core.API.SetOnlineMode(true, "vrchat"); | |||||
VRC.Core.RemoteConfig.Init(); | |||||
} | |||||
LoadEditorResources(); | |||||
return true; | |||||
} | |||||
static void SetDLLPlatforms(string dllName, bool active) | |||||
{ | |||||
string[] assetGuids = AssetDatabase.FindAssets(dllName); | |||||
foreach (string guid in assetGuids) | |||||
{ | |||||
string dllPath = AssetDatabase.GUIDToAssetPath(guid); | |||||
if (string.IsNullOrEmpty(dllPath) || dllPath.ToLower().EndsWith(".dll") == false) | |||||
return; | |||||
PluginImporter importer = AssetImporter.GetAtPath(dllPath) as PluginImporter; | |||||
bool allCorrect = true; | |||||
if (importer.GetCompatibleWithAnyPlatform() != active) | |||||
{ | |||||
allCorrect = false; | |||||
} | |||||
else | |||||
{ | |||||
if (importer.GetCompatibleWithAnyPlatform()) | |||||
{ | |||||
if (importer.GetExcludeEditorFromAnyPlatform() != !active || | |||||
importer.GetExcludeFromAnyPlatform(BuildTarget.StandaloneWindows) != !active) | |||||
{ | |||||
allCorrect = false; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
if (importer.GetCompatibleWithEditor() != active || | |||||
importer.GetCompatibleWithPlatform(BuildTarget.StandaloneWindows) != active) | |||||
{ | |||||
allCorrect = false; | |||||
} | |||||
} | |||||
} | |||||
if (allCorrect == false) | |||||
{ | |||||
if (active) | |||||
{ | |||||
importer.SetCompatibleWithAnyPlatform(true); | |||||
importer.SetExcludeEditorFromAnyPlatform(false); | |||||
importer.SetExcludeFromAnyPlatform(BuildTarget.Android, false); | |||||
importer.SetExcludeFromAnyPlatform(BuildTarget.StandaloneWindows, false); | |||||
importer.SetExcludeFromAnyPlatform(BuildTarget.StandaloneWindows64, false); | |||||
importer.SetExcludeFromAnyPlatform(BuildTarget.StandaloneLinux, false); | |||||
importer.SetExcludeFromAnyPlatform(BuildTarget.StandaloneLinux64, false); | |||||
importer.SetExcludeFromAnyPlatform(BuildTarget.StandaloneOSX, false); | |||||
} | |||||
else | |||||
{ | |||||
importer.SetCompatibleWithAnyPlatform(false); | |||||
importer.SetCompatibleWithEditor(false); | |||||
importer.SetCompatibleWithPlatform(BuildTarget.Android, false); | |||||
importer.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows, false); | |||||
importer.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows64, false); | |||||
importer.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux, false); | |||||
importer.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux64, false); | |||||
importer.SetCompatibleWithPlatform(BuildTarget.StandaloneOSX, false); | |||||
} | |||||
importer.SaveAndReimport(); | |||||
} | |||||
} | |||||
} | |||||
[MenuItem("VRChat SDK/Utilities/Force Configure Player Settings")] | |||||
public static void ConfigurePlayerSettings() | |||||
{ | |||||
Debug.Log("Setting required PlayerSettings..."); | |||||
SetBuildTarget(); | |||||
// Needed for Microsoft.CSharp namespace in DLLMaker | |||||
// Doesn't seem to work though | |||||
if (PlayerSettings.GetApiCompatibilityLevel(EditorUserBuildSettings.selectedBuildTargetGroup) != ApiCompatibilityLevel.NET_2_0) | |||||
PlayerSettings.SetApiCompatibilityLevel(EditorUserBuildSettings.selectedBuildTargetGroup, ApiCompatibilityLevel.NET_2_0); | |||||
if (!PlayerSettings.runInBackground) | |||||
PlayerSettings.runInBackground = true; | |||||
#if !VRC_CLIENT | |||||
SetDLLPlatforms("VRCCore-Standalone", false); | |||||
SetDLLPlatforms("VRCCore-Editor", true); | |||||
#endif | |||||
SetDefaultGraphicsAPIs(); | |||||
SetGraphicsSettings(); | |||||
SetAudioSettings(); | |||||
SetPlayerSettings(); | |||||
#if VRC_CLIENT | |||||
AssetDatabase.SaveAssets(); | |||||
AssetDatabase.Refresh(); | |||||
#else | |||||
// SDK | |||||
// default to steam runtime in sdk (shouldn't matter) | |||||
SetVRSDKs(EditorUserBuildSettings.selectedBuildTargetGroup, new string[] { "None", "OpenVR", "Oculus" }); | |||||
VRC.Core.AnalyticsSDK.Initialize(VRC.Core.SDKClientUtilities.GetSDKVersionDate()); | |||||
#endif | |||||
// VRCLog should handle disk writing | |||||
PlayerSettings.usePlayerLog = false; | |||||
if (EditorUserBuildSettings.selectedBuildTargetGroup != BuildTargetGroup.Standalone) | |||||
{ | |||||
foreach (var logType in Enum.GetValues(typeof(LogType)).Cast<LogType>()) | |||||
PlayerSettings.SetStackTraceLogType(logType, StackTraceLogType.None); | |||||
} | |||||
else | |||||
{ | |||||
foreach (var logType in Enum.GetValues(typeof(LogType)).Cast<LogType>()) | |||||
PlayerSettings.SetStackTraceLogType(logType, StackTraceLogType.ScriptOnly); | |||||
} | |||||
} | |||||
static void EnableBatching(bool enable) | |||||
{ | |||||
PlayerSettings[] playerSettings = Resources.FindObjectsOfTypeAll<PlayerSettings>(); | |||||
if (playerSettings == null) | |||||
return; | |||||
SerializedObject playerSettingsSerializedObject = new SerializedObject(playerSettings); | |||||
SerializedProperty batchingSettings = playerSettingsSerializedObject.FindProperty("m_BuildTargetBatching"); | |||||
if (batchingSettings == null) | |||||
return; | |||||
for (int i = 0; i < batchingSettings.arraySize; i++) | |||||
{ | |||||
SerializedProperty batchingArrayValue = batchingSettings.GetArrayElementAtIndex(i); | |||||
if (batchingArrayValue == null) | |||||
continue; | |||||
IEnumerator batchingEnumerator = batchingArrayValue.GetEnumerator(); | |||||
if (batchingEnumerator == null) | |||||
continue; | |||||
while (batchingEnumerator.MoveNext()) | |||||
{ | |||||
SerializedProperty property = (SerializedProperty)batchingEnumerator.Current; | |||||
if (property != null && property.name == "m_BuildTarget") | |||||
{ | |||||
// only change setting on "Standalone" entry | |||||
if (property.stringValue != "Standalone") | |||||
break; | |||||
} | |||||
if (property != null && property.name == "m_StaticBatching") | |||||
{ | |||||
property.boolValue = enable; | |||||
} | |||||
if (property != null && property.name == "m_DynamicBatching") | |||||
{ | |||||
property.boolValue = enable; | |||||
} | |||||
} | |||||
} | |||||
playerSettingsSerializedObject.ApplyModifiedProperties(); | |||||
} | |||||
public static void SetVRSDKs(BuildTargetGroup buildTargetGroup, string[] sdkNames) | |||||
{ | |||||
Debug.Log("Setting virtual reality SDKs in PlayerSettings: "); | |||||
if (sdkNames != null) | |||||
{ | |||||
foreach (string s in sdkNames) | |||||
Debug.Log("- " + s); | |||||
} | |||||
PlayerSettings[] playerSettings = Resources.FindObjectsOfTypeAll<PlayerSettings>(); | |||||
if (playerSettings == null) | |||||
return; | |||||
SerializedObject playerSettingsSerializedObject = new SerializedObject(playerSettings); | |||||
SerializedProperty settingsGroup = playerSettingsSerializedObject.FindProperty("m_BuildTargetVRSettings"); | |||||
if (settingsGroup == null) | |||||
return; | |||||
for (int i = 0; i < settingsGroup.arraySize; i++) | |||||
{ | |||||
SerializedProperty settingVal = settingsGroup.GetArrayElementAtIndex(i); | |||||
if (settingVal == null) | |||||
continue; | |||||
IEnumerator enumerator = settingVal.GetEnumerator(); | |||||
if (enumerator == null) | |||||
continue; | |||||
while (enumerator.MoveNext()) | |||||
{ | |||||
SerializedProperty property = (SerializedProperty)enumerator.Current; | |||||
if (property != null && property.name == "m_BuildTarget") | |||||
{ | |||||
if (property.stringValue != buildTargetGroup.ToString()) | |||||
break; | |||||
} | |||||
if (property != null && property.name == "m_Devices") | |||||
{ | |||||
bool overwrite = true; | |||||
if (property.arraySize == sdkNames.Length) | |||||
{ | |||||
overwrite = false; | |||||
for (int e = 0; e < sdkNames.Length; ++e) | |||||
{ | |||||
if (property.GetArrayElementAtIndex(e).stringValue != sdkNames[e]) | |||||
overwrite = true; | |||||
} | |||||
} | |||||
if (overwrite) | |||||
{ | |||||
property.ClearArray(); | |||||
property.arraySize = (sdkNames != null) ? sdkNames.Length : 0; | |||||
for (int j = 0; j < property.arraySize; j++) | |||||
{ | |||||
property.GetArrayElementAtIndex(j).stringValue = sdkNames[j]; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
playerSettingsSerializedObject.ApplyModifiedProperties(); | |||||
} | |||||
static void RefreshClientVRSDKs() | |||||
{ | |||||
#if VRC_CLIENT | |||||
#if VRC_VR_STEAM | |||||
SetVRSDKs( BuildTargetGroup.Standalone, new string[] { "None", "OpenVR", "Oculus" }); | |||||
#else | |||||
SetVRSDKs(BuildTargetGroup.Standalone, new string[] { "None", "Oculus", "OpenVR" }); | |||||
#endif | |||||
#endif // VRC_CLIENT | |||||
} | |||||
public static bool CheckForFirstInit() | |||||
{ | |||||
bool firstLaunch = UnityEditor.SessionState.GetBool("EnvConfigFirstLaunch", true); | |||||
if (firstLaunch) | |||||
UnityEditor.SessionState.SetBool("EnvConfigFirstLaunch", false); | |||||
return firstLaunch; | |||||
} | |||||
static void SetDefaultGraphicsAPIs() | |||||
{ | |||||
Debug.Log("Setting Graphics APIs"); | |||||
foreach (BuildTarget target in relevantBuildTargets) | |||||
{ | |||||
var apis = allowedGraphicsAPIs[target]; | |||||
if (apis == null) | |||||
SetGraphicsAPIs(target, true); | |||||
else | |||||
SetGraphicsAPIs(target, false, apis); | |||||
} | |||||
} | |||||
static void SetGraphicsAPIs(BuildTarget platform, bool auto, UnityEngine.Rendering.GraphicsDeviceType[] allowedTypes = null) | |||||
{ | |||||
try | |||||
{ | |||||
if (auto != PlayerSettings.GetUseDefaultGraphicsAPIs(platform)) | |||||
PlayerSettings.SetUseDefaultGraphicsAPIs(platform, auto); | |||||
} | |||||
catch { } | |||||
try | |||||
{ | |||||
UnityEngine.Rendering.GraphicsDeviceType[] graphicsAPIs = PlayerSettings.GetGraphicsAPIs(platform); | |||||
if (((allowedTypes == null || allowedTypes.Length == 0) && (graphicsAPIs != null || graphicsAPIs.Length != 0)) | |||||
|| !allowedTypes.SequenceEqual(graphicsAPIs)) | |||||
PlayerSettings.SetGraphicsAPIs(platform, allowedTypes); | |||||
} | |||||
catch { } | |||||
} | |||||
static void SetGraphicsSettings() | |||||
{ | |||||
Debug.Log("Setting Graphics Settings"); | |||||
const string GraphicsSettingsAssetPath = "ProjectSettings/GraphicsSettings.asset"; | |||||
SerializedObject graphicsManager = new SerializedObject(UnityEditor.AssetDatabase.LoadAllAssetsAtPath(GraphicsSettingsAssetPath)[0]); | |||||
SerializedProperty deferred = graphicsManager.FindProperty("m_Deferred.m_Mode"); | |||||
deferred.enumValueIndex = 1; | |||||
SerializedProperty deferredReflections = graphicsManager.FindProperty("m_DeferredReflections.m_Mode"); | |||||
deferredReflections.enumValueIndex = 1; | |||||
SerializedProperty screenSpaceShadows = graphicsManager.FindProperty("m_ScreenSpaceShadows.m_Mode"); | |||||
screenSpaceShadows.enumValueIndex = 1; | |||||
SerializedProperty legacyDeferred = graphicsManager.FindProperty("m_LegacyDeferred.m_Mode"); | |||||
legacyDeferred.enumValueIndex = 1; | |||||
SerializedProperty depthNormals = graphicsManager.FindProperty("m_DepthNormals.m_Mode"); | |||||
depthNormals.enumValueIndex = 1; | |||||
SerializedProperty motionVectors = graphicsManager.FindProperty("m_MotionVectors.m_Mode"); | |||||
motionVectors.enumValueIndex = 1; | |||||
SerializedProperty lightHalo = graphicsManager.FindProperty("m_LightHalo.m_Mode"); | |||||
lightHalo.enumValueIndex = 1; | |||||
SerializedProperty lensFlare = graphicsManager.FindProperty("m_LensFlare.m_Mode"); | |||||
lensFlare.enumValueIndex = 1; | |||||
#if ENV_SET_INCLUDED_SHADERS && VRC_CLIENT | |||||
SerializedProperty alwaysIncluded = graphicsManager.FindProperty("m_AlwaysIncludedShaders"); | |||||
alwaysIncluded.arraySize = 0; // clear GraphicsSettings->Always Included Shaders - these cause a +5s app startup time increase on Quest. | |||||
// include Shader objects as resources instead | |||||
#if ENV_SEARCH_FOR_SHADERS | |||||
Resources.LoadAll("", typeof(Shader)); | |||||
System.Collections.Generic.List<Shader> foundShaders = Resources.FindObjectsOfTypeAll<Shader>() | |||||
.Where(s => { string name = s.name.ToLower(); return 0 == (s.hideFlags & HideFlags.DontSave); }) | |||||
.GroupBy(s => s.name) | |||||
.Select(g => g.First()) | |||||
.ToList(); | |||||
#else | |||||
System.Collections.Generic.List<Shader> foundShaders = new System.Collections.Generic.List<Shader>(); | |||||
#endif | |||||
for (int shaderIdx = 0; shaderIdx < ensureTheseShadersAreAvailable.Length; ++shaderIdx) | |||||
{ | |||||
if (foundShaders.Any(s => s.name == ensureTheseShadersAreAvailable[shaderIdx])) | |||||
continue; | |||||
Shader namedShader = Shader.Find(ensureTheseShadersAreAvailable[shaderIdx]); | |||||
if (namedShader != null) | |||||
foundShaders.Add(namedShader); | |||||
} | |||||
foundShaders.Sort((s1, s2) => s1.name.CompareTo(s2.name)); | |||||
// populate Resources list of "always included shaders" | |||||
ShaderAssetList alwaysIncludedShaders = AssetDatabase.LoadAssetAtPath<ShaderAssetList>("Assets/Resources/AlwaysIncludedShaders.asset"); | |||||
alwaysIncludedShaders.Shaders = new Shader[foundShaders.Count]; | |||||
for (int shaderIdx = 0; shaderIdx < foundShaders.Count; ++shaderIdx) | |||||
alwaysIncludedShaders.Shaders[shaderIdx] = foundShaders[shaderIdx]; | |||||
#endif | |||||
SerializedProperty preloaded = graphicsManager.FindProperty("m_PreloadedShaders"); | |||||
preloaded.ClearArray(); | |||||
preloaded.arraySize = 0; | |||||
SerializedProperty spritesDefaultMaterial = graphicsManager.FindProperty("m_SpritesDefaultMaterial"); | |||||
spritesDefaultMaterial.objectReferenceValue = Shader.Find("Sprites/Default"); | |||||
SerializedProperty renderPipeline = graphicsManager.FindProperty("m_CustomRenderPipeline"); | |||||
renderPipeline.objectReferenceValue = null; | |||||
SerializedProperty transparencySortMode = graphicsManager.FindProperty("m_TransparencySortMode"); | |||||
transparencySortMode.enumValueIndex = 0; | |||||
SerializedProperty transparencySortAxis = graphicsManager.FindProperty("m_TransparencySortAxis"); | |||||
transparencySortAxis.vector3Value = Vector3.forward; | |||||
SerializedProperty defaultRenderingPath = graphicsManager.FindProperty("m_DefaultRenderingPath"); | |||||
defaultRenderingPath.intValue = 1; | |||||
SerializedProperty defaultMobileRenderingPath = graphicsManager.FindProperty("m_DefaultMobileRenderingPath"); | |||||
defaultMobileRenderingPath.intValue = 1; | |||||
SerializedProperty tierSettings = graphicsManager.FindProperty("m_TierSettings"); | |||||
tierSettings.ClearArray(); | |||||
tierSettings.arraySize = 0; | |||||
#if ENV_SET_LIGHTMAP | |||||
SerializedProperty lightmapStripping = graphicsManager.FindProperty("m_LightmapStripping"); | |||||
lightmapStripping.enumValueIndex = 1; | |||||
SerializedProperty instancingStripping = graphicsManager.FindProperty("m_InstancingStripping"); | |||||
instancingStripping.enumValueIndex = 2; | |||||
SerializedProperty lightmapKeepPlain = graphicsManager.FindProperty("m_LightmapKeepPlain"); | |||||
lightmapKeepPlain.boolValue = true; | |||||
SerializedProperty lightmapKeepDirCombined = graphicsManager.FindProperty("m_LightmapKeepDirCombined"); | |||||
lightmapKeepDirCombined.boolValue = true; | |||||
SerializedProperty lightmapKeepDynamicPlain = graphicsManager.FindProperty("m_LightmapKeepDynamicPlain"); | |||||
lightmapKeepDynamicPlain.boolValue = true; | |||||
SerializedProperty lightmapKeepDynamicDirCombined = graphicsManager.FindProperty("m_LightmapKeepDynamicDirCombined"); | |||||
lightmapKeepDynamicDirCombined.boolValue = true; | |||||
SerializedProperty lightmapKeepShadowMask = graphicsManager.FindProperty("m_LightmapKeepShadowMask"); | |||||
lightmapKeepShadowMask.boolValue = true; | |||||
SerializedProperty lightmapKeepSubtractive = graphicsManager.FindProperty("m_LightmapKeepSubtractive"); | |||||
lightmapKeepSubtractive.boolValue = true; | |||||
#endif | |||||
#if ENV_SET_FOG | |||||
SerializedProperty fogStripping = graphicsManager.FindProperty("m_FogStripping"); | |||||
fogStripping.enumValueIndex = 1; | |||||
SerializedProperty fogKeepLinear = graphicsManager.FindProperty("m_FogKeepLinear"); | |||||
fogKeepLinear.boolValue = true; | |||||
SerializedProperty fogKeepExp = graphicsManager.FindProperty("m_FogKeepExp"); | |||||
fogKeepExp.boolValue = true; | |||||
SerializedProperty fogKeepExp2 = graphicsManager.FindProperty("m_FogKeepExp2"); | |||||
fogKeepExp2.boolValue = true; | |||||
#endif | |||||
SerializedProperty albedoSwatchInfos = graphicsManager.FindProperty("m_AlbedoSwatchInfos"); | |||||
albedoSwatchInfos.ClearArray(); | |||||
albedoSwatchInfos.arraySize = 0; | |||||
SerializedProperty lightsUseLinearIntensity = graphicsManager.FindProperty("m_LightsUseLinearIntensity"); | |||||
lightsUseLinearIntensity.boolValue = true; | |||||
SerializedProperty lightsUseColorTemperature = graphicsManager.FindProperty("m_LightsUseColorTemperature"); | |||||
lightsUseColorTemperature.boolValue = true; | |||||
graphicsManager.ApplyModifiedProperties(); | |||||
} | |||||
static void SetAudioSettings() | |||||
{ | |||||
var config = AudioSettings.GetConfiguration(); | |||||
config.dspBufferSize = 0; // use default | |||||
config.speakerMode = AudioSpeakerMode.Stereo; // use default | |||||
config.sampleRate = 0; // use default | |||||
if (EditorUserBuildSettings.selectedBuildTargetGroup == BuildTargetGroup.Android) | |||||
{ | |||||
config.numRealVoices = 24; | |||||
config.numVirtualVoices = 24; | |||||
} | |||||
else | |||||
{ | |||||
config.numRealVoices = 32; | |||||
config.numVirtualVoices = 63; | |||||
} | |||||
AudioSettings.Reset(config); | |||||
} | |||||
static void SetPlayerSettings() | |||||
{ | |||||
// asset bundles MUST be built with settings that are compatible with VRC client | |||||
#if VRC_OVERRIDE_COLORSPACE_GAMMA | |||||
PlayerSettings.colorSpace = ColorSpace.Gamma; | |||||
#else | |||||
PlayerSettings.colorSpace = ColorSpace.Linear; | |||||
#endif | |||||
#if !VRC_CLIENT // In client rely on platform-switcher | |||||
PlayerSettings.virtualRealitySupported = true; | |||||
#endif | |||||
PlayerSettings.graphicsJobs = false; // else we get occasional crashing | |||||
PlayerSettings.gpuSkinning = true; | |||||
PlayerSettings.stereoRenderingPath = StereoRenderingPath.SinglePass; | |||||
EnableBatching(true); | |||||
} | |||||
static void SetBuildTarget() | |||||
{ | |||||
#if !VRC_CLIENT | |||||
Debug.Log("Setting build target"); | |||||
BuildTarget target = UnityEditor.EditorUserBuildSettings.activeBuildTarget; | |||||
if (!allowedBuildtargets.Contains(target)) | |||||
{ | |||||
Debug.LogError("Target not supported, switching to one that is."); | |||||
target = allowedBuildtargets[0]; | |||||
#pragma warning disable CS0618 // Type or member is obsolete | |||||
EditorUserBuildSettings.SwitchActiveBuildTarget(target); | |||||
#pragma warning restore CS0618 // Type or member is obsolete | |||||
} | |||||
#endif | |||||
} | |||||
private static void LoadEditorResources() | |||||
{ | |||||
AvatarPerformanceStats.Initialize(); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 10d9f721d76e07a47bc9e5f61e2fae72 | |||||
timeCreated: 1455115256 | |||||
licenseType: Free | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
#if UNITY_EDITOR | |||||
using UnityEngine; | |||||
using UnityEditor; | |||||
using UnityEditor.SceneManagement; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
namespace VRCSDK2 | |||||
{ | |||||
[CustomEditor(typeof(VRCSDK2.VRC_EventHandler))] | |||||
public class EventHandlerEditor : Editor | |||||
{ | |||||
bool showDeferredEvents = false; | |||||
static VRCSDK2.VRC_EventHandler.VrcEventType lastAddedEventType = VRC_EventHandler.VrcEventType.SendMessage; | |||||
public override void OnInspectorGUI() | |||||
{ | |||||
VRCSDK2.VRC_EventHandler myTarget = (VRCSDK2.VRC_EventHandler)target; | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("ID:"); | |||||
EditorGUILayout.EndHorizontal(); | |||||
if (myTarget.GetComponent<VRCSDK2.VRC_Trigger>() != null) | |||||
{ | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Add Events via the VRC_Trigger on this object."); | |||||
EditorGUILayout.EndHorizontal(); | |||||
} | |||||
else | |||||
{ | |||||
EditorGUI.BeginChangeCheck(); | |||||
RenderOldEditor(myTarget); | |||||
if (EditorGUI.EndChangeCheck()) | |||||
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); | |||||
} | |||||
if (myTarget.deferredEvents.Count > 0) | |||||
{ | |||||
showDeferredEvents = EditorGUILayout.Foldout(showDeferredEvents, "Deferred Events"); | |||||
if (showDeferredEvents) | |||||
RenderEvents(myTarget.deferredEvents); | |||||
} | |||||
} | |||||
int[] sendMessageMethodIndicies; | |||||
private void RenderOldEditor(VRCSDK2.VRC_EventHandler myTarget) | |||||
{ | |||||
EditorGUILayout.HelpBox("Please use a VRC_Trigger in the future.", MessageType.Error); | |||||
if (GUILayout.Button("Add Event Handler")) | |||||
myTarget.Events.Add(new VRCSDK2.VRC_EventHandler.VrcEvent()); | |||||
bool first = true; | |||||
int deleteEventIndex = -1; | |||||
if (sendMessageMethodIndicies == null || sendMessageMethodIndicies.Length != myTarget.Events.Count) | |||||
sendMessageMethodIndicies = new int[myTarget.Events.Count + 1]; | |||||
for (int i = 0; i < myTarget.Events.Count; ++i) | |||||
{ | |||||
if (!first) | |||||
EditorGUILayout.Separator(); | |||||
first = false; | |||||
EditorGUILayout.LabelField("Event " + (i + 1).ToString()); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Event Name"); | |||||
myTarget.Events[i].Name = EditorGUILayout.TextField(myTarget.Events[i].Name); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Event Type"); | |||||
myTarget.Events[i].EventType = (VRCSDK2.VRC_EventHandler.VrcEventType)EditorGUILayout.EnumPopup(myTarget.Events[i].EventType); | |||||
EditorGUILayout.EndHorizontal(); | |||||
switch (myTarget.Events[i].EventType) | |||||
{ | |||||
case VRCSDK2.VRC_EventHandler.VrcEventType.AnimationBool: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Variable"); | |||||
myTarget.Events[i].ParameterString = EditorGUILayout.TextField(myTarget.Events[i].ParameterString); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Operation"); | |||||
myTarget.Events[i].ParameterBoolOp = (VRCSDK2.VRC_EventHandler.VrcBooleanOp)EditorGUILayout.EnumPopup(myTarget.Events[i].ParameterBoolOp); | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
case VRCSDK2.VRC_EventHandler.VrcEventType.AnimationFloat: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Variable"); | |||||
myTarget.Events[i].ParameterString = EditorGUILayout.TextField(myTarget.Events[i].ParameterString); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Value"); | |||||
myTarget.Events[i].ParameterFloat = EditorGUILayout.FloatField(myTarget.Events[i].ParameterFloat); | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
case VRCSDK2.VRC_EventHandler.VrcEventType.AnimationTrigger: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Trigger"); | |||||
myTarget.Events[i].ParameterString = EditorGUILayout.TextField(myTarget.Events[i].ParameterString); | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
case VRCSDK2.VRC_EventHandler.VrcEventType.AudioTrigger: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("AudioSource"); | |||||
myTarget.Events[i].ParameterObject = (GameObject)EditorGUILayout.ObjectField(myTarget.Events[i].ParameterObject, typeof(GameObject), true); | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
case VRCSDK2.VRC_EventHandler.VrcEventType.MeshVisibility: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Mesh"); | |||||
myTarget.Events[i].ParameterObject = (GameObject)EditorGUILayout.ObjectField(myTarget.Events[i].ParameterObject, typeof(GameObject), true); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Operation"); | |||||
myTarget.Events[i].ParameterBoolOp = (VRCSDK2.VRC_EventHandler.VrcBooleanOp)EditorGUILayout.EnumPopup(myTarget.Events[i].ParameterBoolOp); | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
case VRCSDK2.VRC_EventHandler.VrcEventType.PlayAnimation: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Target"); | |||||
myTarget.Events[i].ParameterObject = (GameObject)EditorGUILayout.ObjectField(myTarget.Events[i].ParameterObject, typeof(GameObject), true); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Animation"); | |||||
myTarget.Events[i].ParameterString = EditorGUILayout.TextField(myTarget.Events[i].ParameterString); | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
case VRCSDK2.VRC_EventHandler.VrcEventType.RunConsoleCommand: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Command"); | |||||
myTarget.Events[i].ParameterString = EditorGUILayout.TextField(myTarget.Events[i].ParameterString); | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
case VRCSDK2.VRC_EventHandler.VrcEventType.SendMessage: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Receiver"); | |||||
myTarget.Events[i].ParameterObject = (GameObject)EditorGUILayout.ObjectField(myTarget.Events[i].ParameterObject, typeof(GameObject), true); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Message"); | |||||
// sorry for this shit show. Below allows us to show a list of public methods, but also allow custom messages | |||||
var methods = VRC_EditorTools.GetAccessibleMethodsOnGameObject(myTarget.Events[i].ParameterObject); | |||||
List<string> methodList = methods.Values.Aggregate(new List<string>(), (acc, lst) => { acc.AddRange(lst.Select(mi => mi.Name)); return acc; }); | |||||
methodList.Add("Custom Message"); | |||||
string[] _choices = methodList.ToArray(); | |||||
int currentIndex = methodList.Count - 1; | |||||
if (methodList.Contains(myTarget.Events[i].ParameterString)) | |||||
currentIndex = methodList.IndexOf(myTarget.Events[i].ParameterString); | |||||
sendMessageMethodIndicies[i] = EditorGUILayout.Popup(currentIndex, _choices); | |||||
if (sendMessageMethodIndicies[i] != methodList.Count - 1) | |||||
{ | |||||
myTarget.Events[i].ParameterString = _choices[sendMessageMethodIndicies[i]]; | |||||
} | |||||
else | |||||
{ | |||||
if (methodList.Contains(myTarget.Events[i].ParameterString)) | |||||
myTarget.Events[i].ParameterString = ""; | |||||
myTarget.Events[i].ParameterString = EditorGUILayout.TextField(myTarget.Events[i].ParameterString); | |||||
} | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
case VRCSDK2.VRC_EventHandler.VrcEventType.SetGameObjectActive: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("GameObject"); | |||||
myTarget.Events[i].ParameterObject = (GameObject)EditorGUILayout.ObjectField(myTarget.Events[i].ParameterObject, typeof(GameObject), true); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Operation"); | |||||
myTarget.Events[i].ParameterBoolOp = (VRCSDK2.VRC_EventHandler.VrcBooleanOp)EditorGUILayout.EnumPopup(myTarget.Events[i].ParameterBoolOp); | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
case VRCSDK2.VRC_EventHandler.VrcEventType.SetParticlePlaying: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Target"); | |||||
myTarget.Events[i].ParameterObject = (GameObject)EditorGUILayout.ObjectField(myTarget.Events[i].ParameterObject, typeof(GameObject), true); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Operation"); | |||||
myTarget.Events[i].ParameterBoolOp = (VRCSDK2.VRC_EventHandler.VrcBooleanOp)EditorGUILayout.EnumPopup(myTarget.Events[i].ParameterBoolOp); | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
case VRCSDK2.VRC_EventHandler.VrcEventType.TeleportPlayer: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Location"); | |||||
myTarget.Events[i].ParameterObject = (GameObject)EditorGUILayout.ObjectField(myTarget.Events[i].ParameterObject, typeof(GameObject), true); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Align Room To Destination"); | |||||
myTarget.Events[i].ParameterBoolOp = (VRCSDK2.VRC_EventHandler.VrcBooleanOp)EditorGUILayout.EnumPopup(myTarget.Events[i].ParameterBoolOp); | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
case VRCSDK2.VRC_EventHandler.VrcEventType.SetWebPanelURI: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("URI"); | |||||
myTarget.Events[i].ParameterString = EditorGUILayout.TextField(myTarget.Events[i].ParameterString); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Panel"); | |||||
myTarget.Events[i].ParameterObject = (GameObject)EditorGUILayout.ObjectField(myTarget.Events[i].ParameterObject, typeof(GameObject), true); | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
case VRCSDK2.VRC_EventHandler.VrcEventType.SetWebPanelVolume: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Volume"); | |||||
myTarget.Events[i].ParameterFloat = EditorGUILayout.FloatField(myTarget.Events[i].ParameterFloat); | |||||
EditorGUILayout.EndHorizontal(); | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Panel"); | |||||
myTarget.Events[i].ParameterObject = (GameObject)EditorGUILayout.ObjectField(myTarget.Events[i].ParameterObject, typeof(GameObject), true); | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
default: | |||||
EditorGUILayout.BeginHorizontal(); | |||||
GUIStyle redText = new GUIStyle(); | |||||
redText.normal.textColor = Color.red; | |||||
EditorGUILayout.LabelField("Unsupported event type", redText); | |||||
EditorGUILayout.EndHorizontal(); | |||||
break; | |||||
} | |||||
EditorGUILayout.BeginHorizontal(); | |||||
EditorGUILayout.LabelField("Delete " + myTarget.Events[i].Name + "?"); | |||||
if (GUILayout.Button("delete")) | |||||
deleteEventIndex = i; | |||||
EditorGUILayout.EndHorizontal(); | |||||
if (myTarget.Events[i].ParameterObject == null) | |||||
myTarget.Events[i].ParameterObject = myTarget.gameObject; | |||||
} | |||||
if (deleteEventIndex != -1) | |||||
myTarget.Events.RemoveAt(deleteEventIndex); | |||||
} | |||||
private void RenderEvents(IEnumerable<VRCSDK2.VRC_EventHandler.EventInfo> entries) | |||||
{ | |||||
foreach (VRCSDK2.VRC_EventHandler.EventInfo entry in entries) | |||||
{ | |||||
EditorGUILayout.PrefixLabel("Target"); | |||||
EditorGUILayout.ObjectField(entry.evt.ParameterObject, typeof(GameObject), true); | |||||
EditorGUILayout.LabelField(string.Format("Name: {0}", entry.evt.Name)); | |||||
EditorGUILayout.LabelField(string.Format("Type: {0}", entry.evt.EventType)); | |||||
EditorGUILayout.LabelField(string.Format("Bool: {0}", entry.evt.ParameterBool)); | |||||
EditorGUILayout.LabelField(string.Format("Float: {0}", entry.evt.ParameterFloat)); | |||||
EditorGUILayout.LabelField(string.Format("Int: {0}", entry.evt.ParameterInt)); | |||||
EditorGUILayout.LabelField(string.Format("String: {0}", entry.evt.ParameterString)); | |||||
EditorGUILayout.Space(); | |||||
} | |||||
} | |||||
public static void RenderEditor(VRCSDK2.VRC_EventHandler myTarget) | |||||
{ | |||||
bool first = true; | |||||
int deleteEventIndex = -1; | |||||
for (int i = 0; i < myTarget.Events.Count; ++i) | |||||
{ | |||||
if (!first) | |||||
EditorGUILayout.Separator(); | |||||
first = false; | |||||
if (RenderEventHeader(myTarget, myTarget.Events[i])) | |||||
deleteEventIndex = i; | |||||
RenderEventHeader(myTarget, myTarget.Events[i]); | |||||
if (myTarget.Events[i].ParameterObject == null) | |||||
myTarget.Events[i].ParameterObject = myTarget.gameObject; | |||||
} | |||||
if (deleteEventIndex != -1) | |||||
myTarget.Events.RemoveAt(deleteEventIndex); | |||||
} | |||||
public static VRCSDK2.VRC_EventHandler.VrcEvent RenderAddEvent(VRCSDK2.VRC_EventHandler myTarget) | |||||
{ | |||||
VRCSDK2.VRC_EventHandler.VrcEvent newEvent = null; | |||||
EditorGUILayout.BeginHorizontal(); | |||||
lastAddedEventType = VRC_EditorTools.FilteredEnumPopup("New Event Type", lastAddedEventType, (v) => v != VRC_EventHandler.VrcEventType.SpawnObject && v != VRC_EventHandler.VrcEventType.SendMessage); | |||||
if (GUILayout.Button("Add")) | |||||
{ | |||||
newEvent = new VRCSDK2.VRC_EventHandler.VrcEvent | |||||
{ | |||||
EventType = lastAddedEventType, | |||||
ParameterObject = myTarget.gameObject | |||||
}; | |||||
myTarget.Events.Add(newEvent); | |||||
EditorUtility.SetDirty(myTarget); | |||||
} | |||||
EditorGUILayout.EndHorizontal(); | |||||
return newEvent; | |||||
} | |||||
public static bool RenderEventHeader(VRCSDK2.VRC_EventHandler myTarget, VRCSDK2.VRC_EventHandler.VrcEvent evt) | |||||
{ | |||||
EditorGUILayout.BeginHorizontal(); | |||||
evt.EventType = VRC_EditorTools.FilteredEnumPopup("New Event Type", evt.EventType, (v) => v != VRC_EventHandler.VrcEventType.SpawnObject && v != VRC_EventHandler.VrcEventType.SendMessage); | |||||
bool delete = GUILayout.Button("Remove"); | |||||
EditorGUILayout.EndHorizontal(); | |||||
return delete; | |||||
} | |||||
} | |||||
} | |||||
#endif |
fileFormatVersion: 2 | |||||
guid: 4810e652e8242384c834320970702290 | |||||
timeCreated: 1454469344 | |||||
licenseType: Pro | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using UnityEngine; | |||||
using System.Collections; | |||||
using UnityEditor; | |||||
public class SDKUpdater : MonoBehaviour | |||||
{ | |||||
static string GetCurrentVersion() | |||||
{ | |||||
string currentVersion = ""; | |||||
string versionTextPath = Application.dataPath + "/VRCSDK/version.txt"; | |||||
if(System.IO.File.Exists(versionTextPath)) | |||||
{ | |||||
string[] versionFileLines = System.IO.File.ReadAllLines(versionTextPath); | |||||
if(versionFileLines.Length > 0) | |||||
currentVersion = versionFileLines[0]; | |||||
} | |||||
return currentVersion; | |||||
} | |||||
[MenuItem("VRChat SDK/Utilities/Check For Updates")] | |||||
static void CheckForUpdatesWithProgressBar() | |||||
{ | |||||
CheckForUpdates(false); | |||||
} | |||||
public static void CheckForUpdates(bool isSilent = true) | |||||
{ | |||||
Debug.Log("Checking for VRChat SDK updates..."); | |||||
if(!isSilent) | |||||
EditorUtility.DisplayProgressBar("SDK Updater", "Checking for updates...", 1f); | |||||
VRC.Core.RemoteConfig.Init(delegate() { | |||||
string currentSdkVersion = GetCurrentVersion(); | |||||
string sdkVersion = VRC.Core.RemoteConfig.GetString("devSdkVersion"); | |||||
string sdkUrl = VRC.Core.RemoteConfig.GetString("devSdkUrl"); | |||||
EditorUtility.ClearProgressBar(); | |||||
if(sdkVersion == currentSdkVersion) | |||||
{ | |||||
ShowDownloadUpdatePopup(false, currentSdkVersion, sdkUrl, isSilent); | |||||
} | |||||
else | |||||
{ | |||||
ShowDownloadUpdatePopup(true, sdkVersion, sdkUrl, isSilent); | |||||
} | |||||
}); | |||||
} | |||||
static void ShowDownloadUpdatePopup(bool updateAvailable, string latestVersion, string sdkUrl, bool isSilent) | |||||
{ | |||||
if(!updateAvailable) | |||||
{ | |||||
if(!isSilent) | |||||
EditorUtility.DisplayDialog("VRChat SDK Updater", "SDK is up to date (version " + latestVersion + ")", "Okay"); | |||||
} | |||||
else | |||||
{ | |||||
if(EditorUtility.DisplayDialog("VRChat SDK Updater", "An update is available (version " + latestVersion + ")", "Download", "Cancel")) | |||||
{ | |||||
DownloadUpdate(sdkUrl); | |||||
} | |||||
} | |||||
} | |||||
static void DownloadUpdate(string sdkUrl) | |||||
{ | |||||
Application.OpenURL(sdkUrl); | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 7b8bb626428d0f341b9ed6a68cb5c9cc | |||||
timeCreated: 1473273663 | |||||
licenseType: Pro | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using System.Security.Cryptography; | |||||
using UnityEngine; | |||||
public static class VRCCachedWWW { | |||||
public const float DefaultCacheTimeHours = 24 * 7; | |||||
public static void ClearOld(float cacheLimitHours = DefaultCacheTimeHours) | |||||
{ | |||||
string cacheDir = CacheDir; | |||||
if (System.IO.Directory.Exists(cacheDir)) | |||||
{ | |||||
foreach (string fileName in System.IO.Directory.GetFiles(cacheDir)) | |||||
{ | |||||
if (GetAge(fileName) > cacheLimitHours) | |||||
System.IO.File.Delete(fileName); | |||||
} | |||||
} | |||||
} | |||||
private static string CacheDir | |||||
{ | |||||
get | |||||
{ | |||||
return Application.temporaryCachePath; | |||||
} | |||||
} | |||||
public static IEnumerator Get(string url, System.Action<WWW> onDone, float cacheLimitHours = DefaultCacheTimeHours) | |||||
{ | |||||
string cacheDir = CacheDir; | |||||
if (!System.IO.Directory.Exists(cacheDir)) | |||||
System.IO.Directory.CreateDirectory(cacheDir); | |||||
string hash = CreateHash(url); | |||||
string cache = cacheDir + "/www_" + hash; | |||||
string location = url; | |||||
bool useCache = false; | |||||
if (System.IO.File.Exists(cache)) | |||||
{ | |||||
if (GetAge(cache) > cacheLimitHours) | |||||
System.IO.File.Delete(cache); | |||||
else | |||||
{ | |||||
location = "file://" + cache; | |||||
useCache = true; | |||||
} | |||||
} | |||||
while (true) | |||||
{ | |||||
WWW target = new WWW(location); | |||||
target.threadPriority = ThreadPriority.Low; | |||||
while (!target.isDone) | |||||
yield return null; | |||||
if (!useCache) | |||||
{ | |||||
if (System.IO.File.Exists(cache)) | |||||
System.IO.File.Delete(cache); | |||||
if (string.IsNullOrEmpty(target.error)) | |||||
System.IO.File.WriteAllBytes(cache, target.bytes); | |||||
onDone(target); | |||||
break; | |||||
} | |||||
else | |||||
{ | |||||
if (string.IsNullOrEmpty(target.error)) | |||||
{ | |||||
onDone(target); | |||||
break; | |||||
} | |||||
else | |||||
{ | |||||
if (System.IO.File.Exists(cache)) | |||||
System.IO.File.Delete(cache); | |||||
location = url; | |||||
useCache = false; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
private static string CreateHash(string _string) | |||||
{ | |||||
SHA256 hash = SHA256.Create(); | |||||
byte[] computed_hash = hash.ComputeHash(System.Text.Encoding.Default.GetBytes(_string)); | |||||
return System.Uri.EscapeDataString(System.Convert.ToBase64String(computed_hash)); | |||||
} | |||||
private static double GetAge(string file) | |||||
{ | |||||
if (!System.IO.File.Exists(file)) | |||||
return 0; | |||||
System.DateTime writeTime = System.IO.File.GetLastWriteTimeUtc(file); | |||||
return System.DateTime.UtcNow.Subtract(writeTime).TotalHours; | |||||
} | |||||
} |
fileFormatVersion: 2 | |||||
guid: 4a9696f3dea8a764f9c4bc6d2e652b74 | |||||
timeCreated: 1519696095 | |||||
licenseType: Pro | |||||
MonoImporter: | |||||
serializedVersion: 2 | |||||
defaultReferences: [] | |||||
executionOrder: 0 | |||||
icon: {instanceID: 0} | |||||
userData: | |||||
assetBundleName: | |||||
assetBundleVariant: |
#if UNITY_EDITOR | |||||
using UnityEngine; | |||||
using UnityEditor; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using UnityEditorInternal; | |||||
using System.Reflection; | |||||
using System; | |||||
namespace VRCSDK2 | |||||
{ | |||||
public static class VRC_EditorTools | |||||
{ | |||||
private static LayerMask LayerMaskPopupInternal(LayerMask selectedValue, System.Func<int, string[], int> showMask) | |||||
{ | |||||
string[] layerNames = InternalEditorUtility.layers; | |||||
List<int> layerNumbers = new List<int>(); | |||||
foreach (string layer in layerNames) | |||||
layerNumbers.Add(LayerMask.NameToLayer(layer)); | |||||
int mask = 0; | |||||
for (int idx = 0; idx < layerNumbers.Count; ++idx) | |||||
if (((1 << layerNumbers[idx]) & selectedValue.value) > 0) | |||||
mask |= (1 << idx); | |||||
mask = showMask(mask, layerNames); | |||||
selectedValue.value = 0; | |||||
for (int idx = 0; idx < layerNumbers.Count; ++idx) | |||||
if (((1 << idx) & mask) > 0) | |||||
selectedValue.value |= (1 << layerNumbers[idx]); | |||||
return selectedValue; | |||||
} | |||||
public static LayerMask LayerMaskPopup(LayerMask selectedValue, params GUILayoutOption[] options) | |||||
{ | |||||
return LayerMaskPopupInternal(selectedValue, (mask, layerNames) => EditorGUILayout.MaskField(mask, layerNames, options)); | |||||
} | |||||
public static LayerMask LayerMaskPopup(string label, LayerMask selectedValue, params GUILayoutOption[] options) | |||||
{ | |||||
return LayerMaskPopupInternal(selectedValue, (mask, layerNames) => EditorGUILayout.MaskField(label, mask, layerNames, options)); | |||||
} | |||||
public static LayerMask LayerMaskPopup(Rect rect, LayerMask selectedValue, GUIStyle style = null) | |||||
{ | |||||
System.Func<int, string[], int> show = (mask, layerNames) => | |||||
{ | |||||
if (style == null) | |||||
return EditorGUI.MaskField(rect, mask, layerNames); | |||||
else | |||||
return EditorGUI.MaskField(rect, mask, layerNames, style); | |||||
}; | |||||
return LayerMaskPopupInternal(selectedValue, show); | |||||
} | |||||
public static LayerMask LayerMaskPopup(Rect rect, string label, LayerMask selectedValue, GUIStyle style = null) | |||||
{ | |||||
System.Func<int, string[], int> show = (mask, layerNames) => | |||||
{ | |||||
if (style == null) | |||||
return EditorGUI.MaskField(rect, label, mask, layerNames); | |||||
else | |||||
return EditorGUI.MaskField(rect, label, mask, layerNames, style); | |||||
}; | |||||
return LayerMaskPopupInternal(selectedValue, show); | |||||
} | |||||
private static T FilteredEnumPopupInternal<T>(T selectedValue, System.Func<T, bool> predicate, System.Func<int, string[], int> showPopup, System.Func<string, string> rename) where T : struct, System.IConvertible | |||||
{ | |||||
if (!typeof(T).IsEnum) | |||||
throw new System.ArgumentException(typeof(T).Name + " is not an Enum", "T"); | |||||
T[] ary = System.Enum.GetValues(typeof(T)).Cast<T>().Where(v => predicate(v)).ToArray(); | |||||
string[] names = ary.Select(e => System.Enum.GetName(typeof(T), e)).ToArray(); | |||||
int selectedIdx = 0; | |||||
for (; selectedIdx < ary.Length; ++selectedIdx) | |||||
if (ary[selectedIdx].Equals(selectedValue)) | |||||
break; | |||||
if (selectedIdx == ary.Length) | |||||
selectedIdx = 0; | |||||
if (ary.Length == 0) | |||||
throw new System.ArgumentException("Predicate filtered out all options", "predicate"); | |||||
if (rename != null) | |||||
return ary[showPopup(selectedIdx, names.Select(rename).ToArray())]; | |||||
else | |||||
return ary[showPopup(selectedIdx, names)]; | |||||
} | |||||
private static void FilteredEnumPopupInternal<T>(SerializedProperty enumProperty, System.Func<T, bool> predicate, System.Func<int, string[], int> showPopup, System.Func<string, string> rename) where T : struct, System.IConvertible | |||||
{ | |||||
string selectedName = enumProperty.enumNames[enumProperty.enumValueIndex]; | |||||
T selectedValue = FilteredEnumPopupInternal<T>((T)System.Enum.Parse(typeof(T), selectedName), predicate, showPopup, rename); | |||||
selectedName = selectedValue.ToString(); | |||||
for (int idx = 0; idx < enumProperty.enumNames.Length; ++idx) | |||||
if (enumProperty.enumNames[idx] == selectedName) | |||||
{ | |||||
enumProperty.enumValueIndex = idx; | |||||
break; | |||||
} | |||||
} | |||||
public static T FilteredEnumPopup<T>(string label, T selectedValue, System.Func<T, bool> predicate, System.Func<string, string> rename = null, params GUILayoutOption[] options) where T : struct, System.IConvertible | |||||
{ | |||||
return FilteredEnumPopupInternal(selectedValue, predicate, (selectedIdx, names) => EditorGUILayout.Popup(label, selectedIdx, names, options), rename); | |||||
} | |||||
public static T FilteredEnumPopup<T>(T selectedValue, System.Func<T, bool> predicate, System.Func<string, string> rename = null, params GUILayoutOption[] options) where T : struct, System.IConvertible | |||||
{ | |||||
return FilteredEnumPopupInternal(selectedValue, predicate, (selectedIdx, names) => EditorGUILayout.Popup(selectedIdx, names, options), rename); | |||||
} | |||||
public static T FilteredEnumPopup<T>(Rect rect, string label, T selectedValue, System.Func<T, bool> predicate, System.Func<string, string> rename = null, GUIStyle style = null) where T : struct, System.IConvertible | |||||
{ | |||||
System.Func<int, string[], int> show = (selectedIdx, names) => | |||||
{ | |||||
if (style != null) | |||||
return EditorGUI.Popup(rect, label, selectedIdx, names, style); | |||||
else | |||||
return EditorGUI.Popup(rect, label, selectedIdx, names); | |||||
}; | |||||
return FilteredEnumPopupInternal(selectedValue, predicate, show, rename); | |||||
} | |||||
public static T FilteredEnumPopup<T>(Rect rect, T selectedValue, System.Func<T, bool> predicate, System.Func<string, string> rename = null, GUIStyle style = null) where T : struct, System.IConvertible | |||||
{ | |||||
System.Func<int, string[], int> show = (selectedIdx, names) => | |||||
{ | |||||
if (style != null) | |||||
return EditorGUI.Popup(rect, selectedIdx, names, style); | |||||
else | |||||
return EditorGUI.Popup(rect, selectedIdx, names); | |||||
}; | |||||
return FilteredEnumPopupInternal(selectedValue, predicate, show, rename); | |||||
} | |||||
public static void FilteredEnumPopup<T>(string label, SerializedProperty selectedValue, System.Func<T, bool> predicate, System.Func<string, string> rename = null, params GUILayoutOption[] options) where T : struct, System.IConvertible | |||||
{ | |||||
FilteredEnumPopupInternal(selectedValue, predicate, (selectedIdx, names) => EditorGUILayout.Popup(label, selectedIdx, names, options), rename); | |||||
} | |||||
public static void FilteredEnumPopup<T>(SerializedProperty selectedValue, System.Func<T, bool> predicate, System.Func<string, string> rename = null, params GUILayoutOption[] options) where T : struct, System.IConvertible | |||||
{ | |||||
FilteredEnumPopupInternal(selectedValue, predicate, (selectedIdx, names) => EditorGUILayout.Popup(selectedIdx, names, options), rename); | |||||
} | |||||
public static void FilteredEnumPopup<T>(Rect rect, string label, SerializedProperty selectedValue, System.Func<T, bool> predicate, System.Func<string, string> rename = null, GUIStyle style = null) where T : struct, System.IConvertible | |||||
{ | |||||
System.Func<int, string[], int> show = (selectedIdx, names) => | |||||
{ | |||||
if (style != null) | |||||
return EditorGUI.Popup(rect, label, selectedIdx, names, style); | |||||
else | |||||
return EditorGUI.Popup(rect, label, selectedIdx, names); | |||||
}; | |||||
FilteredEnumPopupInternal(selectedValue, predicate, show, rename); | |||||
} | |||||
public static void FilteredEnumPopup<T>(Rect rect, SerializedProperty selectedValue, System.Func<T, bool> predicate, System.Func<string, string> rename = null, GUIStyle style = null) where T : struct, System.IConvertible | |||||
{ | |||||
System.Func<int, string[], int> show = (selectedIdx, names) => | |||||
{ | |||||
if (style != null) | |||||
return EditorGUI.Popup(rect, selectedIdx, names, style); | |||||
else | |||||
return EditorGUI.Popup(rect, selectedIdx, names); | |||||
}; | |||||
FilteredEnumPopupInternal(selectedValue, predicate, show, rename); | |||||
} | |||||
private static VRC_Trigger.TriggerEvent CustomTriggerPopupInternal(VRC_Trigger sourceTrigger, VRC_Trigger.TriggerEvent selectedValue, System.Func<int, string[], int> show) | |||||
{ | |||||
if (sourceTrigger == null) | |||||
return null; | |||||
VRC_Trigger.TriggerEvent[] actionsAry = sourceTrigger.Triggers.Where(t => t.TriggerType == VRC_Trigger.TriggerType.Custom).ToArray(); | |||||
string[] names = actionsAry.Select(t => t.Name).ToArray(); | |||||
int selectedIdx = Math.Max(0, names.Length - 1); | |||||
if (selectedValue != null) | |||||
for (; selectedIdx > 0; --selectedIdx) | |||||
if (names[selectedIdx] == selectedValue.Name) | |||||
break; | |||||
if (actionsAry.Length == 0) | |||||
return null; | |||||
return actionsAry[show(selectedIdx, names)]; | |||||
} | |||||
public static VRC_Trigger.TriggerEvent CustomTriggerPopup(Rect rect, VRC_Trigger sourceTrigger, VRC_Trigger.TriggerEvent selectedValue, GUIStyle style = null) | |||||
{ | |||||
System.Func<int, string[], int> show = (selectedIdx, names) => | |||||
{ | |||||
if (style != null) | |||||
return EditorGUI.Popup(rect, selectedIdx, names, style); | |||||
else | |||||
return EditorGUI.Popup(rect, selectedIdx, names); | |||||
}; | |||||
return CustomTriggerPopupInternal(sourceTrigger, selectedValue, show); | |||||
} | |||||
public static VRC_Trigger.TriggerEvent CustomTriggerPopup(Rect rect, string label, VRC_Trigger sourceTrigger, VRC_Trigger.TriggerEvent selectedValue, GUIStyle style = null) | |||||
{ | |||||
System.Func<int, string[], int> show = (selectedIdx, names) => | |||||
{ | |||||
if (style != null) | |||||
return EditorGUI.Popup(rect, label, selectedIdx, names, style); | |||||
else | |||||
return EditorGUI.Popup(rect, label, selectedIdx, names); | |||||
}; | |||||
return CustomTriggerPopupInternal(sourceTrigger, selectedValue, show); | |||||
} | |||||
public static VRC_Trigger.TriggerEvent CustomTriggerPopup(VRC_Trigger sourceTrigger, VRC_Trigger.TriggerEvent selectedValue, params GUILayoutOption[] options) | |||||
{ | |||||
return CustomTriggerPopupInternal(sourceTrigger, selectedValue, (selectedIdx, names) => EditorGUILayout.Popup(selectedIdx, names, options)); | |||||
} | |||||
public static VRC_Trigger.TriggerEvent CustomTriggerPopup(string label, VRC_Trigger sourceTrigger, VRC_Trigger.TriggerEvent selectedValue, params GUILayoutOption[] options) | |||||
{ | |||||
return CustomTriggerPopupInternal(sourceTrigger, selectedValue, (selectedIdx, names) => EditorGUILayout.Popup(label, selectedIdx, names, options)); | |||||
} | |||||
public static VRC_Trigger.TriggerEvent CustomTriggerPopup(string label, VRC_Trigger sourceTrigger, string selectedValue, params GUILayoutOption[] options) | |||||
{ | |||||
if (sourceTrigger == null) | |||||
return null; | |||||
return CustomTriggerPopup(label, sourceTrigger, sourceTrigger.Triggers.FirstOrDefault(t => t.TriggerType == VRC_Trigger.TriggerType.Custom && t.Name == selectedValue), options); | |||||
} | |||||
public static VRC_Trigger.TriggerEvent CustomTriggerPopup(VRC_Trigger sourceTrigger, string selectedValue, params GUILayoutOption[] options) | |||||
{ | |||||
if (sourceTrigger == null) | |||||
return null; | |||||
return CustomTriggerPopup(sourceTrigger, sourceTrigger.Triggers.FirstOrDefault(t => t.TriggerType == VRC_Trigger.TriggerType.Custom && t.Name == selectedValue), options); | |||||
} | |||||
public static VRC_Trigger.TriggerEvent CustomTriggerPopup(Rect rect, VRC_Trigger sourceTrigger, string selectedValue, GUIStyle style = null) | |||||
{ | |||||
if (sourceTrigger == null) | |||||
return null; | |||||
return CustomTriggerPopup(rect, sourceTrigger, sourceTrigger.Triggers.FirstOrDefault(t => t.TriggerType == VRC_Trigger.TriggerType.Custom && t.Name == selectedValue), style); | |||||
} | |||||
public static VRC_Trigger.TriggerEvent CustomTriggerPopup(Rect rect, string label, VRC_Trigger sourceTrigger, string selectedValue, GUIStyle style = null) | |||||
{ | |||||
if (sourceTrigger == null) | |||||
return null; | |||||
return CustomTriggerPopup(rect, label, sourceTrigger, sourceTrigger.Triggers.FirstOrDefault(t => t.TriggerType == VRC_Trigger.TriggerType.Custom && t.Name == selectedValue), style); | |||||
} | |||||
private static void InternalSerializedCustomTriggerPopup(SerializedProperty triggersProperty, SerializedProperty customProperty, System.Func<int, string[], int> show, System.Action fail) | |||||
{ | |||||
if (customProperty == null || (customProperty.propertyType != SerializedPropertyType.String)) | |||||
throw new ArgumentException("Expected a string for customProperty"); | |||||
if (triggersProperty == null || (!triggersProperty.isArray && triggersProperty.propertyType != SerializedPropertyType.ObjectReference)) | |||||
throw new ArgumentException("Expected an object or array for triggersProperty"); | |||||
List<String> customNames = new List<string>(); | |||||
bool allNull = true; | |||||
if (triggersProperty.isArray) | |||||
{ | |||||
int idx; | |||||
for (idx = 0; idx < triggersProperty.arraySize; ++idx) | |||||
{ | |||||
GameObject obj = triggersProperty.GetArrayElementAtIndex(idx).objectReferenceValue as GameObject; | |||||
if (obj != null) | |||||
{ | |||||
customNames = obj.GetComponent<VRC_Trigger>().Triggers.Where(t => t.TriggerType == VRC_Trigger.TriggerType.Custom).Select(t => t.Name).ToList(); | |||||
allNull = false; | |||||
break; | |||||
} | |||||
} | |||||
for (; idx < triggersProperty.arraySize; ++idx) | |||||
{ | |||||
GameObject obj = triggersProperty.GetArrayElementAtIndex(idx).objectReferenceValue as GameObject; | |||||
if (obj != null) | |||||
{ | |||||
List<string> thisCustomNames = obj.GetComponent<VRC_Trigger>().Triggers.Where(t => t.TriggerType == VRC_Trigger.TriggerType.Custom).Select(t => t.Name).ToList(); | |||||
customNames.RemoveAll(s => thisCustomNames.Contains(s) == false); | |||||
} | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
GameObject obj = triggersProperty.objectReferenceValue as GameObject; | |||||
if (obj != null) | |||||
{ | |||||
allNull = false; | |||||
customNames = obj.GetComponent<VRC_Trigger>().Triggers.Where(t => t.TriggerType == VRC_Trigger.TriggerType.Custom).Select(t => t.Name).ToList(); | |||||
} | |||||
} | |||||
if (customNames.Count == 0 && !allNull && triggersProperty.isArray) | |||||
{ | |||||
fail(); | |||||
customProperty.stringValue = ""; | |||||
} | |||||
else | |||||
{ | |||||
if (customNames.Count == 0) | |||||
customNames.Add(""); | |||||
int selectedIdx = Math.Max(0, customNames.Count - 1); | |||||
if (!string.IsNullOrEmpty(customProperty.stringValue)) | |||||
for (; selectedIdx > 0; --selectedIdx) | |||||
if (customNames[selectedIdx] == customProperty.stringValue) | |||||
break; | |||||
selectedIdx = show(selectedIdx, customNames.ToArray()); | |||||
customProperty.stringValue = customNames[selectedIdx]; | |||||
} | |||||
} | |||||
public static void CustomTriggerPopup(string label, SerializedProperty triggersProperty, SerializedProperty customProperty, params GUILayoutOption[] options) | |||||
{ | |||||
InternalSerializedCustomTriggerPopup(triggersProperty, customProperty, (idx, names) => EditorGUILayout.Popup(label, idx, names, options), () => EditorGUILayout.HelpBox("Receivers do not have Custom Triggers which share names.", MessageType.Warning)); | |||||
} | |||||
public static void CustomTriggerPopup(SerializedProperty triggersProperty, SerializedProperty customProperty, params GUILayoutOption[] options) | |||||
{ | |||||
InternalSerializedCustomTriggerPopup(triggersProperty, customProperty, (idx, names) => EditorGUILayout.Popup(idx, names, options), () => EditorGUILayout.HelpBox("Receivers do not have Custom Triggers which share names.", MessageType.Warning)); | |||||
} | |||||
public static void CustomTriggerPopup(Rect rect, SerializedProperty triggersProperty, SerializedProperty customProperty, GUIStyle style = null) | |||||
{ | |||||
InternalSerializedCustomTriggerPopup(triggersProperty, customProperty, (idx, names) => style == null ? EditorGUI.Popup(rect, idx, names) : EditorGUI.Popup(rect, idx, names, style), () => EditorGUI.HelpBox(rect, "Receivers do not have Custom Triggers which share names.", MessageType.Warning)); | |||||
} | |||||
public static void CustomTriggerPopup(Rect rect, string label, SerializedProperty triggersProperty, SerializedProperty customProperty, GUIStyle style = null) | |||||
{ | |||||
InternalSerializedCustomTriggerPopup(triggersProperty, customProperty, (idx, names) => style == null ? EditorGUI.Popup(rect, label, idx, names) : EditorGUI.Popup(rect, label, idx, names, style), () => EditorGUI.HelpBox(rect, "Receivers do not have Custom Triggers which share names.", MessageType.Warning)); | |||||
} | |||||
public static void DrawTriggerActionCallback(string actionLabel, VRC_Trigger trigger, VRC_EventHandler.VrcEvent e) | |||||
{ | |||||
VRC_Trigger.TriggerEvent triggerEvent = VRC_EditorTools.CustomTriggerPopup(actionLabel, trigger, e.ParameterString); | |||||
e.ParameterString = triggerEvent == null ? null : triggerEvent.Name; | |||||
} | |||||
public static Dictionary<string, List<MethodInfo>> GetSharedAccessibleMethodsOnGameObjects(SerializedProperty objectsProperty) | |||||
{ | |||||
Dictionary<string, List<MethodInfo>> methods = new Dictionary<string, List<MethodInfo>>(); | |||||
int idx = 0; | |||||
for (; idx < objectsProperty.arraySize; ++idx) | |||||
{ | |||||
SerializedProperty prop = objectsProperty.GetArrayElementAtIndex(idx); | |||||
GameObject obj = prop.objectReferenceValue != null ? prop.objectReferenceValue as GameObject : null; | |||||
if (obj != null) | |||||
{ | |||||
methods = VRC_EditorTools.GetAccessibleMethodsOnGameObject(obj); | |||||
break; | |||||
} | |||||
} | |||||
List<string> toRemove = new List<string>(); | |||||
for (; idx < objectsProperty.arraySize; ++idx) | |||||
{ | |||||
SerializedProperty prop = objectsProperty.GetArrayElementAtIndex(idx); | |||||
GameObject obj = prop.objectReferenceValue != null ? prop.objectReferenceValue as GameObject : null; | |||||
if (obj != null) | |||||
{ | |||||
Dictionary<string, List<MethodInfo>> thisObjMethods = VRC_EditorTools.GetAccessibleMethodsOnGameObject(obj); | |||||
foreach (string className in methods.Keys.Where(s => thisObjMethods.Keys.Contains(s) == false)) | |||||
toRemove.Add(className); | |||||
} | |||||
} | |||||
foreach (string className in toRemove) | |||||
methods.Remove(className); | |||||
return methods; | |||||
} | |||||
public static Dictionary<string, List<MethodInfo>> GetAccessibleMethodsOnGameObject(GameObject go) | |||||
{ | |||||
Dictionary<string, List<MethodInfo>> methods = new Dictionary<string, List<MethodInfo>>(); | |||||
if (go == null) | |||||
return methods; | |||||
Component[] cs = go.GetComponents<Component>(); | |||||
if (cs == null) | |||||
return methods; | |||||
foreach (Component c in cs.Where(co => co != null)) | |||||
{ | |||||
Type t = c.GetType(); | |||||
if (methods.ContainsKey(t.Name)) | |||||
continue; | |||||
// if component is the eventhandler | |||||
if (t == typeof(VRC_EventHandler)) | |||||
continue; | |||||
List<MethodInfo> l = GetAccessibleMethodsForClass(t); | |||||
methods.Add(t.Name, l); | |||||
} | |||||
return methods; | |||||
} | |||||
public static List<MethodInfo> GetAccessibleMethodsForClass(Type t) | |||||
{ | |||||
// Get the public methods. | |||||
MethodInfo[] myArrayMethodInfo = t.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); | |||||
List<MethodInfo> methods = new List<MethodInfo>(); | |||||
// if component is in UnityEngine namespace, skip it | |||||
if (!string.IsNullOrEmpty(t.Namespace) && (t.Namespace.Contains("UnityEngine") || t.Namespace.Contains("UnityEditor"))) | |||||
return methods; | |||||
bool isVRCSDK2 = !string.IsNullOrEmpty(t.Namespace) && t.Namespace.Contains("VRCSDK2"); | |||||
// Display information for all methods. | |||||
for (int i = 0; i < myArrayMethodInfo.Length; i++) | |||||
{ | |||||
MethodInfo myMethodInfo = (MethodInfo)myArrayMethodInfo[i]; | |||||
// if it's VRCSDK2, require RPC | |||||
if (isVRCSDK2 && myMethodInfo.GetCustomAttributes(typeof(VRCSDK2.RPC), true).Length == 0) | |||||
continue; | |||||
methods.Add(myMethodInfo); | |||||
} | |||||
return methods; | |||||
} | |||||
public static byte[] ReadBytesFromProperty(SerializedProperty property) | |||||
{ | |||||
byte[] bytes = new byte[property.arraySize]; | |||||
for (int idx = 0; idx < property.arraySize; ++idx) | |||||
bytes[idx] = (byte)property.GetArrayElementAtIndex(idx).intValue; | |||||
return bytes; | |||||
} | |||||
public static void WriteBytesToProperty(SerializedProperty property, byte[] bytes) | |||||
{ | |||||
property.arraySize = bytes != null ? bytes.Length : 0; | |||||
for (int idx = 0; idx < property.arraySize; ++idx) | |||||
property.GetArrayElementAtIndex(idx).intValue = (int)bytes[idx]; | |||||
} | |||||
} | |||||
} | |||||
#endif |