Last active
March 17, 2024 15:23
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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