Skip to content

Instantly share code, notes, and snippets.

@TayouVR
Last active March 17, 2024 15:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TayouVR/e1bf7928ce6293ba93ac90d505031313 to your computer and use it in GitHub Desktop.
Save TayouVR/e1bf7928ce6293ba93ac90d505031313 to your computer and use it in GitHub Desktop.
Check all renderer bounds in children of the provided transform. Applies a highlight in the list if the bounds exceed the "Very Poor" rating of VRChat
// SPDX-FileCopyrightText: 2024 Tayou <contact@tayou.org>
// SPDX-License-Identifier: CC0-1.0
/*
* Copyright (C) 2024 Tayou <git@tayou.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
*/
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace DefaultNamespace {
public class CheckBounds : EditorWindow {
private ObjectField _objectField;
private Button _button;
private ScrollView _list;
private Vector3 MAX_BOUNDS = new(5, 6, 5);
#if VRC_SDK_VRCSDK3
public const string GUID_VERY_POOR_ICON = "2886eb1248200a94d9eaec82336fbbad";
static Texture2D ICON_VERY_POOR {
get {
Texture2D tex = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(GUID_VERY_POOR_ICON));
tex.filterMode = FilterMode.Bilinear;
return tex;
}
}
#endif
private Transform _originTransform;
private Dictionary<Transform, List<Bounds>> _result = new();
[MenuItem("Tools/Tayou/Check Bounds")]
private static void Init() {
// Get existing open window or if none, make a new one:
CheckBounds window = (CheckBounds)EditorWindow.GetWindow(typeof(CheckBounds));
window.titleContent = new GUIContent("Check Bounds");
window.Show();
}
private void CreateGUI() {
_objectField = new ObjectField("Root Transform") {
objectType = typeof(Transform),
allowSceneObjects = true
};
_objectField.RegisterValueChangedCallback(evt => {
_originTransform = evt.newValue as Transform;
});
_button = new Button(() => {
if (_originTransform != null) {
_result.Clear();
Check(_originTransform);
_list.Clear();
foreach (var kvp in _result) {
foreach (var value in kvp.Value) {
string boundsString = $"X:{value.extents.x*2,5:00.00} Y:{value.extents.y*2,5:00.00} Z:{value.extents.z*2,5:00.00}";
if (value.extents.x*2 > MAX_BOUNDS.x
|| value.extents.y*2 > MAX_BOUNDS.y
|| value.extents.z*2 > MAX_BOUNDS.z) {
Debug.LogWarning($"Transform: {kvp.Key.name}, Bounds: {boundsString}");
_list.Add(MakeBoundsUIContainer(kvp.Key, value, true));
} else {
Debug.Log($"Transform: {kvp.Key.name}, Bounds: {boundsString}");
_list.Add(MakeBoundsUIContainer(kvp.Key, value, false));
}
}
}
}
}) {
text = "Check Bounds"
};
_list = new ScrollView(ScrollViewMode.Vertical);
rootVisualElement.Add(_objectField);
rootVisualElement.Add(_button);
rootVisualElement.Add(_list);
}
VisualElement MakeBoundsUIContainer(Transform transform, Bounds bounds, bool aboveLimits) {
var container = new VisualElement();
container.style.flexDirection = FlexDirection.Row;
if (aboveLimits) {
container.style.backgroundColor = new Color(1, 0, 0, 0.25f);
#if VRC_SDK_VRCSDK3
container.Add(new Image {
image = ICON_VERY_POOR,
style = {
height = EditorGUIUtility.singleLineHeight,
width = EditorGUIUtility.singleLineHeight
}
});
#endif
}
var objectField = new ObjectField {
objectType = typeof(Transform),
value = transform,
style = { flexGrow = 1 }
};
var labelX = new Label("X:");
var valueX = new FloatField { value = bounds.extents.x * 2, isReadOnly = true, style = { width = 40 } };
var labelY = new Label("Y:");
var valueY = new FloatField { value = bounds.extents.y * 2, isReadOnly = true, style = { width = 40 } };
var labelZ = new Label("Z:");
var valueZ = new FloatField { value = bounds.extents.z * 2, isReadOnly = true, style = { width = 40 } };
container.Add(objectField);
container.Add(labelX);
container.Add(valueX);
container.Add(labelY);
container.Add(valueY);
container.Add(labelZ);
container.Add(valueZ);
return container;
}
private void Check(Transform transform) {
//Bounds bounds = new Bounds(transform.position, Vector3.zero);
Renderer[] renderers = transform.GetComponentsInChildren<Renderer>(true);
foreach (Renderer renderer in renderers) {
//bounds.Encapsulate(renderer.bounds);
_result.TryGetValue(renderer.transform, out var boundsList);
boundsList ??= new List<Bounds>();
boundsList.Add(renderer.bounds);
_result[renderer.transform] = boundsList;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment