Add VRChat and GitHub packages to Unity project

This commit is contained in:
gunnbr committed 2021-01-18 09:14:18 -08:00
1 parent 0334a52b21
commit 85538aaccc
3297 files changed
+847877

No files matched your search

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 02cde43b860294140a44ee8e3f228987
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: 059f8224659cefb4fa29c1c01d87a653
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: daf80f83bd8638d4886542fc3230e9f6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,18 @@
#if VRC_SDK_PIPELINE_SAMPLES
using UnityEditor;
namespace VRC.SDKBase.Editor.BuildPipeline.Samples
{
public class VRCSDKBuildRequestedCallbackSample : IVRCSDKBuildRequestedCallback
{
public int callbackOrder => 0;
public bool OnBuildRequested(VRCSDKRequestedBuildType requestedBuildType)
{
return EditorUtility.DisplayDialog("Build Confirmation", "Are you sure you want to build?", "Yes", "Not Yes");
}
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a1d20f4241085e46bdddc71b691465b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,12 @@
{
"name": "VRC.SDKBase.Editor.BuildPipeline",
"references": [],
"optionalUnityReferences": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": []
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 21332e1f0d937794d916d2402ba1943a
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 095dab1d766b9f74ea16555fc915be80
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,218 @@
using UnityEngine;
using System.Collections;
using UnityEditor;
using VRC.SDKBase;
[InitializeOnLoad]
public class AutoAddSpatialAudioComponents
{
public static bool Enabled = true;
static AutoAddSpatialAudioComponents()
{
EditorApplication.hierarchyChanged += OnHierarchyWindowChanged;
EditorApplication.projectChanged += OnProjectWindowChanged;
RegisterCallbacks();
}
static void OnHierarchyWindowChanged()
{
if (!Enabled)
{
EditorApplication.hierarchyChanged -= 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<VRC.SDKBase.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 (vrcsp == null)
{
// no onsp and no vrcsp, so add
vrcsp = audioSrc.gameObject.AddComponent<VRC.SDKBase.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<VRC.SDKBase.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<VRC.SDKBase.VRC_SpatialAudioSource>();
if (vrcsp == null)
{
// copy the values from deprecated component
vrcsp = src.gameObject.AddComponent<VRC.SDKBase.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<VRC.SDKBase.VRC_SpatialAudioSource>();
if (vrcsp != null) return;
vrcsp = src.gameObject.AddComponent<VRC.SDKBase.VRC_SpatialAudioSource>();
// add default values
bool isAvatar = src.gameObject.GetComponentInParent<VRC.SDKBase.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,357 @@
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using System.Collections.Generic;
using System.Linq;
namespace VRCSDK2
{
#if VRC_SDK_VRCSDK2
[CustomEditor(typeof(VRCSDK2.VRC_EventHandler))]
public class EventHandlerEditor : Editor
{
bool showDeferredEvents = false;
static VRCSDK2.VRC_EventHandler.VrcEventType lastAddedEventType = VRCSDK2.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 != VRCSDK2.VRC_EventHandler.VrcEventType.SpawnObject && v != VRCSDK2.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 != VRCSDK2.VRC_EventHandler.VrcEventType.SpawnObject && v != VRCSDK2.VRC_EventHandler.VrcEventType.SendMessage);
bool delete = GUILayout.Button("Remove");
EditorGUILayout.EndHorizontal();
return delete;
}
}
[CustomEditor(typeof(VRC.SDKBase.VRC_EventHandler))]
public class SDKBaseEventHandlerEditor : Editor
{
public override void OnInspectorGUI()
{
EditorGUILayout.LabelField("Event Handlers are not supported in VRCSDK3.");
if (GUILayout.Button("replace me with the correct VRC_EventHandler"))
{
var go = ((VRC.SDKBase.VRC_EventHandler)target).gameObject;
DestroyImmediate(target);
go.AddComponent<VRCSDK2.VRC_EventHandler>();
}
}
}
#else
[CustomEditor(typeof(VRC.SDKBase.VRC_EventHandler))]
public class SDKBaseEventHandlerEditor : Editor
{
public override void OnInspectorGUI()
{
EditorGUILayout.LabelField("Event Handlers are not supported in VRCSDK3.");
if( GUILayout.Button("delete me") )
DestroyImmediate(target);
}
}
#endif
}
#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,50 @@
#if VRC_SDK_VRCSDK2
#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
#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,225 @@
#if VRC_SDK_VRCSDK2
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using VRC.SDK3.Editor;
using VRC.SDKBase.Editor;
[CustomEditor(typeof(VRCSDK2.VRC_AvatarDescriptor))]
public class AvatarDescriptorEditor : Editor
{
VRCSDK2.VRC_AvatarDescriptor avatarDescriptor;
VRC.Core.PipelineManager pipelineManager;
SkinnedMeshRenderer selectedMesh;
List<string> blendShapeNames = null;
bool shouldRefreshVisemes = false;
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" ) )
VRCSdkControlPanelAvatarBuilder.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:
SkinnedMeshRenderer prev = avatarDescriptor.VisemeSkinnedMesh;
avatarDescriptor.VisemeSkinnedMesh = (SkinnedMeshRenderer)EditorGUILayout.ObjectField("Face Mesh", avatarDescriptor.VisemeSkinnedMesh, typeof(SkinnedMeshRenderer), true);
if (avatarDescriptor.VisemeSkinnedMesh != prev)
shouldRefreshVisemes = 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];
}
if (shouldRefreshVisemes)
AutoDetectVisemes();
}
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;
if ((selectedMesh != null) && (selectedMesh.sharedMesh != null))
{
for (int i = 0; i < selectedMesh.sharedMesh.blendShapeCount; ++i)
blendShapeNames.Add(selectedMesh.sharedMesh.GetBlendShapeName(i));
}
}
}
void AutoDetectVisemes()
{
// prioritize strict - but fallback to looser - naming and don't touch user-overrides
List<string> blendShapes = new List<string>(blendShapeNames);
blendShapes.Remove("-none-");
for (int v = 0; v < avatarDescriptor.VisemeBlendShapes.Length; v++)
{
if (string.IsNullOrEmpty(avatarDescriptor.VisemeBlendShapes[v]))
{
string viseme = ((VRCSDK2.VRC_AvatarDescriptor.Viseme)v).ToString().ToLowerInvariant();
foreach (string s in blendShapes)
{
if (s.ToLowerInvariant() == "vrc.v_" + viseme)
{
avatarDescriptor.VisemeBlendShapes[v] = s;
goto next;
}
}
foreach (string s in blendShapes)
{
if (s.ToLowerInvariant() == "v_" + viseme)
{
avatarDescriptor.VisemeBlendShapes[v] = s;
goto next;
}
}
foreach (string s in blendShapes)
{
if (s.ToLowerInvariant().EndsWith(viseme))
{
avatarDescriptor.VisemeBlendShapes[v] = s;
goto next;
}
}
foreach (string s in blendShapes)
{
if (s.ToLowerInvariant() == viseme)
{
avatarDescriptor.VisemeBlendShapes[v] = s;
goto next;
}
}
foreach (string s in blendShapes)
{
if (s.ToLowerInvariant().Contains(viseme))
{
avatarDescriptor.VisemeBlendShapes[v] = s;
goto next;
}
}
next: { }
}
}
shouldRefreshVisemes = false;
}
void AutoDetectLipSync()
{
var smrs = avatarDescriptor.GetComponentsInChildren<SkinnedMeshRenderer>();
foreach (var smr in smrs)
{
if (smr.sharedMesh.blendShapeCount > 0)
{
avatarDescriptor.lipSyncJawBone = null;
if (smr.sharedMesh.blendShapeCount > 1)
{
avatarDescriptor.lipSync = VRCSDK2.VRC_AvatarDescriptor.LipSyncStyle.VisemeBlendShape;
avatarDescriptor.VisemeSkinnedMesh = smr;
shouldRefreshVisemes = true;
}
else
{
avatarDescriptor.lipSync = VRCSDK2.VRC_AvatarDescriptor.LipSyncStyle.JawFlapBlendShape;
avatarDescriptor.VisemeSkinnedMesh = null;
}
return;
}
}
Animator a = avatarDescriptor.GetComponent<Animator>();
if (!a)
EditorUtility.DisplayDialog("Ooops", "This avatar has no Animator and can have no lipsync.", "OK");
else if (a.GetBoneTransform(HumanBodyBones.Jaw) != null)
{
avatarDescriptor.lipSync = VRCSDK2.VRC_AvatarDescriptor.LipSyncStyle.JawFlapBone;
avatarDescriptor.lipSyncJawBone = avatarDescriptor.GetComponent<Animator>().GetBoneTransform(HumanBodyBones.Jaw);
avatarDescriptor.VisemeSkinnedMesh = null;
return;
}
}
}
#endif
@@ -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,23 @@
#if VRC_SDK_VRCSDK2
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();
}
}
#endif
@@ -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,25 @@
#if VRC_SDK_VRCSDK2
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);
}
}
#endif
@@ -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,37 @@
#if VRC_SDK_VRCSDK2
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();
}
}
}
#endif
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 8986a640e24a0754ea0aded12234b808
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,109 @@
#if VRC_SDK_VRCSDK2
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<VRCSDK2.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;
}
}
}
#endif
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 792e7964a56e51f4188e1221751642e9
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,46 @@
#if VRC_SDK_VRCSDK2
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;
SerializedProperty onRemoteEnter;
SerializedProperty onRemoteExit;
SerializedProperty onLocalEnter;
SerializedProperty onLocalExit;
void OnEnable()
{
if(myTarget == null)
myTarget = (VRCSDK2.VRC_Station)target;
onRemoteEnter = serializedObject.FindProperty("OnRemotePlayerEnterStation");
onRemoteExit = serializedObject.FindProperty("OnRemotePlayerExitStation");
onLocalEnter = serializedObject.FindProperty("OnLocalPlayerEnterStation");
onLocalExit = serializedObject.FindProperty("OnLocalPlayerExitStation");
}
public override void OnInspectorGUI()
{
myTarget.PlayerMobility = (VRC.SDKBase.VRCStation.Mobility)EditorGUILayout.EnumPopup("Player Mobility", myTarget.PlayerMobility);
myTarget.canUseStationFromStation = EditorGUILayout.Toggle("Can Use Station From Station", myTarget.canUseStationFromStation);
myTarget.animatorController = (RuntimeAnimatorController)EditorGUILayout.ObjectField("Animator Controller", myTarget.animatorController, typeof(RuntimeAnimatorController), false);
myTarget.disableStationExit = EditorGUILayout.Toggle("Disable Station Exit", myTarget.disableStationExit);
myTarget.seated = EditorGUILayout.Toggle("Seated", myTarget.seated);
myTarget.stationEnterPlayerLocation = (Transform)EditorGUILayout.ObjectField("Player Enter Location", myTarget.stationEnterPlayerLocation, typeof(Transform), true);
myTarget.stationExitPlayerLocation = (Transform)EditorGUILayout.ObjectField("Player Exit Location", myTarget.stationExitPlayerLocation, typeof(Transform), true);
myTarget.controlsObject = (VRC.SDKBase.VRC_ObjectApi)EditorGUILayout.ObjectField("API Object", myTarget.controlsObject, typeof(VRC.SDKBase.VRC_ObjectApi), false);
EditorGUILayout.PropertyField(onRemoteEnter, new GUIContent("On Remote Player Enter"));
EditorGUILayout.PropertyField(onRemoteExit, new GUIContent("On Remote Player Exit"));
EditorGUILayout.PropertyField(onLocalEnter, new GUIContent("On Local Player Enter"));
EditorGUILayout.PropertyField(onLocalExit, new GUIContent("On Local Player Exit"));
}
}
#endif
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 5262a02c32e41e047bdfdfc3b63db8ff
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,29 @@
#if VRC_SDK_VRCSDK2
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();
}
}
#endif
@@ -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,93 @@
#if VRC_SDK_VRCSDK2
#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)VRCSDK2.VRC_DataStorage.VrcDataType.Bool:
valueProperty = property.FindPropertyRelative("valueBool");
break;
case (int)VRCSDK2.VRC_DataStorage.VrcDataType.Float:
valueProperty = property.FindPropertyRelative("valueFloat");
break;
case (int)VRCSDK2.VRC_DataStorage.VrcDataType.Int:
valueProperty = property.FindPropertyRelative("valueInt");
break;
case (int)VRCSDK2.VRC_DataStorage.VrcDataType.String:
valueProperty = property.FindPropertyRelative("valueString");
break;
case (int)VRCSDK2.VRC_DataStorage.VrcDataType.SerializeObject:
valueProperty = property.FindPropertyRelative("serializeComponent");
break;
case (int)VRCSDK2.VRC_DataStorage.VrcDataType.None:
case (int)VRCSDK2.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)VRCSDK2.VRC_DataStorage.VrcDataMirror.None:
if (valueProperty == null)
VRC_EditorTools.FilteredEnumPopup<VRCSDK2.VRC_DataStorage.VrcDataType>(typeValueRect, typeProperty, t => true);
else
{
VRC_EditorTools.FilteredEnumPopup<VRCSDK2.VRC_DataStorage.VrcDataType>(typeRect, typeProperty, t => true);
EditorGUI.PropertyField(valueRect, valueProperty, GUIContent.none);
}
break;
case (int)VRCSDK2.VRC_DataStorage.VrcDataMirror.SerializeComponent:
typeProperty.enumValueIndex = (int)VRCSDK2.VRC_DataStorage.VrcDataType.SerializeObject;
EditorGUI.PropertyField(typeValueRect, valueProperty, GUIContent.none);
break;
default:
VRC_EditorTools.FilteredEnumPopup<VRCSDK2.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
#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 VRC.SDKBase;
[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"));
VRCSDK2.VRC_EditorTools.DrawTriggerActionCallback("On Damaged Action", ds.onDamagedTrigger, ds.onDamagedEvent);
EditorGUILayout.PropertyField(onDestroyedTrigger, new GUIContent("On Destructed Trigger"));
VRCSDK2.VRC_EditorTools.DrawTriggerActionCallback("On Destructed Action", ds.onDestructedTrigger, ds.onDestructedEvent);
EditorGUILayout.PropertyField(onHealedTrigger, new GUIContent("On Healed Trigger"));
VRCSDK2.VRC_EditorTools.DrawTriggerActionCallback("On Healed Action", ds.onHealedTrigger, ds.onHealedEvent);
EditorGUILayout.PropertyField(onFullHealedTrigger, new GUIContent("On Full Healed Trigger"));
VRCSDK2.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,19 @@
#if VRC_SDK_VRCSDK2
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();
}
}
#endif
@@ -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,76 @@
#if VRC_SDK_VRCSDK2
#if UNITY_EDITOR
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEditor.Build;
using System;
using System.Linq;
namespace VRCSDK2
{
[CustomEditor(typeof(VRCSDK2.VRC_Pickup))]
public class VRC_PickupEditor : Editor
{
private void InspectorField(string propertyName, string humanName)
{
SerializedProperty propertyField = serializedObject.FindProperty(propertyName);
EditorGUILayout.PropertyField(propertyField, new GUIContent(humanName), true);
}
private SerializedProperty momentumTransferMethodProperty;
private SerializedProperty disallowTheftProperty;
private SerializedProperty exactGunProperty;
private SerializedProperty exactGripProperty;
private SerializedProperty allowManipulationWhenEquippedProperty;
private SerializedProperty orientationProperty;
private SerializedProperty autoHoldProperty;
private SerializedProperty interactionTextProperty;
private SerializedProperty useTextProperty;
private SerializedProperty throwVelocityBoostMinSpeedProperty;
private SerializedProperty throwVelocityBoostScaleProperty;
private SerializedProperty pickupableProperty;
private SerializedProperty proximityProperty;
public override void OnInspectorGUI()
{
momentumTransferMethodProperty = serializedObject.FindProperty("MomentumTransferMethod");
disallowTheftProperty = serializedObject.FindProperty("DisallowTheft");
exactGunProperty = serializedObject.FindProperty("ExactGun");
exactGripProperty = serializedObject.FindProperty("ExactGrip");
allowManipulationWhenEquippedProperty = serializedObject.FindProperty("allowManipulationWhenEquipped");
orientationProperty = serializedObject.FindProperty("orientation");
autoHoldProperty = serializedObject.FindProperty("AutoHold");
interactionTextProperty = serializedObject.FindProperty("InteractionText");
useTextProperty = serializedObject.FindProperty("UseText");
throwVelocityBoostMinSpeedProperty = serializedObject.FindProperty("ThrowVelocityBoostMinSpeed");
throwVelocityBoostScaleProperty = serializedObject.FindProperty("ThrowVelocityBoostScale");
pickupableProperty = serializedObject.FindProperty("pickupable");
proximityProperty = serializedObject.FindProperty("proximity");
EditorGUILayout.BeginVertical(GUILayout.MaxWidth(EditorGUIUtility.currentViewWidth - 30));
EditorGUILayout.PropertyField(momentumTransferMethodProperty, new GUIContent("Momentum Transfer Method"));
EditorGUILayout.PropertyField(disallowTheftProperty, new GUIContent("Disallow Theft"));
EditorGUILayout.PropertyField(exactGunProperty, new GUIContent("Exact Gun"));
EditorGUILayout.PropertyField(exactGripProperty, new GUIContent("Exact Grip"));
EditorGUILayout.PropertyField(allowManipulationWhenEquippedProperty, new GUIContent("Allow Manipulation When Equipped"));
EditorGUILayout.PropertyField(orientationProperty, new GUIContent("Orientation"));
EditorGUILayout.PropertyField(autoHoldProperty, new GUIContent("AutoHold", "If the pickup is supposed to be aligned to the hand (i.e. orientation field is set to Gun or Grip), auto-detect means that it will be Equipped(not dropped when they release trigger), otherwise just hold as a normal pickup."));
EditorGUILayout.PropertyField(interactionTextProperty, new GUIContent("Interaction Text","Text displayed when user hovers over the pickup."));
if (autoHoldProperty.enumValueIndex != (int)VRCSDK2.VRC_Pickup.AutoHoldMode.No)
EditorGUILayout.PropertyField(useTextProperty, new GUIContent("Use Text", "Text to display describing action for clicking button, when this pickup is already being held."));
EditorGUILayout.PropertyField(throwVelocityBoostMinSpeedProperty, new GUIContent("Throw Velocity Boost Min Speed"));
EditorGUILayout.PropertyField(throwVelocityBoostScaleProperty, new GUIContent("Throw Velocity Boost Scale"));
EditorGUILayout.PropertyField(pickupableProperty, new GUIContent("Pickupable"));
EditorGUILayout.PropertyField(proximityProperty, new GUIContent("Proximity"));
EditorGUILayout.EndVertical();
serializedObject.ApplyModifiedProperties();
}
}
}
#endif
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4aff4e5c0d600c845b29d7b8b7965d68
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,106 @@
#if VRC_SDK_VRCSDK2
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
using System;
namespace VRCSDK2
{
[CustomEditor(typeof(VRCSDK2.VRC_PlayerAudioOverride))]
public class VRC_PlayerAudioOverrideEditor : Editor
{
private bool voShow = true;
private bool voAdv = false;
private bool avShow = true;
private bool avAdv = false;
private SerializedProperty prioProperty;
private SerializedProperty globalProperty;
private SerializedProperty regionProperty;
private SerializedProperty voGainProperty;
private SerializedProperty voNearProperty;
private SerializedProperty voFarProperty;
private SerializedProperty voRadiusProperty;
private SerializedProperty voDisableLpProperty;
private SerializedProperty avGainProperty;
private SerializedProperty avNearProperty;
private SerializedProperty avFarProperty;
private SerializedProperty avRadiusProperty;
private SerializedProperty avForceSpatialProperty;
private SerializedProperty avAllowCustomProperty;
public override void OnInspectorGUI()
{
globalProperty = serializedObject.FindProperty("global");
regionProperty = serializedObject.FindProperty("region");
prioProperty = serializedObject.FindProperty("regionPriority");
voGainProperty = serializedObject.FindProperty("VoiceGain");
voNearProperty = serializedObject.FindProperty("VoiceNear");
voFarProperty = serializedObject.FindProperty("VoiceFar");
voRadiusProperty = serializedObject.FindProperty("VoiceVolumetricRadius");
voDisableLpProperty = serializedObject.FindProperty("VoiceDisableLowpass");
avGainProperty = serializedObject.FindProperty("AvatarGainLimit");
avNearProperty = serializedObject.FindProperty("AvatarNearLimit");
avFarProperty = serializedObject.FindProperty("AvatarFarLimit");
avRadiusProperty = serializedObject.FindProperty("AvatarVolumetricRadiusLimit");
avForceSpatialProperty = serializedObject.FindProperty("AvatarForceSpatial");
avAllowCustomProperty = serializedObject.FindProperty("AvatarAllowCustomCurve");
serializedObject.Update();
EditorGUILayout.BeginVertical();
var ovr = serializedObject.targetObject as VRCSDK2.VRC_PlayerAudioOverride;
EditorGUILayout.PropertyField(globalProperty, new GUIContent("Global"));
if (!ovr.global)
{
EditorGUILayout.PropertyField(regionProperty, new GUIContent("Region"));
EditorGUILayout.PropertyField(prioProperty, new GUIContent("Priority"));
}
voShow = EditorGUILayout.Foldout(voShow, "Voice Settings");
if (voShow)
{
EditorGUILayout.PropertyField(voGainProperty, new GUIContent("Gain"));
EditorGUILayout.PropertyField(voFarProperty, new GUIContent("Far"));
EditorGUI.indentLevel++;
voAdv = EditorGUILayout.Foldout(voAdv, "Advanced Options");
if (voAdv)
{
EditorGUILayout.PropertyField(voNearProperty, new GUIContent("Near"));
EditorGUILayout.PropertyField(voRadiusProperty, new GUIContent("Volumetric Radius"));
EditorGUILayout.PropertyField(voDisableLpProperty, new GUIContent("Disable Lowpass Filter"));
}
EditorGUI.indentLevel--;
}
avShow = EditorGUILayout.Foldout(avShow, "Avatar Audio Limits");
if (avShow)
{
EditorGUILayout.PropertyField(avGainProperty, new GUIContent("Gain Limit"));
EditorGUILayout.PropertyField(avFarProperty, new GUIContent("Far Limit"));
EditorGUI.indentLevel++;
avAdv = EditorGUILayout.Foldout(avAdv, "Advanced Options");
if (avAdv)
{
EditorGUILayout.PropertyField(avNearProperty, new GUIContent("Near Limit"));
EditorGUILayout.PropertyField(avRadiusProperty, new GUIContent("Volumetric Radius Limit"));
EditorGUILayout.PropertyField(avForceSpatialProperty, new GUIContent("Force Spatial"));
EditorGUILayout.PropertyField(avAllowCustomProperty, new GUIContent("Allow Custom Curve"));
}
EditorGUI.indentLevel--;
}
EditorGUILayout.EndVertical();
serializedObject.ApplyModifiedProperties();
}
}
}
#endif
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 5c545625e0bf93045ac1c5864141c5c1
timeCreated: 1474315179
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,60 @@
#if VRC_SDK_VRCSDK2
#if UNITY_EDITOR
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
using System;
namespace VRCSDK2
{
[CustomEditor(typeof(VRCSDK2.VRC_SpatialAudioSource))]
public class VRC_SpatialAudioSourceEditor : Editor
{
private bool showAdvancedOptions = false;
private SerializedProperty gainProperty;
private SerializedProperty nearProperty;
private SerializedProperty farProperty;
private SerializedProperty volRadiusProperty;
private SerializedProperty enableSpatialProperty;
private SerializedProperty useCurveProperty;
public override void OnInspectorGUI()
{
gainProperty = serializedObject.FindProperty("Gain");
nearProperty = serializedObject.FindProperty("Near");
farProperty = serializedObject.FindProperty("Far");
volRadiusProperty = serializedObject.FindProperty("VolumetricRadius");
enableSpatialProperty = serializedObject.FindProperty("EnableSpatialization");
useCurveProperty = serializedObject.FindProperty("UseAudioSourceVolumeCurve");
serializedObject.Update();
VRCSDK2.VRC_SpatialAudioSource target = serializedObject.targetObject as VRCSDK2.VRC_SpatialAudioSource;
AudioSource source = target.GetComponent<AudioSource>();
EditorGUILayout.BeginVertical();
EditorGUILayout.PropertyField(gainProperty, new GUIContent("Gain"));
EditorGUILayout.PropertyField(farProperty, new GUIContent("Far"));
showAdvancedOptions = EditorGUILayout.Foldout(showAdvancedOptions, "Advanced Options");
bool enableSp = enableSpatialProperty.boolValue;
if (showAdvancedOptions)
{
EditorGUILayout.PropertyField(nearProperty, new GUIContent("Near"));
EditorGUILayout.PropertyField(volRadiusProperty, new GUIContent("Volumetric Radius"));
EditorGUILayout.PropertyField(enableSpatialProperty, new GUIContent("Enable Spatialization"));
if (enableSp)
EditorGUILayout.PropertyField(useCurveProperty, new GUIContent("Use AudioSource Volume Curve"));
}
EditorGUILayout.EndVertical();
if (source != null)
source.spatialize = enableSp;
serializedObject.ApplyModifiedProperties();
}
}
}
#endif
#endif
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0d2d4cba733f5eb4ba170368e67710d2
timeCreated: 1474315179
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,104 @@
#if VRC_SDK_VRCSDK2
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");
}
}
#endif
@@ -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,116 @@
#if VRC_SDK_VRCSDK2
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(live, new GUIContent("SyncType"), true) + EditorGUIUtility.standardVerticalSpacing
+ EditorGUI.GetPropertyHeight(sync, 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 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");
}
}
#endif
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3f9dccfed0b072f49a307b3f20a7e768
timeCreated: 1528745185
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large. Load diff
@@ -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 VRC_SDK_VRCSDK2
#if UNITY_EDITOR
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEditor.Build;
using System;
using System.Linq;
namespace VRCSDK2
{
[CustomEditor(typeof(VRCSDK2.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;
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_SyncVideoPlayer instead!", MessageType.Error);
EditorGUILayout.Space();
InspectorField("proximity", "Proximity for Interactivity");
EditorGUILayout.Space();
VRCSDK2.VRC_WebPanel web = (VRCSDK2.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 (VRCSettings.Get().DisplayHelpBoxes)
{
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
#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 && VRC_SDK_VRCSDK2
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: 92a4896241003fe4a8fc71eeb5c7268d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,59 @@
/*
#if VRC_SDK_VRCSDK3
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using System;
[CustomEditor(typeof(VRC.SDK3.Components.VRCDestructibleUdon))]
public class VRCDestructibleUdonEditor : Editor
{
VRC.SDK3.Components.VRCDestructibleUdon myTarget;
void OnEnable()
{
if (myTarget == null)
myTarget = (VRC.SDK3.Components.VRCDestructibleUdon)target;
}
string[] UdonMethods = null;
string[] UdonVariables = null;
public override void OnInspectorGUI()
{
var udon = myTarget.GetComponent<VRC.Udon.UdonBehaviour>();
if (udon != null)
{
#if VRC_CLIENT
myTarget.UdonMethodApplyDamage = EditorGUILayout.TextField("On Apply Damage", myTarget.UdonMethodApplyDamage);
myTarget.UdonMethodApplyHealing= EditorGUILayout.TextField("On Apply Healing", myTarget.UdonMethodApplyHealing);
myTarget.UdonVariableCurrentHealth= EditorGUILayout.TextField("Current Health Variable", myTarget.UdonVariableCurrentHealth);
myTarget.UdonVariableMaxHealth = EditorGUILayout.TextField("On Max Health Variable", myTarget.UdonVariableMaxHealth);
#else
List<string> methods = new List<string>(udon.GetPrograms());
methods.Insert(0, "-none-");
myTarget.UdonMethodApplyDamage = DrawUdonProgramPicker("On Apply Damage", myTarget.UdonMethodApplyDamage, methods);
myTarget.UdonMethodApplyHealing = DrawUdonProgramPicker("On Apply Healing", myTarget.UdonMethodApplyHealing, methods);
List<string> variables = new List<string>(udon.publicVariables.VariableSymbols);
variables.Insert(0, "-none-");
myTarget.UdonVariableCurrentHealth = DrawUdonProgramPicker("Current Health Variable", myTarget.UdonVariableCurrentHealth, variables);
myTarget.UdonVariableMaxHealth = DrawUdonProgramPicker("Max Health Variable", myTarget.UdonVariableMaxHealth, variables);
#endif
}
}
string DrawUdonProgramPicker(string title, string current, List<string> choices)
{
int index = choices.IndexOf(current);
if (index == -1)
index = 0;
int value = EditorGUILayout.Popup(title, index, choices.ToArray());
if (value != 0)
return choices[value];
return current;
}
}
#endif
*/
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d57b23c04034119448f23c5fdbc57662
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,33 @@
#if VRC_SDK_VRCSDK3
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using System;
[CustomEditor(typeof(VRC.SDK3.Components.VRCStation))]
public class VRCPlayerStationEditor3 : Editor
{
VRC.SDK3.Components.VRCStation myTarget;
void OnEnable()
{
if(myTarget == null)
myTarget = (VRC.SDK3.Components.VRCStation)target;
}
public override void OnInspectorGUI()
{
myTarget.PlayerMobility = (VRC.SDKBase.VRCStation.Mobility)EditorGUILayout.EnumPopup("Player Mobility", myTarget.PlayerMobility);
myTarget.canUseStationFromStation = EditorGUILayout.Toggle("Can Use Station From Station", myTarget.canUseStationFromStation);
myTarget.animatorController = (RuntimeAnimatorController) EditorGUILayout.ObjectField("Animator Controller", myTarget.animatorController, typeof(RuntimeAnimatorController), false );
myTarget.disableStationExit = EditorGUILayout.Toggle("Disable Station Exit", myTarget.disableStationExit );
myTarget.seated = EditorGUILayout.Toggle("Seated", myTarget.seated);
myTarget.stationEnterPlayerLocation = (Transform)EditorGUILayout.ObjectField("Player Enter Location", myTarget.stationEnterPlayerLocation, typeof(Transform), true);
myTarget.stationExitPlayerLocation = (Transform)EditorGUILayout.ObjectField("Player Exit Location", myTarget.stationExitPlayerLocation, typeof(Transform), true);
myTarget.controlsObject = (VRC.SDKBase.VRC_ObjectApi)EditorGUILayout.ObjectField("API Object", myTarget.controlsObject, typeof(VRC.SDKBase.VRC_ObjectApi), false);
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8901d07a685ca424492a3cabff506184
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,27 @@
#if VRC_SDK_VRCSDK3
using UnityEditor;
[CustomEditor (typeof(VRC.SDK3.Components.VRCSceneDescriptor))]
public class VRCSceneDescriptorEditor3 : Editor
{
VRC.SDK3.Components.VRCSceneDescriptor sceneDescriptor;
VRC.Core.PipelineManager pipelineManager;
public override void OnInspectorGUI()
{
if(sceneDescriptor == null)
sceneDescriptor = (VRC.SDK3.Components.VRCSceneDescriptor)target;
if(pipelineManager == null)
{
pipelineManager = sceneDescriptor.GetComponent<VRC.Core.PipelineManager>();
if(pipelineManager == null)
sceneDescriptor.gameObject.AddComponent<VRC.Core.PipelineManager>();
}
DrawDefaultInspector();
}
}
#endif
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4b2b9ac625bc5b04c887ff9ee9b5fdbe
timeCreated: 1450463561
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,73 @@
#if VRC_SDK_VRCSDK3
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
namespace VRCSDK2
{
[CustomEditor(typeof(VRC.SDK3.Components.VRCPickup))]
public class VRC_PickupEditor3 : Editor
{
private void InspectorField(string propertyName, string humanName)
{
SerializedProperty propertyField = serializedObject.FindProperty(propertyName);
EditorGUILayout.PropertyField(propertyField, new GUIContent(humanName), true);
}
private SerializedProperty momentumTransferMethodProperty;
private SerializedProperty disallowTheftProperty;
private SerializedProperty exactGunProperty;
private SerializedProperty exactGripProperty;
private SerializedProperty allowManipulationWhenEquippedProperty;
private SerializedProperty orientationProperty;
private SerializedProperty autoHoldProperty;
private SerializedProperty interactionTextProperty;
private SerializedProperty useTextProperty;
private SerializedProperty throwVelocityBoostMinSpeedProperty;
private SerializedProperty throwVelocityBoostScaleProperty;
private SerializedProperty pickupableProperty;
private SerializedProperty proximityProperty;
public override void OnInspectorGUI()
{
momentumTransferMethodProperty = serializedObject.FindProperty("MomentumTransferMethod");
disallowTheftProperty = serializedObject.FindProperty("DisallowTheft");
exactGunProperty = serializedObject.FindProperty("ExactGun");
exactGripProperty = serializedObject.FindProperty("ExactGrip");
allowManipulationWhenEquippedProperty = serializedObject.FindProperty("allowManipulationWhenEquipped");
orientationProperty = serializedObject.FindProperty("orientation");
autoHoldProperty = serializedObject.FindProperty("AutoHold");
interactionTextProperty = serializedObject.FindProperty("InteractionText");
useTextProperty = serializedObject.FindProperty("UseText");
throwVelocityBoostMinSpeedProperty = serializedObject.FindProperty("ThrowVelocityBoostMinSpeed");
throwVelocityBoostScaleProperty = serializedObject.FindProperty("ThrowVelocityBoostScale");
pickupableProperty = serializedObject.FindProperty("pickupable");
proximityProperty = serializedObject.FindProperty("proximity");
EditorGUILayout.BeginVertical(GUILayout.MaxWidth(EditorGUIUtility.currentViewWidth - 30));
EditorGUILayout.PropertyField(momentumTransferMethodProperty, new GUIContent("Momentum Transfer Method"));
EditorGUILayout.PropertyField(disallowTheftProperty, new GUIContent("Disallow Theft"));
EditorGUILayout.PropertyField(exactGunProperty, new GUIContent("Exact Gun"));
EditorGUILayout.PropertyField(exactGripProperty, new GUIContent("Exact Grip"));
EditorGUILayout.PropertyField(allowManipulationWhenEquippedProperty, new GUIContent("Allow Manipulation When Equipped"));
EditorGUILayout.PropertyField(orientationProperty, new GUIContent("Orientation"));
EditorGUILayout.PropertyField(autoHoldProperty, new GUIContent("AutoHold", "If the pickup is supposed to be aligned to the hand (i.e. orientation field is set to Gun or Grip), auto-detect means that it will be Equipped(not dropped when they release trigger), otherwise just hold as a normal pickup."));
EditorGUILayout.PropertyField(interactionTextProperty, new GUIContent("Interaction Text","Text displayed when user hovers over the pickup."));
if (autoHoldProperty.enumValueIndex != (int)VRC.SDK3.Components.VRCPickup.AutoHoldMode.No)
EditorGUILayout.PropertyField(useTextProperty, new GUIContent("Use Text", "Text to display describing action for clicking button, when this pickup is already being held."));
EditorGUILayout.PropertyField(throwVelocityBoostMinSpeedProperty, new GUIContent("Throw Velocity Boost Min Speed"));
EditorGUILayout.PropertyField(throwVelocityBoostScaleProperty, new GUIContent("Throw Velocity Boost Scale"));
EditorGUILayout.PropertyField(pickupableProperty, new GUIContent("Pickupable"));
EditorGUILayout.PropertyField(proximityProperty, new GUIContent("Proximity"));
EditorGUILayout.EndVertical();
serializedObject.ApplyModifiedProperties();
}
}
}
#endif
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a8cc4c1876b26174fbaeb062178a6bda
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,58 @@
#if VRC_SDK_VRCSDK3
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
namespace VRC.SDK3.Editor
{
[CustomEditor(typeof(VRC.SDK3.Components.VRCSpatialAudioSource))]
public class VRC_SpatialAudioSourceEditor3 : UnityEditor.Editor
{
private bool showAdvancedOptions = false;
private SerializedProperty gainProperty;
private SerializedProperty nearProperty;
private SerializedProperty farProperty;
private SerializedProperty volRadiusProperty;
private SerializedProperty enableSpatialProperty;
private SerializedProperty useCurveProperty;
public override void OnInspectorGUI()
{
gainProperty = serializedObject.FindProperty("Gain");
nearProperty = serializedObject.FindProperty("Near");
farProperty = serializedObject.FindProperty("Far");
volRadiusProperty = serializedObject.FindProperty("VolumetricRadius");
enableSpatialProperty = serializedObject.FindProperty("EnableSpatialization");
useCurveProperty = serializedObject.FindProperty("UseAudioSourceVolumeCurve");
serializedObject.Update();
VRC.SDKBase.VRC_SpatialAudioSource target = serializedObject.targetObject as VRC.SDKBase.VRC_SpatialAudioSource;
AudioSource source = target.GetComponent<AudioSource>();
EditorGUILayout.BeginVertical();
EditorGUILayout.PropertyField(gainProperty, new GUIContent("Gain"));
EditorGUILayout.PropertyField(farProperty, new GUIContent("Far"));
showAdvancedOptions = EditorGUILayout.Foldout(showAdvancedOptions, "Advanced Options");
bool enableSp = enableSpatialProperty.boolValue;
if (showAdvancedOptions)
{
EditorGUILayout.PropertyField(nearProperty, new GUIContent("Near"));
EditorGUILayout.PropertyField(volRadiusProperty, new GUIContent("Volumetric Radius"));
EditorGUILayout.PropertyField(enableSpatialProperty, new GUIContent("Enable Spatialization"));
if (enableSp)
EditorGUILayout.PropertyField(useCurveProperty, new GUIContent("Use AudioSource Volume Curve"));
}
EditorGUILayout.EndVertical();
if (source != null)
source.spatialize = enableSp;
serializedObject.ApplyModifiedProperties();
}
}
}
#endif
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3f8f999a8e1ebee4588f94a8a618d7c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6a7071a2aea77fb48bfbe2492a2f911e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,9 @@
public interface IVRCSdkControlPanelBuilder
{
void ShowSettingsOptions();
bool IsValidBuilder(out string message);
void ShowBuilder();
void RegisterBuilder(VRCSdkControlPanel baseBuilder);
void SelectAllComponents();
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 310a760e312f2984e85eece367bab19a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,246 @@
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 (!ConfigManager.RemoteConfig.IsInitialized())
{
VRC.Core.API.SetOnlineMode(true, "vrchat");
ConfigManager.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();
}
public static GUIStyle titleGuiStyle;
public static GUIStyle boxGuiStyle;
public static GUIStyle infoGuiStyle;
public static GUIStyle listButtonStyleEven;
public static GUIStyle listButtonStyleOdd;
public static GUIStyle listButtonStyleSelected;
public static GUIStyle scrollViewSeparatorStyle;
public static GUIStyle searchBarStyle;
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.3f, 0.3f, 0.3f));
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));
}
scrollViewSeparatorStyle = new GUIStyle("Toolbar");
scrollViewSeparatorStyle.fixedWidth = SdkWindowWidth + 10;
scrollViewSeparatorStyle.fixedHeight = 4;
scrollViewSeparatorStyle.margin.top = 1;
searchBarStyle = new GUIStyle("Toolbar");
searchBarStyle.fixedWidth = SdkWindowWidth;
searchBarStyle.fixedHeight = 23;
searchBarStyle.padding.top = 3;
}
void Init()
{
InitializeStyles();
ResetIssues();
InitAccount();
}
void OnEnable()
{
OnEnableAccount();
AssemblyReloadEvents.afterAssemblyReload += BuilderAssemblyReload;
}
void OnDisable()
{
AssemblyReloadEvents.afterAssemblyReload -= BuilderAssemblyReload;
}
void OnDestroy()
{
AccountDestroy();
}
public 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.BeginHorizontal();
GUILayout.FlexibleSpace();
GUILayout.BeginVertical();
GUILayout.Box(_bannerImage);
if (Application.isPlaying)
{
GUI.enabled = false;
GUILayout.Space(20);
EditorGUILayout.LabelField("Unity Application is running ...\nStop it to access the Control Panel", titleGuiStyle, GUILayout.Width(SdkWindowWidth));
GUI.enabled = true;
GUILayout.EndVertical();
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
return;
}
EditorGUILayout.Space();
EnvConfig.SetActiveSDKDefines();
#if VRC_SDK_VRCSDK2
VRCSettings.Get().activeWindowPanel = GUILayout.Toolbar(VRCSettings.Get().activeWindowPanel, new string[] { "Authentication", "Builder", "Content Manager", "Settings" }, GUILayout.Width(SdkWindowWidth));
int showPanel = VRCSettings.Get().activeWindowPanel;
#elif VRC_SDK_VRCSDK3
VRC.SDK3.Editor.VRCSettings.Get().activeWindowPanel = GUILayout.Toolbar(VRC.SDK3.Editor.VRCSettings.Get().activeWindowPanel, new string[] { "Authentication", "Builder", "Content Manager", "Settings" }, GUILayout.Width(SdkWindowWidth));
int showPanel = VRC.SDK3.Editor.VRCSettings.Get().activeWindowPanel;
#else
int showPanel = 0;
#endif
GUILayout.EndVertical();
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
if (APIUser.IsLoggedInWithCredentials == false && showPanel != 3)
showPanel = 0;
switch (showPanel)
{
case 1:
ShowBuilders();
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();
// style backgrounds may be nulled on scene load. detect if so has happened
if((boxGuiStyle != null) && (boxGuiStyle.normal.background == null))
InitializeStyles();
}
[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,594 @@
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(); } }
public static bool DefaultFutureProofPublishEnabled { get { return true; } }
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 VRC_SDK_VRCSDK2
if (VRCSettings.Get().DisplayAdvancedSettings)
newEnv = (ApiServerEnvironment)EditorGUILayout.EnumPopup("Use API", serverEnvironment);
#elif VRC_SDK_VRCSDK3
if (VRC.SDK3.Editor.VRCSettings.Get().DisplayAdvancedSettings)
newEnv = (ApiServerEnvironment)EditorGUILayout.EnumPopup("Use API", serverEnvironment);
#endif
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.ConfigManager.RemoteConfig.IsInitialized())
{
if (VRC.Core.ConfigManager.RemoteConfig.HasKey("sdkUnityVersion"))
{
string sdkUnityVersion = VRC.Core.ConfigManager.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.ConfigManager.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();
// 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)
{
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,639 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using VRCSDK2.Validation.Performance;
using Object = UnityEngine.Object;
using VRC.SDK3.Editor;
using VRC.SDKBase.Editor;
public partial class VRCSdkControlPanel : EditorWindow
{
public static System.Action _EnableSpatialization = null; // assigned in AutoAddONSPAudioSourceComponents
public const string AVATAR_OPTIMIZATION_TIPS_URL = "https://docs.vrchat.com/docs/avatar-optimizing-tips";
public const string AVATAR_RIG_REQUIREMENTS_URL = "https://docs.vrchat.com/docs/rig-requirements";
const string kCantPublishContent = "Before you can upload avatars or worlds, you will need to spend some time in VRChat.";
const string kCantPublishAvatars = "Before you can upload avatars, you will need to spend some time in VRChat.";
const string kCantPublishWorlds = "Before you can upload worlds, you will need to spend some time in VRChat.";
private const string FIX_ISSUES_TO_BUILD_OR_TEST_WARNING_STRING = "You must address the above issues before you can build or test this content!";
static Texture _perfIcon_Excellent;
static Texture _perfIcon_Good;
static Texture _perfIcon_Medium;
static Texture _perfIcon_Poor;
static Texture _perfIcon_VeryPoor;
static Texture _bannerImage;
public void ResetIssues()
{
GUIErrors.Clear();
GUIInfos.Clear();
GUIWarnings.Clear();
GUILinks.Clear();
GUIStats.Clear();
CheckedForIssues = false;
}
public bool CheckedForIssues { get; set; } = false;
class Issue
{
public string issueText;
public System.Action showThisIssue;
public System.Action fixThisIssue;
public PerformanceRating performanceRating;
public Issue(string text, System.Action show, System.Action fix, PerformanceRating rating = PerformanceRating.None)
{
issueText = text;
showThisIssue = show;
fixThisIssue = fix;
performanceRating = rating;
}
public class Equality : IEqualityComparer<Issue>, IComparer<Issue>
{
public bool Equals(Issue b1, Issue b2)
{
return (b1.issueText == b2.issueText);
}
public int Compare(Issue b1, Issue b2)
{
return string.Compare(b1.issueText, b2.issueText);
}
public int GetHashCode(Issue bx)
{
return bx.issueText.GetHashCode();
}
}
}
Dictionary<Object, List<Issue>> GUIErrors = new Dictionary<Object, List<Issue>>();
Dictionary<Object, List<Issue>> GUIWarnings = new Dictionary<Object, List<Issue>>();
Dictionary<Object, List<Issue>> GUIInfos = new Dictionary<Object, List<Issue>>();
Dictionary<Object, List<Issue>> GUILinks = new Dictionary<Object, List<Issue>>();
Dictionary<Object, List<Issue>> GUIStats = new Dictionary<Object, List<Issue>>();
public bool NoGuiErrorsOrIssues()
{
return GUIErrors.Count == 0 && CheckedForIssues;
}
void AddToReport(Dictionary<Object, List<Issue>> report, Object subject, string output, System.Action show, System.Action fix)
{
if (subject == null)
subject = this;
if (!report.ContainsKey(subject))
report.Add(subject, new List<Issue>());
var issue = new Issue(output, show, fix);
if (!report[subject].Contains(issue, new Issue.Equality()))
{
report[subject].Add(issue);
report[subject].Sort(new Issue.Equality());
}
}
void BuilderAssemblyReload()
{
ResetIssues();
}
public void OnGUIError(Object subject, string output, System.Action show, System.Action fix)
{
AddToReport(GUIErrors, subject, output, show, fix);
}
public void OnGUIWarning(Object subject, string output, System.Action show, System.Action fix)
{
AddToReport(GUIWarnings, subject, output, show, fix);
}
public void OnGUIInformation(Object subject, string output)
{
AddToReport(GUIInfos, subject, output, null, null);
}
public void OnGUILink(Object subject, string output, string link)
{
AddToReport(GUILinks, subject, output + "\n" + link, null, null);
}
public void OnGUIStat(Object subject, string output, PerformanceRating rating, System.Action show, System.Action fix)
{
if (subject == null)
subject = this;
if (!GUIStats.ContainsKey(subject))
GUIStats.Add(subject, new List<Issue>());
GUIStats[subject].Add(new Issue(output, show, fix, rating));
}
public int triggerLineMode
{
get { return EditorPrefs.GetInt("VRC.SDKBase_triggerLineMode", 0); }
set { EditorPrefs.SetInt("VRC.SDKBase_triggerLineMode", value); }
}
private void ShowSettingsOptionsForBuilders()
{
if (_sdkBuilders == null)
{
PopulateSdkBuilders();
}
for (int i = 0; i < _sdkBuilders.Length; i++)
{
IVRCSdkControlPanelBuilder builder = _sdkBuilders[i];
builder.ShowSettingsOptions();
if (i < _sdkBuilders.Length - 1)
{
EditorGUILayout.Separator();
}
}
}
private IVRCSdkControlPanelBuilder[] _sdkBuilders;
private static List<Type> GetSdkBuilderTypesFromAttribute()
{
Type sdkBuilderInterfaceType = typeof(IVRCSdkControlPanelBuilder);
Type sdkBuilderAttributeType = typeof(VRCSdkControlPanelBuilderAttribute);
List<Type> moduleTypesFromAttribute = new List<Type>();
foreach(Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
VRCSdkControlPanelBuilderAttribute[] sdkBuilderAttributes;
try
{
sdkBuilderAttributes = (VRCSdkControlPanelBuilderAttribute[])assembly.GetCustomAttributes(sdkBuilderAttributeType, false);
}
catch
{
sdkBuilderAttributes = new VRCSdkControlPanelBuilderAttribute[0];
}
foreach(VRCSdkControlPanelBuilderAttribute udonWrapperModuleAttribute in sdkBuilderAttributes)
{
if(udonWrapperModuleAttribute == null)
{
continue;
}
if(!sdkBuilderInterfaceType.IsAssignableFrom(udonWrapperModuleAttribute.Type))
{
continue;
}
moduleTypesFromAttribute.Add(udonWrapperModuleAttribute.Type);
}
}
return moduleTypesFromAttribute;
}
private void PopulateSdkBuilders()
{
if (_sdkBuilders != null)
{
return;
}
List<IVRCSdkControlPanelBuilder> builders = new List<IVRCSdkControlPanelBuilder>();
foreach (Type type in GetSdkBuilderTypesFromAttribute())
{
IVRCSdkControlPanelBuilder builder = (IVRCSdkControlPanelBuilder)Activator.CreateInstance(type);
builder.RegisterBuilder(this);
builders.Add(builder);
}
_sdkBuilders = builders.ToArray();
}
void ShowBuilders()
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
GUILayout.BeginVertical();
if (VRC.Core.ConfigManager.RemoteConfig.IsInitialized())
{
string sdkUnityVersion = VRC.Core.ConfigManager.RemoteConfig.GetString("sdkUnityVersion");
if (Application.unityVersion != sdkUnityVersion)
{
OnGUIWarning(null, "You are not using the recommended Unity version for the VRChat SDK. Content built with this version may not work correctly. Please use Unity " + sdkUnityVersion,
null,
() => { Application.OpenURL("https://unity3d.com/get-unity/download/archive"); }
);
}
}
if (VRCSdk3Analysis.IsSdkDllActive(VRCSdk3Analysis.SdkVersion.VRCSDK2) && VRCSdk3Analysis.IsSdkDllActive(VRCSdk3Analysis.SdkVersion.VRCSDK3))
{
List<Component> sdk2Components = VRCSdk3Analysis.GetSDKInScene(VRCSdk3Analysis.SdkVersion.VRCSDK2);
List<Component> sdk3Components = VRCSdk3Analysis.GetSDKInScene(VRCSdk3Analysis.SdkVersion.VRCSDK3);
if (sdk2Components.Count > 0 && sdk3Components.Count > 0)
{
OnGUIError(null,
"This scene contains components from the VRChat SDK version 2 and version 3. Version two elements will have to be replaced with their version 3 counterparts to build with SDK3 and UDON.",
() => { Selection.objects = sdk2Components.ToArray(); },
null
);
}
}
if (Lightmapping.giWorkflowMode == Lightmapping.GIWorkflowMode.Iterative)
{
OnGUIWarning(null,
"Automatic lightmap generation is enabled, which may stall the Unity build process. Before building and uploading, consider turning off 'Auto Generate' at the bottom of the Lighting Window.",
() =>
{
EditorWindow lightingWindow = GetLightingWindow();
if (lightingWindow)
{
lightingWindow.Show();
lightingWindow.Focus();
}
},
() =>
{
Lightmapping.giWorkflowMode = Lightmapping.GIWorkflowMode.OnDemand;
EditorWindow lightingWindow = GetLightingWindow();
if (!lightingWindow) return;
lightingWindow.Repaint();
Focus();
}
);
}
PopulateSdkBuilders();
IVRCSdkControlPanelBuilder selectedBuilder = null;
string errorMessage = null;
foreach (IVRCSdkControlPanelBuilder sdkBuilder in _sdkBuilders)
{
if (!sdkBuilder.IsValidBuilder(out string message))
{
if (selectedBuilder == null)
{
errorMessage = message;
}
}
else
{
if (selectedBuilder == null)
{
selectedBuilder = sdkBuilder;
errorMessage = null;
}
else
{
errorMessage =
"A Unity scene cannot contain a VRChat Scene Descriptor and also contain VRChat Avatar Descriptors";
}
}
}
if (selectedBuilder == null)
{
#if VRC_SDK_VRCSDK2
EditorGUILayout.LabelField("A VRC_SceneDescriptor or VRC_AvatarDescriptor\nis required to build VRChat SDK Content", titleGuiStyle, GUILayout.Width(SdkWindowWidth));
#elif VRC_SDK_VRCSDK3
EditorGUILayout.LabelField("A VRCSceneDescriptor or VRCAvatarDescriptor\nis required to build VRChat SDK Content", titleGuiStyle, GUILayout.Width(SdkWindowWidth));
#endif
}
else if (errorMessage != null)
{
OnGUIError(null,
errorMessage,
() => {
foreach (IVRCSdkControlPanelBuilder builder in _sdkBuilders)
{
builder.SelectAllComponents();
} },
null
);
OnGUIShowIssues();
}
else
{
selectedBuilder.ShowBuilder();
}
if (Event.current.type == EventType.Used) return;
GUILayout.EndVertical();
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}
public bool showLayerHelp = false;
bool ShouldShowLightmapWarning
{
get
{
const string GraphicsSettingsAssetPath = "ProjectSettings/GraphicsSettings.asset";
SerializedObject graphicsManager = new SerializedObject(UnityEditor.AssetDatabase.LoadAllAssetsAtPath(GraphicsSettingsAssetPath)[0]);
SerializedProperty lightmapStripping = graphicsManager.FindProperty("m_LightmapStripping");
return lightmapStripping.enumValueIndex == 0;
}
}
bool ShouldShowFogWarning
{
get
{
const string GraphicsSettingsAssetPath = "ProjectSettings/GraphicsSettings.asset";
SerializedObject graphicsManager = new SerializedObject(UnityEditor.AssetDatabase.LoadAllAssetsAtPath(GraphicsSettingsAssetPath)[0]);
SerializedProperty lightmapStripping = graphicsManager.FindProperty("m_FogStripping");
return lightmapStripping.enumValueIndex == 0;
}
}
void DrawIssueBox(MessageType msgType, Texture icon, string message, System.Action show, System.Action fix)
{
bool haveButtons = ((show != null) || (fix != null));
GUIStyle style = new GUIStyle("HelpBox");
style.fixedWidth = (haveButtons ? (SdkWindowWidth - 90) : SdkWindowWidth);
float minHeight = 40;
try
{
EditorGUILayout.BeginHorizontal();
if (icon != null)
{
GUIContent c = new GUIContent(message, icon);
float height = style.CalcHeight(c, style.fixedWidth);
GUILayout.Box(c, style, GUILayout.MinHeight(Mathf.Max(minHeight, height)));
}
else
{
GUIContent c = new GUIContent(message);
float height = style.CalcHeight(c, style.fixedWidth);
Rect rt = GUILayoutUtility.GetRect(c, style, GUILayout.MinHeight(Mathf.Max(minHeight, height)));
EditorGUI.HelpBox(rt, message, msgType); // note: EditorGUILayout resulted in uneven button layout in this case
}
if (haveButtons)
{
EditorGUILayout.BeginVertical();
float buttonHeight = ((show == null || fix == null) ? minHeight : (minHeight * 0.5f));
if ((show != null) && GUILayout.Button("Select", GUILayout.Height(buttonHeight)))
show();
if ((fix != null) && GUILayout.Button("Auto Fix", GUILayout.Height(buttonHeight)))
{
fix();
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
CheckedForIssues = false;
Repaint();
}
EditorGUILayout.EndVertical();
}
EditorGUILayout.EndHorizontal();
}
catch
{
// mutes 'ArgumentException: Getting control 0's position in a group with only 0 controls when doing repaint'
}
}
public void OnGuiFixIssuesToBuildOrTest()
{
GUIStyle s = new GUIStyle(EditorStyles.label) { alignment = TextAnchor.MiddleCenter };
EditorGUILayout.Space();
GUILayout.BeginVertical(boxGuiStyle, GUILayout.Height(WARNING_ICON_SIZE), GUILayout.Width(SdkWindowWidth));
GUILayout.FlexibleSpace();
EditorGUILayout.BeginHorizontal();
var textDimensions = s.CalcSize(new GUIContent(FIX_ISSUES_TO_BUILD_OR_TEST_WARNING_STRING));
GUILayout.Label(new GUIContent(warningIconGraphic), GUILayout.Width(WARNING_ICON_SIZE), GUILayout.Height(WARNING_ICON_SIZE));
EditorGUILayout.LabelField(FIX_ISSUES_TO_BUILD_OR_TEST_WARNING_STRING, s, GUILayout.Width(textDimensions.x), GUILayout.Height(WARNING_ICON_SIZE));
EditorGUILayout.EndHorizontal();
GUILayout.FlexibleSpace();
GUILayout.EndVertical();
}
public void OnGUIShowIssues(Object subject = null)
{
if (subject == null)
subject = this;
EditorGUI.BeginChangeCheck();
GUIStyle style = GUI.skin.GetStyle("HelpBox");
if (GUIErrors.ContainsKey(subject))
foreach (Issue error in GUIErrors[subject].Where(s => !string.IsNullOrEmpty(s.issueText)))
DrawIssueBox(MessageType.Error, null, error.issueText, error.showThisIssue, error.fixThisIssue);
if (GUIWarnings.ContainsKey(subject))
foreach (Issue error in GUIWarnings[subject].Where(s => !string.IsNullOrEmpty(s.issueText)))
DrawIssueBox(MessageType.Warning, null, error.issueText, error.showThisIssue, error.fixThisIssue);
if (GUIStats.ContainsKey(subject))
{
foreach (var kvp in GUIStats[subject].Where(k => k.performanceRating == PerformanceRating.VeryPoor))
DrawIssueBox(MessageType.Warning, GetPerformanceIconForRating(kvp.performanceRating), kvp.issueText, kvp.showThisIssue, kvp.fixThisIssue);
foreach (var kvp in GUIStats[subject].Where(k => k.performanceRating == PerformanceRating.Poor))
DrawIssueBox(MessageType.Warning, GetPerformanceIconForRating(kvp.performanceRating), kvp.issueText, kvp.showThisIssue, kvp.fixThisIssue);
foreach (var kvp in GUIStats[subject].Where(k => k.performanceRating == PerformanceRating.Medium))
DrawIssueBox(MessageType.Warning, GetPerformanceIconForRating(kvp.performanceRating), kvp.issueText, kvp.showThisIssue, kvp.fixThisIssue);
foreach (var kvp in GUIStats[subject].Where(k => k.performanceRating == PerformanceRating.Good || k.performanceRating == PerformanceRating.Excellent))
DrawIssueBox(MessageType.Warning, GetPerformanceIconForRating(kvp.performanceRating), kvp.issueText, kvp.showThisIssue, kvp.fixThisIssue);
}
if (GUIInfos.ContainsKey(subject))
foreach (Issue error in GUIInfos[subject].Where(s => !string.IsNullOrEmpty(s.issueText)))
EditorGUILayout.HelpBox(error.issueText, MessageType.Info);
if (GUILinks.ContainsKey(subject))
{
EditorGUILayout.BeginVertical(style);
foreach (Issue error in GUILinks[subject].Where(s => !string.IsNullOrEmpty(s.issueText)))
{
var s = error.issueText.Split('\n');
EditorGUILayout.BeginHorizontal();
GUILayout.Label(s[0]);
if (GUILayout.Button("Open Link", GUILayout.Width(100)))
Application.OpenURL(s[1]);
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndVertical();
}
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(subject);
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene());
}
}
private Texture GetPerformanceIconForRating(PerformanceRating value)
{
if (_perfIcon_Excellent == null)
_perfIcon_Excellent = Resources.Load<Texture>("PerformanceIcons/Perf_Great_32");
if (_perfIcon_Good == null)
_perfIcon_Good = Resources.Load<Texture>("PerformanceIcons/Perf_Good_32");
if (_perfIcon_Medium == null)
_perfIcon_Medium = Resources.Load<Texture>("PerformanceIcons/Perf_Medium_32");
if (_perfIcon_Poor == null)
_perfIcon_Poor = Resources.Load<Texture>("PerformanceIcons/Perf_Poor_32");
if (_perfIcon_VeryPoor == null)
_perfIcon_VeryPoor = Resources.Load<Texture>("PerformanceIcons/Perf_Horrible_32");
switch (value)
{
case PerformanceRating.Excellent:
return _perfIcon_Excellent;
case PerformanceRating.Good:
return _perfIcon_Good;
case PerformanceRating.Medium:
return _perfIcon_Medium;
case PerformanceRating.Poor:
return _perfIcon_Poor;
case PerformanceRating.None:
case PerformanceRating.VeryPoor:
return _perfIcon_VeryPoor;
}
return _perfIcon_Excellent;
}
Texture2D CreateBackgroundColorImage(UnityEngine.Color color)
{
int w = 4, h = 4;
Texture2D back = new Texture2D(w, h);
UnityEngine.Color[] buffer = new UnityEngine.Color[w * h];
for (int i = 0; i < w; ++i)
for (int j = 0; j < h; ++j)
buffer[i + w * j] = color;
back.SetPixels(buffer);
back.Apply(false);
return back;
}
public static void DrawContentInfo(string name, string version, string description, string capacity, string releaseStatus, List<string> tags)
{
EditorGUILayout.LabelField("Name: " + name);
EditorGUILayout.LabelField("Version: " + version.ToString());
EditorGUILayout.LabelField("Description: " + description);
if (capacity != null)
EditorGUILayout.LabelField("Capacity: " + capacity);
EditorGUILayout.LabelField("Release: " + releaseStatus);
if (tags != null)
{
string tagString = "";
for (int i = 0; i < tags.Count; i++)
{
if (i != 0) tagString += ", ";
tagString += tags[i];
}
EditorGUILayout.LabelField("Tags: " + tagString);
}
}
public static void DrawContentPlatformSupport(VRC.Core.ApiModel m)
{
if (m.supportedPlatforms == VRC.Core.ApiModel.SupportedPlatforms.StandaloneWindows || m.supportedPlatforms == VRC.Core.ApiModel.SupportedPlatforms.All)
EditorGUILayout.LabelField("Windows Support: YES");
else
EditorGUILayout.LabelField("Windows Support: NO");
if (m.supportedPlatforms == VRC.Core.ApiModel.SupportedPlatforms.Android || m.supportedPlatforms == VRC.Core.ApiModel.SupportedPlatforms.All)
EditorGUILayout.LabelField("Android Support: YES");
else
EditorGUILayout.LabelField("Android Support: NO");
}
public static void DrawBuildTargetSwitcher()
{
EditorGUILayout.LabelField("Active Build Target: " + EditorUserBuildSettings.activeBuildTarget);
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneWindows || EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneWindows64 && GUILayout.Button("Switch Build Target to Android"))
{
if (EditorUtility.DisplayDialog("Build Target Switcher", "Are you sure you want to switch your build target to Android? This could take a while.", "Confirm", "Cancel"))
EditorUserBuildSettings.SwitchActiveBuildTargetAsync(BuildTargetGroup.Android, BuildTarget.Android);
}
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android && GUILayout.Button("Switch Build Target to Windows"))
{
if (EditorUtility.DisplayDialog("Build Target Switcher", "Are you sure you want to switch your build target to Windows? This could take a while.", "Confirm", "Cancel"))
EditorUserBuildSettings.SwitchActiveBuildTargetAsync(BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows64);
}
}
public static string GetBuildAndPublishButtonString()
{
string buildButtonString = "Build & Publish for UNSUPPORTED";
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneWindows || EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneWindows64)
buildButtonString = "Build & Publish for Windows";
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
buildButtonString = "Build & Publish for Android";
return buildButtonString;
}
public static Object[] GetSubstanceObjects(GameObject obj = null, bool earlyOut = false)
{
// if 'obj' is null we check entire scene
// if 'earlyOut' is true we only return 1st object (to detect if substances are present)
List<Object> objects = new List<Object>();
if (obj == null) return objects.Count < 1 ? null : objects.ToArray();
Renderer[] renderers = obj ? obj.GetComponentsInChildren<Renderer>(true) : FindObjectsOfType<Renderer>();
if (renderers == null || renderers.Length < 1)
return null;
foreach (Renderer r in renderers)
{
if (r.sharedMaterials.Length < 1)
continue;
foreach (Material m in r.sharedMaterials)
{
if (!m)
continue;
string path = AssetDatabase.GetAssetPath(m);
if (string.IsNullOrEmpty(path))
continue;
if (path.EndsWith(".sbsar", true, System.Globalization.CultureInfo.InvariantCulture))
{
objects.Add(r.gameObject);
if (earlyOut)
return objects.ToArray();
}
}
}
return objects.Count < 1 ? null : objects.ToArray();
}
public static bool HasSubstances(GameObject obj = null)
{
return (GetSubstanceObjects(obj, true) != null);
}
EditorWindow GetLightingWindow()
{
var editorAsm = typeof(UnityEditor.Editor).Assembly;
return EditorWindow.GetWindow(editorAsm.GetType("UnityEditor.LightingWindow"));
}
public static void ShowContentPublishPermissionsDialog()
{
if (!VRC.Core.ConfigManager.RemoteConfig.IsInitialized())
{
VRC.Core.ConfigManager.RemoteConfig.Init(() => ShowContentPublishPermissionsDialog());
return;
}
string message = VRC.Core.ConfigManager.RemoteConfig.GetString("sdkNotAllowedToPublishMessage");
int result = UnityEditor.EditorUtility.DisplayDialogComplex("VRChat SDK", message, "Developer FAQ", "VRChat Discord", "OK");
if (result == 0)
{
ShowDeveloperFAQ();
}
if (result == 1)
{
ShowVRChatDiscord();
}
}
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 4c73e735ee0380241b186a8993fa56bf
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,19 @@
using System;
using System.Collections;
using System.Collections.Generic;
using JetBrains.Annotations;
using UnityEngine;
namespace VRC.SDKBase.Editor
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
[MeansImplicitUse]
public class VRCSdkControlPanelBuilderAttribute : Attribute
{
public Type Type { get; }
public VRCSdkControlPanelBuilderAttribute(Type type)
{
Type = type;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c768b42ca9a2f2b48afeb1fa03d5e1bf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,682 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using UnityEngine;
using UnityEditor;
using UnityEngine.Networking;
using VRC.Core;
public partial class VRCSdkControlPanel : EditorWindow
{
const int PageLimit = 20;
static List<ApiAvatar> uploadedAvatars = null;
static List<ApiWorld> uploadedWorlds = null;
static List<ApiAvatar> testAvatars = 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;
private static bool TestAvatarsToggle = 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;
if (testAvatars != null)
testAvatars = null;
ImageCache.Clear();
}
IEnumerator FetchUploadedData()
{
if (!ConfigManager.RemoteConfig.IsInitialized())
ConfigManager.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());
FetchTestAvatars();
}
private static void FetchAvatars(int offset = 0)
{
ApiAvatar.FetchList(
delegate (IEnumerable<ApiAvatar> obj)
{
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
);
}
private static void FetchTestAvatars()
{
#if VRC_SDK_VRCSDK3
string sdkAvatarFolder = VRC.SDK3.Editor.VRC_SdkBuilder.GetKnownFolderPath(VRC.SDK3.Editor.VRC_SdkBuilder.LocalLowGUID) + "/VRChat/vrchat/Avatars/";
string[] sdkavatars = Directory.GetFiles(sdkAvatarFolder);
string filename = "";
List<ApiAvatar> avatars = new List<ApiAvatar>();
foreach(string sdkap in sdkavatars)
{
if(Path.GetExtension(sdkap) != ".vrca")
continue;
filename = Path.GetFileNameWithoutExtension(sdkap);
ApiAvatar sdka = API.FromCacheOrNew<ApiAvatar>("local:sdk_" + filename);
sdka.assetUrl = sdkap;
sdka.name = filename;
sdka.releaseStatus = "public";
ApiAvatar.AddLocal(sdka);
avatars.Add(sdka);
}
testAvatars = avatars;
#else
testAvatars = new List<ApiAvatar>();
#endif
}
private static void FetchWorlds(int offset = 0)
{
ApiWorld.FetchList(
delegate (IEnumerable<ApiWorld> obj)
{
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 || uploadedAvatars.Any(a2 => a2.id == a.id));
foreach(var avatar in avatars)
{
if (string.IsNullOrEmpty(avatar.name))
avatar.name = "(unnamed)";
}
if (avatars.Count > 0)
{
uploadedAvatars.AddRange(avatars);
uploadedAvatars.Sort((w1, w2) => w1.name.CompareTo(w2.name));
}
}
static void DownloadImage(string id, string url)
{
if (string.IsNullOrEmpty(url))
return;
if (ImageCache.ContainsKey(id) && ImageCache[id] != null)
return;
System.Action<Texture2D> onDone = (texture) =>
{
if (texture != null)
{
ImageCache[id] = texture;
}
else if (ImageCache.ContainsKey(id))
ImageCache.Remove(id);
};
EditorCoroutine.Start(VRCCachedWWW.Get(url, (onDone)));
}
Vector2 contentScrollPos;
bool OnGUIUserInfo()
{
bool updatedContent = false;
if (!ConfigManager.RemoteConfig.IsInitialized())
ConfigManager.RemoteConfig.Init();
if (APIUser.IsLoggedInWithCredentials && uploadedWorlds != null && uploadedAvatars != null && testAvatars != null)
{
bool expandedLayout = false; // (position.width > MAX_ALL_INFORMATION_WIDTH); // uncomment for future wide layouts
if (!expandedLayout)
{
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
}
GUILayout.BeginHorizontal();
GUILayout.BeginVertical(searchBarStyle);
EditorGUILayout.BeginHorizontal();
float searchFieldShrinkOffset = 30f;
GUILayoutOption layoutOption = (expandedLayout ? GUILayout.Width(position.width - searchFieldShrinkOffset) : GUILayout.Width(SdkWindowWidth - searchFieldShrinkOffset));
searchString = EditorGUILayout.TextField(searchString, GUI.skin.FindStyle("SearchTextField"), layoutOption);
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();
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
if (!expandedLayout)
{
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
}
layoutOption = (expandedLayout ? GUILayout.Width(position.width) : GUILayout.Width(SdkWindowWidth));
contentScrollPos = EditorGUILayout.BeginScrollView(contentScrollPos, layoutOption);
GUIStyle descriptionStyle = new GUIStyle(EditorStyles.wordWrappedLabel);
descriptionStyle.wordWrap = true;
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();
}
}
}
if (testAvatars.Count > 0)
{
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Test Avatars", EditorStyles.boldLabel, GUILayout.ExpandWidth(false), GUILayout.Width(100));
TestAvatarsToggle = EditorGUILayout.Foldout(TestAvatarsToggle, new GUIContent(""));
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
if (TestAvatarsToggle)
{
List<ApiAvatar> tmpAvatars = new List<ApiAvatar>();
if (testAvatars.Count > 0)
tmpAvatars = new List<ApiAvatar>(testAvatars);
foreach (ApiAvatar a in tmpAvatars)
{
if (!a.name.ToLowerInvariant().Contains(searchString.ToLowerInvariant()))
{
continue;
}
EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
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));
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"))
{
API.Delete<ApiAvatar>(a.id);
testAvatars.RemoveAll(avatar => avatar.id == a.id);
File.Delete(a.assetUrl);
updatedContent = true;
}
}
if (expandedLayout)
EditorGUILayout.EndHorizontal();
else
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
}
}
}
EditorGUILayout.EndScrollView();
if (!expandedLayout)
{
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}
if ((updatedContent) && (null != window)) window.Reset();
return true;
}
else
{
return false;
}
}
void ShowContent()
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
GUILayout.BeginVertical();
if (uploadedWorlds == null || uploadedAvatars == null || testAvatars == null)
{
if (uploadedWorlds == null)
uploadedWorlds = new List<ApiWorld>();
if (uploadedAvatars == null)
uploadedAvatars = new List<ApiAvatar>();
if (testAvatars == null)
testAvatars = 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();
}
GUILayout.EndVertical();
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
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 VRC.SDKBase;
public partial class VRCSdkControlPanel : EditorWindow
{
[MenuItem("VRChat SDK/Help/Developer FAQ")]
public static void ShowDeveloperFAQ()
{
if (!ConfigManager.RemoteConfig.IsInitialized())
{
ConfigManager.RemoteConfig.Init(() => ShowDeveloperFAQ());
return;
}
Application.OpenURL(ConfigManager.RemoteConfig.GetString("sdkDeveloperFaqUrl"));
}
[MenuItem("VRChat SDK/Help/VRChat Discord")]
public static void ShowVRChatDiscord()
{
if (!ConfigManager.RemoteConfig.IsInitialized())
{
ConfigManager.RemoteConfig.Init(() => ShowVRChatDiscord());
return;
}
Application.OpenURL(ConfigManager.RemoteConfig.GetString("sdkDiscordUrl"));
}
[MenuItem("VRChat SDK/Help/Avatar Optimization Tips")]
public static void ShowAvatarOptimizationTips()
{
if (!ConfigManager.RemoteConfig.IsInitialized())
{
ConfigManager.RemoteConfig.Init(() => ShowAvatarOptimizationTips());
return;
}
Application.OpenURL(AVATAR_OPTIMIZATION_TIPS_URL);
}
[MenuItem("VRChat SDK/Help/Avatar Rig Requirements")]
public static void ShowAvatarRigRequirements()
{
if (!ConfigManager.RemoteConfig.IsInitialized())
{
ConfigManager.RemoteConfig.Init(() => ShowAvatarRigRequirements());
return;
}
Application.OpenURL(AVATAR_RIG_REQUIREMENTS_URL);
}
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f3507a74e4b8cfd469afac127fa5f4e5
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,265 @@
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()
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
GUILayout.BeginVertical();
settingsScroll = EditorGUILayout.BeginScrollView(settingsScroll, GUILayout.Width(SdkWindowWidth));
EditorGUILayout.BeginVertical(boxGuiStyle);
EditorGUILayout.LabelField("Developer", EditorStyles.boldLabel);
#if VRC_SDK_VRCSDK2
VRCSettings.Get().DisplayAdvancedSettings = EditorGUILayout.ToggleLeft("Show Extra Options on build page and account page", VRCSettings.Get().DisplayAdvancedSettings);
bool prevDisplayHelpBoxes = VRCSettings.Get().DisplayHelpBoxes;
VRCSettings.Get().DisplayHelpBoxes = EditorGUILayout.ToggleLeft("Show Help Boxes on SDK components", VRCSettings.Get().DisplayHelpBoxes);
if (VRCSettings.Get().DisplayHelpBoxes != prevDisplayHelpBoxes)
#elif VRC_SDK_VRCSDK3
VRC.SDK3.Editor.VRCSettings.Get().DisplayAdvancedSettings = EditorGUILayout.ToggleLeft("Show Extra Options on build page and account page", VRC.SDK3.Editor.VRCSettings.Get().DisplayAdvancedSettings);
bool prevDisplayHelpBoxes = VRC.SDK3.Editor.VRCSettings.Get().DisplayHelpBoxes;
VRC.SDK3.Editor.VRCSettings.Get().DisplayHelpBoxes = EditorGUILayout.ToggleLeft("Show Help Boxes on SDK components", VRC.SDK3.Editor.VRCSettings.Get().DisplayHelpBoxes);
if (VRC.SDK3.Editor.VRCSettings.Get().DisplayHelpBoxes != prevDisplayHelpBoxes)
#endif
{
Editor[] editors = (Editor[])Resources.FindObjectsOfTypeAll<Editor>();
for (int i = 0; i < editors.Length; i++)
{
editors[i].Repaint();
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.Separator();
ShowSdk23CompatibilitySettings();
EditorGUILayout.Separator();
ShowSettingsOptionsForBuilders();
// 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();
GUILayout.EndVertical();
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}
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();
}
static void ShowSdk23CompatibilitySettings()
{
return;
// EditorGUILayout.BeginVertical(boxGuiStyle);
// EditorGUILayout.LabelField("VRCSDK2 & VRCSDK3 Compatibility", EditorStyles.boldLabel);
//#if !VRC_CLIENT
// bool sdk2Present = VRCSdk3Analysis.GetSDKInScene(VRCSdk3Analysis.SdkVersion.VRCSDK2).Count > 0;
// bool sdk3Present = VRCSdk3Analysis.GetSDKInScene(VRCSdk3Analysis.SdkVersion.VRCSDK3).Count > 0;
// bool sdk2DllActive = VRCSdk3Analysis.IsSdkDllActive(VRCSdk3Analysis.SdkVersion.VRCSDK2);
// bool sdk3DllActive = VRCSdk3Analysis.IsSdkDllActive(VRCSdk3Analysis.SdkVersion.VRCSDK3);
// if ( sdk2DllActive && sdk3DllActive)
// {
// GUILayout.TextArea("You have not yet configured this project for development with VRCSDK2 and Triggers or VRCSDK3 and Udon. ");
// if (sdk2Present && sdk3Present)
// {
// GUILayout.TextArea("This scene contains both SDK2 and SDK3 elements. " +
// "Please modify this scene to contain only one type or the other before completing your configuration.");
// }
// else if (sdk2Present)
// {
// GUILayout.TextArea("This scene contains SDK2 scripts. " +
// "Check below to configure this project for use with VRCSDK2 or remove your VRCSDK2 scripts to upgrade to VRCSDK3");
// bool downgrade = EditorGUILayout.ToggleLeft("Configure for use with VRCSDK2 and Triggers", false);
// if (downgrade)
// VRCSdk3Analysis.SetSdkVersionActive(VRCSdk3Analysis.SdkVersion.VRCSDK2);
// }
// else if (sdk3Present)
// {
// GUILayout.TextArea("This scene contains only SDK3 scripts and it ready to upgrade. " +
// "Click below to get started.");
// bool upgrade = EditorGUILayout.ToggleLeft("Configure for use with VRCSDK3 and Udon - Let's Rock!", false);
// if (upgrade)
// VRCSdk3Analysis.SetSdkVersionActive(VRCSdk3Analysis.SdkVersion.VRCSDK3);
// }
// else
// {
// GUILayout.TextArea("This scene is a blank slate. " +
// "Click below to get started.");
// bool upgrade = EditorGUILayout.ToggleLeft("Configure for use with VRCSDK3 and Udon - Let's Rock!", false);
// if (upgrade)
// VRCSdk3Analysis.SetSdkVersionActive(VRCSdk3Analysis.SdkVersion.VRCSDK3);
// }
// }
// else if (sdk2DllActive)
// {
// GUILayout.TextArea("This project has been configured to be built with VRCSDK2. " +
// "To upgrade, VRCSDK3 must be enabled here.");
// bool upgrade = EditorGUILayout.ToggleLeft("VRCSDK3 Scripts can be used", false);
// if (upgrade)
// VRCSdk3Analysis.SetSdkVersionActive(VRCSdk3Analysis.SdkVersion.VRCSDK3);
// }
// else if (sdk3DllActive)
// {
// GUILayout.TextArea("This project has been configured to be built with VRCSDK3. " +
// "Congratulations, you're ready to go. " +
// "You can still downgrade by activating VRCSDK2 here.");
// bool downgrade = EditorGUILayout.ToggleLeft("VRCSDK2 Scripts can be used", false);
// if (downgrade)
// VRCSdk3Analysis.SetSdkVersionActive(VRCSdk3Analysis.SdkVersion.VRCSDK2);
// }
// else
// {
// GUILayout.TextArea("Somehow you have disabled both VRCSDK2 and VRCSDK3. Oops. " +
// "Click here to begin development with VRCSDK3.");
// bool begin = EditorGUILayout.ToggleLeft("VRCSDK3 Scripts can be used", false);
// if (begin)
// VRCSdk3Analysis.SetSdkVersionActive(VRCSdk3Analysis.SdkVersion.VRCSDK3);
// }
//#else
// GUILayout.TextArea("I think you're in the main VRChat project. " +
// "You should not be enabling or disabling SDKs from here.");
//#endif
// EditorGUILayout.EndVertical();
}
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8357b9b7ef2416946ae86f465a64c0e0
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f2a720a30f1043247af7742fdfd0b8e5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,773 @@
#define ENV_SET_INCLUDED_SHADERS
using UnityEngine;
using UnityEditor;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
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.StandaloneLinux64,
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.StandaloneLinux64, null },
{ BuildTarget.StandaloneWindows, new UnityEngine.Rendering.GraphicsDeviceType[] { UnityEngine.Rendering.GraphicsDeviceType.Direct3D11 } },
{ BuildTarget.StandaloneWindows64, new UnityEngine.Rendering.GraphicsDeviceType[] { UnityEngine.Rendering.GraphicsDeviceType.Direct3D11 } },
{ BuildTarget.StandaloneOSX, null }
};
#if ENV_SET_INCLUDED_SHADERS && VRC_CLIENT
static string[] ensureTheseShadersAreAvailable = new string[]
{
"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",
"Video/RealtimeEmissiveGamma",
"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()
{
CheckForFirstInit();
if (EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isUpdating)
return false;
ConfigurePlayerSettings();
if (!VRC.Core.ConfigManager.RemoteConfig.IsInitialized())
{
VRC.Core.API.SetOnlineMode(true, "vrchat");
VRC.Core.ConfigManager.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.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.StandaloneLinux64, false);
importer.SetCompatibleWithPlatform(BuildTarget.StandaloneOSX, false);
}
importer.SaveAndReimport();
}
}
}
[MenuItem("VRChat SDK/Utilities/Force Configure Player Settings")]
public static void ConfigurePlayerSettings()
{
VRC.Core.Logger.Log("Setting required PlayerSettings...", VRC.Core.DebugLevel.All);
SetBuildTarget();
// Needed for Microsoft.CSharp namespace in DLLMaker
// Doesn't seem to work though
if (PlayerSettings.GetApiCompatibilityLevel(EditorUserBuildSettings.selectedBuildTargetGroup) != ApiCompatibilityLevel.NET_4_6)
PlayerSettings.SetApiCompatibilityLevel(EditorUserBuildSettings.selectedBuildTargetGroup, ApiCompatibilityLevel.NET_4_6);
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
PlatformSwitcher.RefreshRequiredPackages(EditorUserBuildSettings.selectedBuildTargetGroup);
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
#if VRC_CLIENT
// VRCLog should handle disk writing
PlayerSettings.usePlayerLog = false;
foreach (LogType logType in Enum.GetValues(typeof(LogType)).Cast<LogType>())
{
switch(logType)
{
case LogType.Assert:
case LogType.Exception:
{
PlayerSettings.SetStackTraceLogType(logType, StackTraceLogType.ScriptOnly);
break;
}
case LogType.Error:
case LogType.Warning:
case LogType.Log:
{
PlayerSettings.SetStackTraceLogType(logType, StackTraceLogType.None);
break;
}
default:
{
throw new ArgumentOutOfRangeException();
}
}
}
#endif
}
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)
{
VRC.Core.Logger.Log("Setting virtual reality SDKs in PlayerSettings: ", VRC.Core.DebugLevel.All);
if (sdkNames != null)
{
foreach (string s in sdkNames)
VRC.Core.Logger.Log("- " + s, VRC.Core.DebugLevel.All);
}
PlayerSettings.SetVirtualRealitySDKs(buildTargetGroup, sdkNames);
}
public static bool CheckForFirstInit()
{
bool firstLaunch = UnityEditor.SessionState.GetBool("EnvConfigFirstLaunch", true);
if (firstLaunch)
UnityEditor.SessionState.SetBool("EnvConfigFirstLaunch", false);
return firstLaunch;
}
static void SetDefaultGraphicsAPIs()
{
VRC.Core.Logger.Log("Setting Graphics APIs", VRC.Core.DebugLevel.All);
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))
{
if (allowedTypes == null)
{
allowedTypes = PlayerSettings.GetGraphicsAPIs(platform);
}
PlayerSettings.SetGraphicsAPIs(platform, allowedTypes);
}
}
catch { }
}
static void SetGraphicsSettings()
{
VRC.Core.Logger.Log("Setting Graphics Settings", VRC.Core.DebugLevel.All);
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
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();
}
public static FogSettings GetFogSettings()
{
VRC.Core.Logger.Log("Force-enabling Fog", VRC.Core.DebugLevel.All);
const string graphicsSettingsAssetPath = "ProjectSettings/GraphicsSettings.asset";
SerializedObject graphicsManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath(graphicsSettingsAssetPath)[0]);
SerializedProperty fogStrippingSerializedProperty = graphicsManager.FindProperty("m_FogStripping");
FogSettings.FogStrippingMode fogStripping = (FogSettings.FogStrippingMode)fogStrippingSerializedProperty.enumValueIndex;
SerializedProperty fogKeepLinearSerializedProperty = graphicsManager.FindProperty("m_FogKeepLinear");
bool keepLinear = fogKeepLinearSerializedProperty.boolValue;
SerializedProperty fogKeepExpSerializedProperty = graphicsManager.FindProperty("m_FogKeepExp");
bool keepExp = fogKeepExpSerializedProperty.boolValue;
SerializedProperty fogKeepExp2SerializedProperty = graphicsManager.FindProperty("m_FogKeepExp2");
bool keepExp2 = fogKeepExp2SerializedProperty.boolValue;
FogSettings fogSettings = new FogSettings(fogStripping, keepLinear, keepExp, keepExp2);
return fogSettings;
}
public static void SetFogSettings(FogSettings fogSettings)
{
VRC.Core.Logger.Log("Force-enabling Fog", VRC.Core.DebugLevel.All);
const string graphicsSettingsAssetPath = "ProjectSettings/GraphicsSettings.asset";
SerializedObject graphicsManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath(graphicsSettingsAssetPath)[0]);
SerializedProperty fogStripping = graphicsManager.FindProperty("m_FogStripping");
fogStripping.enumValueIndex = (int)fogSettings.fogStrippingMode;
SerializedProperty fogKeepLinear = graphicsManager.FindProperty("m_FogKeepLinear");
fogKeepLinear.boolValue = fogSettings.keepLinear;
SerializedProperty fogKeepExp = graphicsManager.FindProperty("m_FogKeepExp");
fogKeepExp.boolValue = fogSettings.keepExp;
SerializedProperty fogKeepExp2 = graphicsManager.FindProperty("m_FogKeepExp2");
fogKeepExp2.boolValue = fogSettings.keepExp2;
graphicsManager.ApplyModifiedProperties();
}
static void SetAudioSettings()
{
var config = AudioSettings.GetConfiguration();
config.dspBufferSize = 0; // use default
config.speakerMode = AudioSpeakerMode.Stereo; // use default
config.sampleRate = 48000; // forcing 48k seems to avoid sample rate conversion problems
if (EditorUserBuildSettings.selectedBuildTargetGroup == BuildTargetGroup.Android)
{
config.numRealVoices = 24;
config.numVirtualVoices = 32;
}
else
{
config.numRealVoices = 32;
config.numVirtualVoices = 64;
}
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.SetVirtualRealitySupported(EditorUserBuildSettings.selectedBuildTargetGroup, true);
#endif
PlayerSettings.graphicsJobs = false; // else we get occasional crashing
PlayerSettings.gpuSkinning = true;
PlayerSettings.stereoRenderingPath = StereoRenderingPath.SinglePass;
#if UNITY_2018_4_OR_NEWER
PlayerSettings.scriptingRuntimeVersion = ScriptingRuntimeVersion.Latest;
#endif
#if VRC_VR_OCULUS_QUEST
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
#elif VRC_VR_FOCUS
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARMv7;
#endif
#if UNITY_ANDROID
if(PlayerSettings.Android.targetArchitectures.HasFlag(AndroidArchitecture.ARM64))
{
// Since we need different IL2CPP args we can't build ARM64 with other Architectures.
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
PlayerSettings.SetAdditionalIl2CppArgs("");
}
else
{
PlayerSettings.SetAdditionalIl2CppArgs("--linker-flags=\"-long-plt\"");
}
#else
PlayerSettings.SetAdditionalIl2CppArgs("");
#endif
SetActiveSDKDefines();
EnableBatching(true);
}
public static void SetActiveSDKDefines()
{
bool definesChanged = false;
BuildTargetGroup buildTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
List<string> defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup).Split(';').ToList();
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
if (assemblies.Any(assembly => assembly.GetType("VRC.Udon.UdonBehaviour") != null))
{
if (!defines.Contains("UDON", StringComparer.OrdinalIgnoreCase))
{
defines.Add("UDON");
definesChanged = true;
}
}
else if (defines.Contains("UDON"))
defines.Remove("UDON");
if (VRCSdk3Analysis.IsSdkDllActive(VRCSdk3Analysis.SdkVersion.VRCSDK2))
{
if (!defines.Contains("VRC_SDK_VRCSDK2", StringComparer.OrdinalIgnoreCase))
{
defines.Add("VRC_SDK_VRCSDK2");
definesChanged = true;
}
}
else if (defines.Contains("VRC_SDK_VRCSDK2"))
defines.Remove("VRC_SDK_VRCSDK2");
if (VRCSdk3Analysis.IsSdkDllActive(VRCSdk3Analysis.SdkVersion.VRCSDK3))
{
if (!defines.Contains("VRC_SDK_VRCSDK3", StringComparer.OrdinalIgnoreCase))
{
defines.Add("VRC_SDK_VRCSDK3");
definesChanged = true;
}
}
else if (defines.Contains("VRC_SDK_VRCSDK3"))
defines.Remove("VRC_SDK_VRCSDK3");
if (definesChanged)
PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, string.Join(";", defines.ToArray()));
}
static void SetBuildTarget()
{
#if !VRC_CLIENT
VRC.Core.Logger.Log("Setting build target", VRC.Core.DebugLevel.All);
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();
}
public struct FogSettings
{
public enum FogStrippingMode
{
Automatic,
Custom
}
public readonly FogStrippingMode fogStrippingMode;
public readonly bool keepLinear;
public readonly bool keepExp;
public readonly bool keepExp2;
public FogSettings(FogStrippingMode fogStrippingMode)
{
this.fogStrippingMode = fogStrippingMode;
keepLinear = true;
keepExp = true;
keepExp2 = true;
}
public FogSettings(FogStrippingMode fogStrippingMode, bool keepLinear, bool keepExp, bool keepExp2)
{
this.fogStrippingMode = fogStrippingMode;
this.keepLinear = keepLinear;
this.keepExp = keepExp;
this.keepExp2 = keepExp2;
}
}
}
@@ -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,73 @@
using UnityEditor;
using UnityEngine;
public static class HDRColorFixerUtility
{
[MenuItem("VRChat SDK/Utilities/Convert HDR Material Colors/To Linear", false, 995)]
private static void ConvertToLinear()
{
if (!TryConvert())
EditorUtility.DisplayDialog("Error", "Please select one or more HDR materials to convert.", "OK");
}
[MenuItem("VRChat SDK/Utilities/Convert HDR Material Colors/To Gamma", false, 996)]
private static void ConvertToGamma()
{
if (!TryConvert(false))
EditorUtility.DisplayDialog("Error", "Please select one or more HDR materials to convert.", "OK");
}
static bool TryConvert(bool toLinear = true)
{
Object[] selection = Selection.objects;
if (selection == null)
return false;
int matCount = 0;
int colorCount = 0;
foreach (Material mat in selection)
{
matCount++;
MaterialProperty[] props = MaterialEditor.GetMaterialProperties(new Material[] { mat });
if ((props == null) || (props.Length == 0))
return false;
foreach (MaterialProperty m in props)
{
if (m.flags == MaterialProperty.PropFlags.HDR)
{
//Color prev = m.colorValue;
m.colorValue = (toLinear ? m.colorValue.linear : m.colorValue.gamma);
colorCount++;
//Debug.Log("prev: " + prev + ", current: " + m.colorValue);
}
}
}
if (colorCount == 0)
EditorUtility.DisplayDialog("Result", "Found no HDR Color properties in the selected material" + (matCount > 1 ? "s." : "."), "OK");
else
EditorUtility.DisplayDialog("Result", "Converted " + colorCount + " HDR Color propert"+ (colorCount > 1 ? "ies" : "y") + " in "+matCount+" material"+(matCount > 1 ? "s":"") + " to " + (toLinear ? "Linear" : "Gamma") + " color space.", "OK");
return true;
}
[MenuItem("VRChat SDK/Utilities/Convert HDR Material Colors/To Linear", true, 995)]
[MenuItem("VRChat SDK/Utilities/Convert HDR Material Colors/To Gamma", true, 996)]
private static bool CheckSelection()
{
if (Selection.objects.Length == 0)
return false;
bool allMaterials = true;
foreach (Object obj in Selection.objects)
{
if (obj.GetType() != typeof(Material))
{
allMaterials = false;
break;
}
}
return allMaterials;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c3399613f583f3e46b2df27ae87dd5d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 57304ced9b2de5f48a30b7b662d18c19
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,120 @@
using System.Reflection;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;
using UnityEditor;
public class VRCSdk3Analysis
{
static Assembly GetAssemblyByName(string name)
{
return AppDomain.CurrentDomain.GetAssemblies().
SingleOrDefault(assembly => assembly.GetName().Name == name);
}
static List<Component> GetSceneComponentsFromAssembly( Assembly assembly )
{
if (assembly == null)
return new List<Component>();
Type[] types = assembly.GetTypes();
List<Component> present = new List<Component>();
foreach (var type in types )
{
if (!type.IsSubclassOf(typeof(MonoBehaviour)))
continue;
var monos = VRC.Tools.FindSceneObjectsOfTypeAll(type);
present.AddRange(monos);
}
return present;
}
public enum SdkVersion
{
VRCSDK2,
VRCSDK3
};
public static List<Component> GetSDKInScene(SdkVersion version)
{
var assembly = GetAssemblyByName( version.ToString() );
return GetSceneComponentsFromAssembly(assembly);
}
public static bool IsSdkDllActive(SdkVersion version)
{
string assembly = version.ToString();
PluginImporter importer = AssetImporter.GetAtPath("Assets/VRCSDK/Plugins/" + assembly + ".dll") as PluginImporter;
if (importer == false)
{
//Handle Avatar Dll Split
importer = AssetImporter.GetAtPath("Assets/VRCSDK/Plugins/" + assembly + "A.dll") as PluginImporter;
if (importer == false)
return false;
}
return importer.GetCompatibleWithAnyPlatform();
}
//public static void SetSdkVersionActive(SdkVersion version)
//{
// AssetDatabase.StartAssetEditing();
// PluginImporter importer = AssetImporter.GetAtPath("Assets/VRCSDK/Plugins/" + version + ".dll") as PluginImporter;
// if (importer == null)
// return;
// SetSDKDefine(version);
// var other = SdkVersion.VRCSDK2;
// if (version == SdkVersion.VRCSDK2)
// other = SdkVersion.VRCSDK3;
// SetSDKAssembly(other, false);
// SetSDKAssembly(version, true);
// AssetDatabase.StopAssetEditing();
//}
//static void SetSDKAssembly( SdkVersion version, bool active )
//{
// string assembly = version.ToString();
// PluginImporter importer = AssetImporter.GetAtPath("Assets/VRCSDK/Plugins/" + assembly + ".dll") as PluginImporter;
// if (importer)
// {
// importer.SetCompatibleWithAnyPlatform(active);
// importer.SetCompatibleWithEditor(active);
// importer.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows, active);
// importer.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows64, active);
// importer.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux64, active);
// importer.SetCompatibleWithPlatform(BuildTarget.StandaloneOSX, active);
// importer.SetCompatibleWithPlatform(BuildTarget.Android, active);
// importer.SaveAndReimport();
// }
//}
//static void SetSDKDefine( SdkVersion version )
//{
// string defineString = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone);
// var defs = defineString.Split(';');
// string finalDefs = null;
// foreach( var s in defs )
// {
// if (s != "VRC_SDK_VRCSDK2" && s != "VRC_SDK_VRCSDK3")
// {
// if (finalDefs == null)
// finalDefs = s;
// else
// finalDefs += ";" + s;
// }
// }
// if (version == SdkVersion.VRCSDK2)
// finalDefs += ";VRC_SDK_VRCSDK2";
// else if (version == SdkVersion.VRCSDK3)
// finalDefs += ";VRC_SDK_VRCSDK3";
// PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone, finalDefs);
//}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 93710d221addc0243ba90dd20369844b
MonoImporter:
externalObjects: {}
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.ConfigManager.RemoteConfig.Init(delegate() {
string currentSdkVersion = GetCurrentVersion();
string sdkVersion = VRC.Core.ConfigManager.RemoteConfig.GetString("devSdkVersion");
string sdkUrl = VRC.Core.ConfigManager.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,383 @@
// Original ShaderKeywordsUtility by ScruffyRules#0879
// Thank you to Xiexe and all that tested!
// Licensed under the MIT License (see https://vrchat.com/legal/attribution)
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
public class ShaderKeywordsUtility : EditorWindow
{
private static Dictionary<VRC.SDKBase.VRC_AvatarDescriptor, Dictionary<Material, bool>> avatars = new Dictionary<VRC.SDKBase.VRC_AvatarDescriptor, Dictionary<Material, bool>>();
private Dictionary<VRC.SDKBase.VRC_AvatarDescriptor, bool> avatarsOpened = new Dictionary<VRC.SDKBase.VRC_AvatarDescriptor, bool>();
private Vector2 scrollPos;
private static GUIStyle titleGuiStyle;
public static HashSet<string> keywordBlacklist = new HashSet<string>(new string[]
{
// Unity Keywords, these don't matter at all. (They should be loaded)
// All Keywords that are in Standard Unity Shaders
"_ALPHABLEND_ON",
"_ALPHAMODULATE_ON",
"_ALPHAPREMULTIPLY_ON",
"_ALPHATEST_ON",
"_COLORADDSUBDIFF_ON",
"_COLORCOLOR_ON",
"_COLOROVERLAY_ON",
"_DETAIL_MULX2",
"_EMISSION",
"_FADING_ON",
"_GLOSSYREFLECTIONS_OFF",
"_GLOSSYREFLECTIONS_OFF",
"_MAPPING_6_FRAMES_LAYOUT",
"_METALLICGLOSSMAP",
"_NORMALMAP",
"_PARALLAXMAP",
"_REQUIRE_UV2",
"_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A",
"_SPECGLOSSMAP",
"_SPECULARHIGHLIGHTS_OFF",
"_SPECULARHIGHLIGHTS_OFF",
"_SUNDISK_HIGH_QUALITY",
"_SUNDISK_NONE",
"_SUNDISK_SIMPLE",
"_TERRAIN_NORMAL_MAP",
"BILLBOARD_FACE_CAMERA_POS",
"EFFECT_BUMP",
"EFFECT_HUE_VARIATION",
"ETC1_EXTERNAL_ALPHA",
"GEOM_TYPE_BRANCH",
"GEOM_TYPE_BRANCH_DETAIL",
"GEOM_TYPE_FROND",
"GEOM_TYPE_LEAF",
"GEOM_TYPE_MESH",
"LOD_FADE_CROSSFADE",
"PIXELSNAP_ON",
"SOFTPARTICLES_ON",
"STEREO_INSTANCING_ON",
"STEREO_MULTIVIEW_ON",
"UNITY_HDR_ON",
"UNITY_SINGLE_PASS_STEREO",
"UNITY_UI_ALPHACLIP",
"UNITY_UI_CLIP_RECT",
// Post Processing Stack V1 and V2
// This is mostly just safe keeping somewhere
"FOG_OFF",
"FOG_LINEAR",
"FOG_EXP",
"FOG_EXP2",
"ANTI_FLICKER",
"UNITY_COLORSPACE_GAMMA",
"SOURCE_GBUFFER",
"AUTO_KEY_VALUE",
"GRAIN",
"DITHERING",
"TONEMAPPING_NEUTRAL",
"TONEMAPPING_FILMIC",
"CHROMATIC_ABERRATION",
"DEPTH_OF_FIELD",
"DEPTH_OF_FIELD_COC_VIEW",
"BLOOM",
"BLOOM_LENS_DIRT",
"COLOR_GRADING",
"COLOR_GRADING_LOG_VIEW",
"USER_LUT",
"VIGNETTE_CLASSIC",
"VIGNETTE_MASKED",
"FXAA",
"FXAA_LOW",
"FXAA_KEEP_ALPHA",
"STEREO_INSTANCING_ENABLED",
"STEREO_DOUBLEWIDE_TARGET",
"TONEMAPPING_ACES",
"TONEMAPPING_CUSTOM",
"APPLY_FORWARD_FOG",
"DISTORT",
"CHROMATIC_ABERRATION_LOW",
"BLOOM_LOW",
"VIGNETTE",
"FINALPASS",
"COLOR_GRADING_HDR_3D",
"COLOR_GRADING_HDR",
"AUTO_EXPOSURE"
});
const string keywordDescription = "Unity has a global limit of 256 keywords. A lot (~60) are used internally by Unity.\n\nAny new keyword you encounter goes onto a global list, and will stay until you restart the client.\n\nKeywords are used to create compile time branches and remove code, to optimize a shader, however, because of the 256 keyword limit, using them in VRChat can cause other shaders which use keywords to break, as once you hit the limit, any new keyword will get ignored.\n\nIt's best in the confines of VRChat to stay away from using custom keywords if possible, as not to cause issues with (your) shaders breaking.\n\nFor the full list of internal keywords, see 'ShaderKeywordsUtility.cs'";
private static bool avatarsDirty = true;
private int loadedScenes = 0;
[MenuItem("VRChat SDK/Utilities/Avatar Shader Keywords Utility", false, 990)]
static void Init()
{
ShaderKeywordsUtility window = EditorWindow.GetWindow<ShaderKeywordsUtility>();
window.titleContent = new GUIContent("Shader Keywords Utility");
window.minSize = new Vector2(325, 410);
window.Show();
titleGuiStyle = new GUIStyle
{
fontSize = 15,
fontStyle = FontStyle.BoldAndItalic,
alignment = TextAnchor.MiddleCenter,
wordWrap = true
};
if (EditorGUIUtility.isProSkin)
titleGuiStyle.normal.textColor = Color.white;
else
titleGuiStyle.normal.textColor = Color.black;
}
public static List<VRC.SDKBase.VRC_AvatarDescriptor> getADescs()
{
List<GameObject> GOs = new List<GameObject>();
for (int i = 0; i < UnityEditor.SceneManagement.EditorSceneManager.sceneCount; i++)
{
Scene scene = UnityEditor.SceneManagement.EditorSceneManager.GetSceneAt(i);
if (scene.isLoaded)
{
GameObject[] GOs2 = scene.GetRootGameObjects();
foreach (GameObject go in GOs2)
{
GOs.Add(go);
}
}
}
List<VRC.SDKBase.VRC_AvatarDescriptor> descriptors = new List<VRC.SDKBase.VRC_AvatarDescriptor>();
foreach (GameObject go in GOs)
{
var vrcdescs = go.GetComponentsInChildren<VRC.SDKBase.VRC_AvatarDescriptor>(true);
foreach (VRC.SDKBase.VRC_AvatarDescriptor vrcdesc in vrcdescs)
{
descriptors.Add(vrcdesc);
}
}
return descriptors;
}
public static bool DetectCustomShaderKeywords(VRC.SDKBase.VRC_AvatarDescriptor ad)
{
foreach (Renderer renderer in ad.transform.GetComponentsInChildren<Renderer>(true))
{
foreach (Material mat in renderer.sharedMaterials)
{
if (mat != null)
{
foreach (string keyword in mat.shaderKeywords)
{
if (!keywordBlacklist.Contains(keyword))
return true;
}
}
}
}
return false;
}
void OnGUI()
{
GUILayout.Space(10);
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
GUILayout.Label("Shader Keywords Utility", titleGuiStyle);
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.Space(15);
bool showHelp = EditorPrefs.GetBool("VRCSDK_ShowShaderKeywordsHelp", true);
if (showHelp)
{
GUILayout.Label(keywordDescription, EditorStyles.helpBox, GUILayout.ExpandWidth(true));
GUILayout.Space(15);
}
int _loadedScenes = 0;
for (int i = 0; i < UnityEditor.SceneManagement.EditorSceneManager.sceneCount; i++)
{
Scene scene = UnityEditor.SceneManagement.EditorSceneManager.GetSceneAt(i);
if (scene.isLoaded)
_loadedScenes += 1;
}
if (_loadedScenes != loadedScenes)
{
// Debug.Log("Loaded Scenes changed");
loadedScenes = _loadedScenes;
avatarsDirty = true;
}
GUILayout.BeginHorizontal();
if (GUILayout.Button("Refresh Avatars", GUILayout.ExpandWidth(false)))
avatarsDirty = true;
GUILayout.FlexibleSpace();
if (GUILayout.Button((showHelp ? "Hide" : "Show") + " Info about Keywords"))
{
showHelp = !showHelp;
EditorPrefs.SetBool("VRCSDK_ShowShaderKeywordsHelp", showHelp);
}
GUILayout.EndHorizontal();
GUILayout.Space(5);
scrollPos = EditorGUILayout.BeginScrollView(scrollPos, false, false);
ListAvatars();
EditorGUILayout.EndScrollView();
}
void ListAvatars()
{
if (avatarsDirty)
CacheAvatars();
Dictionary<VRC.SDKBase.VRC_AvatarDescriptor, Dictionary<Material, bool>> avatarsE = new Dictionary<VRC.SDKBase.VRC_AvatarDescriptor, Dictionary<Material, bool>>(avatars);
foreach (VRC.SDKBase.VRC_AvatarDescriptor vrcAD in avatarsE.Keys)
{
List<string> keywords = new List<string>();
foreach (Material mat in avatars[vrcAD].Keys)
{
foreach (string keyword in mat.shaderKeywords)
{
if (!keywords.Contains(keyword) && !keywordBlacklist.Contains(keyword))
keywords.Add(keyword);
}
}
if (keywords.Count == 0)
{
avatars.Remove(vrcAD);
avatarsOpened.Remove(vrcAD);
continue;
}
GUILayout.BeginHorizontal();
bool avatarOpened = avatarsOpened[vrcAD];
avatarOpened = EditorGUILayout.ToggleLeft("", avatarOpened, GUILayout.MaxWidth(15f));
avatarsOpened[vrcAD] = avatarOpened;
EditorGUILayout.ObjectField(vrcAD, typeof(VRC.SDKBase.VRC_AvatarDescriptor), true);
GUILayout.EndHorizontal();
if (avatarOpened)
{
GUILayout.BeginHorizontal();
GUILayout.Space(23.0879f);
GUILayout.Label("Total Custom Keywords on Avatar: " + keywords.Count);
GUILayout.EndHorizontal();
Dictionary<Material, bool> materials = new Dictionary<Material, bool>(avatars[vrcAD]);
foreach (KeyValuePair<Material, bool> matKeyVal in materials)
{
Material material = matKeyVal.Key;
bool materialOpened = matKeyVal.Value;
GUILayout.BeginHorizontal();
GUILayout.Space(23.0879f);
materialOpened = EditorGUILayout.ToggleLeft("", materialOpened, GUILayout.MaxWidth(15f));
avatars[vrcAD][material] = materialOpened;
EditorGUILayout.ObjectField(material, typeof(Material), false);
GUILayout.EndHorizontal();
if (materialOpened)
{
GUILayout.BeginHorizontal();
GUILayout.Space(23.0879f * 2f);
if (GUILayout.Button("Delete ALL Keywords on this Material"))
{
if (EditorUtility.DisplayDialog("Delete All Keywords on this Material", "Are you sure you want to delete all Shader Keywords on this material?\nSome shaders might use these!", "Yes", "No"))
{
foreach (string keyword in material.shaderKeywords)
{
if (!keywordBlacklist.Contains(keyword))
material.DisableKeyword(keyword);
}
avatars[vrcAD].Remove(material);
}
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Space(23.0879f * 2f);
GUILayout.Label("Keywords", EditorStyles.boldLabel);
GUILayout.EndHorizontal();
int keywordsCount = 0;
foreach (string keyword in material.shaderKeywords)
{
if (!keywordBlacklist.Contains(keyword))
{
keywordsCount++;
GUILayout.BeginHorizontal();
GUILayout.Space(23.0879f * 2f);
GUILayout.Label(keyword);
if (GUILayout.Button("Delete", GUILayout.ExpandWidth(false)))
material.DisableKeyword(keyword);
GUILayout.EndHorizontal();
}
}
if (keywordsCount == 0)
avatars[vrcAD].Remove(material);
}
}
GUILayout.Space(2f);
}
}
}
void CacheAvatars()
{
//Debug.Log("Caching avatars");
avatars = new Dictionary<VRC.SDKBase.VRC_AvatarDescriptor, Dictionary<Material, bool>>();
List<VRC.SDKBase.VRC_AvatarDescriptor> avatarDescriptors = getADescs();
foreach (VRC.SDKBase.VRC_AvatarDescriptor aD in avatarDescriptors)
{
if (!avatars.ContainsKey(aD))
avatars.Add(aD, new Dictionary<Material, bool>());
if (!avatarsOpened.ContainsKey(aD))
avatarsOpened.Add(aD, false);
foreach (Renderer renderer in aD.transform.GetComponentsInChildren<Renderer>(true))
{
foreach (Material mat in renderer.sharedMaterials)
{
if (mat != null)
{
if (!avatars[aD].ContainsKey(mat))
{
foreach (string keyword in mat.shaderKeywords)
{
if (!keywordBlacklist.Contains(keyword))
{
avatars[aD].Add(mat, false);
break;
}
}
}
}
}
}
if (avatars[aD].Count == 0)
{
avatars.Remove(aD);
avatarsOpened.Remove(aD);
}
}
// prevent leaking
Dictionary<VRC.SDKBase.VRC_AvatarDescriptor, bool> avatarsOpenedE = new Dictionary<VRC.SDKBase.VRC_AvatarDescriptor, bool>();
foreach (VRC.SDKBase.VRC_AvatarDescriptor aO in avatarsOpenedE.Keys)
{
if (!avatarDescriptors.Contains(aO))
avatarsOpened.Remove(aO);
}
avatarsDirty = false;
}
}
#endif
Loaded 100 of 3297 files, more files were not shown because too many files have changed in this diff. Show more