Added Unity project files

This commit is contained in:
2026-06-07 16:58:24 +01:00
parent 3cc05d260b
commit 23bbcab156
3942 changed files with 453676 additions and 0 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c8eaf99d4376fef428e695736944b925
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 73acba29b9a1642488ce2db2127141f3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,53 @@
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using VRCSceneDescriptor = VRC.SDK3.Components.VRCSceneDescriptor;
namespace VRC.SDK3.Editor
{
[InitializeOnLoad]
public static class SpawnGizmoDrawer
{
private static VRCSceneDescriptor sceneDescriptor;
static SpawnGizmoDrawer()
{
SceneView.duringSceneGui += OnSceneGUI;
}
static void OnSceneGUI(SceneView sceneView)
{
if (Selection.activeTransform == null)
return;
if (sceneDescriptor == null)
{
sceneDescriptor = GameObject.FindFirstObjectByType<VRCSceneDescriptor>();
if (sceneDescriptor == null)
return;
}
Transform selected = Selection.activeTransform;
foreach (Transform spawn in sceneDescriptor.spawns)
{
if (spawn == null)
continue;
if (spawn == selected)
{
if (sceneDescriptor.spawnRadius != 0)
Handles.DrawWireDisc(spawn.position, Vector3.up, sceneDescriptor.spawnRadius);
else
{
float size = HandleUtility.GetHandleSize(spawn.position) * 0.5f;
Vector3 pos = spawn.position;
Vector3 offset1 = (Vector3.forward + Vector3.right).normalized * size;
Vector3 offset2 = (Vector3.forward - Vector3.right).normalized * size;
Handles.DrawLine(pos + offset1, pos - offset1);
Handles.DrawLine(pos + offset2, pos - offset2);
}
}
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 59a956eb4084499dbbc4004a6922c503
timeCreated: 1744910458

View File

@ -0,0 +1,166 @@
using System;
using System.Net;
using System.Threading.Tasks;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
using VRC.SDK3.Components;
using VRC.SDKBase.Editor.Api;
namespace VRC.SDK3.Editor
{
[CanEditMultipleObjects]
[CustomEditor(typeof(VRCAvatarPedestal))]
public class VRCAvatarPedestalEditor : VRCInspectorBase
{
private SerializedProperty _blueprintId;
private SerializedProperty _placement;
private SerializedProperty _changeAvatarsOnUse;
private SerializedProperty _scale;
private PropertyField _fieldBlueprintId;
private PropertyField _fieldPlacement;
private PropertyField _fieldChangeAvatarsOnUse;
private PropertyField _fieldScale;
private HelpBox _errorMessageBox;
private HelpBox _warningMessageBox;
private const string ERROR_PRIVATE_AVATAR = "This pedestal contains a private avatar ID. Only the author of the avatar will be able to see the pedestal and interact with it in VRChat.";
private const string ERROR_PRIVATE_OWN_AVATAR = "This pedestal contains a private avatar ID of your own. Only you will be able to see the pedestal and interact with it in VRChat.";
private const string ERROR_FAILED_TO_LOAD = "Failed to load avatar information. Make sure the avatar ID is valid and the avatar is public.";
private const string ERROR_UNAUTHORIZED = "Failed to load avatar information. Make sure you are logged in via the VRChat SDK Control Panel.";
private void OnEnable()
{
_blueprintId = serializedObject.FindProperty(nameof(VRCAvatarPedestal.blueprintId));
_placement = serializedObject.FindProperty(nameof(VRCAvatarPedestal.Placement));
_changeAvatarsOnUse = serializedObject.FindProperty(nameof(VRCAvatarPedestal.ChangeAvatarsOnUse));
_scale = serializedObject.FindProperty(nameof(VRCAvatarPedestal.scale));
}
public override void BuildInspectorGUI()
{
base.BuildInspectorGUI();
_fieldBlueprintId = AddFieldLabel(_blueprintId, "Avatar ID");
_errorMessageBox = new HelpBox(string.Empty, HelpBoxMessageType.Error)
{
style =
{
display = DisplayStyle.None
}
};
Root.Add(_errorMessageBox);
_warningMessageBox = new HelpBox(string.Empty, HelpBoxMessageType.Warning)
{
style =
{
display = DisplayStyle.None
}
};
Root.Add(_warningMessageBox);
_fieldPlacement = AddField(_placement);
_fieldChangeAvatarsOnUse = AddField(_changeAvatarsOnUse);
_fieldScale = AddField(_scale);
_fieldBlueprintId.RegisterValueChangeCallback(evt => AvatarChanged(evt.changedProperty.stringValue).ConfigureAwait(false));
AvatarChanged(_blueprintId.stringValue).ConfigureAwait(false);
}
private void ShowError(string message)
{
HideWarning();
_errorMessageBox.text = message;
_errorMessageBox.style.display = DisplayStyle.Flex;
}
private void HideError()
{
_errorMessageBox.style.display = DisplayStyle.None;
}
private void ShowWarning(string message)
{
HideError();
_warningMessageBox.text = message;
_warningMessageBox.style.display = DisplayStyle.Flex;
}
private void HideWarning()
{
_warningMessageBox.style.display = DisplayStyle.None;
}
private async Task AvatarChanged(string id)
{
if (string.IsNullOrWhiteSpace(id))
{
HideError();
HideWarning();
return;
}
try
{
// Attempt to log in if the user is not logged in
if (!Core.APIUser.IsLoggedIn)
{
// No void task completion source in .NET Standard, so we use a <bool> here
var resultTask = new TaskCompletionSource<bool>();
Core.APIUser.InitialFetchCurrentUser(_ => resultTask.SetResult(true), _ => resultTask.SetResult(false));
await resultTask.Task;
}
var avatarInfo = await VRCApi.GetAvatar(id, true);
// AVM Avatars should not trigger a warning or error
if (avatarInfo.ReleaseStatus != "public" && !avatarInfo.Lock)
{
if (avatarInfo.AuthorId == Core.APIUser.CurrentUser?.id)
{
Core.Logger.LogWarning(ERROR_PRIVATE_OWN_AVATAR);
ShowWarning(ERROR_PRIVATE_OWN_AVATAR);
}
else
{
Core.Logger.LogError(ERROR_PRIVATE_AVATAR);
ShowError(ERROR_PRIVATE_AVATAR);
}
return;
}
// If everything is ok - we can hide all the messages
HideWarning();
HideError();
}
catch (ApiErrorException e)
{
if (e.StatusCode == HttpStatusCode.NotFound)
{
Core.Logger.LogError(ERROR_PRIVATE_AVATAR);
ShowError(ERROR_PRIVATE_AVATAR);
return;
}
if (e.StatusCode == HttpStatusCode.Unauthorized)
{
Core.Logger.LogWarning(ERROR_UNAUTHORIZED);
ShowWarning(ERROR_UNAUTHORIZED);
return;
}
Core.Logger.LogException(e);
Core.Logger.LogError(e.ErrorMessage);
Core.Logger.LogWarning(ERROR_FAILED_TO_LOAD);
ShowWarning(ERROR_FAILED_TO_LOAD);
}
catch (Exception e)
{
Core.Logger.LogException(e);
Core.Logger.LogWarning(ERROR_FAILED_TO_LOAD);
ShowWarning(ERROR_FAILED_TO_LOAD);
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 92daf15a37b84806a147aa8127651a17
timeCreated: 1746046539

View File

@ -0,0 +1,328 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using VRC.SDK3.Components;
namespace VRC.SDK3.Editor
{
[InitializeOnLoad]
public static class VRCCameraDollyDrawer
{
private static readonly Color[] SplineColors =
{
new(0f, 0.7f, 0.7f),
new(1f, 0.5f, 0f),
new(0.6f, 0f, 0.8f),
new(0.6f, 0.4f, 0.2f),
new(0.2f, 0.6f, 0.9f),
new(0.9f, 0.6f, 0.7f),
new(0.3f, 0.3f, 0.7f),
Color.yellow,
new(0.8f, 0.3f, 0.3f),
Color.magenta,
};
private static VRCCameraDollyAnimation ANIMATION;
static VRCCameraDollyDrawer()
{
SceneView.duringSceneGui += OnSceneGUI;
}
static void OnSceneGUI(SceneView sceneView)
{
// don't draw if gizmos are off
if (!SceneView.currentDrawingSceneView.drawGizmos) return;
Transform[] selection = Selection.transforms;
if (selection == null || selection.Length == 0) return;
// check each selected object
foreach (Transform selected in selection)
{
VRCCameraDollyPath path;
// if an animation is selected, draw all of its paths
if (selected.TryGetComponent(out ANIMATION))
{
if (ANIMATION.Paths == null) return;
// draw paths
int pathIndex;
for (pathIndex = 0; pathIndex < ANIMATION.Paths.Length; pathIndex++)
{
path = ANIMATION.Paths[pathIndex];
if (path == null) continue;
DrawPath(ANIMATION, path);
DrawPoints(ANIMATION, path);
}
}
else
{
// if a path is selected, draw it
if (selected.TryGetComponent(out path))
ANIMATION = path.GetComponentInParent<VRCCameraDollyAnimation>();
// if a point is selected, also draw its path
else if (selected.TryGetComponent(out VRCCameraDollyPathPoint point))
{
ANIMATION = point.GetComponentInParent<VRCCameraDollyAnimation>();
path = point.GetComponentInParent<VRCCameraDollyPath>();
}
// if selected object isn't an animation, path, or point, don't draw anything
else return;
DrawPath(ANIMATION, path);
DrawPoints(ANIMATION, path);
}
}
}
private static void DrawPath(VRCCameraDollyAnimation animation, VRCCameraDollyPath path)
{
if (!IsPathValid(animation, path)) return;
int index = path.transform.GetSiblingIndex();
Handles.color = animation.gameObject.activeInHierarchy
? SplineColors[index % SplineColors.Length]
: Color.gray;
var points = path.Points
.Where(p => p != null)
.Select(p => p.transform.position)
.ToList();
VRCCameraDollyAnimation.VRCCameraDollyPathType pathType = animation.PathType;
if (points.Count < 4)
{
pathType = VRCCameraDollyAnimation.VRCCameraDollyPathType.Linear;
}
if (pathType == VRCCameraDollyAnimation.VRCCameraDollyPathType.Linear)
{
for (int i = 0; i <= points.Count - 2; i++)
{
Handles.DrawLine(points[i], points[i+1], 5);
}
}
else
{
Vector3 prev = GetPointOnSpline(points, 0f, pathType);
for (int i = 1; i <= VRCCameraDollyAnimation.RESOLUTION; i++)
{
float t = i / (float)VRCCameraDollyAnimation.RESOLUTION;
Vector3 curr = GetPointOnSpline(points, t, pathType);
Handles.DrawLine(prev, curr, 5);
prev = curr;
}
}
// draw path label in the path's color
Handles.Label(points[0] + new Vector3(0,0.3f,0), $"Path {index+1}",
new GUIStyle { fontSize = 25, normal = new GUIStyleState { textColor = Handles.color } });
}
private static void DrawPoints(VRCCameraDollyAnimation animation, VRCCameraDollyPath path)
{
if (!IsPathValid(animation, path)) return;
for (int i = 0; i < path.Points.Length; i++)
{
var point = path.Points[i];
if (point == null) continue;
if (animation.PathType != VRCCameraDollyAnimation.VRCCameraDollyPathType.Linear &&
path.Points.Length >= 4 && (i == 0 || i == path.Points.Length - 1))
{
Handles.color = Color.red;
Handles.DrawWireCube(point.transform.position, new Vector3(0.15f, 0.15f, 0.15f));
Handles.Label(point.transform.position + new Vector3(0,0.1f,0), $"{(i == 0 ? "Start" : "End")} Anchor");
// anchors show a dotted line
Handles.color = Color.blue;
if (i == 0)
Handles.DrawDottedLine(point.transform.position, path.Points[1].transform.position, 5);
else
Handles.DrawDottedLine(path.Points[i - 1].transform.position, point.transform.position,
5);
}
else
{
Vector3 pos = point.transform.position;
Quaternion rot = point.transform.rotation;
Handles.color = Color.grey;
Handles.SphereHandleCap(0, pos, rot, 0.1f, EventType.Repaint);
Handles.Label(point.transform.position + new Vector3(0,0.1f,0), $"Point {i+1}");
}
}
}
static bool IsPathValid(VRCCameraDollyAnimation animation, VRCCameraDollyPath path)
{
if (animation == null ||
path == null ||
path.Points == null ||
path.Points.Length < 2)
return false;
return true;
}
static Vector3 GetPointOnSpline(List<Vector3> points, float t, VRCCameraDollyAnimation.VRCCameraDollyPathType pathType)
{
return pathType switch
{
VRCCameraDollyAnimation.VRCCameraDollyPathType.Linear => Linear(points, t),
VRCCameraDollyAnimation.VRCCameraDollyPathType.Loose => CatmullRom(points, t),
VRCCameraDollyAnimation.VRCCameraDollyPathType.Fitted => BSpline(points, t),
_ => Vector3.zero
};
}
static Vector3 Linear(List<Vector3> pts, float t)
{
int i = Mathf.FloorToInt(t * (pts.Count - 1));
i = Mathf.Clamp(i, 0, pts.Count - 2);
float localT = t * (pts.Count - 1) - i;
return Vector3.Lerp(pts[i], pts[i + 1], localT);
}
static Vector3 CatmullRom(List<Vector3> points, float t)
{
if (points.Count < 4) return Linear(points, t);
int numSections = points.Count - 3;
float u = t * numSections;
int i = Mathf.Clamp(Mathf.FloorToInt(u), 0, numSections - 1);
u -= i;
Vector3 p0 = points[i];
Vector3 p1 = points[i + 1];
Vector3 p2 = points[i + 2];
Vector3 p3 = points[i + 3];
return 0.5f * (
2f * p1 +
(-p0 + p2) * u +
(2f * p0 - 5f * p1 + 4f * p2 - p3) * u * u +
(-p0 + 3f * p1 - 3f * p2 + p3) * u * u * u
);
}
private static Vector3 BSpline(List<Vector3> points, float t)
{
if (points.Count < 4) return Linear(points, t);
int numSections = points.Count - 3;
float u = t * numSections;
int i = Mathf.Clamp(Mathf.FloorToInt(u), 0, numSections - 1);
u -= i;
Vector3 p0 = points[i];
Vector3 p1 = points[i + 1];
Vector3 p2 = points[i + 2];
Vector3 p3 = points[i + 3];
return GetBSplinePoint(p0, p1, p2, p3, u);
}
private static Vector3 GetBSplinePoint(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
{
float t2 = t * t;
float t3 = t2 * t;
float b0 = (-t3 + 3f * t2 - 3f * t + 1f) / 6f;
float b1 = (3f * t3 - 6f * t2 + 4f) / 6f;
float b2 = (-3f * t3 + 3f * t2 + 3f * t + 1f) / 6f;
float b3 = t3 / 6f;
Vector3 position = b0 * p0 + b1 * p1 + b2 * p2 + b3 * p3;
return position;
}
}
[CustomEditor(typeof(VRCCameraDollyAnimation))]
public class VRCCameraDollyAnimationEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if (GUILayout.Button("Collect Paths & Points"))
{
var animation = (VRCCameraDollyAnimation)target;
SerializedObject animationSO = new SerializedObject(animation);
SerializedProperty pathsProp = animationSO.FindProperty("Paths");
pathsProp.ClearArray();
int pathIndex = 0;
foreach (Transform path in animation.transform)
{
if (!path.TryGetComponent<VRCCameraDollyPath>(out var pathComponent)) continue;
SerializedObject pathSO = new SerializedObject(pathComponent);
SerializedProperty pointsProp = pathSO.FindProperty("Points");
pointsProp.ClearArray();
int pointIndex = 0;
foreach (Transform point in path)
{
if (!point.TryGetComponent<VRCCameraDollyPathPoint>(out var pointComponent)) continue;
if (pointComponent != null)
{
pointsProp.InsertArrayElementAtIndex(pointIndex);
pointsProp.GetArrayElementAtIndex(pointIndex).objectReferenceValue = pointComponent;
pointIndex++;
}
}
pathSO.ApplyModifiedProperties();
EditorUtility.SetDirty(pathComponent);
pathsProp.InsertArrayElementAtIndex(pathIndex);
pathsProp.GetArrayElementAtIndex(pathIndex).objectReferenceValue = pathComponent;
pathIndex++;
}
animationSO.ApplyModifiedProperties();
EditorUtility.SetDirty(animation);
EditorSceneManager.MarkSceneDirty(animation.gameObject.scene);
}
}
}
[CustomEditor(typeof(VRCCameraDollyPath))]
public class VRCCameraDollyPathEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if (GUILayout.Button("Collect Points"))
{
var path = (VRCCameraDollyPath)target;
SerializedObject pathSO = new SerializedObject(path);
SerializedProperty pointsProp = pathSO.FindProperty("Points");
pointsProp.ClearArray();
int pointIndex = 0;
foreach (Transform point in path.transform)
{
if (!point.TryGetComponent<VRCCameraDollyPathPoint>(out var pointComponent)) continue;
if (pointComponent != null)
{
pointsProp.InsertArrayElementAtIndex(pointIndex);
pointsProp.GetArrayElementAtIndex(pointIndex).objectReferenceValue = pointComponent;
pointIndex++;
}
}
pathSO.ApplyModifiedProperties();
EditorUtility.SetDirty(path);
EditorSceneManager.MarkSceneDirty(path.gameObject.scene);
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6348c1cdc3444611a7fdbac6d268dc58
timeCreated: 1748027556

View File

@ -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
*/

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d57b23c04034119448f23c5fdbc57662
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,25 @@
using UnityEditor;
using UnityEngine;
using VRC.SDK3.Midi;
using VRC.SDKBase.Midi;
#if (UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN) && !UNITY_ANDROID
namespace VRC.SDK3.Editor
{
[CustomEditor(typeof(VRCMidiListener))]
public class VRCMidiListenerEditor : UnityEditor.Editor
{
#if UNITY_STANDALONE_WIN
[RuntimeInitializeOnLoadMethod]
public static void InitializeMidi()
{
VRCMidiHandler.OnLog = (message) => Debug.Log(message);
VRCMidiHandler.Initialize = () =>
{
return VRCMidiHandler.OpenMidiInput<VRCPortMidiInput>(
EditorPrefs.GetString(VRCMidiWindow.DEVICE_NAME_STRING));
};
}
#endif
}
}
#endif

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5b1017097f3d46cd949892e0fce3ece9
timeCreated: 1612853300

View File

@ -0,0 +1,319 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using VRC.SDK3.Midi;
public class VRCMidiEditorVisualizer : EditorWindow
{
private MidiFile _midiFile;
private Vector2 _scroll;
private bool _hasGenerated;
private float _maxDistanceNotes;
private PreviewRenderUtility _previewRenderUtility;
private Texture _outputTexture;
private Mesh _meshMidi;
private Mesh _meshSideNotes;
private Mesh _meshTime;
private Material _mainMaterial;
private List<int> _usedChannels;
private Dictionary<int, Color> _colors;
public static void Init(MidiFile midiFile)
{
// Get existing open window or if none, make a new one:
VRCMidiEditorVisualizer window = GetWindow<VRCMidiEditorVisualizer>();
window._midiFile = midiFile;
window.Show();
}
private void OnEnable()
{
_previewRenderUtility = new PreviewRenderUtility(false);
var camera = _previewRenderUtility.camera;
camera.orthographic = true;
camera.nearClipPlane = 0.3f;
camera.farClipPlane = 10;
camera.orthographicSize = 20f;
camera.transform.position = new Vector3(0f, 2f, 0f);
camera.transform.LookAt(Vector3.zero);
InititlizeData();
wantsMouseMove = true;
}
private void InititlizeData()
{
_mainMaterial = new Material(Shader.Find("VRChat/Mobile/Toon Lit"));
_meshMidi = new Mesh();
_meshSideNotes = new Mesh();
_meshTime = new Mesh();
_hasGenerated = false;
}
public void OnDisable()
{
if (_previewRenderUtility != null)
{
_previewRenderUtility.Cleanup();
}
if (_meshMidi != null)
{
DestroyImmediate(_meshMidi);
DestroyImmediate(_meshSideNotes);
DestroyImmediate(_meshTime);
DestroyImmediate(_mainMaterial);
}
}
void OnGUI()
{
if (_midiFile == null)
{
EditorGUILayout.HelpBox("Editor was created without Midi File.", MessageType.Error);
return;
}
if (_meshMidi == null)
{
InititlizeData();
}
if (!_hasGenerated)
{
GenerateNoteObject();
GenerateMeshTime();
}
GenerateSideNotes();
ShowChannelLegend();
EditorGUILayout.BeginHorizontal();
// Main Note area
_scroll = EditorGUILayout.BeginScrollView(_scroll, false, false, GUILayout.ExpandWidth(true));
Rect rect = GUILayoutUtility.GetRect(_maxDistanceNotes*10, 1280);
EditorGUILayout.EndScrollView();
rect.width = position.width-16;
rect.height = position.height - EditorGUIUtility.singleLineHeight*2 -3;
rect.y += EditorGUIUtility.singleLineHeight+3;
var camera = _previewRenderUtility.camera;
camera.orthographicSize = rect.height / 20;
camera.transform.position = new Vector3(rect.width / 20 + _scroll.x / 10, 2, 128 - rect.height / 20 - _scroll.y / 10);
_previewRenderUtility.BeginPreview(rect, GUIStyle.none);
_previewRenderUtility.DrawMesh(_meshTime, Matrix4x4.identity, _mainMaterial, 0);
_previewRenderUtility.DrawMesh(_meshMidi,Matrix4x4.identity,_mainMaterial,0);
_previewRenderUtility.DrawMesh(_meshSideNotes, Vector3.right * (_scroll.x / 10), Quaternion.identity, _mainMaterial,0);
_previewRenderUtility.camera.Render();
_previewRenderUtility.EndAndDrawPreview(rect);
EditorGUILayout.EndHorizontal();
if (Event.current.type == EventType.MouseMove)
Repaint();
}
private void ShowChannelLegend()
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Channels:");
foreach (int channel in _usedChannels)
{
EditorGUILayout.LabelField(channel.ToString(), new GUIStyle(){alignment = TextAnchor.MiddleCenter, normal = new GUIStyleState(){textColor = _colors[channel]}}, new GUILayoutOption[]{GUILayout.Width(20)});
}
EditorGUILayout.EndHorizontal();
}
public void GenerateNoteObject()
{
_meshMidi.Clear();
_usedChannels = new List<int>();
MidiData data = _midiFile.data;
List<Vector3> positions = new List<Vector3>();
List<int> tri = new List<int>();
List<Color> colors = new List<Color>();
// Iterate over the list once to get all the used channels
foreach (var track in data.tracks)
{
foreach (var block in track.blocks)
{
if(!_usedChannels.Contains(block.channel)) _usedChannels.Add(block.channel);
}
}
// Generate colors for all channels, spread across spectrum evenly
_colors = new Dictionary<int, Color>();
for (int i = 0; i < _usedChannels.Count; i++)
{
float normalizedPosition = Mathf.InverseLerp(0, _usedChannels.Count, i);
_colors.Add(_usedChannels[i], Color.HSVToRGB(normalizedPosition, .9f, .9f));
}
int index = 0;
for (int TrackIndex = 0; TrackIndex < data.tracks.Length; TrackIndex++)
{
MidiData.MidiTrack track = data.tracks[TrackIndex];
MidiData.MidiBlock[] blocks = track.blocks;
for(int blockIndex = 0; blockIndex < blocks.Length; blockIndex++)
{
MidiData.MidiBlock block = blocks[blockIndex];
float endTime = block.endTimeMs / 100 + 10;
if ( _maxDistanceNotes < endTime)
{
_maxDistanceNotes = endTime;
}
positions.Add(new Vector3((block.startTimeMs / 100f) + 10, 0, block.note ));
positions.Add(new Vector3(endTime, 0, block.note ));
positions.Add(new Vector3((block.startTimeMs / 100f) + 10, 0, block.note + 1f));
positions.Add(new Vector3(endTime, 0, block.note + 1f));
tri.Add(index);
tri.Add(index + 2);
tri.Add(index + 1);
tri.Add(index + 1);
tri.Add(index + 2);
tri.Add(index + 3);
index += 4;
colors.Add(_colors[block.channel]);
colors.Add(_colors[block.channel]);
colors.Add(_colors[block.channel]);
colors.Add(_colors[block.channel]);
if(!_usedChannels.Contains(block.channel)) _usedChannels.Add(block.channel);
}
}
var camera = _previewRenderUtility.camera;
camera.transform.position = new Vector3(_maxDistanceNotes/2, 2f, 64);
_meshMidi.vertices = positions.ToArray();
_meshMidi.triangles = tri.ToArray();
_meshMidi.colors = colors.ToArray();
_hasGenerated = true;
}
public void GenerateSideNotes()
{
_meshSideNotes.Clear();
List<Vector3> positions = new List<Vector3>();
List<int> tri = new List<int>();
List<Color> colors = new List<Color>();
int index = 0;
int skip = -1;
bool whiteNote = true;
Color color;
for (int Notes = 0; Notes < 128; Notes++)
{
skip++;
skip %= 12;
if (skip == 5 || skip == 0)
{
whiteNote = !whiteNote;
}
whiteNote = !whiteNote;
if (whiteNote)
{
positions.Add(new Vector3(0, 0.3f, Notes + 0.05f));
positions.Add(new Vector3(10, 0.3f, Notes + 0.05f));
positions.Add(new Vector3(0, 0.3f, Notes + 0.95f));
positions.Add(new Vector3(10, 0.3f, Notes + 0.95f));
color = Color.white;
}
else
{
positions.Add(new Vector3(0, 0.3f, Notes + 0.05f));
positions.Add(new Vector3(10, 0.3f, Notes + 0.05f));
positions.Add(new Vector3(0, 0.3f, Notes + 0.95f));
positions.Add(new Vector3(10, 0.3f, Notes + 0.95f));
color = Color.black;
}
if(Mathf.FloorToInt((1280 - (GUIUtility.GUIToScreenPoint(Event.current.mousePosition).y + _scroll.y - position.y - EditorGUIUtility.singleLineHeight*2.3f))/ 10) == Notes)
{
color = Color.gray;
}
colors.Add(color);
colors.Add(color);
colors.Add(color);
colors.Add(color);
tri.Add(index);
tri.Add(index + 2);
tri.Add(index + 1);
tri.Add(index + 1);
tri.Add(index + 2);
tri.Add(index + 3);
index += 4;
}
_meshSideNotes.vertices = positions.ToArray();
_meshSideNotes.triangles = tri.ToArray();
_meshSideNotes.colors = colors.ToArray();
}
private void GenerateMeshTime()
{
_meshTime.Clear();
List<Vector3> positions = new List<Vector3>();
List<int> tri = new List<int>();
List<Color> colors = new List<Color>();
int index = 0;
int amount = Mathf.CeilToInt(((_maxDistanceNotes-10) / 600) * _midiFile.data.bpm);
Color color = Color.black;
for (int beats = 0; beats < amount; beats++)
{
float offset = (beats * (600f / _midiFile.data.bpm)) + 10;
positions.Add(new Vector3(-0.1f + offset, -0.3f, 0));
positions.Add(new Vector3(0.1f + offset, -0.3f, 0));
positions.Add(new Vector3(-0.1f + offset, -0.3f, 128));
positions.Add(new Vector3(0.1f + offset, -0.3f, 128));
colors.Add(color);
colors.Add(color);
colors.Add(color);
colors.Add(color);
tri.Add(index);
tri.Add(index + 2);
tri.Add(index + 1);
tri.Add(index + 1);
tri.Add(index + 2);
tri.Add(index + 3);
index += 4;
}
_meshTime.vertices = positions.ToArray();
_meshTime.triangles = tri.ToArray();
_meshTime.colors = colors.ToArray();
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 88390b175b72faa49b553b95cbcac908
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,144 @@
using UnityEditor;
using UnityEngine;
using VRC.SDK3.Midi;
namespace VRC.SDK3.Editor
{
[CustomEditor(typeof(VRCMidiPlayer))]
public class VRCMidiPlayerEditor : UnityEditor.Editor
{
private VRCMidiPlayer _player;
public bool displayDebugBlocks;
// Serialized Properties
private SerializedProperty _midiFileProp;
private SerializedProperty _audioSourceProp;
private SerializedProperty _targetBehavioursProp;
private const string MidiAssetReloadKey = "MidiAssetReloaded";
void OnEnable()
{
// Fetch the objects from the GameObject script to display in the inspector
_midiFileProp = serializedObject.FindProperty(nameof(VRCMidiPlayer.midiFile));
_audioSourceProp = serializedObject.FindProperty(nameof(VRCMidiPlayer.audioSource));
_targetBehavioursProp = serializedObject.FindProperty(nameof(VRCMidiPlayer.targetBehaviours));
_player = (VRCMidiPlayer)target;
}
private void Awake()
{
displayDebugBlocks = EditorPrefs.GetBool(GetPrefsNameFor(nameof(displayDebugBlocks)), false);
}
private static string GetPrefsNameFor(string value)
{
return $"VRCMidiPlayerEditor.{value}";
}
public override void OnInspectorGUI()
{
bool _isReady = _player.midiFile != null &&
_player.audioSource != null &&
_player.audioSource.clip != null &&
_player.targetBehaviours.Length > 0 &&
_player.targetBehaviours[0] != null ;
if (_isReady)
{
EditorGUILayout.HelpBox("✔ Midi Player is Ready!", MessageType.None);
}
else
{
EditorGUILayout.HelpBox("Not Ready - see messages below.", MessageType.Warning);
}
// Display Midi File Field
EditorGUILayout.PropertyField(
_midiFileProp,
new GUIContent(
"Midi File", null,
"The MIDI file in SMF format whose data you want to trigger."
));
// Ensure a Midi File is set before continuing
if (!_player.midiFile)
{
EditorGUILayout.HelpBox("Choose a Midi File to continue setting up the Player.", MessageType.Info);
serializedObject.ApplyModifiedProperties();
return;
}
// Display Audio Source Field
EditorGUILayout.PropertyField(
_audioSourceProp,
new GUIContent(
"Audio Source", null,
"The AudioSource component with the audio clip corresponding to your MIDI data."
));
// Add audio source if it's not set
if (!_player.audioSource)
{
EditorGUILayout.HelpBox("Set or Create an AudioSource to continue.", MessageType.Info);
if (GUILayout.Button("Create One Here"))
{
_player.audioSource = _player.gameObject.AddComponent<AudioSource>();
}
serializedObject.ApplyModifiedProperties();
return;
}
// Force reimport midi assets one time per session
if (_player.midiFile != null && _player.midiFile.audioClip == null)
{
string key = $"{MidiAssetReloadKey}-{_player.midiFile.GetInstanceID()}";
if (!SessionState.GetBool(key, false))
{
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(_player.midiFile), ImportAssetOptions.ForceUpdate);
SessionState.SetBool(key, true);
}
}
// Automatically set AudioSource clip from MidiAsset if possible
else if (_player.midiFile.audioClip != null && _player.audioSource.clip == null || _player.audioSource.clip != _player.midiFile.audioClip )
{
_player.audioSource.clip = _player.midiFile.audioClip;
}
if (_player.audioSource.clip == null)
{
EditorGUILayout.HelpBox("You need to set the AudioClip in the AudioSource.", MessageType.Warning);
serializedObject.ApplyModifiedProperties();
return;
}
// Display target UdonBehaviours field
EditorGUILayout.PropertyField(
_targetBehavioursProp,
new GUIContent(
"Target Behaviours", null,
"An array of UdonBehaviours which will have MIDI Note On and Off events sent to them"
));
// Exit Early if there are not target behaviours set
if (_player.targetBehaviours.Length == 0 || _player.targetBehaviours[0] == null)
{
EditorGUILayout.HelpBox("Set some target UdonBehaviours above to continue.", MessageType.Info);
serializedObject.ApplyModifiedProperties();
return;
}
bool openVisualizer = GUILayout.Button("Open Visualizer");
if (openVisualizer)
{
VRCMidiEditorVisualizer.Init(_player.midiFile);
}
// Apply changes to the serializedProperty - always do this at the end of OnInspectorGUI.
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 76fb4f8f2f07c024795a6acecfeaefcc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,244 @@
#if VRC_SDK_VRCSDK3 && UNITY_EDITOR
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using VRC.SDKBase;
using VRC.SDKBase.Editor.Versioning;
using VRCPickup = VRC.SDK3.Components.VRCPickup;
namespace VRC.SDK3.Editor
{
[CanEditMultipleObjects]
[CustomEditor(typeof(VRCPickup))]
public class VRCPickupEditor3 : VRCInspectorBase
{
private SerializedProperty propVersion;
private SerializedProperty propMomentumTransferMethod;
private SerializedProperty propDisallowTheft;
private SerializedProperty propExactGun;
private SerializedProperty propExactGrip;
private SerializedProperty propAllowManipulationWhenEquipped;
private SerializedProperty propOrientation;
private SerializedProperty propAutoHold;
private SerializedProperty propInteractionText;
private SerializedProperty propUseText;
private SerializedProperty propThrowVelocityBoostMinSpeed;
private SerializedProperty propThrowVelocityBoostScale;
private SerializedProperty propPickupable;
private SerializedProperty propProximity;
private PropertyField fieldMomentumTransferMethod;
private PropertyField fieldDisallowTheft;
private PropertyField fieldExactGun;
private PropertyField fieldExactGrip;
private PropertyField fieldAllowManipulationWhenEquipped;
private PropertyField fieldOrientation;
private PropertyField fieldAutoHold;
private PropertyField fieldInteractionText;
private PropertyField fieldUseText;
private PropertyField fieldThrowVelocityBoostMinSpeed;
private PropertyField fieldThrowVelocityBoostScale;
private PropertyField fieldPickupable;
private PropertyField fieldProximity;
private ComponentVersionUI<VRCPickup.Version> versionUI;
private void OnEnable()
{
propVersion = serializedObject.FindProperty(nameof(VRCPickup.version));
propMomentumTransferMethod = serializedObject.FindProperty(nameof(VRCPickup.MomentumTransferMethod));
propDisallowTheft = serializedObject.FindProperty(nameof(VRCPickup.DisallowTheft));
propExactGun = serializedObject.FindProperty(nameof(VRCPickup.ExactGun));
propExactGrip = serializedObject.FindProperty(nameof(VRCPickup.ExactGrip));
propAllowManipulationWhenEquipped = serializedObject.FindProperty(nameof(VRCPickup.allowManipulationWhenEquipped));
propOrientation = serializedObject.FindProperty(nameof(VRCPickup.orientation));
propAutoHold = serializedObject.FindProperty(nameof(VRCPickup.AutoHold));
propInteractionText = serializedObject.FindProperty(nameof(VRCPickup.InteractionText));
propUseText = serializedObject.FindProperty(nameof(VRCPickup.UseText));
propThrowVelocityBoostMinSpeed = serializedObject.FindProperty(nameof(VRCPickup.ThrowVelocityBoostMinSpeed));
propThrowVelocityBoostScale = serializedObject.FindProperty(nameof(VRCPickup.ThrowVelocityBoostScale));
propPickupable = serializedObject.FindProperty(nameof(VRCPickup.pickupable));
propProximity = serializedObject.FindProperty(nameof(VRCPickup.proximity));
}
#region Inspector GUI Construction (Common Pattern for All Custom Editors)
public override void BuildInspectorGUI()
{
base.BuildInspectorGUI();
// Add version system
var migrator = new VRCPickupVersionMigrator(propAutoHold, propOrientation, propInteractionText, OnVersionChanged);
versionUI = AddVersionSystem(propVersion, migrator,
"https://creators.vrchat.com/worlds/components/vrc_pickup#versions");
// Create AutoHold enum field (shown in V1.0, hidden in V1.1+ when toggle is used)
fieldAutoHold = AddField(propAutoHold);
fieldAutoHold.RegisterValueChangeCallback(AutoHoldCallback);
fieldUseText = AddFieldTooltip(propUseText,
"Text to display describing action for clicking button, when this pickup is already being held.");
fieldInteractionText = AddFieldTooltip(propInteractionText,
"Text displayed when user hovers over the pickup.");
fieldProximity = AddField(propProximity);
fieldOrientation = AddField(propOrientation);
fieldOrientation.RegisterValueChangeCallback(OrientationCallback);
fieldExactGun = AddField(propExactGun);
fieldExactGrip = AddField(propExactGrip);
fieldPickupable = AddField(propPickupable);
fieldDisallowTheft = AddField(propDisallowTheft);
fieldAllowManipulationWhenEquipped = AddField(propAllowManipulationWhenEquipped);
fieldMomentumTransferMethod = AddField(propMomentumTransferMethod);
fieldThrowVelocityBoostMinSpeed = AddField(propThrowVelocityBoostMinSpeed);
fieldThrowVelocityBoostScale = AddField(propThrowVelocityBoostScale);
// Now that all fields are created, we can update their visibility based on version
var pickup = target as VRCPickup;
SetupAutoHoldField(pickup.version);
RefreshAllFieldVisibility(pickup.version);
}
// Creates the toggle field for modern AutoHold UI (V1.1+)
private void SetupAutoHoldField(VRCPickup.Version version)
{
var container = fieldAutoHold.parent;
if (!fieldAutoHold.ClassListContains("auto-hold-enum-field"))
fieldAutoHold.AddToClassList("auto-hold-enum-field");
var toggleField = container.Query().Name("autoHoldToggle").First() as Toggle;
if (toggleField == null)
{
toggleField = new Toggle("Auto Hold")
{
name = "autoHoldToggle",
tooltip = "When enabled, the pickup will stay in hand when trigger is released"
};
toggleField.AddToClassList("auto-hold-toggle-field");
toggleField.RegisterValueChangedCallback(evt => {
serializedObject.Update();
propAutoHold.enumValueIndex = evt.newValue ?
(int)VRC_Pickup.AutoHoldMode.Yes :
(int)VRC_Pickup.AutoHoldMode.No;
serializedObject.ApplyModifiedProperties();
AutoHoldChanged();
});
container.Insert(container.IndexOf(fieldAutoHold) + 1, toggleField);
}
}
// Switches between enum dropdown (V1.0) and toggle (V1.1+) for AutoHold field
private void UpdateAutoHoldFieldVisibility(VRCPickup.Version version)
{
var container = fieldAutoHold.parent;
var toggleField = container.Query().Name("autoHoldToggle").First() as Toggle;
if (toggleField == null) return;
if (IsModernVersion(version))
{
fieldAutoHold.style.display = DisplayStyle.None;
toggleField.style.display = DisplayStyle.Flex;
UpdateToggleFromEnumValue(toggleField);
}
else
{
fieldAutoHold.style.display = DisplayStyle.Flex;
toggleField.style.display = DisplayStyle.None;
}
}
// Syncs toggle state with underlying enum value without triggering callbacks
private void UpdateToggleFromEnumValue(Toggle toggle)
{
bool treatAsAutoHold = propAutoHold.enumValueIndex
is (int)VRC_Pickup.AutoHoldMode.Yes
or (int)VRC_Pickup.AutoHoldMode.Sometimes;
toggle.SetValueWithoutNotify(treatAsAutoHold);
}
#endregion
#region VRC Pickup-Specific Helper Methods
// Checks if version uses modern UI (toggle instead of enum dropdown)
private bool IsModernVersion(VRCPickup.Version version)
{
return version > VRCPickup.Version.Version_1_0;
}
private void AutoHoldCallback(SerializedPropertyChangeEvent evt)
{
AutoHoldChanged();
}
// Updates UseText field visibility when AutoHold setting changes
private void AutoHoldChanged()
{
bool canDisplayUseText = propAutoHold.enumValueIndex
is (int)VRC_Pickup.AutoHoldMode.Yes
or (int)VRC_Pickup.AutoHoldMode.Sometimes
or (int)VRC_Pickup.AutoHoldMode.AutoDetect; // Use text can appear if gun or grip transforms are assigned.
fieldUseText.SetVisible(canDisplayUseText);
// Update version upgrade info visibility
versionUI?.RefreshUpgradeInfo();
}
private void OrientationCallback(SerializedPropertyChangeEvent evt) => OrientationChanged();
// Shows/hides ExactGun and ExactGrip fields based on pickup orientation
private void OrientationChanged()
{
switch ((VRC_Pickup.PickupOrientation)propOrientation.enumValueIndex)
{
case VRC_Pickup.PickupOrientation.Any:
fieldExactGun.SetVisible(true);
fieldExactGrip.SetVisible(true);
break;
case VRC_Pickup.PickupOrientation.Grip:
fieldExactGun.SetVisible(false);
fieldExactGrip.SetVisible(true);
break;
case VRC_Pickup.PickupOrientation.Gun:
fieldExactGun.SetVisible(true);
fieldExactGrip.SetVisible(false);
break;
}
// Update version upgrade info since orientation affects AutoDetect migration
versionUI?.RefreshUpgradeInfo();
}
#endregion
#region Version-Dependent UI Management (Pattern for Versioned Components)
// Refreshes all field visibility based on current version and field states
private void RefreshAllFieldVisibility(VRCPickup.Version version)
{
versionUI?.RefreshUpgradeInfo();
UpdateAutoHoldFieldVisibility(version);
OrientationChanged();
AutoHoldChanged();
}
// Called when version changes to update UI elements
private void OnVersionChanged(VRCPickup.Version newVersion)
{
RefreshAllFieldVisibility(newVersion);
}
#endregion
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a8cc4c1876b26174fbaeb062178a6bda
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,154 @@
using UnityEditor;
using VRC.SDK3.Components;
using VRC.SDKBase;
using VRC.SDKBase.Editor.Versioning;
namespace VRC.SDK3.Editor
{
/// <summary>
/// Version migration logic for VRCPickup
/// </summary>
internal class VRCPickupVersionMigrator : ComponentVersionMigrator<VRCPickup.Version>
{
private readonly SerializedProperty autoHoldProperty;
private readonly SerializedProperty orientationProperty;
private readonly SerializedProperty interactionTextProperty;
private readonly System.Action<VRCPickup.Version> onVersionChangedCallback;
public VRCPickupVersionMigrator(SerializedProperty autoHoldProperty, SerializedProperty orientationProperty, SerializedProperty interactionTextProperty, System.Action<VRCPickup.Version> onVersionChangedCallback = null)
{
this.autoHoldProperty = autoHoldProperty;
this.orientationProperty = orientationProperty;
this.interactionTextProperty = interactionTextProperty;
this.onVersionChangedCallback = onVersionChangedCallback;
}
// Creates the success dialog message explaining what specific changes were made during upgrade
public override string GetUpgradeChangesMessage(VRCPickup.Version oldVersion, VRCPickup.Version newVersion, SerializedObject serializedObject)
{
if (newVersion <= oldVersion) return null;
// Handle multi-selection with simplified message
if (serializedObject.isEditingMultipleObjects)
return $"Version upgraded successfully!\n{serializedObject.targetObjects.Length} pickup(s) upgraded to Version 1.1.";
var orientation = (VRC_Pickup.PickupOrientation)orientationProperty.enumValueIndex;
var message = "Version upgraded successfully!\n";
int oldAutoHoldValue = autoHoldProperty.enumValueIndex;
var changes = new System.Collections.Generic.List<string>();
if (oldAutoHoldValue == (int)VRC_Pickup.AutoHoldMode.Sometimes)
{
changes.Add("Changed 'Sometimes' to 'Yes' for better controller compatibility");
}
else if (oldAutoHoldValue == (int)VRC_Pickup.AutoHoldMode.AutoDetect)
{
bool willBeAutoHold = VRC_Pickup.IsGlobalAutoHoldPickup((VRC_Pickup.AutoHoldMode)oldAutoHoldValue, orientation);
var newValue = willBeAutoHold ? "Yes" : "No";
var change = $"Changed 'Auto Detect' to '{newValue}' based on orientation ({orientation})";
if (newValue == "No")
{
change += "\n'Any' orientation pickups don't use auto-hold";
}
else
{
change += "\nGrip/Gun orientation pickups use auto-hold";
}
changes.Add(change);
}
if (changes.Count > 0)
{
message += "Changes made:\n" + string.Join("\n", changes);
}
else
{
message += "No changes needed - your settings are already compatible with this version.";
}
return message;
}
// Performs the actual data migration when upgrading to a specific version
public override void MigrateToVersion(VRCPickup.Version oldVersion, VRCPickup.Version newVersion, SerializedObject serializedObject)
{
// Handle migration from old busted AutoHold to Global AutoHold
if (oldVersion == VRCPickup.Version.Version_1_0)
{
var currentOrientation = (VRC_Pickup.PickupOrientation)orientationProperty.enumValueIndex;
var currentAutoHoldMode = (VRC_Pickup.AutoHoldMode)autoHoldProperty.enumValueIndex;
bool willBeAutoHold = VRC_Pickup.IsGlobalAutoHoldPickup(currentAutoHoldMode, currentOrientation);
var newAutoHoldMode = willBeAutoHold ? VRC_Pickup.AutoHoldMode.Yes : VRC_Pickup.AutoHoldMode.No;
if ((int)newAutoHoldMode != autoHoldProperty.enumValueIndex)
{
autoHoldProperty.enumValueIndex = (int)newAutoHoldMode;
autoHoldProperty.serializedObject.ApplyModifiedProperties();
}
}
}
// Determines when to show the upgrade info box at the top of the inspector
public override bool ShouldShowUpgradePrompt(VRCPickup.Version version, SerializedObject serializedObject)
{
// Always show upgrade for ANY Version 1.0 pickup in multi-selection
if (serializedObject.isEditingMultipleObjects)
return version == VRCPickup.Version.Version_1_0;
return version == VRCPickup.Version.Version_1_0 &&
(autoHoldProperty.enumValueIndex == (int)VRC_Pickup.AutoHoldMode.Sometimes ||
autoHoldProperty.enumValueIndex == (int)VRC_Pickup.AutoHoldMode.AutoDetect);
}
// Returns message about why they should upgrade
public override string GetUpgradePromptText(VRCPickup.Version currentVersion, VRCPickup.Version latestVersion)
{
// Multi-selection mode - simplified message
if (autoHoldProperty.serializedObject.isEditingMultipleObjects)
return "Selected pickups use older settings.\nUpgrade all to Version 1.1 for better compatibility and simplified options.";
int currentAutoHoldValue = autoHoldProperty.enumValueIndex;
var orientation = (VRC_Pickup.PickupOrientation)orientationProperty.enumValueIndex;
bool willBeAutoHold = VRC_Pickup.IsGlobalAutoHoldPickup((VRC_Pickup.AutoHoldMode)currentAutoHoldValue, orientation);
// Handle Sometimes - always problematic
if (currentAutoHoldValue == (int)VRC_Pickup.AutoHoldMode.Sometimes)
{
return "This pickup uses older auto-hold settings that don't work for many controllers.\n" +
"Upgrade to Version 1.1 for better compatibility and reduced hand fatigue.";
}
// Handle AutoDetect - check what it will become
if (currentAutoHoldValue == (int)VRC_Pickup.AutoHoldMode.AutoDetect)
{
if (willBeAutoHold)
{
return "This pickup uses older auto-hold settings that don't work for many controllers.\n" +
"Upgrade to Version 1.1 for better compatibility and reduced hand fatigue.";
}
}
// Handle No and AutoDetect that becomes No - won't change function but will simplify UI
if (!willBeAutoHold)
{
return "This pickup uses older auto-hold settings.\nUpgrading won't change the way it functions,\n" +
"but it will simplify the options below.";
}
// Default fallback
return "Upgrade to Version 1.1 for improved compatibility and simplified settings.";
}
// Called after version change to notify editor for UI updates
public override void OnVersionChanged(VRCPickup.Version version, SerializedObject serializedObject)
{
onVersionChangedCallback?.Invoke(version);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e5f6789012345678901234abcdef0123
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,52 @@
#if VRC_SDK_VRCSDK3 && UNITY_EDITOR
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using System;
using UnityEngine.UIElements;
using VRCStation = VRC.SDK3.Components.VRCStation;
namespace VRC.SDK3.Editor
{
[CanEditMultipleObjects]
[CustomEditor(typeof(VRCStation))]
public class VRCPlayerStationEditor3 : VRCInspectorBase
{
private SerializedProperty propPlayerMobility;
private SerializedProperty propCanUseStationFromStation;
private SerializedProperty propAnimatorController;
private SerializedProperty propDisableStationExit;
private SerializedProperty propSeated;
private SerializedProperty propStationEnterPlayerLocation;
private SerializedProperty propStationExitPlayerLocation;
private void OnEnable()
{
propPlayerMobility = serializedObject.FindProperty(nameof(VRCStation.PlayerMobility));
propCanUseStationFromStation = serializedObject.FindProperty(nameof(VRCStation.canUseStationFromStation));
propAnimatorController = serializedObject.FindProperty(nameof(VRCStation.animatorController));
propDisableStationExit = serializedObject.FindProperty(nameof(VRCStation.disableStationExit));
propSeated = serializedObject.FindProperty(nameof(VRCStation.seated));
propStationEnterPlayerLocation = serializedObject.FindProperty(nameof(VRCStation.stationEnterPlayerLocation));
propStationExitPlayerLocation = serializedObject.FindProperty(nameof(VRCStation.stationExitPlayerLocation));
}
public override void BuildInspectorGUI()
{
base.BuildInspectorGUI();
AddField(propPlayerMobility);
AddField(propSeated);
AddField(propDisableStationExit);
AddField(propCanUseStationFromStation);
AddField(propStationEnterPlayerLocation);
AddField(propStationExitPlayerLocation);
AddField(propAnimatorController);
}
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8901d07a685ca424492a3cabff506184
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,51 @@
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
using VRC.SDKBase;
using VRCPortalMarker = VRC.SDK3.Components.VRCPortalMarker;
namespace VRC.SDK3.Editor
{
[CanEditMultipleObjects]
[CustomEditor(typeof(VRCPortalMarker))]
public class VRCPortalMarkerEditor : VRCInspectorBase
{
private SerializedProperty propWorld;
private SerializedProperty propRoomId;
private SerializedProperty propCustomPortalName;
private PropertyField fieldWorld;
private PropertyField fieldRoomId;
private PropertyField fieldCustomPortalName;
private HelpBox helpBoxTag;
private void OnEnable()
{
propWorld = serializedObject.FindProperty(nameof(VRCPortalMarker.world));
propRoomId = serializedObject.FindProperty(nameof(VRCPortalMarker.roomId));
propCustomPortalName = serializedObject.FindProperty(nameof(VRCPortalMarker.customPortalName));
}
public override void BuildInspectorGUI()
{
base.BuildInspectorGUI();
fieldRoomId = AddFieldLabel(propRoomId, "World ID");
fieldCustomPortalName = AddField(propCustomPortalName);
fieldWorld = AddField(propWorld);
fieldWorld.RegisterValueChangeCallback(evt => WorldChanged());
WorldChanged();
}
private void WorldChanged()
{
bool value = (VRC_PortalMarker.VRChatWorld)propWorld.enumValueIndex == VRC_PortalMarker.VRChatWorld.None;
fieldRoomId.SetEnabled(value);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d0eab965d110d6a41b44e8c56b81f7bd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,213 @@
#if VRC_SDK_VRCSDK3 && UNITY_EDITOR
using System;
using System.Linq;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using VRC.Core;
using VRCSceneDescriptor = VRC.SDK3.Components.VRCSceneDescriptor;
namespace VRC.SDK3.Editor
{
[CanEditMultipleObjects]
[CustomEditor(typeof(VRCSceneDescriptor))]
public class VRCSceneDescriptorEditor3 : VRCInspectorBase
{
private VRCSceneDescriptor sceneDescriptor;
private SerializedProperty propSpawns;
private SerializedProperty propSpawnRadius;
private SerializedProperty propSpawnOrder;
private SerializedProperty propSpawnOrientation;
private SerializedProperty propReferenceCamera;
private SerializedProperty propRespawnHeightY;
private SerializedProperty propObjectBehaviourAtRespawnHeight;
private SerializedProperty propForbidUserPortals;
private SerializedProperty propUnityVersion;
private SerializedProperty propDynamicPrefabs;
private SerializedProperty propDynamicMaterials;
private SerializedProperty propNetworkIDs;
private SerializedProperty propPortraitCameraPositionOffset;
private SerializedProperty propPortraitCameraRotationOffset;
private SerializedProperty propInteractPassthrough;
[NonSerialized] private string[] layerNames;
private int mask;
private const string INTERACTION_HELPBOX_LABEL =
"Interaction through User layers is blocked by default. Use the \"Interact Passthrough\" mask to define layers that will be transparent to interaction (allow interactions to pass through).";
private const string INTERACTION_HELPBOX_URL = "https://creators.vrchat.com/worlds/layers/#interaction-block-and-passthrough-on-vrchat-layers";
private const int USER_LAYER_START = 22;
private const int USER_LAYER_COUNT = 10;
private const float HANDLE_SIZE = 0.1f;
private static readonly Color RespawnHeightGizmoColor = new(0, 1, 0, 0.25f);
private Vector3[] respawnHeightGizmoCorners;
private void OnEnable()
{
sceneDescriptor = (VRCSceneDescriptor)target;
propSpawns = serializedObject.FindProperty(nameof(VRCSceneDescriptor.spawns));
propSpawnRadius = serializedObject.FindProperty(nameof(VRCSceneDescriptor.spawnRadius));
propSpawnOrder = serializedObject.FindProperty(nameof(VRCSceneDescriptor.spawnOrder));
propSpawnOrientation = serializedObject.FindProperty(nameof(VRCSceneDescriptor.spawnOrientation));
propReferenceCamera = serializedObject.FindProperty(nameof(VRCSceneDescriptor.ReferenceCamera));
propRespawnHeightY = serializedObject.FindProperty(nameof(VRCSceneDescriptor.RespawnHeightY));
propObjectBehaviourAtRespawnHeight = serializedObject.FindProperty(nameof(VRCSceneDescriptor.ObjectBehaviourAtRespawnHeight));
propForbidUserPortals = serializedObject.FindProperty(nameof(VRCSceneDescriptor.ForbidUserPortals));
propUnityVersion = serializedObject.FindProperty(nameof(VRCSceneDescriptor.unityVersion));
propDynamicPrefabs = serializedObject.FindProperty(nameof(VRCSceneDescriptor.DynamicPrefabs));
propDynamicMaterials = serializedObject.FindProperty(nameof(VRCSceneDescriptor.DynamicMaterials));
propPortraitCameraPositionOffset = serializedObject.FindProperty(nameof(VRCSceneDescriptor.portraitCameraPositionOffset));
propPortraitCameraRotationOffset = serializedObject.FindProperty(nameof(VRCSceneDescriptor.portraitCameraRotationOffset));
propInteractPassthrough = serializedObject.FindProperty(nameof(VRCSceneDescriptor.interactThruLayers));
// Using NetworkIDCollection here doesn't expose the actual list of network IDs in the inspector
propNetworkIDs = serializedObject.FindProperty("NetworkIDs");
GetRespawnHeightGizmoPlaneCorners(false);
PopulateUserLayerNames();
HierarchyChanged();
EditorApplication.hierarchyChanged += HierarchyChanged;
}
private void OnDisable()
{
EditorApplication.hierarchyChanged -= HierarchyChanged;
}
private void OnSceneGUI()
{
var handlePosition = new Vector3(
sceneDescriptor.transform.position.x,
sceneDescriptor.RespawnHeightY,
sceneDescriptor.transform.position.z);
var handleSize = HandleUtility.GetHandleSize(handlePosition) * HANDLE_SIZE;
EditorGUI.BeginChangeCheck();
Vector3 newHandlePosition = Handles.FreeMoveHandle(handlePosition, handleSize, Vector3.up, Handles.DotHandleCap);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(sceneDescriptor, "Move Respawn Height Y");
sceneDescriptor.RespawnHeightY = newHandlePosition.y;
EditorUtility.SetDirty(sceneDescriptor);
}
GetRespawnHeightGizmoPlaneCorners();
Handles.DrawSolidRectangleWithOutline(respawnHeightGizmoCorners, RespawnHeightGizmoColor, Color.green);
foreach (Transform spawn in sceneDescriptor.spawns)
{
if (!spawn) continue;
Vector3 position = spawn.position;
Handles.color = Color.white;
if (sceneDescriptor.spawnRadius > 0)
Handles.DrawWireDisc(position, Vector3.up, sceneDescriptor.spawnRadius);
else
{
float size = HandleUtility.GetHandleSize(spawn.position) * 0.5f;
Vector3 pos = spawn.position;
Vector3 offset1 = (Vector3.forward + Vector3.right).normalized * size;
Vector3 offset2 = (Vector3.forward - Vector3.right).normalized * size;
Handles.DrawLine(pos + offset1, pos - offset1);
Handles.DrawLine(pos + offset2, pos - offset2);
}
Handles.color = Color.green;
Handles.DrawLine(position, position + Vector3.up);
Handles.color = Color.blue;
Handles.DrawLine(position, position + spawn.forward);
}
Handles.color = Color.white;
}
private void HierarchyChanged()
{
// This cannot be a RequireComponent because VRC.Core isn't included in VRC.Base.
if (!sceneDescriptor.GetComponent<PipelineManager>())
{
sceneDescriptor.gameObject.AddComponent<PipelineManager>();
}
if (sceneDescriptor.spawns == null || sceneDescriptor.spawns.Length == 0)
{
Undo.RecordObject(sceneDescriptor, "Grabbed new Spawn Position");
sceneDescriptor.spawns = new[] { sceneDescriptor.transform };
Debug.LogWarning($"Scene Descriptor spawns were empty, adding a default Spawn.");
}
}
public override void BuildInspectorGUI()
{
base.BuildInspectorGUI();
AddField(propSpawns);
AddFieldTooltip(propSpawnRadius, "Players spawn at a random spot within the radius. Set to zero to have players spawn at the exact spawn position.");
AddField(propSpawnOrder);
AddField(propSpawnOrientation);
AddField(propReferenceCamera);
AddField(propRespawnHeightY);
AddField(propForbidUserPortals);
AddField(propObjectBehaviourAtRespawnHeight);
AddField(propNetworkIDs, "Network IDs", "The Network ID Collection");
MaskField fieldPassthrough = new ("Interact Passthrough");
fieldPassthrough.AddToClassList("unity-base-field__aligned");
fieldPassthrough.choices = layerNames.ToList();
fieldPassthrough.BindProperty(propInteractPassthrough);
Root.Add(fieldPassthrough);
HelpBox helpBox = new (INTERACTION_HELPBOX_LABEL, HelpBoxMessageType.Info);
Button buttonDocs = new () { text = "Docs" };
buttonDocs.clicked += () => Application.OpenURL(INTERACTION_HELPBOX_URL);
helpBox.Add(buttonDocs);
Root.Add(helpBox);
}
private void PopulateUserLayerNames()
{
if (layerNames == null)
{
layerNames = new string[USER_LAYER_COUNT];
}
for (int i = 0; i < USER_LAYER_COUNT; ++i)
{
string layerName = LayerMask.LayerToName(USER_LAYER_START + i);
if (string.IsNullOrWhiteSpace(layerName))
{
layerNames[i] = $"<<layer {USER_LAYER_START + i}>>";
}
else
{
layerNames[i] = layerName;
}
}
}
private void GetRespawnHeightGizmoPlaneCorners(bool checkRespawnHeightChanged = true)
{
// only get new corners if respawn height has changed
if (checkRespawnHeightChanged &&
Mathf.Approximately(respawnHeightGizmoCorners[0].y, sceneDescriptor.RespawnHeightY))
{
return;
}
respawnHeightGizmoCorners = new[]
{
new Vector3(sceneDescriptor.transform.position.x-5, sceneDescriptor.RespawnHeightY, sceneDescriptor.transform.position.z-5),
new Vector3(sceneDescriptor.transform.position.x-5, sceneDescriptor.RespawnHeightY, sceneDescriptor.transform.position.z+5),
new Vector3(sceneDescriptor.transform.position.x+5, sceneDescriptor.RespawnHeightY, sceneDescriptor.transform.position.z+5),
new Vector3(sceneDescriptor.transform.position.x+5, sceneDescriptor.RespawnHeightY, sceneDescriptor.transform.position.z-5)
};
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4b2b9ac625bc5b04c887ff9ee9b5fdbe
timeCreated: 1450463561
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,77 @@
#if VRC_SDK_VRCSDK3
using UnityEngine;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
using VRCSpatialAudioSource = VRC.SDK3.Components.VRCSpatialAudioSource;
namespace VRC.SDK3.Editor
{
[CanEditMultipleObjects]
[CustomEditor(typeof(VRCSpatialAudioSource))]
public class VRCSpatialAudioSourceEditor3 : VRCInspectorBase
{
private const string SHOW_ADVANCED_OPTIONS_KEY = "VRC.SDK3.Components.VRCSpatialAudioSource.ShowAdvancedOptions";
private SerializedProperty propGain;
private SerializedProperty propNear;
private SerializedProperty propFar;
private SerializedProperty propVolumetricRadius;
private SerializedProperty propEnableSpatialization;
private SerializedProperty propUseAudioSourceVolumeCurve;
private PropertyField fieldEnableSpatialization;
private PropertyField fieldUseAudioSourceVolumeCurve;
private VRCSpatialAudioSource script;
private AudioSource source;
private void OnEnable()
{
script = (VRCSpatialAudioSource)target;
source = script.GetComponent<AudioSource>();
propGain = serializedObject.FindProperty(nameof(VRCSpatialAudioSource.Gain));
propNear = serializedObject.FindProperty(nameof(VRCSpatialAudioSource.Near));
propFar = serializedObject.FindProperty(nameof(VRCSpatialAudioSource.Far));
propVolumetricRadius = serializedObject.FindProperty(nameof(VRCSpatialAudioSource.VolumetricRadius));
propEnableSpatialization = serializedObject.FindProperty(nameof(VRCSpatialAudioSource.EnableSpatialization));
propUseAudioSourceVolumeCurve = serializedObject.FindProperty(nameof(VRCSpatialAudioSource.UseAudioSourceVolumeCurve));
}
public override void BuildInspectorGUI()
{
base.BuildInspectorGUI();
AddField(propGain);
AddField(propFar);
Foldout foldout = AddKeyedFoldout("Advanced Options", SHOW_ADVANCED_OPTIONS_KEY);
foldout.Add(AddField(propNear));
foldout.Add(AddField(propVolumetricRadius));
fieldEnableSpatialization = AddField(propEnableSpatialization);
fieldEnableSpatialization.RegisterValueChangeCallback(EnableSpatializationCallback);
foldout.Add(fieldEnableSpatialization);
fieldUseAudioSourceVolumeCurve = AddField(propUseAudioSourceVolumeCurve);
foldout.Add(fieldUseAudioSourceVolumeCurve);
UseAudioSourceVolumeCurveChanged();
}
private void EnableSpatializationCallback(SerializedPropertyChangeEvent evt) => UseAudioSourceVolumeCurveChanged();
private void UseAudioSourceVolumeCurveChanged()
{
source.spatialize = propEnableSpatialization.boolValue;
fieldUseAudioSourceVolumeCurve.SetVisible(propEnableSpatialization.boolValue);
}
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3f8f999a8e1ebee4588f94a8a618d7c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,314 @@
using TMPro;
using TMPro.EditorUtilities;
using UnityEditor;
using UnityEditor.Presets;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace VRC.SDK3.Components.Editor
{
public class VRCTMP
{
private static TMP_DefaultControls.Resources s_StandardResources;
private const string kUILayerName = "Default";
private const string kStandardSpritePath = "UI/Skin/UISprite.psd";
private const string kBackgroundSpritePath = "UI/Skin/Background.psd";
private const string kInputFieldBackgroundPath = "UI/Skin/InputFieldBackground.psd";
private const string kKnobPath = "UI/Skin/Knob.psd";
private const string kCheckmarkPath = "UI/Skin/Checkmark.psd";
private const string kDropdownArrowPath = "UI/Skin/DropdownArrow.psd";
private const string kMaskPath = "UI/Skin/UIMask.psd";
private static TMP_DefaultControls.Resources GetStandardResources()
{
if (s_StandardResources.standard == null)
{
s_StandardResources.standard = AssetDatabase.GetBuiltinExtraResource<Sprite>(kStandardSpritePath);
s_StandardResources.background = AssetDatabase.GetBuiltinExtraResource<Sprite>(kBackgroundSpritePath);
s_StandardResources.inputField = AssetDatabase.GetBuiltinExtraResource<Sprite>(kInputFieldBackgroundPath);
s_StandardResources.knob = AssetDatabase.GetBuiltinExtraResource<Sprite>(kKnobPath);
s_StandardResources.checkmark = AssetDatabase.GetBuiltinExtraResource<Sprite>(kCheckmarkPath);
s_StandardResources.dropdown = AssetDatabase.GetBuiltinExtraResource<Sprite>(kDropdownArrowPath);
s_StandardResources.mask = AssetDatabase.GetBuiltinExtraResource<Sprite>(kMaskPath);
}
return s_StandardResources;
}
[MenuItem("GameObject/UI/Text - TextMeshPro (VRC)", false, 9)]
private static void CreateTextVRCTMP(MenuCommand menuCommand)
{
GameObject go = TMP_DefaultControls.CreateText(GetStandardResources());
TextMeshProUGUI textComponent = go.GetComponent<TextMeshProUGUI>();
textComponent.fontSize = TMP_Settings.defaultFontSize;
textComponent.color = Color.white;
textComponent.text = "New Text";
PlaceUIElementRoot(go, menuCommand);
}
[MenuItem("GameObject/UI/Button - TextMeshPro (VRC)", false, 10)]
public static void AddButton(MenuCommand menuCommand)
{
GameObject go = TMP_DefaultControls.CreateButton(GetStandardResources());
// Override font size
TMP_Text textComponent = go.GetComponentInChildren<TMP_Text>();
textComponent.fontSize = 24;
PlaceUIElementRoot(go, menuCommand);
}
[MenuItem("GameObject/UI/Dropdown - TextMeshPro (VRC)", false, 11)]
private static void CreateTextVRCDropdown(MenuCommand menuCommand)
{
GameObject go = TMP_DefaultControls.CreateDropdown(GetStandardResources());
PlaceUIElementRoot(go, menuCommand);
}
[MenuItem("GameObject/UI/Input Field - TextMeshPro (VRC)", false, 12)]
private static void CreateTextVRCInputfield(MenuCommand menuCommand)
{
GameObject go = TMP_DefaultControls.CreateInputField(GetStandardResources());
PlaceUIElementRoot(go, menuCommand);
}
// TMP Object creation code from TextMeshPro edited to place in a vrc way
private static void PlaceUIElementRoot(GameObject element, MenuCommand menuCommand)
{
GameObject parent = menuCommand.context as GameObject;
bool explicitParentChoice = true;
if (parent == null)
{
parent = GetOrCreateCanvasGameObject();
explicitParentChoice = false;
// If in Prefab Mode, Canvas has to be part of Prefab contents,
// otherwise use Prefab root instead.
PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage != null && !prefabStage.IsPartOfPrefabContents(parent))
parent = prefabStage.prefabContentsRoot;
}
if (parent.GetComponentsInParent<Canvas>(true).Length == 0)
{
// Create canvas under context GameObject,
// and make that be the parent which UI element is added under.
GameObject canvas = CreateNewUI();
Undo.SetTransformParent(canvas.transform, parent.transform, "");
parent = canvas;
}
GameObjectUtility.EnsureUniqueNameForSibling(element);
SetParentAndAlign(element, parent);
if (!explicitParentChoice) // not a context click, so center in sceneview
SetPositionVisibleinSceneView(parent.GetComponent<RectTransform>(), element.GetComponent<RectTransform>());
// This call ensure any change made to created Objects after they where registered will be part of the Undo.
Undo.RegisterFullObjectHierarchyUndo(parent == null ? element : parent, "");
// We have to fix up the undo name since the name of the object was only known after reparenting it.
Undo.SetCurrentGroupName("Create " + element.name);
Selection.activeGameObject = element;
}
// Helper function that returns a Canvas GameObject; preferably a parent of the selection, or other existing Canvas.
public static GameObject GetOrCreateCanvasGameObject()
{
GameObject selectedGo = Selection.activeGameObject;
// Try to find a gameobject that is the selected GO or one if its parents.
Canvas canvas = (selectedGo != null) ? selectedGo.GetComponentInParent<Canvas>() : null;
if (IsValidCanvas(canvas))
return canvas.gameObject;
// No canvas in selection or its parents? Then use any valid canvas.
// We have to find all loaded Canvases, not just the ones in main scenes.
Canvas[] canvasArray = StageUtility.GetCurrentStageHandle().FindComponentsOfType<Canvas>();
for (int i = 0; i < canvasArray.Length; i++)
if (IsValidCanvas(canvasArray[i]))
return canvasArray[i].gameObject;
// No canvas in the scene at all? Then create a new one.
return CreateNewUI();
}
static bool IsValidCanvas(Canvas canvas)
{
if (canvas == null || !canvas.gameObject.activeInHierarchy)
return false;
// It's important that the non-editable canvas from a prefab scene won't be rejected,
// but canvases not visible in the Hierarchy at all do. Don't check for HideAndDontSave.
if (EditorUtility.IsPersistent(canvas) || (canvas.hideFlags & HideFlags.HideInHierarchy) != 0)
return false;
if (StageUtility.GetStageHandle(canvas.gameObject) != StageUtility.GetCurrentStageHandle())
return false;
return true;
}
private static void SetParentAndAlign(GameObject child, GameObject parent)
{
if (parent == null)
return;
Undo.SetTransformParent(child.transform, parent.transform, "");
RectTransform rectTransform = child.transform as RectTransform;
if (rectTransform)
{
rectTransform.anchoredPosition = Vector2.zero;
Vector3 localPosition = rectTransform.localPosition;
localPosition.z = 0;
rectTransform.localPosition = localPosition;
}
else
{
child.transform.localPosition = Vector3.zero;
}
child.transform.localRotation = Quaternion.identity;
child.transform.localScale = Vector3.one;
SetLayerRecursively(child, parent.layer);
}
private static void SetLayerRecursively(GameObject go, int layer)
{
go.layer = layer;
Transform t = go.transform;
for (int i = 0; i < t.childCount; i++)
SetLayerRecursively(t.GetChild(i).gameObject, layer);
}
public static GameObject CreateNewUI()
{
// Root for the UI
var root = new GameObject("Canvas");
root.layer = LayerMask.NameToLayer(kUILayerName);
Canvas canvas = root.AddComponent<Canvas>();
RectTransform canvasRTransform = canvas.GetComponent<RectTransform>();
canvasRTransform.localScale = new Vector3(0.001f, 0.001f,0.001f);
canvasRTransform.sizeDelta = new Vector2(1000, 1000);
SceneView sceneView = SceneView.lastActiveSceneView;
if (sceneView == null && SceneView.sceneViews.Count > 0)
sceneView = SceneView.sceneViews[0] as SceneView;
// Couldn't find a SceneView. Don't set position.
if (sceneView != null && sceneView.camera != null)
{
Camera camera = sceneView.camera;
canvasRTransform.position = camera.transform.position + camera.transform.forward * 2;
}
canvas.renderMode = RenderMode.WorldSpace;
root.AddComponent<CanvasScaler>();
root.AddComponent<GraphicRaycaster>();
root.AddComponent<VRCUiShape>();
// Works for all stages.
StageUtility.PlaceGameObjectInCurrentStage(root);
bool customScene = false;
PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage != null)
{
root.transform.SetParent(prefabStage.prefabContentsRoot.transform, false);
customScene = true;
}
Undo.RegisterCreatedObjectUndo(root, "Create " + root.name);
// If there is no event system add one...
// No need to place event system in custom scene as these are temporary anyway.
// It can be argued for or against placing it in the user scenes,
// but let's not modify scene user is not currently looking at.
if (!customScene)
CreateEventSystem(false);
return root;
}
private static void SetPositionVisibleinSceneView(RectTransform canvasRTransform, RectTransform itemTransform)
{
// Find the best scene view
SceneView sceneView = SceneView.lastActiveSceneView;
if (sceneView == null && SceneView.sceneViews.Count > 0)
sceneView = SceneView.sceneViews[0] as SceneView;
// Couldn't find a SceneView. Don't set position.
if (sceneView == null || sceneView.camera == null)
return;
// Create world space Plane from canvas position.
Camera camera = sceneView.camera;
Vector3 position = Vector3.zero;
Vector2 localPlanePosition;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRTransform, new Vector2(camera.pixelWidth / 2, camera.pixelHeight / 2), camera, out localPlanePosition))
{
// Adjust for canvas pivot
localPlanePosition.x = localPlanePosition.x + canvasRTransform.sizeDelta.x * canvasRTransform.pivot.x;
localPlanePosition.y = localPlanePosition.y + canvasRTransform.sizeDelta.y * canvasRTransform.pivot.y;
localPlanePosition.x = Mathf.Clamp(localPlanePosition.x, 0, canvasRTransform.sizeDelta.x);
localPlanePosition.y = Mathf.Clamp(localPlanePosition.y, 0, canvasRTransform.sizeDelta.y);
// Adjust for anchoring
position.x = localPlanePosition.x - canvasRTransform.sizeDelta.x * itemTransform.anchorMin.x;
position.y = localPlanePosition.y - canvasRTransform.sizeDelta.y * itemTransform.anchorMin.y;
Vector3 minLocalPosition;
minLocalPosition.x = canvasRTransform.sizeDelta.x * (0 - canvasRTransform.pivot.x) + itemTransform.sizeDelta.x * itemTransform.pivot.x;
minLocalPosition.y = canvasRTransform.sizeDelta.y * (0 - canvasRTransform.pivot.y) + itemTransform.sizeDelta.y * itemTransform.pivot.y;
Vector3 maxLocalPosition;
maxLocalPosition.x = canvasRTransform.sizeDelta.x * (1 - canvasRTransform.pivot.x) - itemTransform.sizeDelta.x * itemTransform.pivot.x;
maxLocalPosition.y = canvasRTransform.sizeDelta.y * (1 - canvasRTransform.pivot.y) - itemTransform.sizeDelta.y * itemTransform.pivot.y;
position.x = Mathf.Clamp(position.x, minLocalPosition.x, maxLocalPosition.x);
position.y = Mathf.Clamp(position.y, minLocalPosition.y, maxLocalPosition.y);
}
itemTransform.anchoredPosition = position;
itemTransform.localRotation = Quaternion.identity;
itemTransform.localScale = Vector3.one;
}
private static void CreateEventSystem(bool select)
{
CreateEventSystem(select, null);
}
private static void CreateEventSystem(bool select, GameObject parent)
{
var esys = Object.FindFirstObjectByType<EventSystem>();
if (esys == null)
{
var eventSystem = new GameObject("EventSystem");
GameObjectUtility.SetParentAndAlign(eventSystem, parent);
esys = eventSystem.AddComponent<EventSystem>();
eventSystem.AddComponent<StandaloneInputModule>();
Undo.RegisterCreatedObjectUndo(eventSystem, "Create " + eventSystem.name);
}
if (select && esys != null)
{
Selection.activeGameObject = esys.gameObject;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 577bc48ccbd86fc4e8804e4ed36a6dac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 23f17aebd51f4e47a14b911202aadc67
timeCreated: 1687986184

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 43abf37538cf87c47bc585a3b129b533
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2ea84963dc71d3d4b9d00a0bad947493
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,5 @@
<UXML xmlns="UnityEngine.UIElements">
<VisualElement name="notification-block" class="col mt-2 mb-2 w-100 align-items-center">
<Label text="Your world was built successfully!" class="text-lg" />
</VisualElement>
</UXML>

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 236433fe0b3378242a1b83d2199b9d27
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a4675f35fd0b48947b0f1870568c7209
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

View File

@ -0,0 +1,14 @@
using UnityEngine;
using UnityEngine.UIElements;
namespace VRC.SDK3A.Editor.Elements
{
public class WorldBuildSuccessNotification: VisualElement
{
public WorldBuildSuccessNotification()
{
Resources.Load<VisualTreeAsset>("WorldBuildSuccessNotification").CloneTree(this);
styleSheets.Add(Resources.Load<StyleSheet>("WorldBuildSuccessNotificationStyles"));
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8917c827433f542428ebdaf7cc31bf34
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 204d80e392324bdd9d3501521801054b
timeCreated: 1687987392

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1a36a593f0532114eab83a5da968c0c9
timeCreated: 1687898224

View File

@ -0,0 +1,8 @@
<UXML xmlns="UnityEngine.UIElements">
<VisualElement name="notification-block" class="col mt-2 mb-2 w-100">
<Label text="Your world failed to build or upload because of the following reason" />
<Label name="notification-error-reason" class="mt-2 p-2 white-space-normal" />
<Label text="We recommend taking a look at the console for more details" class="mt-2" />
<Button class="mt-3 pl-4 pr-4 pt-2 pb-2 text-bold" text="Check Console for more details" name="open-unity-console" />
</VisualElement>
</UXML>

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ceb22344bc36ee24cb99cf412a7534d7
timeCreated: 1687898224

View File

@ -0,0 +1,3 @@
#notification-error-reason {
background-color: rgba(255,255,255,0.2);
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b7d711ed3e43b3b4cbdc2b976f450581
timeCreated: 1687898224

View File

@ -0,0 +1,20 @@
using UnityEngine;
using UnityEngine.UIElements;
using VRC.SDKBase;
namespace VRC.SDK3.Editor.Elements
{
public class WorldUploadErrorNotification: VisualElement
{
public WorldUploadErrorNotification(string error)
{
Resources.Load<VisualTreeAsset>("WorldUploadErrorNotification").CloneTree(this);
styleSheets.Add(Resources.Load<StyleSheet>("WorldUploadErrorNotificationStyles"));
this.Q<Label>("notification-error-reason").text = error;
var openUnityConsole = this.Q<Button>("open-unity-console");
openUnityConsole.clicked += VRC_EditorTools.OpenConsoleWindow;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 75cec36013175db44880a380b8f9b334
timeCreated: 1687898224

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d4c631740417436d826d7897a41ade5b
timeCreated: 1687987392

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5aa8a359743c55245afd9d6e2d2ab053
timeCreated: 1687895445

View File

@ -0,0 +1,6 @@
<UXML xmlns="UnityEngine.UIElements">
<VisualElement name="notification-block" class="col mt-2 mb-2 w-100 align-items-center">
<Label text="Your world was published to VRChat!" class="text-lg" />
<Button class="mt-3 pl-4 pr-4 pt-2 pb-2 text-bold" text="See it on the VRChat Website" name="open-world-page-button" />
</VisualElement>
</UXML>

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e0cb08821623b5c46ae5e6a0b1f3e2b1
timeCreated: 1687895455

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 501977f645ca1b947b49df74d5162a8b
timeCreated: 1687895466

View File

@ -0,0 +1,20 @@
using UnityEngine;
using UnityEngine.UIElements;
namespace VRC.SDK3.Editor.Elements
{
public class WorldUploadSuccessNotification: VisualElement
{
public WorldUploadSuccessNotification(string id)
{
Resources.Load<VisualTreeAsset>("WorldUploadSuccessNotification").CloneTree(this);
styleSheets.Add(Resources.Load<StyleSheet>("WorldUploadSuccessNotificationStyles"));
var openWorldPageButton = this.Q<Button>("open-world-page-button");
openWorldPageButton.clicked += () =>
{
Application.OpenURL($"https://vrchat.com/home/world/{id}");
};
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 11e30a0715a549f4086eadde63e2d2de
timeCreated: 1687895210

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6a3d4a940f274e42a8c0de5d08c7866c
timeCreated: 1687987606

View File

@ -0,0 +1,120 @@
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using UnityEngine;
using VRC.SDKBase.Editor;
using VRC.SDKBase.Editor.Api;
namespace VRC.SDK3.Editor
{
/// <summary>
/// This is the public interface you can use to interact with the Worlds SDK Builder
/// </summary>
public interface IVRCSdkWorldBuilderApi : IVRCSdkBuilderApi
{
/// <summary>
/// Builds the currently open scene and returns a path to the built world bundle.
/// Make sure the world has a valid SceneDescriptor and PipelineManager components present.
/// </summary>
/// <returns>Path to the bundle</returns>
/// <exception cref="BuilderException">Build process has encountered an error</exception>
/// <exception cref="BuildBlockedException">Build was blocked by the SDK Callback</exception>
/// <exception cref="ValidationException">Content has validation errors</exception>
[PublicAPI]
Task<string> Build();
/// <summary>
/// Builds the currently open scene and returns a path + signature of the newly built bundle.
/// Make sure the world has a valid SceneDescriptor and PipelineManager components present.
/// </summary>
/// <returns>Tuple containing the path to the bundle and its signature</returns>
/// <exception cref="BuilderException">Build process has encountered an error</exception>
/// <exception cref="BuildBlockedException">Build was blocked by the SDK Callback</exception>
/// <exception cref="ValidationException">Content has validation errors</exception>
[PublicAPI]
Task<(string path, string signature)> BuildWithSignature();
/// <summary>
/// Builds and uploads the currently open scene for the VRCWorld specified.
/// Make sure the world has a valid SceneDescriptor and PipelineManager components present
/// </summary>
/// <param name="world">VRCWorld object with world info. Must have a Name for world creation</param>
/// <param name="thumbnailPath">Path to the thumbnail image on disk. Must be specified for world creation</param>
/// <param name="cancellationToken"></param>
/// <exception cref="BuilderException">Build process has encountered an error</exception>
/// <exception cref="BuildBlockedException">Build was blocked by the SDK Callback</exception>
/// <exception cref="ValidationException">Content has validation errors</exception>
/// <exception cref="OwnershipException">Current User does not own the target content</exception>
/// <exception cref="UploadException">Content failed to upload</exception>
/// <exception cref="BundleExistsException">This exact bundle was already uploaded</exception>
[PublicAPI]
Task BuildAndUpload(VRCWorld world, string thumbnailPath = null, CancellationToken cancellationToken = default);
/// <summary>
/// Builds and uploads the currently open scene for the VRCWorld specified.
/// Make sure the world has a valid SceneDescriptor and PipelineManager components present
/// </summary>
/// <param name="world">VRCWorld object with world info. Must have a Name for world creation</param>
/// <param name="signature">Bundle signature provided by the SDK</param>
/// <param name="thumbnailPath">Path to the thumbnail image on disk. Must be specified for world creation</param>
/// <param name="cancellationToken"></param>
/// <exception cref="BuilderException">Build process has encountered an error</exception>
/// <exception cref="BuildBlockedException">Build was blocked by the SDK Callback</exception>
/// <exception cref="ValidationException">Content has validation errors</exception>
/// <exception cref="OwnershipException">Current User does not own the target content</exception>
/// <exception cref="UploadException">Content failed to upload</exception>
/// /// <exception cref="BundleExistsException">This exact bundle was already uploaded</exception>
[PublicAPI]
Task BuildAndUpload(VRCWorld world, string signature, string thumbnailPath = null,
CancellationToken cancellationToken = default);
/// <summary>
/// Starts a multi-platform build chain for the currently open scene
/// This will automatically switch the editor to each of the supported platforms and perform a build+upload
/// If any of the platforms encounter an error, the build chain will be stopped and the error will be thrown similar to BuildAndUpload
/// </summary>
/// <param name="world">VRCWorld object with world info. Must have a Name for world creation</param>
/// <param name="thumbnailPath">Path to the thumbnail image on disk. Must be specified for world creation</param>
/// <param name="cancellationToken"></param>
/// <exception cref="BuilderException">Build process has encountered an error</exception>
/// <exception cref="BuildBlockedException">Build was blocked by the SDK Callback</exception>
/// <exception cref="ValidationException">Content has validation errors</exception>
/// <exception cref="OwnershipException">Current User does not own the target content</exception>
/// <exception cref="UploadException">Content failed to upload</exception>
/// <exception cref="BundleExistsException">This exact bundle was already uploaded</exception>
[PublicAPI]
Task BuildAndUploadMultiPlatform(VRCWorld world, string thumbnailPath = null,
CancellationToken cancellationToken = default);
/// <summary>
/// Builds the currently open scene and launches / reloads a test client
/// </summary>
/// <exception cref="BuilderException">Build process has encountered an error</exception>
/// <exception cref="BuildBlockedException">Build was blocked by the SDK Callback</exception>
/// <exception cref="ValidationException">Content has validation errors</exception>
[PublicAPI]
Task BuildAndTest();
/// <summary>
/// Reopens / reloads the test clients with the last built world
/// </summary>
/// <exception cref="BuilderException">Build process has encountered an error</exception>
/// <exception cref="BuildBlockedException">Build was blocked by the SDK Callback</exception>
/// <exception cref="ValidationException">Content has validation errors</exception>
[PublicAPI]
Task TestLastBuild();
/// <summary>
/// Uploads the last built world for the VRCWorld specified
/// </summary>
/// <param name="world">VRCWorld object with world info. Must have a Name for world creation</param>
/// <param name="thumbnailPath">Path to the thumbnail image on disk. Must be specified for world creation</param>
/// <param name="cancellationToken"></param>
/// <exception cref="OwnershipException">Current User does not own the target content</exception>
/// <exception cref="UploadException">Content failed to upload</exception>
/// <exception cref="BundleExistsException">This exact bundle was already uploaded</exception>
[PublicAPI]
Task UploadLastBuild(VRCWorld world, string thumbnailPath = null,
CancellationToken cancellationToken = default);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: dd8923a5088f4aa89bcd97d8cdab1dbe
timeCreated: 1687987621

View File

@ -0,0 +1,63 @@
using System;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace VRC.SDK3.Editor
{
public class PublishConfirmationWindow: PopupWindowContent
{
//Set the window size
public override Vector2 GetWindowSize()
{
return new Vector2(400, 300);
}
public override void OnGUI(Rect rect)
{
// Intentionally left empty
}
private string _title;
private string _text;
private string _yesText;
private string _noText;
private Action _yesAction;
private Action _noAction;
public PublishConfirmationWindow(string title, string text, string yesText, string noText, Action yesAction = null, Action noAction = null)
{
_title = title;
_text = text;
_yesText = yesText;
_noText = noText;
_yesAction = yesAction;
_noAction = noAction;
}
private VisualElement _r;
public override void OnOpen()
{
_r = editorWindow.rootVisualElement;
Resources.Load<VisualTreeAsset>("PublishConfirmationWindow").CloneTree(_r);
_r.styleSheets.Add(Resources.Load<StyleSheet>("PublishConfirmationWindowStyles"));
_r.styleSheets.Add(Resources.Load<StyleSheet>("VRCSdkPanelStyles"));
_r.Q<Label>("title").text = _title;
_r.Q<Label>("body").text = _text;
_r.Q<Button>("yes-button").text = _yesText;
_r.Q<Button>("no-button").text = _noText;
if (_yesAction != null)
{
_r.Q<Button>("yes-button").clicked += _yesAction;
}
_r.Q<Button>("yes-button").clicked += editorWindow.Close;
if (_noAction != null)
{
_r.Q<Button>("no-button").clicked += _noAction;
}
_r.Q<Button>("no-button").clicked += editorWindow.Close;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6ef91745551f415993180eaec9a0c74d
timeCreated: 1691082161

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f9556a92e1094bbea79b9f30db892d9a
timeCreated: 1687972218

View File

@ -0,0 +1,12 @@
<UXML xmlns="UnityEngine.UIElements">
<ScrollView>
<VisualElement name="root" class="p-2">
<Label name="title" class="header3 mb-2" />
<Label name="body" enable-rich-text="true" class="mt-2 mb-2 white-space-normal" />
<VisualElement class="mb-2 row align-items-center w-100">
<Button class="mr-2 bg-button-bg flex-1 pt-2 pb-2" name="yes-button" />
<Button name="no-button" class="flex-1 pt-2 pb-2" />
</VisualElement>
</VisualElement>
</ScrollView>
</UXML>

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 019a4b561d5d4614a85046e7a1c58751
timeCreated: 1691075541

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: da1f468c8c7846afab7d03f3f4c52139
timeCreated: 1691075553

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

View File

@ -0,0 +1,140 @@
fileFormatVersion: 2
guid: babec5659a990ea42ae98eef1116739c
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,48 @@
<UXML xmlns="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xmlns:vrc="VRC.SDKBase.Editor.Elements">
<VisualElement class="col relative" name="section-3">
<VisualElement class="mt-2 col pr-2 pl-2" name="build-buttons-block">
<VisualElement class="row">
<VisualElement class="col flex-grow-1 align-items-start mr-3" name="build-type-container">
<Label class="d-flex mt-2 mb-2 text-bold" text="Build Type" />
<!-- build-type-dropdown gets inserted here -->
</VisualElement>
<VisualElement class="col" name="platform-container">
<vrc:PlatformSwitcherPopup label="Platform(s)" name="platform-switcher-popup" />
</VisualElement>
<VisualElement class="col ml-3" name="num-clients-container">
<Label class="ml-0 mr-1 mt-2 mb-2 pr-2 d-flex text-bold" text="Clients" />
<uie:IntegerField name="num-clients" class="ml-0" value="1"/>
</VisualElement>
</VisualElement>
<VisualElement class="row justify-content-between">
<VisualElement class="row" name="force-non-vr-container">
<Toggle name="force-non-vr"/>
<Label text="Force Non-VR" class="white-space-normal m-2 options-text-color" />
</VisualElement>
<VisualElement class="row" name="enable-world-reload-container">
<Label text="Enable World Reload" class="white-space-normal m-2 options-text-color" />
<Toggle name="enable-world-reload"/>
</VisualElement>
</VisualElement>
<VisualElement class="mt-2">
<Button name="main-action-button" class="pt-4 pb-4 text-lg text-bold ml-0 mr-0" />
<VisualElement name="main-action-disabled-block" class="d-none absolute text-lg text-bold text-grey-200">
<Label name="main-action-disabled-text" text="You must fix the issues listed above before you can Upload a Build" class="white-space-normal" />
</VisualElement>
</VisualElement>
<VisualElement class="row justify-content-between">
<VisualElement class="row m-2 d-none">
<Label text="Run Performance Streaming" class="ml-2 flex-shrink-1 white-space-normal pr-2 options-text-color text-right" />
<Toggle name="run-performance-streaming" />
</VisualElement>
</VisualElement>
</VisualElement>
<VisualElement class="d-none" name="v3-block" />
<vrc:BuilderProgress name="progress-bar" />
</VisualElement>
</UXML>

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fddc9f028e2d45a097fc34a58821d37b
timeCreated: 1685525413

View File

@ -0,0 +1,8 @@
#local-test-settings Toggle {
border-bottom-width: 0;
background-color: rgba(0,0,0,0);
}
#local-test-settings Toggle Label {
-unity-font-style: normal;
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3924ac38bc424700bf8f1f30557680d2
timeCreated: 1687972283

View File

@ -0,0 +1,90 @@
<UXML xmlns="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xmlns:vrc="VRC.SDKBase.Editor.Elements">
<VisualElement class="row pt-2 pl-2 pr-2 pb-2 flex-grow-1" name="content-info">
<VisualElement class="col mr-2 flex-7">
<vrc:VRCTextField class="content-info-field mb-2" required="true" label="Name" placeholder="Enter your world's public name..." name="content-name" vertical="true" />
<VisualElement class="row mb-2 m-unity-field">
<VisualElement class="col flex-1">
<VisualElement class="row align-items-center justify-content-between w-100 mb-1">
<Label class="text-bold" text="Max. Capacity" />
<Button class="help-button" tooltip="What is Maximum Capacity" name="show-capacity-help-button" />
</VisualElement>
<uie:IntegerField tooltip="Maximum capacity" class="ml-0" value="32" name="content-capacity" required="true" />
</VisualElement>
<VisualElement class="col flex-1">
<VisualElement class="row align-items-center justify-content-between w-100 mb-1">
<Label class="text-bold" text="Rec. Capacity" />
<Button class="help-button" tooltip="What is Recommended Capacity" name="show-recommended-capacity-help-button" />
</VisualElement>
<uie:IntegerField tooltip="Recommended Capacity" class="ml-0 mr-0" value="16" name="content-recommended-capacity" />
</VisualElement>
</VisualElement>
<VisualElement class="row m-unity-field" name="warnings-tags-block">
<VisualElement class="col flex-1">
<vrc:ContentWarningsField label="Content Warnings" class="mb-2 mr-unity-field" name="content-warnings" />
</VisualElement>
<VisualElement class="col flex-1">
<vrc:TagsField label="Tags" class="content-info-field w-100 mt-2" name="content-tags" />
</VisualElement>
</VisualElement>
<vrc:VRCTextField class="content-info-field mb-2" label="Description" multiline="true" placeholder="Describe world so it is easier to find!" name="content-description" vertical="true" />
<VisualElement class="row mb-3">
<VisualElement class="col m-unity-field mt-2">
<Label class="field-label text-bold mb-2" text="Last Updated" />
<Label text="Loading..." name="last-updated-label" />
</VisualElement>
<VisualElement class="col m-unity-field mt-2">
<Label class="field-label text-bold mb-2" text="Version" />
<Label text="Loading..." name="version-label" />
</VisualElement>
</VisualElement>
<VisualElement class="col m-unity-field">
<Label class="field-label text-bold mb-2" text="Supported Platforms" />
<Label text="Loading..." name="content-platform-info" />
</VisualElement>
<VisualElement class="mt-2 mb-2 w-100 col d-none">
<VisualElement class="row align-items-center m-unity-field">
<Label class="field-label" text="Current Visibility" />
<Label text="Loading..." name="visibility-label" />
</VisualElement>
<VisualElement class="mt-2 d-none row align-items-center" name="publish-block">
<Button name="publish-button" class="flex-grow-1" />
<Button class="help-button" tooltip="Learn more about Community Labs" name="community-labs-help-button" />
</VisualElement>
</VisualElement>
</VisualElement>
<VisualElement class="col flex-5">
<VisualElement name="visibility-block" class="col mb-2" />
<vrc:Modal title="Publish to Community Labs" name="labs-publish-modal">
<VisualElement class="col p-3">
<Label class="white-space-normal mb-2" text="Publishing this world will put it in to the Community Labs" />
<Label class="white-space-normal mb-2" text="Other users will be able to see your world, and it will either stay in the Labs, get promoted to Public status, or be placed back in to Private status, based on community response." />
<Label class="white-space-normal mb-2" text="We encourage you to get the word out about your world if you want it to survive! If your world violates our Community Guidelines, you could get in trouble by posting it!" />
<Label class="white-space-normal" text="You're only allowed to publish one world per week, so make sure to put your best foot forward!" />
</VisualElement>
<VisualElement class="row pl-3 pr-3 pb-3">
<Button text="Yes, do it!" name="publish-to-labs-btn" class="flex-1 ml-0" />
<Button text="No, keep the world private" name="publish-to-labs-cancel-btn" class="flex-1 mr-0" />
</VisualElement>
</vrc:Modal>
<vrc:Modal title="Unpublishing a World" name="unpublish-modal">
<VisualElement class="col p-3">
<Label class="white-space-normal mb-2" text="Unpublishing this world will remove it from Public." />
<Label class="white-space-normal mb-2" text="If you want to make it public again, it will need to go through Community Labs." />
<Label class="white-space-normal mb-2" text="You're only allowed to publish one world per week, and when you remove a world from the labs, you don't get your one world back. Are you sure?" />
</VisualElement>
<VisualElement class="row pl-3 pr-3 pb-3">
<Button text="Yes, do it!" name="unpublish-btn" class="flex-1 ml-0" />
<Button text="No, keep the world public" name="unpublish-cancel-btn" class="flex-1 mr-0" />
</VisualElement>
</vrc:Modal>
<VisualElement class="col m-unity-field">
<vrc:ThumbnailBlock />
</VisualElement>
<VisualElement class="row align-items-center justify-content-end m-unity-field">
<Label text="World Debugging" class="field-label text-right mr-2" />
<Toggle name="world-debugging-toggle" class="top-05 relative" />
<Button class="help-button" tooltip="What is World Debugging" name="show-world-debugging-help-button" />
</VisualElement>
</VisualElement>
</VisualElement>
</UXML>

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f7edf86396674750aa7d941446bba8fe
timeCreated: 1684521742

View File

@ -0,0 +1,19 @@
#world-debugging-toggle {
border-bottom-width: 0;
background-color: rgba(0,0,0,0);
padding-left: 0;
}
#visibility-block PopupField {
flex-direction: column;
}
#visibility-block PopupField > Label {
font-size: 12px;
-unity-font-style: bold;
margin-bottom: 5px;
padding-top: 0;
}
#content-description {
min-height: 77px;
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 140c4a1abe4d4a5bb6ebfc5853bd8f22
timeCreated: 1687972622

View File

@ -0,0 +1,48 @@
using System.IO;
using System.Threading.Tasks;
using UnityEditor;
using VRC.SDKBase.Editor.Source.Helpers;
namespace VRC.SDK3.Editor
{
[InitializeOnLoad]
public class SDK3ImportFix
{
private const string worldsReimportedKey = "WORLDS_REIMPORTED";
static SDK3ImportFix()
{
// Skip if we've already checked for the canary file during this Editor Session
if (!SessionState.GetBool(worldsReimportedKey, false))
{
// Check for canary file in Library - package probably needs a reimport after a Library wipe
string canaryFilePath = Path.Combine("Library", worldsReimportedKey);
if (File.Exists(canaryFilePath))
{
SessionState.SetBool(worldsReimportedKey, true);
}
else
{
#pragma warning disable 4014
ReloadSDK();
#pragma warning restore 4014
File.WriteAllText(canaryFilePath, worldsReimportedKey);
}
}
}
public static async Task ReloadSDK()
{
// Set session key to true, limiting the reload to one run per session
SessionState.SetBool(worldsReimportedKey, true);
//Wait for project to finish compiling
while (EditorApplication.isCompiling || EditorApplication.isUpdating)
{
await Task.Delay(250);
}
ReloadUtil.ReloadSDK();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 857dfa28ea5a4d00b87e04081e0d68e2
timeCreated: 1632519867

View File

@ -0,0 +1,71 @@
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
namespace VRC.SDK3.Editor
{
public class SampleImporter
{
private const string exampleScenePath =
"Packages/com.vrchat.worlds/Samples/UdonExampleScene/UdonExampleScene.unity";
private const string ccplayerhitScenePath =
"Packages/com.vrchat.worlds/Samples/OnControllerColliderHitExampleScene/OnControllerColliderHitSampleScene.unity";
private const string minimapScenePath =
"Packages/com.vrchat.worlds/Samples/GraphicsBlitExampleScene/Minimap Sample Scene.unity";
private const string midiPlaybackScenePath =
"Packages/com.vrchat.worlds/Samples/MidiPlaybackExampleScene/MidiPlaybackScene.unity";
private const string aiNavigationScenePath =
"Packages/com.vrchat.worlds/Samples/AINavmeshScene/AINavmeshSceneExample.unity";
[MenuItem("VRChat SDK/Samples/UdonExampleScene", false, 981)]
private static void OpenSampleUdonExampleScene()
{
if(EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
EditorSceneManager.OpenScene(exampleScenePath);
}
}
[MenuItem("VRChat SDK/Samples/ControllerColliderPlayerHit", false, 982)]
private static void OpenCCPlayerHitExampleScene()
{
if(EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
EditorSceneManager.OpenScene(ccplayerhitScenePath);
}
}
[MenuItem("VRChat SDK/Samples/Minimap", false, 983)]
private static void OpenMinimapExampleScene()
{
if(EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
EditorSceneManager.OpenScene(minimapScenePath);
}
}
[MenuItem("VRChat SDK/Samples/MidiPlayback", false, 984)]
private static void OpenMidiPlaybackExampleScene()
{
if(EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
EditorSceneManager.OpenScene(midiPlaybackScenePath);
}
}
[MenuItem("VRChat SDK/Samples/Show Sample Documentation", false, 985)]
private static void ShowSampleDocumentation()
{
Application.OpenURL("https://creators.vrchat.com/worlds/examples/");
}
[MenuItem("VRChat SDK/Samples/AI Navigation")]
private static void OpenAINavigationScene()
{
if(EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
EditorSceneManager.OpenScene(aiNavigationScenePath);
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5b56ebc0667f4a2eb02271d4b50dfb25
timeCreated: 1674684606

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f0b73331be6c26f4b89114d305cf4b19
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 81474508413c9834f828b4df9f6ea8b8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,16 @@
#listinginfo-elem {
flex-direction: row;
align-items: center;
}
#copylisting-btn {
flex-grow: 0;
}
#copygroup-btn {
flex-grow: 1;
}
#groupinfo-label {
flex-grow: 1;
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d224dc29736cb9841a28474730e7cab2
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

View File

@ -0,0 +1,8 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:VisualElement name="listinginfo-elem" >
<Style src="ListingInfo.uss" />
<ui:Button text="Copy Listing ID" name="copylisting-btn" />
<ui:Button text="Copy Group ID" name="copygroup-btn" />
<ui:Label text="This listing is not used in any group." name="groupinfo-label" />
</ui:VisualElement>
</ui:UXML>

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 6724ec48439eb974296016be79041d9a
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@ -0,0 +1,100 @@
#product-elem {
height: 64px;
flex-direction: row;
margin-top: 2px;
margin-bottom: 2px;
}
#image-elem {
width: 64px;
flex-shrink: 0;
background-color: rgba(0, 0, 0, 0);
border-left-width: 1px;
border-right-width: 1px;
border-top-width: 1px;
border-bottom-width: 1px;
margin-left: 0;
margin-right: 5px;
margin-top: 0;
margin-bottom: 0;
border-left-color: rgba(0, 0, 0, 0.25);
border-right-color: rgba(0, 0, 0, 0.25);
border-top-color: rgba(0, 0, 0, 0.25);
border-bottom-color: rgba(0, 0, 0, 0.25);
}
#imagefetch-btn {
height: auto;
width: auto;
flex-grow: 1;
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
white-space: normal;
flex-basis: 0;
}
#imagedelete-btn {
height: 12px;
width: 12px;
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
white-space: nowrap;
flex-grow: 0;
-unity-font-style: bold;
-unity-text-align: middle-center;
font-size: 12px;
border-left-width: 0;
border-right-width: 0;
border-top-width: 0;
border-bottom-width: 0;
position: absolute;
left: 50px;
}
#text-elem {
font-size: 12px;
width: 100%;
}
#name-label {
-unity-font-style: bold;
font-size: 14px;
flex-wrap: wrap;
flex-shrink: 1;
overflow: hidden;
}
#desc-label {
white-space: normal;
flex-wrap: wrap;
font-size: 11px;
-unity-font-style: normal;
flex-shrink: 1;
overflow: hidden;
}
#buttons-elem {
flex-grow: 1;
display: flex;
width: 112px;
flex-shrink: 0;
max-width: 112px;
}
#customgui-elem > Button {
flex-grow: 1;
}
#customgui-elem {
display: none;
flex-grow: 1;
}
#find-btn {
flex-grow: 1;
white-space: normal;
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7a117358ea147804091dc5ea3caff5e5
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

View File

@ -0,0 +1,17 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:VisualElement name="product-elem">
<Style src="UdonProduct.uss" />
<ui:VisualElement name="image-elem" tooltip="Fetched product images are stored in your Unity project, which may increase the size of your world. It is recommended to only fetch the images if you plan on using them with Udon.">
<ui:Button text="Fetch image" name="imagefetch-btn" />
<ui:Button text="✖" name="imagedelete-btn" />
</ui:VisualElement>
<ui:VisualElement name="text-elem" >
<ui:Label text="Product A" binding-path="_Name" name="name-label" />
<ui:Label text="Description of the product, this is a description of the product right here as you can see. " binding-path="_Description" name="desc-label" />
</ui:VisualElement>
<ui:VisualElement name="buttons-elem" >
<ui:VisualElement name="customgui-elem" />
<ui:Button text="Find in project" name="find-btn" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 812df186f845ade4aa400a80e7aa8577
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@ -0,0 +1,29 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:VisualElement name="header-elem">
<Style src="UdonProductsManager_Common.uss" />
<ui:VisualElement name="logintext-elem" class="infobox error">
<ui:Label text="You need to be logged in before fetching the details of Udon products." name="logintext-label" />
</ui:VisualElement>
<ui:Button text="Import/Refresh all UdonProducts" name="importrefresh-btn" />
<ui:VisualElement name="importbrowse-elem">
<ui:Label text="Import in..." name="importbrowse-label" />
<ui:TextField readonly="true" focusable="false" binding-path="importPath" name="importbrowse-textfield" />
<uie:ToolbarButton text="Browse" name="importbrowse-btn" />
</ui:VisualElement>
<ui:VisualElement name="sort-elem">
<uie:ToolbarToggle focusable="false" label="Sort by Scene/Project" name="sortbyproject-btn" />
<uie:ToolbarToggle focusable="false" label="Sort by Listings" name="sortbylistings-btn" />
</ui:VisualElement>
<uie:ToolbarSearchField focusable="true" name="searchbar-input" style="display: none;" />
</ui:VisualElement>
<ui:VisualElement name="main-elem">
<Style src="UdonProductsManager_Common.uss" />
<ui:ScrollView name="main-scrollview" />
</ui:VisualElement>
<ui:VisualElement name="footer-elem" >
<Style src="UdonProductsManager_Common.uss" />
<ui:VisualElement name="infobox-elem" class="infobox" style="visibility: hidden;">
<ui:Label name="infobox-label" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 4f37d939a10aa6f4db958867a3134583
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@ -0,0 +1,124 @@
#logintext-elem {
margin-top: 2px;
margin-bottom: 2px;
}
#infobox-elem {
width: 100%;
min-width: 100%;
flex-grow: 1;
}
#infobox-label {
white-space: normal;
justify-content: center;
overflow: hidden;
}
.infobox {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
border-left-width: 1px;
border-right-width: 1px;
border-top-width: 1px;
border-bottom-width: 1px;
}
.infobox > Label {
-unity-text-align: middle-left;
flex-grow: 1;
padding-left: 6px;
}
#header-elem {
padding-top: 5px;
padding-bottom: 1px;
padding-right: 5px;
padding-left: 5px;
background-color: rgba(0, 0, 0, 0.15);
border-bottom-width: 2px;
border-bottom-color: rgba(0, 0, 0, 0.1);
flex-shrink: 0;
}
#footer-elem {
padding-top: 5px;
padding-bottom: 5px;
padding-right: 5px;
padding-left: 5px;
background-color: rgba(0, 0, 0, 0.15);
border-top-width: 2px;
border-top-color: rgba(0, 0, 0, 0.1);
flex-shrink: 0;
}
#importrefresh-btn {
margin-right: 0;
margin-left: 0;
margin-top: 2px;
margin-bottom: 2px;
}
#sort-elem {
flex-direction: row;
padding-top: 1px;
padding-bottom: 1px;
}
#sortbyproject-btn, #sortbylistings-btn
{
flex-grow: 1;
}
#searchbar-input {
width: auto;
height: auto;
margin-right: 0;
margin-left: 0;
display: none;
}
#main-elem {
height: auto;
padding-left: 0;
padding-right: 0;
padding-top: 5px;
padding-bottom: 5px;
flex-direction: column;
flex-grow: 1;
opacity: 1;
}
#main-scrollview {
padding-left: 5px;
padding-right: 5px;
}
#logintext-elem {
margin-top: 2px;
margin-bottom: 2px;
}
#importbrowse-elem {
flex-direction: row;
margin-top: 2px;
margin-bottom: 2px;
}
#importbrowse-label {
-unity-text-align: middle-left;
}
#importbrowse-textfield {
flex-grow: 1;
}
#footer-elem {
min-height: 3%;
flex-direction: column-reverse;
justify-content: flex-start;
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f4ea363175552f5448a58f058e68e1c0
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

View File

@ -0,0 +1,27 @@
.infobox {
border-color: rgb(35, 35, 35);
background-color: rgba(96, 96, 96, 0.2);
}
.infobox > Label {
color: rgb(189, 189, 189);
}
.infobox.warning {
border-color: rgba(255, 215, 0, 0.5);
background-color: rgba(255, 215, 0, 0.25);
}
.infobox.warning > Label {
color: rgb(255, 215, 0);
}
.infobox.error {
border-color: rgba(255, 0, 0, 0.5);
background-color: rgba(255, 0, 0, 0.1);
}
.infobox.error > Label {
color: rgb(255, 100, 100);
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bbc798c6928475444a1e396633f50b3d
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

View File

@ -0,0 +1,26 @@
.infobox {
border-color: rgba(0, 0, 0, 0.27);
background-color: rgba(235, 235, 235, 0.2);
}
.infobox > Label {
color: rgba(22, 22, 22, 255);
}
.infobox.warning {
border-color: rgba(255, 215, 0, 0.5);
background-color: rgba(255, 215, 0, 0.25);
}
.infobox.warning > Label {
color: rgb(255, 255, 200);
}
.infobox.error {
border-color: rgba(255, 0, 0, 0.5);
background-color: rgba(255, 0, 0, 0.1);
}
.infobox.error > Label {
color: rgb(166, 28, 28);
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5674ec0d53513c2438781be77c07e365
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e86b4bbd3fb4fa44fbe478e1e59b73e2
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,701 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
OcclusionCullingSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
m_SceneGUID: 00000000000000000000000000000000
m_OcclusionCullingData: {fileID: 0}
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 9
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.6037736, g: 0.6037736, b: 0.6037736, a: 1}
m_AmbientEquatorColor: {r: 0.3542186, g: 0.36578855, b: 0.3773585, a: 1}
m_AmbientGroundColor: {r: 0.1981132, g: 0.19344072, b: 0.18409576, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 1
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
m_SkyboxMaterial: {fileID: 2100000, guid: 21221da753878694b9b9518a540dda85, type: 2}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.3322065, g: 0.3627174, b: 0.46474278, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 12
m_GIWorkflowMode: 1
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 1
m_EnableRealtimeLightmaps: 1
m_LightmapEditorSettings:
serializedVersion: 12
m_Resolution: 2
m_BakeResolution: 40
m_AtlasSize: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_ExtractAmbientOcclusion: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 256
m_ReflectionCompression: 2
m_MixedBakeMode: 2
m_BakeBackend: 1
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 500
m_PVRBounces: 2
m_PVREnvironmentSampleCount: 500
m_PVREnvironmentReferencePointCount: 2048
m_PVRFilteringMode: 2
m_PVRDenoiserTypeDirect: 0
m_PVRDenoiserTypeIndirect: 0
m_PVRDenoiserTypeAO: 0
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVREnvironmentMIS: 0
m_PVRCulling: 1
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 112000000, guid: 93758136d0b55324482fcfce76a34bff,
type: 2}
m_LightingSettings: {fileID: 4890085278179872738, guid: 7774fab823fc47d4283c662c6d671e8d,
type: 2}
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 3
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
buildHeightMesh: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &358170787
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 358170790}
- component: {fileID: 358170789}
- component: {fileID: 358170788}
m_Layer: 0
m_Name: EventSystem
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &358170788
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 358170787}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
m_Name:
m_EditorClassIdentifier:
m_SendPointerHoverToParent: 1
m_HorizontalAxis: Horizontal
m_VerticalAxis: Vertical
m_SubmitButton: Submit
m_CancelButton: Cancel
m_InputActionsPerSecond: 10
m_RepeatDelay: 0.5
m_ForceModuleActive: 0
--- !u!114 &358170789
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 358170787}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1
m_DragThreshold: 10
--- !u!4 &358170790
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 358170787}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1069902874
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1069902877}
- component: {fileID: 1069902876}
- component: {fileID: 1069902875}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &1069902875
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1069902874}
m_Enabled: 1
--- !u!20 &1069902876
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1069902874}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 0
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 1
m_AllowMSAA: 1
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &1069902877
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1069902874}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1.5, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1787983409
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1787983411}
- component: {fileID: 1787983410}
m_Layer: 0
m_Name: Directional Light
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!108 &1787983410
Light:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1787983409}
m_Enabled: 1
serializedVersion: 10
m_Type: 1
m_Shape: 0
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_Intensity: 1
m_Range: 10
m_SpotAngle: 30
m_InnerSpotAngle: 21.80208
m_CookieSize: 10
m_Shadows:
m_Type: 2
m_Resolution: -1
m_CustomResolution: -1
m_Strength: 1
m_Bias: 0.05
m_NormalBias: 0.4
m_NearPlane: 0.2
m_CullingMatrixOverride:
e00: 1
e01: 0
e02: 0
e03: 0
e10: 0
e11: 1
e12: 0
e13: 0
e20: 0
e21: 0
e22: 1
e23: 0
e30: 0
e31: 0
e32: 0
e33: 1
m_UseCullingMatrixOverride: 0
m_Cookie: {fileID: 0}
m_DrawHalo: 0
m_Flare: {fileID: 0}
m_RenderMode: 0
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingLayerMask: 1
m_Lightmapping: 4
m_LightShadowCasterMode: 0
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
m_UseBoundingSphereOverride: 0
m_UseViewFrustumForShadowCasterCull: 1
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!4 &1787983411
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1787983409}
serializedVersion: 2
m_LocalRotation: {x: 0.73976463, y: 0.34240803, z: 0.05048304, w: 0.5770238}
m_LocalPosition: {x: 0, y: 6, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 55, y: 125, z: 100}
--- !u!114 &3231720197660963110
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3480278762663670689}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 45115577ef41a5b4ca741ed302693907, type: 3}
m_Name:
m_EditorClassIdentifier:
interactTextPlacement: {fileID: 0}
interactText: Use
interactTextGO: {fileID: 0}
proximity: 2
SynchronizePosition: 0
AllowCollisionOwnershipTransfer: 0
Reliable: 0
_syncMethod: 1
serializedProgramAsset: {fileID: 11400000, guid: 21a13e0a0a257474f97830fdcc78b27e,
type: 2}
programSource: {fileID: 11400000, guid: c8df303ceb45ae84f85a11591f741734, type: 2}
serializedPublicVariablesBytesString: Ai8AAAAAATIAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAFQAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAAAAAAYBAAAAAAAAACcBBAAAAHQAeQBwAGUAAWgAAABTAHkAcwB0AGUAbQAuAEMAbwBsAGwAZQBjAHQAaQBvAG4AcwAuAEcAZQBuAGUAcgBpAGMALgBMAGkAcwB0AGAAMQBbAFsAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4ALgBJAG4AdABlAHIAZgBhAGMAZQBzAC4ASQBVAGQAbwBuAFYAYQByAGkAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AXQBdACwAIABtAHMAYwBvAHIAbABpAGIAAQEJAAAAVgBhAHIAaQBhAGIAbABlAHMALwEAAAABaAAAAFMAeQBzAHQAZQBtAC4AQwBvAGwAbABlAGMAdABpAG8AbgBzAC4ARwBlAG4AZQByAGkAYwAuAEwAaQBzAHQAYAAxAFsAWwBWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAEkAbgB0AGUAcgBmAGEAYwBlAHMALgBJAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgBdAF0ALAAgAG0AcwBjAG8AcgBsAGkAYgABAAAABgQAAAAAAAAAAi8CAAAAAUoAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAGAAMQBbAFsAUwB5AHMAdABlAG0ALgBTAGkAbgBnAGwAZQAsACAAbQBzAGMAbwByAGwAaQBiAF0AXQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAgAAAAYCAAAAAAAAACcBBAAAAHQAeQBwAGUAARcAAABTAHkAcwB0AGUAbQAuAFMAdAByAGkAbgBnACwAIABtAHMAYwBvAHIAbABpAGIAJwEKAAAAUwB5AG0AYgBvAGwATgBhAG0AZQABCwAAAGoAdQBtAHAASQBtAHAAdQBsAHMAZQAnAQQAAAB0AHkAcABlAAEXAAAAUwB5AHMAdABlAG0ALgBTAGkAbgBnAGwAZQAsACAAbQBzAGMAbwByAGwAaQBiAB8BBQAAAFYAYQBsAHUAZQAAAEBABwUCMAIAAAADAAAABgIAAAAAAAAAJwEEAAAAdAB5AHAAZQABFwAAAFMAeQBzAHQAZQBtAC4AUwB0AHIAaQBuAGcALAAgAG0AcwBjAG8AcgBsAGkAYgAnAQoAAABTAHkAbQBiAG8AbABOAGEAbQBlAAEJAAAAdwBhAGwAawBTAHAAZQBlAGQAJwEEAAAAdAB5AHAAZQABFwAAAFMAeQBzAHQAZQBtAC4AUwBpAG4AZwBsAGUALAAgAG0AcwBjAG8AcgBsAGkAYgAfAQUAAABWAGEAbAB1AGUAAAAAQAcFAjACAAAABAAAAAYCAAAAAAAAACcBBAAAAHQAeQBwAGUAARcAAABTAHkAcwB0AGUAbQAuAFMAdAByAGkAbgBnACwAIABtAHMAYwBvAHIAbABpAGIAJwEKAAAAUwB5AG0AYgBvAGwATgBhAG0AZQABCAAAAHIAdQBuAFMAcABlAGUAZAAnAQQAAAB0AHkAcABlAAEXAAAAUwB5AHMAdABlAG0ALgBTAGkAbgBnAGwAZQAsACAAbQBzAGMAbwByAGwAaQBiAB8BBQAAAFYAYQBsAHUAZQAAAIBABwUCMAIAAAAFAAAABgIAAAAAAAAAJwEEAAAAdAB5AHAAZQABFwAAAFMAeQBzAHQAZQBtAC4AUwB0AHIAaQBuAGcALAAgAG0AcwBjAG8AcgBsAGkAYgAnAQoAAABTAHkAbQBiAG8AbABOAGEAbQBlAAELAAAAcwB0AHIAYQBmAGUAUwBwAGUAZQBkACcBBAAAAHQAeQBwAGUAARcAAABTAHkAcwB0AGUAbQAuAFMAaQBuAGcAbABlACwAIABtAHMAYwBvAHIAbABpAGIAHwEFAAAAVgBhAGwAdQBlAAAAAEAHBQcFBwU=
publicVariablesUnityEngineObjects: []
publicVariablesSerializationDataFormat: 0
--- !u!4 &3480278762663400089
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3480278762663670689}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -2.558}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &3480278762663670689
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3480278762663400089}
- component: {fileID: 7111575897785925491}
- component: {fileID: 3591906996255472209}
- component: {fileID: 3231720197660963110}
- component: {fileID: 3480278762663670690}
m_Layer: 0
m_Name: VRCWorld
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &3480278762663670690
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3480278762663670689}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 45115577ef41a5b4ca741ed302693907, type: 3}
m_Name:
m_EditorClassIdentifier:
interactTextPlacement: {fileID: 0}
interactText: Use
interactTextGO: {fileID: 0}
proximity: 2
SynchronizePosition: 0
AllowCollisionOwnershipTransfer: 1
Reliable: 0
_syncMethod: 1
serializedProgramAsset: {fileID: 11400000, guid: a82912e628ffbe845afde2e220e1a277,
type: 2}
programSource: {fileID: 11400000, guid: 566cc00e27d5822449529a3785eae366, type: 2}
serializedPublicVariablesBytesString: Ai8AAAAAATIAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAFQAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAAAAAAYBAAAAAAAAACcBBAAAAHQAeQBwAGUAAWgAAABTAHkAcwB0AGUAbQAuAEMAbwBsAGwAZQBjAHQAaQBvAG4AcwAuAEcAZQBuAGUAcgBpAGMALgBMAGkAcwB0AGAAMQBbAFsAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4ALgBJAG4AdABlAHIAZgBhAGMAZQBzAC4ASQBVAGQAbwBuAFYAYQByAGkAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AXQBdACwAIABtAHMAYwBvAHIAbABpAGIAAQEJAAAAVgBhAHIAaQBhAGIAbABlAHMALwEAAAABaAAAAFMAeQBzAHQAZQBtAC4AQwBvAGwAbABlAGMAdABpAG8AbgBzAC4ARwBlAG4AZQByAGkAYwAuAEwAaQBzAHQAYAAxAFsAWwBWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAEkAbgB0AGUAcgBmAGEAYwBlAHMALgBJAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgBdAF0ALAAgAG0AcwBjAG8AcgBsAGkAYgABAAAABgQAAAAAAAAAAi8CAAAAAUsAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAGAAMQBbAFsAUwB5AHMAdABlAG0ALgBCAG8AbwBsAGUAYQBuACwAIABtAHMAYwBvAHIAbABpAGIAXQBdACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgACAAAABgIAAAAAAAAAJwEEAAAAdAB5AHAAZQABFwAAAFMAeQBzAHQAZQBtAC4AUwB0AHIAaQBuAGcALAAgAG0AcwBjAG8AcgBsAGkAYgAnAQoAAABTAHkAbQBiAG8AbABOAGEAbQBlAAEUAAAAZABpAHMAYQBiAGwAZQBBAHYAYQB0AGEAcgBTAGMAYQBsAGkAbgBnACcBBAAAAHQAeQBwAGUAARgAAABTAHkAcwB0AGUAbQAuAEIAbwBvAGwAZQBhAG4ALAAgAG0AcwBjAG8AcgBsAGkAYgArAQUAAABWAGEAbAB1AGUAAAcFAjACAAAAAwAAAAYCAAAAAAAAACcBBAAAAHQAeQBwAGUAARcAAABTAHkAcwB0AGUAbQAuAFMAdAByAGkAbgBnACwAIABtAHMAYwBvAHIAbABpAGIAJwEKAAAAUwB5AG0AYgBvAGwATgBhAG0AZQABEwAAAGEAbAB3AGEAeQBzAEUAbgBmAG8AcgBjAGUASABlAGkAZwBoAHQAJwEEAAAAdAB5AHAAZQABGAAAAFMAeQBzAHQAZQBtAC4AQgBvAG8AbABlAGEAbgAsACAAbQBzAGMAbwByAGwAaQBiACsBBQAAAFYAYQBsAHUAZQAABwUCLwMAAAABSgAAAFYAUgBDAC4AVQBkAG8AbgAuAEMAbwBtAG0AbwBuAC4AVQBkAG8AbgBWAGEAcgBpAGEAYgBsAGUAYAAxAFsAWwBTAHkAcwB0AGUAbQAuAFMAaQBuAGcAbABlACwAIABtAHMAYwBvAHIAbABpAGIAXQBdACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAEAAAABgIAAAAAAAAAJwEEAAAAdAB5AHAAZQABFwAAAFMAeQBzAHQAZQBtAC4AUwB0AHIAaQBuAGcALAAgAG0AcwBjAG8AcgBsAGkAYgAnAQoAAABTAHkAbQBiAG8AbABOAGEAbQBlAAENAAAAbQBpAG4AaQBtAHUAbQBIAGUAaQBnAGgAdAAnAQQAAAB0AHkAcABlAAEXAAAAUwB5AHMAdABlAG0ALgBTAGkAbgBnAGwAZQAsACAAbQBzAGMAbwByAGwAaQBiAB8BBQAAAFYAYQBsAHUAZQDNzEw+BwUCMAMAAAAFAAAABgIAAAAAAAAAJwEEAAAAdAB5AHAAZQABFwAAAFMAeQBzAHQAZQBtAC4AUwB0AHIAaQBuAGcALAAgAG0AcwBjAG8AcgBsAGkAYgAnAQoAAABTAHkAbQBiAG8AbABOAGEAbQBlAAENAAAAbQBhAHgAaQBtAHUAbQBIAGUAaQBnAGgAdAAnAQQAAAB0AHkAcABlAAEXAAAAUwB5AHMAdABlAG0ALgBTAGkAbgBnAGwAZQAsACAAbQBzAGMAbwByAGwAaQBiAB8BBQAAAFYAYQBsAHUAZQAAAKBABwUHBQcF
publicVariablesUnityEngineObjects: []
publicVariablesSerializationDataFormat: 0
--- !u!114 &3591906996255472209
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3480278762663670689}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -1427037861, guid: 4ecd63eff847044b68db9453ce219299, type: 3}
m_Name:
m_EditorClassIdentifier:
launchedFromSDKPipeline: 0
completedSDKPipeline: 0
blueprintId:
contentType: 1
assetBundleUnityVersion:
fallbackStatus: 0
--- !u!114 &7111575897785925491
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3480278762663670689}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -17141911, guid: 661092b4961be7145bfbe56e1e62337b, type: 3}
m_Name:
m_EditorClassIdentifier:
spawns:
- {fileID: 3480278762663400089}
spawnRadius: 0.2
spawnOrder: 2
spawnOrientation: 0
ReferenceCamera: {fileID: 1069902874}
RespawnHeightY: -100
ObjectBehaviourAtRespawnHeight: 0
ForbidUserPortals: 0
interactThruLayers: 0
autoSpatializeAudioSources: 0
gravity: {x: 0, y: -9.81, z: 0}
layerCollisionArr: 01010101010001010101010100010001010101010101010101010101010101010101010101000101010101010001000101010101010101010101010101010101010101010100010101010101000100010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101000101010101010001000101010101010101010101010101010101000000010000010100000000000000000000000000000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100010101010101000100010101010101010101010101010101010101010101010001010100000100000000000001010101010101010101010101010101010101000101010000010000000000000101010101010101010101010101010101010100010101010101000100010101010101010101010101010101010100000001000001010000000000000000000000000000010101010101010101010101010101000101010000010001010101010000000001010101010101010101000000010000010100000000000100000000000000000101010101010101010101010101010001010100000100010001010101010101010101010101010101010101010101000101010000010001000101010101010101010101010101010101010101010100010101000001000100010101010101010101010101010101010101010101010001010101010100000001010101010101010101010101010101010101010101000101010101010000000101010101010101010101010101010101010101010100010101010101000000010101010101010101010101010101010101010101010001010101010100000001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101
capacity: 0
contentSex: 0
contentViolence: 0
contentGore: 0
contentOther: 0
releasePublic: 0
unityVersion: 2019.4.31f1
udonProducts: []
Name:
NSFW: 0
SpawnPosition: {x: 0, y: 0, z: 0}
SpawnLocation: {fileID: 0}
DrawDistance: 0
useAssignedLayers: 0
DynamicPrefabs: []
DynamicMaterials:
- {fileID: 2100000, guid: 74de320d298ce3e498b0401ec1ffcb7f, type: 2}
- {fileID: 2100000, guid: 1c987494452b85f4ab4cac3322415907, type: 2}
- {fileID: 2100000, guid: c815f7613a04b724089c206857e57c6a, type: 2}
- {fileID: 2100000, guid: fd20e45036ef323459e8286e9c23c02c, type: 2}
LightMapsNear: []
LightMapsFar: []
LightMode: 0
RenderAmbientEquatorColor: {r: 0, g: 0, b: 0, a: 0}
RenderAmbientGroundColor: {r: 0, g: 0, b: 0, a: 0}
RenderAmbientIntensity: 0
RenderAmbientLight: {r: 0, g: 0, b: 0, a: 0}
RenderAmbientMode: 0
RenderAmbientProbe:
sh[ 0]: 0
sh[ 1]: 0
sh[ 2]: 0
sh[ 3]: 0
sh[ 4]: 0
sh[ 5]: 0
sh[ 6]: 0
sh[ 7]: 0
sh[ 8]: 0
sh[ 9]: 0
sh[10]: 0
sh[11]: 0
sh[12]: 0
sh[13]: 0
sh[14]: 0
sh[15]: 0
sh[16]: 0
sh[17]: 0
sh[18]: 0
sh[19]: 0
sh[20]: 0
sh[21]: 0
sh[22]: 0
sh[23]: 0
sh[24]: 0
sh[25]: 0
sh[26]: 0
RenderAmbientSkyColor: {r: 0, g: 0, b: 0, a: 0}
RenderFog: 0
RenderFogColor: {r: 0, g: 0, b: 0, a: 0}
RenderFogMode: 0
RenderFogDensity: 0
RenderFogLinearStart: 0
RenderFogLinearEnd: 0
RenderHaloStrength: 0
RenderFlareFadeSpeed: 0
RenderFlareStrength: 0
RenderCustomReflection: {fileID: 0}
RenderDefaultReflectionMode: 0
RenderDefaultReflectionResolution: 0
RenderReflectionBounces: 0
RenderReflectionIntensity: 0
RenderSkybox: {fileID: 0}
portraitCameraPositionOffset: {x: 0, y: 0, z: 0}
portraitCameraRotationOffset: {x: 0, y: 1, z: 0, w: -0.00000004371139}
PlayerPersistence: []
--- !u!64 &7606902903243430482
MeshCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7606902903243430483}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 5
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!1 &7606902903243430483
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7606902903243430487}
- component: {fileID: 7606902903243430484}
- component: {fileID: 7606902903243430485}
- component: {fileID: 7606902903243430482}
m_Layer: 0
m_Name: Floor
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!33 &7606902903243430484
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7606902903243430483}
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &7606902903243430485
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7606902903243430483}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: fd20e45036ef323459e8286e9c23c02c, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!4 &7606902903243430487
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7606902903243430483}
serializedVersion: 2
m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 100, y: 100, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0}
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
m_Roots:
- {fileID: 3480278762663400089}
- {fileID: 1069902877}
- {fileID: 1787983411}
- {fileID: 7606902903243430487}
- {fileID: 358170790}

Some files were not shown because too many files have changed in this diff Show More