diff --git a/AVVR/Assets/_Scripts/AudioCameraPositioner.cs b/AVVR/Assets/_Scripts/AudioCameraPositioner.cs index 2b8f8bfeab4c6dee4649a8c97327c7a9e21fdd62..8e814a86f9844578516ab7f655235b3563082670 100644 --- a/AVVR/Assets/_Scripts/AudioCameraPositioner.cs +++ b/AVVR/Assets/_Scripts/AudioCameraPositioner.cs @@ -1,63 +1,49 @@ -using UnityEngine; -using System.Collections.Generic; #if UNITY_EDITOR +using UnityEngine; using UnityEditor; -#endif +using System.Collections.Generic; -public class AudioCameraPositioner : MonoBehaviour +// Shared data structure +[System.Serializable] +public class PositionSetting { - public Camera mainCamera; - public List<AudioSource> audioSources = new List<AudioSource>(); - public GameObject modelWrapper; - - [System.Serializable] - public class PositionSetting - { - public string name; - public Vector3 position; - } - - public PositionSetting cameraPosition = new PositionSetting { name = "Camera" }; - public List<PositionSetting> audioSourcePositions = new List<PositionSetting>(); - - private Vector3 roomSize; - private Vector3 roomCenter; - private Vector3 roomMinPoint; + public string name; + public Vector3 position; +} - public void PositionCamera() +// Shared logic class that both MonoBehaviour and EditorWindow can use +public static class AudioCameraPositionerLogic +{ + public static void PositionCamera(Camera camera, Vector3 position) { - if (mainCamera == null) + if (camera == null) { Debug.LogError("Main camera is not assigned!"); return; } - mainCamera.transform.position = cameraPosition.position; - Debug.Log($"Camera positioned at: {cameraPosition.position}"); + Undo.RecordObject(camera.transform, "Position Camera"); + camera.transform.position = position; + Debug.Log($"Camera positioned at: {position}"); } - public void PositionAudioSources() + public static void PositionAudioSources(List<AudioSource> sources, List<PositionSetting> positions) { - for (int i = 0; i < audioSources.Count && i < audioSourcePositions.Count; i++) + for (int i = 0; i < sources.Count && i < positions.Count; i++) { - if (audioSources[i] == null) + if (sources[i] == null) { Debug.LogWarning($"Audio source at index {i} is not assigned!"); continue; } - audioSources[i].transform.position = audioSourcePositions[i].position; - Debug.Log($"Audio source '{audioSourcePositions[i].name}' positioned at: {audioSourcePositions[i].position}"); + Undo.RecordObject(sources[i].transform, "Position Audio Source"); + sources[i].transform.position = positions[i].position; + Debug.Log($"Audio source '{positions[i].name}' positioned at: {positions[i].position}"); } } - public void PositionAll() - { - PositionCamera(); - PositionAudioSources(); - } - - public void AlignRoomCorner(int cornerIndex) + public static void AlignRoomCorner(GameObject modelWrapper, int cornerIndex) { if (modelWrapper == null) { @@ -65,20 +51,22 @@ public class AudioCameraPositioner : MonoBehaviour return; } + Undo.RecordObject(modelWrapper.transform, "Align Room Corner"); + // Step 1: Reset to origin modelWrapper.transform.position = Vector3.zero; modelWrapper.transform.rotation = Quaternion.identity; - // Step 2: Calculate initial dimensions using mesh vertices + // Step 2: Calculate initial dimensions Vector3 minPoint, maxPoint; - CalculateMeshDimensions(out minPoint, out maxPoint); + CalculateMeshDimensions(modelWrapper, out minPoint, out maxPoint); // Step 3: Rotate based on corner index Quaternion rotation = Quaternion.Euler(0, 90 * cornerIndex, 0); modelWrapper.transform.rotation = rotation; // Step 4: Recalculate dimensions after rotation - CalculateMeshDimensions(out minPoint, out maxPoint); + CalculateMeshDimensions(modelWrapper, out minPoint, out maxPoint); // Step 5: Move the most negative corner to origin Vector3 translation = -minPoint; @@ -87,12 +75,12 @@ public class AudioCameraPositioner : MonoBehaviour Debug.Log($"Room aligned to corner {cornerIndex}. Position: {modelWrapper.transform.position}, Rotation: {modelWrapper.transform.rotation.eulerAngles}"); } - private void CalculateMeshDimensions(out Vector3 minPoint, out Vector3 maxPoint) + public static void CalculateMeshDimensions(GameObject obj, out Vector3 minPoint, out Vector3 maxPoint) { minPoint = Vector3.positiveInfinity; maxPoint = Vector3.negativeInfinity; - MeshFilter[] meshFilters = modelWrapper.GetComponentsInChildren<MeshFilter>(); + MeshFilter[] meshFilters = obj.GetComponentsInChildren<MeshFilter>(); foreach (MeshFilter mf in meshFilters) { Vector3[] vertices = mf.sharedMesh.vertices; @@ -103,18 +91,126 @@ public class AudioCameraPositioner : MonoBehaviour maxPoint = Vector3.Max(maxPoint, worldVertex); } } + } +} + +// Original MonoBehaviour Component +public class AudioCameraPositioner : MonoBehaviour +{ + public Camera mainCamera; + public List<AudioSource> audioSources = new List<AudioSource>(); + public GameObject modelWrapper; + public PositionSetting cameraPosition = new PositionSetting { name = "Camera" }; + public List<PositionSetting> audioSourcePositions = new List<PositionSetting>(); + + public void PositionCamera() + { + AudioCameraPositionerLogic.PositionCamera(mainCamera, cameraPosition.position); + } + + public void PositionAudioSources() + { + AudioCameraPositionerLogic.PositionAudioSources(audioSources, audioSourcePositions); + } + + public void AlignRoomCorner(int cornerIndex) + { + AudioCameraPositionerLogic.AlignRoomCorner(modelWrapper, cornerIndex); + } +} + +// Editor Window +public class AudioCameraPositionerWindow : EditorWindow +{ + private Camera mainCamera; + private List<AudioSource> audioSources = new List<AudioSource>(); + private GameObject modelWrapper; + private PositionSetting cameraPosition = new PositionSetting { name = "Camera" }; + private List<PositionSetting> audioSourcePositions = new List<PositionSetting>(); + + [MenuItem("AVVR/Audio Camera Positioner")] + public static void ShowWindow() + { + GetWindow<AudioCameraPositionerWindow>("Audio Camera Positioner"); + } + + private void OnGUI() + { + EditorGUILayout.Space(10); + + // Camera Section + EditorGUILayout.LabelField("Camera Settings", EditorStyles.boldLabel); + mainCamera = (Camera)EditorGUILayout.ObjectField("Main Camera", mainCamera, typeof(Camera), true); + cameraPosition.position = EditorGUILayout.Vector3Field("Camera Position", cameraPosition.position); + + EditorGUI.BeginDisabledGroup(mainCamera == null); + if (GUILayout.Button("Position Camera")) + { + AudioCameraPositionerLogic.PositionCamera(mainCamera, cameraPosition.position); + } + EditorGUI.EndDisabledGroup(); + + EditorGUILayout.Space(10); + + // Audio Section + EditorGUILayout.LabelField("Audio Settings", EditorStyles.boldLabel); + + if (GUILayout.Button("Add Audio Source")) + { + audioSources.Add(null); + audioSourcePositions.Add(new PositionSetting { name = $"Audio Source {audioSources.Count}" }); + } + + for (int i = 0; i < audioSources.Count; i++) + { + EditorGUILayout.BeginHorizontal(); + audioSources[i] = (AudioSource)EditorGUILayout.ObjectField( + audioSources[i], typeof(AudioSource), true + ); + + if (i < audioSourcePositions.Count) + { + audioSourcePositions[i].name = EditorGUILayout.TextField(audioSourcePositions[i].name, GUILayout.Width(100)); + audioSourcePositions[i].position = EditorGUILayout.Vector3Field("", audioSourcePositions[i].position); + } + + if (GUILayout.Button("X", GUILayout.Width(20))) + { + audioSources.RemoveAt(i); + audioSourcePositions.RemoveAt(i); + break; + } + EditorGUILayout.EndHorizontal(); + } - roomSize = maxPoint - minPoint; - roomCenter = (minPoint + maxPoint) / 2; - roomMinPoint = minPoint; + if (GUILayout.Button("Position Audio Sources")) + { + AudioCameraPositionerLogic.PositionAudioSources(audioSources, audioSourcePositions); + } - Debug.Log($"Room size: {roomSize}"); - Debug.Log($"Room center: {roomCenter}"); - Debug.Log($"Room min point: {roomMinPoint}"); + EditorGUILayout.Space(10); + + // Room Section + EditorGUILayout.LabelField("Room Settings", EditorStyles.boldLabel); + modelWrapper = (GameObject)EditorGUILayout.ObjectField( + "Model Wrapper", modelWrapper, typeof(GameObject), true + ); + + EditorGUI.BeginDisabledGroup(modelWrapper == null); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Align Corner 0")) AudioCameraPositionerLogic.AlignRoomCorner(modelWrapper, 0); + if (GUILayout.Button("Align Corner 1")) AudioCameraPositionerLogic.AlignRoomCorner(modelWrapper, 1); + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Align Corner 2")) AudioCameraPositionerLogic.AlignRoomCorner(modelWrapper, 2); + if (GUILayout.Button("Align Corner 3")) AudioCameraPositionerLogic.AlignRoomCorner(modelWrapper, 3); + EditorGUILayout.EndHorizontal(); + EditorGUI.EndDisabledGroup(); } } -#if UNITY_EDITOR +// Inspector UI for the MonoBehaviour component [CustomEditor(typeof(AudioCameraPositioner))] public class AudioCameraPositionerEditor : Editor { @@ -163,11 +259,6 @@ public class AudioCameraPositionerEditor : Editor positioner.PositionAudioSources(); } - if (GUILayout.Button("Position All")) - { - positioner.PositionAll(); - } - EditorGUILayout.Space(); EditorGUILayout.LabelField("Room Alignment", EditorStyles.boldLabel); diff --git a/AVVR/Assets/_Scripts/MeshDimensionCalculator.cs b/AVVR/Assets/_Scripts/MeshDimensionCalculator.cs index 3c6a153b4ce8a507d8159b7c2dc3b97228fb5e3a..ba15c24e2c29769ec3dabc4325d5da365fec7a9f 100644 --- a/AVVR/Assets/_Scripts/MeshDimensionCalculator.cs +++ b/AVVR/Assets/_Scripts/MeshDimensionCalculator.cs @@ -1,37 +1,36 @@ -using UnityEngine; -using System.Collections.Generic; #if UNITY_EDITOR +using UnityEngine; using UnityEditor; -#endif +using System.Collections.Generic; -public class MeshDimensionCalculator : MonoBehaviour +// Shared data structure for dimension results +public class DimensionResults { - public GameObject targetObject; - private Vector3 totalMin = Vector3.positiveInfinity; - private Vector3 totalMax = Vector3.negativeInfinity; - private Vector3 dimensions; - private Vector3 center; + public Vector3 totalMin = Vector3.positiveInfinity; + public Vector3 totalMax = Vector3.negativeInfinity; + public Vector3 dimensions; + public Vector3 center; +} - [SerializeField] private Vector3 scaleFactors = Vector3.one; - [SerializeField] private float uniformScaleFactor = 1f; - public void CalculateDimensions() +// Shared logic class +public static class MeshDimensionCalculatorLogic +{ + public static DimensionResults CalculateDimensions(GameObject targetObject) { if (targetObject == null) { Debug.LogError("Target object is not assigned!"); - return; + return null; } - totalMin = Vector3.positiveInfinity; - totalMax = Vector3.negativeInfinity; - + DimensionResults results = new DimensionResults(); List<MeshFilter> meshFilters = new List<MeshFilter>(); CollectMeshFilters(targetObject.transform, meshFilters); if (meshFilters.Count == 0) { Debug.LogError("No meshes found in the target object's hierarchy!"); - return; + return null; } foreach (MeshFilter meshFilter in meshFilters) @@ -43,20 +42,22 @@ public class MeshDimensionCalculator : MonoBehaviour for (int i = 0; i < vertices.Length; i++) { Vector3 worldVertex = meshFilter.transform.TransformPoint(vertices[i]); - totalMin = Vector3.Min(totalMin, worldVertex); - totalMax = Vector3.Max(totalMax, worldVertex); + results.totalMin = Vector3.Min(results.totalMin, worldVertex); + results.totalMax = Vector3.Max(results.totalMax, worldVertex); } } - dimensions = totalMax - totalMin; - center = (totalMin + totalMax) / 2; + results.dimensions = results.totalMax - results.totalMin; + results.center = (results.totalMin + results.totalMax) / 2; + + Debug.Log($"Total Dimensions: {results.dimensions}"); + Debug.Log($"Center: {results.center}"); + Debug.Log($"Floor Y position: {results.totalMin.y}"); - Debug.Log($"Total Dimensions: {dimensions}"); - Debug.Log($"Center: {center}"); - Debug.Log($"Floor Y position: {totalMin.y}"); + return results; } - private void CollectMeshFilters(Transform parent, List<MeshFilter> meshFilters) + private static void CollectMeshFilters(Transform parent, List<MeshFilter> meshFilters) { MeshFilter meshFilter = parent.GetComponent<MeshFilter>(); if (meshFilter != null) @@ -70,7 +71,7 @@ public class MeshDimensionCalculator : MonoBehaviour } } - public void ResetToOrigin() + public static void ResetToOrigin(GameObject targetObject) { if (targetObject == null) { @@ -78,11 +79,12 @@ public class MeshDimensionCalculator : MonoBehaviour return; } + Undo.RecordObject(targetObject.transform, "Reset To Origin"); targetObject.transform.position = Vector3.zero; Debug.Log("Target object has been reset to (0,0,0)."); } - public void ResetFloorToZero() + public static void ResetFloorToZero(GameObject targetObject, float floorY) { if (targetObject == null) { @@ -90,18 +92,14 @@ public class MeshDimensionCalculator : MonoBehaviour return; } - if (totalMin.y == Mathf.Infinity) - { - Debug.LogWarning("Please calculate dimensions first!"); - return; - } - + Undo.RecordObject(targetObject.transform, "Reset Floor To Zero"); Vector3 currentPosition = targetObject.transform.position; - targetObject.transform.position = new Vector3(currentPosition.x, -totalMin.y, currentPosition.z); - Debug.Log($"Target object floor has been reset to Y = 0. New position: {targetObject.transform.position}"); + Vector3 newPosition = new Vector3(currentPosition.x, -floorY, currentPosition.z); + targetObject.transform.position = newPosition; + Debug.Log($"Target object floor has been reset to Y = 0. New position: {newPosition}"); } - public void ScaleObject() + public static void ScaleObject(GameObject targetObject, Vector3 scaleFactors) { if (targetObject == null) { @@ -109,18 +107,14 @@ public class MeshDimensionCalculator : MonoBehaviour return; } + Undo.RecordObject(targetObject.transform, "Scale Object"); Vector3 currentScale = targetObject.transform.localScale; - Vector3 newScale = new Vector3( - currentScale.x * scaleFactors.x, - currentScale.y * scaleFactors.y, - currentScale.z * scaleFactors.z - ); - + Vector3 newScale = Vector3.Scale(currentScale, scaleFactors); targetObject.transform.localScale = newScale; Debug.Log($"Target object scaled. New scale: {newScale}"); } - public void ScaleObjectUniform() + public static void ScaleObjectUniform(GameObject targetObject, float uniformScaleFactor) { if (targetObject == null) { @@ -128,14 +122,14 @@ public class MeshDimensionCalculator : MonoBehaviour return; } + Undo.RecordObject(targetObject.transform, "Scale Object Uniform"); Vector3 currentScale = targetObject.transform.localScale; Vector3 newScale = currentScale * uniformScaleFactor; - targetObject.transform.localScale = newScale; Debug.Log($"Target object scaled uniformly. New scale: {newScale}"); } - public void ResetScale() + public static void ResetScale(GameObject targetObject) { if (targetObject == null) { @@ -143,12 +137,58 @@ public class MeshDimensionCalculator : MonoBehaviour return; } + Undo.RecordObject(targetObject.transform, "Reset Scale"); targetObject.transform.localScale = Vector3.one; Debug.Log("Target object scale has been reset to (1, 1, 1)."); } } -#if UNITY_EDITOR +// MonoBehaviour Component +public class MeshDimensionCalculator : MonoBehaviour +{ + public GameObject targetObject; + private DimensionResults results; + + [SerializeField] private Vector3 scaleFactors = Vector3.one; + [SerializeField] private float uniformScaleFactor = 1f; + + public void CalculateDimensions() + { + results = MeshDimensionCalculatorLogic.CalculateDimensions(targetObject); + } + + public void ResetToOrigin() + { + MeshDimensionCalculatorLogic.ResetToOrigin(targetObject); + } + + public void ResetFloorToZero() + { + if (results == null || results.totalMin.y == Mathf.Infinity) + { + Debug.LogWarning("Please calculate dimensions first!"); + return; + } + MeshDimensionCalculatorLogic.ResetFloorToZero(targetObject, results.totalMin.y); + } + + public void ScaleObject() + { + MeshDimensionCalculatorLogic.ScaleObject(targetObject, scaleFactors); + } + + public void ScaleObjectUniform() + { + MeshDimensionCalculatorLogic.ScaleObjectUniform(targetObject, uniformScaleFactor); + } + + public void ResetScale() + { + MeshDimensionCalculatorLogic.ResetScale(targetObject); + } +} + +// Inspector UI for the MonoBehaviour component [CustomEditor(typeof(MeshDimensionCalculator))] public class MeshDimensionCalculatorEditor : Editor { @@ -167,7 +207,7 @@ public class MeshDimensionCalculatorEditor : Editor { serializedObject.Update(); - EditorGUILayout.PropertyField(targetObjectProperty); + EditorGUILayout.PropertyField(targetObjectProperty, new GUIContent("ModelWrapper")); MeshDimensionCalculator calculator = (MeshDimensionCalculator)target; @@ -213,4 +253,87 @@ public class MeshDimensionCalculatorEditor : Editor serializedObject.ApplyModifiedProperties(); } } + +// Editor Window +public class MeshDimensionCalculatorWindow : EditorWindow +{ + private GameObject targetObject; + private DimensionResults results; + private Vector3 scaleFactors = Vector3.one; + private float uniformScaleFactor = 1f; + + [MenuItem("AVVR/Mesh Dimension Calculator")] + public static void ShowWindow() + { + GetWindow<MeshDimensionCalculatorWindow>("Mesh Dimensions"); + } + + private void OnGUI() + { + GUILayout.Label("Mesh Dimension Calculator", EditorStyles.boldLabel); + + EditorGUI.BeginChangeCheck(); + targetObject = (GameObject)EditorGUILayout.ObjectField("ModelWrapper", targetObject, typeof(GameObject), true); + + EditorGUI.BeginDisabledGroup(targetObject == null); + + if (GUILayout.Button("Calculate Dimensions")) + { + results = MeshDimensionCalculatorLogic.CalculateDimensions(targetObject); + Repaint(); + } + + if (GUILayout.Button("Reset to Origin (0,0,0)")) + { + MeshDimensionCalculatorLogic.ResetToOrigin(targetObject); + } + + if (GUILayout.Button("Reset Floor to Y = 0")) + { + if (results != null) + { + MeshDimensionCalculatorLogic.ResetFloorToZero(targetObject, results.totalMin.y); + } + else + { + EditorUtility.DisplayDialog("Error", "Please calculate dimensions first!", "OK"); + } + } + + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Scaling Options", EditorStyles.boldLabel); + + scaleFactors = EditorGUILayout.Vector3Field("Scale Factors (X, Y, Z)", scaleFactors); + if (GUILayout.Button("Apply Scale (X, Y, Z)")) + { + MeshDimensionCalculatorLogic.ScaleObject(targetObject, scaleFactors); + } + + EditorGUILayout.Space(); + + uniformScaleFactor = EditorGUILayout.FloatField("Uniform Scale Factor", uniformScaleFactor); + if (GUILayout.Button("Apply Uniform Scale")) + { + MeshDimensionCalculatorLogic.ScaleObjectUniform(targetObject, uniformScaleFactor); + } + + EditorGUILayout.Space(); + + if (GUILayout.Button("Reset Scale to (1, 1, 1)")) + { + MeshDimensionCalculatorLogic.ResetScale(targetObject); + } + + EditorGUI.EndDisabledGroup(); + + if (results != null && results.dimensions != Vector3.zero) + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Results:", EditorStyles.boldLabel); + EditorGUILayout.Vector3Field("Dimensions", results.dimensions); + EditorGUILayout.Vector3Field("Center", results.center); + EditorGUILayout.FloatField("Floor Y Position", results.totalMin.y); + } + } +} #endif \ No newline at end of file diff --git a/Positions_in_Rooms.pptx b/Positions_in_Rooms.pptx index b4a9c98fde3dfef852b68a87febbe86c797192f0..b5a964d3b2f21db232439ddeffcb16260b130fd2 100644 Binary files a/Positions_in_Rooms.pptx and b/Positions_in_Rooms.pptx differ