@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 7232873a97408ef4fbf8e655841e61ed | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 9ceea87507dde1e4e9f4d2f9b3218898 | |||
folderAsset: yes | |||
timeCreated: 1521506758 | |||
licenseType: Pro | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: c3215fde7fc71504fb3b192b10dbf263 | |||
folderAsset: yes | |||
timeCreated: 1521506802 | |||
licenseType: Pro | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,143 @@ | |||
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: |
@@ -0,0 +1,7 @@ | |||
fileFormatVersion: 2 | |||
guid: 40895a3d0d3ec475c8ff555d0c40f7cb | |||
folderAsset: yes | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 23868bd667cf64b479fbd8d1039e2cd2 | |||
folderAsset: yes | |||
timeCreated: 1448340266 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 1d2c94db16e356840a089b257eb5d536 | |||
folderAsset: yes | |||
timeCreated: 1480638868 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,24 @@ | |||
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: |
@@ -0,0 +1,24 @@ | |||
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: |
@@ -0,0 +1,24 @@ | |||
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: |
@@ -0,0 +1,24 @@ | |||
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: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 3a71aca790a5f774e9b2c6802399180d | |||
folderAsset: yes | |||
timeCreated: 1499820116 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,133 @@ | |||
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: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: ecaca62aaec760a4dbd18ddd39d3d81b | |||
folderAsset: yes | |||
timeCreated: 1499820171 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 94693a1781c168a47a2a3ef863992cd8 | |||
folderAsset: yes | |||
timeCreated: 1499820184 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,114 @@ | |||
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: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 318c96e9cf64fb44a8aeb0f088e53f96 | |||
folderAsset: yes | |||
timeCreated: 1499820192 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,114 @@ | |||
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: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 99a3cc965a6419644b54113eb9983bd0 | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 63a46438a8152c74c980a66bfaf7b61c | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 574563b688a5ed54b978ae8718c2194d | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,101 @@ | |||
/************************************************************************************ | |||
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); | |||
} | |||
} | |||
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: cb850b86de9091d4db4595959c56f954 | |||
timeCreated: 1442269815 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: d082e53096d08f441bc71078ece58e73 | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,393 @@ | |||
/************************************************************************************ | |||
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; | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
fileFormatVersion: 2 | |||
guid: e503ea6418d27594caa33b93cac1b06a | |||
MonoImporter: | |||
externalObjects: {} | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 1 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: e86b1ecf748c17744a6a94f8ee6f50ba | |||
folderAsset: yes | |||
timeCreated: 1500596137 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,34 @@ | |||
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: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 534760d5f8b40420d8dbff996c9060a8 | |||
folderAsset: yes | |||
timeCreated: 1449532728 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,7 @@ | |||
fileFormatVersion: 2 | |||
guid: f3c17e56945504a4eaf427a9ae38ad3a | |||
folderAsset: yes | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: a45642ab77cf9604887c9bcb222c596f | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,127 @@ | |||
// | |||
// 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()); | |||
} | |||
}); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 3d6a1d7b0624f414ba6fb922687a06da | |||
timeCreated: 1480975716 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 027731dadc7571046abaf43e4f52e9ae | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,19 @@ | |||
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(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 39cdf3092ab81be4b9e623cb5a8819d8 | |||
timeCreated: 1509575680 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,239 @@ | |||
#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; | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
fileFormatVersion: 2 | |||
guid: 0a364ece829b6234888c59987a305a00 | |||
MonoImporter: | |||
externalObjects: {} | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,62 @@ | |||
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(); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 89005ebc9543e0a4284893c09ca19b1d | |||
timeCreated: 1473271738 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,17 @@ | |||
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(); | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
fileFormatVersion: 2 | |||
guid: 3d6c2e367eaa9564ebf6267ec163cfbd | |||
MonoImporter: | |||
externalObjects: {} | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,47 @@ | |||
#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 |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 482185bf29f12074dada194ffef6a682 | |||
timeCreated: 1475877803 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,134 @@ | |||
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; | |||
} | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 5e83254bb97e84795ac882692ae124ba | |||
timeCreated: 1450462624 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,21 @@ | |||
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(); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 26a75599848adb449b7aceed5090e35c | |||
timeCreated: 1463516633 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,22 @@ | |||
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); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: ed4aad2698d3b62408e69b57c7748791 | |||
timeCreated: 1463516212 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,34 @@ | |||
// 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(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
fileFormatVersion: 2 | |||
guid: 8986a640e24a0754ea0aded12234b808 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,107 @@ | |||
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; | |||
} | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
fileFormatVersion: 2 | |||
guid: 792e7964a56e51f4188e1221751642e9 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,22 @@ | |||
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(); | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
fileFormatVersion: 2 | |||
guid: 5262a02c32e41e047bdfdfc3b63db8ff | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,27 @@ | |||
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(); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: e9cbc493bbbc443fb92898aa84d221ec | |||
timeCreated: 1450463561 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,130 @@ | |||
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(); | |||
// } | |||
//} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: eeda995d0ceac6443a54716996eab52e | |||
timeCreated: 1511373338 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,91 @@ | |||
#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 |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 0ac7998a36f085844847acbc046d4e27 | |||
timeCreated: 1478191469 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,57 @@ | |||
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 (); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 3b63b118c0591b548ba1797e6be4292e | |||
timeCreated: 1477161996 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,17 @@ | |||
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(); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: e19a7147a2386554a8e4d6e414f190a2 | |||
timeCreated: 1504908295 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,101 @@ | |||
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"); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: ae0e74693b7899f47bd98864f94b9311 | |||
timeCreated: 1499468412 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,114 @@ | |||
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"); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 3f9dccfed0b072f49a307b3f20a7e768 | |||
timeCreated: 1528745185 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 3aecd666943878944a811acb9db2ace7 | |||
timeCreated: 1474315179 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,216 @@ | |||
#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 |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: d09b36020f697be4d9a0f5a6a48cfa83 | |||
timeCreated: 1457992191 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,20 @@ | |||
#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 |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 764e26c1ca28e2e45a30c778c1955a47 | |||
timeCreated: 1474675311 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: e751dcaa3656a324f91244e7b795d83a | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,206 @@ | |||
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(); | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
fileFormatVersion: 2 | |||
guid: 20b4cdbdda9655947aab6f8f2c90690f | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,590 @@ | |||
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; | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
fileFormatVersion: 2 | |||
guid: 5066cd5c1cc208143a1253cac821714a | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,7 @@ | |||
fileFormatVersion: 2 | |||
guid: 4c73e735ee0380241b186a8993fa56bf | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,551 @@ | |||
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(); | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
fileFormatVersion: 2 | |||
guid: c7333cdb3df19724b84b4a1b05093fe0 | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,59 @@ | |||
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); | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
fileFormatVersion: 2 | |||
guid: f3507a74e4b8cfd469afac127fa5f4e5 | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,166 @@ | |||
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(); | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
fileFormatVersion: 2 | |||
guid: 8357b9b7ef2416946ae86f465a64c0e0 | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,30 @@ | |||
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: |
@@ -0,0 +1,687 @@ | |||
#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(); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 10d9f721d76e07a47bc9e5f61e2fae72 | |||
timeCreated: 1455115256 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,325 @@ | |||
#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 |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 4810e652e8242384c834320970702290 | |||
timeCreated: 1454469344 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,70 @@ | |||
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); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 7b8bb626428d0f341b9ed6a68cb5c9cc | |||
timeCreated: 1473273663 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,105 @@ | |||
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; | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 4a9696f3dea8a764f9c4bc6d2e652b74 | |||
timeCreated: 1519696095 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,457 @@ | |||
#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 |