From 61f6da7a7d7036f7acab1453a311e7cd738c290f Mon Sep 17 00:00:00 2001 From: Michal Pikulski Date: Thu, 18 Dec 2025 15:07:27 +0100 Subject: [PATCH] Add horizontal camera scaling for devices --- .../CameraScreenAdapterEditor.cs | 84 ++++++++++++++ .../CameraScreenAdapterEditor.cs.meta | 3 + .../ScreenReferenceMarkerEditor.cs | 105 +++++++++++++++++ .../ScreenReferenceMarkerEditor.cs.meta | 3 + Assets/Scenes/MiniGames/BirdPoop.unity | 6 +- .../AppleHillsCamera/CameraScreenAdapter.cs | 50 ++++++-- .../AppleHillsCamera/ScreenReferenceMarker.cs | 107 ++++++++++++++---- 7 files changed, 326 insertions(+), 32 deletions(-) create mode 100644 Assets/Editor/CustomEditorsAndDrawers/CameraScreenAdapterEditor.cs create mode 100644 Assets/Editor/CustomEditorsAndDrawers/CameraScreenAdapterEditor.cs.meta create mode 100644 Assets/Editor/CustomEditorsAndDrawers/ScreenReferenceMarkerEditor.cs create mode 100644 Assets/Editor/CustomEditorsAndDrawers/ScreenReferenceMarkerEditor.cs.meta diff --git a/Assets/Editor/CustomEditorsAndDrawers/CameraScreenAdapterEditor.cs b/Assets/Editor/CustomEditorsAndDrawers/CameraScreenAdapterEditor.cs new file mode 100644 index 00000000..8cf51f4a --- /dev/null +++ b/Assets/Editor/CustomEditorsAndDrawers/CameraScreenAdapterEditor.cs @@ -0,0 +1,84 @@ +using UnityEngine; +using UnityEditor; +using AppleHillsCamera; + +namespace Editor.CustomEditorsAndDrawers +{ + /// + /// Custom editor for CameraScreenAdapter component. + /// Shows scaling mode info and provides helper buttons. + /// + [CustomEditor(typeof(CameraScreenAdapter))] + public class CameraScreenAdapterEditor : UnityEditor.Editor + { + private SerializedProperty _referenceMarkerProp; + private SerializedProperty _adjustOnStartProp; + private SerializedProperty _adjustOnScreenResizeProp; + private SerializedProperty _debugLoggingProp; + + private void OnEnable() + { + _referenceMarkerProp = serializedObject.FindProperty("referenceMarker"); + _adjustOnStartProp = serializedObject.FindProperty("adjustOnStart"); + _adjustOnScreenResizeProp = serializedObject.FindProperty("adjustOnScreenResize"); + _debugLoggingProp = serializedObject.FindProperty("debugLogging"); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + CameraScreenAdapter adapter = (CameraScreenAdapter)target; + + // Reference Marker + EditorGUILayout.PropertyField(_referenceMarkerProp); + + // Show current scaling mode info if reference marker is assigned + if (adapter.referenceMarker != null) + { + EditorGUILayout.Space(5); + + ScreenReferenceMarker.ScalingMode mode = adapter.referenceMarker.scalingMode; + string modeStr = mode == ScreenReferenceMarker.ScalingMode.Width ? "Width" : "Height"; + + EditorGUILayout.HelpBox( + $"Current Scaling Mode: {modeStr}\n" + + (mode == ScreenReferenceMarker.ScalingMode.Width + ? $"Target Width: {adapter.referenceMarker.targetWidth:F2} units" + : $"Target Height: {adapter.referenceMarker.targetHeight:F2} units"), + MessageType.Info + ); + } + else + { + EditorGUILayout.Space(5); + EditorGUILayout.HelpBox( + "Assign a ScreenReferenceMarker to configure camera scaling.", + MessageType.Warning + ); + } + + EditorGUILayout.Space(10); + + // Settings + EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel); + EditorGUILayout.PropertyField(_adjustOnStartProp); + EditorGUILayout.PropertyField(_adjustOnScreenResizeProp); + EditorGUILayout.PropertyField(_debugLoggingProp); + + EditorGUILayout.Space(10); + + // Manual adjustment button + GUI.enabled = adapter.referenceMarker != null; + if (GUILayout.Button("Adjust Camera Now")) + { + adapter.AdjustCamera(); + SceneView.RepaintAll(); // Refresh scene view to show changes + } + GUI.enabled = true; + + serializedObject.ApplyModifiedProperties(); + } + } +} + diff --git a/Assets/Editor/CustomEditorsAndDrawers/CameraScreenAdapterEditor.cs.meta b/Assets/Editor/CustomEditorsAndDrawers/CameraScreenAdapterEditor.cs.meta new file mode 100644 index 00000000..363b510d --- /dev/null +++ b/Assets/Editor/CustomEditorsAndDrawers/CameraScreenAdapterEditor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 534f6a2da4584452b0df63f25d0d95df +timeCreated: 1766065528 \ No newline at end of file diff --git a/Assets/Editor/CustomEditorsAndDrawers/ScreenReferenceMarkerEditor.cs b/Assets/Editor/CustomEditorsAndDrawers/ScreenReferenceMarkerEditor.cs new file mode 100644 index 00000000..14e8efb6 --- /dev/null +++ b/Assets/Editor/CustomEditorsAndDrawers/ScreenReferenceMarkerEditor.cs @@ -0,0 +1,105 @@ +using UnityEngine; +using UnityEditor; +using AppleHillsCamera; + +namespace Editor.CustomEditorsAndDrawers +{ + /// + /// Custom editor for ScreenReferenceMarker component. + /// Shows only relevant fields based on the selected scaling mode. + /// + [CustomEditor(typeof(ScreenReferenceMarker))] + public class ScreenReferenceMarkerEditor : UnityEditor.Editor + { + private SerializedProperty _scalingModeProp; + private SerializedProperty _targetWidthProp; + private SerializedProperty _targetHeightProp; + private SerializedProperty _topMarginProp; + private SerializedProperty _bottomMarginProp; + private SerializedProperty _leftMarginProp; + private SerializedProperty _rightMarginProp; + private SerializedProperty _gizmoColorProp; + private SerializedProperty _screenEdgeColorProp; + private SerializedProperty _showVerticalMarginsProp; + private SerializedProperty _showHorizontalMarginsProp; + + private void OnEnable() + { + _scalingModeProp = serializedObject.FindProperty("scalingMode"); + _targetWidthProp = serializedObject.FindProperty("targetWidth"); + _targetHeightProp = serializedObject.FindProperty("targetHeight"); + _topMarginProp = serializedObject.FindProperty("topMargin"); + _bottomMarginProp = serializedObject.FindProperty("bottomMargin"); + _leftMarginProp = serializedObject.FindProperty("leftMargin"); + _rightMarginProp = serializedObject.FindProperty("rightMargin"); + _gizmoColorProp = serializedObject.FindProperty("gizmoColor"); + _screenEdgeColorProp = serializedObject.FindProperty("screenEdgeColor"); + _showVerticalMarginsProp = serializedObject.FindProperty("showVerticalMargins"); + _showHorizontalMarginsProp = serializedObject.FindProperty("showHorizontalMargins"); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + // Scaling Mode + EditorGUILayout.PropertyField(_scalingModeProp); + + EditorGUILayout.Space(5); + + // Reference Dimensions Header + EditorGUILayout.LabelField("Reference Dimensions", EditorStyles.boldLabel); + + // Show appropriate dimension field based on scaling mode + ScreenReferenceMarker.ScalingMode mode = (ScreenReferenceMarker.ScalingMode)_scalingModeProp.enumValueIndex; + + if (mode == ScreenReferenceMarker.ScalingMode.Width) + { + EditorGUILayout.PropertyField(_targetWidthProp, new GUIContent( + "Target Width", + "The target width that should match the screen width" + )); + + // Show info about height + EditorGUILayout.HelpBox( + "Height will automatically adjust based on screen aspect ratio.", + MessageType.Info + ); + } + else // ScalingMode.Height + { + EditorGUILayout.PropertyField(_targetHeightProp, new GUIContent( + "Target Height", + "The target height that should match the screen height" + )); + + // Show info about width + EditorGUILayout.HelpBox( + "Width will automatically adjust based on screen aspect ratio.", + MessageType.Info + ); + } + + EditorGUILayout.Space(10); + + // Margins + EditorGUILayout.LabelField("Margins", EditorStyles.boldLabel); + EditorGUILayout.PropertyField(_topMarginProp); + EditorGUILayout.PropertyField(_bottomMarginProp); + EditorGUILayout.PropertyField(_leftMarginProp); + EditorGUILayout.PropertyField(_rightMarginProp); + + EditorGUILayout.Space(10); + + // Visualization + EditorGUILayout.LabelField("Visualization", EditorStyles.boldLabel); + EditorGUILayout.PropertyField(_gizmoColorProp); + EditorGUILayout.PropertyField(_screenEdgeColorProp); + EditorGUILayout.PropertyField(_showVerticalMarginsProp); + EditorGUILayout.PropertyField(_showHorizontalMarginsProp); + + serializedObject.ApplyModifiedProperties(); + } + } +} + diff --git a/Assets/Editor/CustomEditorsAndDrawers/ScreenReferenceMarkerEditor.cs.meta b/Assets/Editor/CustomEditorsAndDrawers/ScreenReferenceMarkerEditor.cs.meta new file mode 100644 index 00000000..986ddef7 --- /dev/null +++ b/Assets/Editor/CustomEditorsAndDrawers/ScreenReferenceMarkerEditor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9988ac8e5878470997a08ecb42697daf +timeCreated: 1766065516 \ No newline at end of file diff --git a/Assets/Scenes/MiniGames/BirdPoop.unity b/Assets/Scenes/MiniGames/BirdPoop.unity index 7b690156..2ec013f2 100644 --- a/Assets/Scenes/MiniGames/BirdPoop.unity +++ b/Assets/Scenes/MiniGames/BirdPoop.unity @@ -820,7 +820,7 @@ Transform: m_GameObject: {fileID: 941621855} serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -14.66, y: 0, z: 0} + m_LocalPosition: {x: -21.326666, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: @@ -872,6 +872,7 @@ MonoBehaviour: OnPlayerDamaged: m_PersistentCalls: m_Calls: [] + flapCooldown: 0.15 --- !u!114 &941621860 MonoBehaviour: m_ObjectHideFlags: 0 @@ -1314,7 +1315,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 3058fe4801134fea916ad685f924668f, type: 3} m_Name: m_EditorClassIdentifier: AppleHillsScripts::AppleHillsCamera.ScreenReferenceMarker + scalingMode: 1 targetWidth: 40 + targetHeight: 30.21 topMargin: 0.2 bottomMargin: 0.2 leftMargin: 0.2 @@ -2021,6 +2024,7 @@ MonoBehaviour: referenceMarker: {fileID: 1143700529} adjustOnStart: 1 adjustOnScreenResize: 1 + debugLogging: 0 --- !u!1 &2116132838 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/AppleHillsCamera/CameraScreenAdapter.cs b/Assets/Scripts/AppleHillsCamera/CameraScreenAdapter.cs index 8eb3e081..5ded04bd 100644 --- a/Assets/Scripts/AppleHillsCamera/CameraScreenAdapter.cs +++ b/Assets/Scripts/AppleHillsCamera/CameraScreenAdapter.cs @@ -19,6 +19,9 @@ namespace AppleHillsCamera [Tooltip("Whether to adjust the camera automatically when the screen size changes")] public bool adjustOnScreenResize = true; + + [Tooltip("Enable debug logging")] + public bool debugLogging; // Event that other components can subscribe to when camera is adjusted public event Action OnCameraAdjusted; @@ -71,7 +74,7 @@ namespace AppleHillsCamera } /// - /// Manually trigger camera adjustment to match the reference width. + /// Manually trigger camera adjustment to match the reference width or height. /// public void AdjustCamera() { @@ -81,13 +84,34 @@ namespace AppleHillsCamera return; } - // Calculate the orthographic size based on the target width and screen aspect ratio - float targetWidth = referenceMarker.targetWidth; - float screenAspect = (float)Screen.height / Screen.width; + float orthoSize; - // Orthographic size is half the height, so we calculate: - // orthoSize = (targetWidth / 2) * (screenHeight / screenWidth) - float orthoSize = (targetWidth / 2f) * screenAspect; + if (referenceMarker.scalingMode == ScreenReferenceMarker.ScalingMode.Width) + { + // Calculate the orthographic size based on the target width and screen aspect ratio + float targetWidth = referenceMarker.targetWidth; + float screenAspect = (float)Screen.height / Screen.width; + + // Orthographic size is half the height, so we calculate: + // orthoSize = (targetWidth / 2) * (screenHeight / screenWidth) + orthoSize = (targetWidth / 2f) * screenAspect; + + if (debugLogging) + { + Logging.Debug($"CameraScreenAdapter: Scaling by Width - targetWidth={targetWidth:F2}, aspect={screenAspect:F2}, orthoSize={orthoSize:F2}"); + } + } + else // ScalingMode.Height + { + // When scaling by height, the orthographic size directly matches half the target height + float targetHeight = referenceMarker.targetHeight; + orthoSize = targetHeight / 2f; + + if (debugLogging) + { + Logging.Debug($"CameraScreenAdapter: Scaling by Height - targetHeight={targetHeight:F2}, orthoSize={orthoSize:F2}"); + } + } // Apply the calculated size to the camera if (_usingCinemachine) @@ -96,7 +120,11 @@ namespace AppleHillsCamera var lens = _virtualCamera.Lens; lens.OrthographicSize = orthoSize; _virtualCamera.Lens = lens; - Logging.Debug($"Cinemachine Camera adapted: Width={targetWidth}, Aspect={screenAspect:F2}, OrthoSize={orthoSize:F2}"); + + if (debugLogging) + { + Logging.Debug($"Cinemachine Camera adapted: OrthoSize={orthoSize:F2}"); + } } else { @@ -104,7 +132,11 @@ namespace AppleHillsCamera if (_regularCamera.orthographic) { _regularCamera.orthographicSize = orthoSize; - Logging.Debug($"Camera adapted: Width={targetWidth}, Aspect={screenAspect:F2}, OrthoSize={orthoSize:F2}"); + + if (debugLogging) + { + Logging.Debug($"Camera adapted: OrthoSize={orthoSize:F2}"); + } } else { diff --git a/Assets/Scripts/AppleHillsCamera/ScreenReferenceMarker.cs b/Assets/Scripts/AppleHillsCamera/ScreenReferenceMarker.cs index 5ac28829..67c65870 100644 --- a/Assets/Scripts/AppleHillsCamera/ScreenReferenceMarker.cs +++ b/Assets/Scripts/AppleHillsCamera/ScreenReferenceMarker.cs @@ -8,11 +8,24 @@ namespace AppleHillsCamera /// public class ScreenReferenceMarker : MonoBehaviour { - [Header("Horizontal Reference")] - [Tooltip("The target width that should match the screen width")] - public float targetWidth = 10f; + public enum ScalingMode + { + Width, + Height + } - [Header("Vertical References")] + [Header("Scaling Mode")] + [Tooltip("Whether to scale the camera based on width or height")] + public ScalingMode scalingMode = ScalingMode.Width; + + [Header("Reference Dimensions")] + [Tooltip("The target width that should match the screen width (used when scaling by width)")] + public float targetWidth = 10f; + + [Tooltip("The target height that should match the screen height (used when scaling by height)")] + public float targetHeight = 5f; + + [Header("Margins")] [Tooltip("Distance from top of screen to use for anchoring")] public float topMargin = 1f; @@ -49,20 +62,8 @@ namespace AppleHillsCamera Vector3 position = transform.position; - // Draw the width reference - Vector3 left = position + Vector3.left * (targetWidth / 2f); - Vector3 right = position + Vector3.right * (targetWidth / 2f); - Gizmos.DrawLine(left, right); - - // Draw vertical endpoints - float endCapSize = 0.5f; - Gizmos.DrawLine(left, left + Vector3.up * endCapSize); - Gizmos.DrawLine(left, left + Vector3.down * endCapSize); - Gizmos.DrawLine(right, right + Vector3.up * endCapSize); - Gizmos.DrawLine(right, right + Vector3.down * endCapSize); - - // Calculate visual screen edges based on actual camera viewport - float halfWidth = targetWidth / 2f; + // Calculate visual screen edges based on scaling mode and actual camera viewport + float halfWidth; float halfHeight; // Try to get camera references in the preferred order @@ -71,14 +72,37 @@ namespace AppleHillsCamera Camera mainCamera = Camera.main; if (mainCamera != null && mainCamera.orthographic) { - // Use the main camera's actual orthographic size for the height - halfHeight = mainCamera.orthographicSize; + if (scalingMode == ScalingMode.Width) + { + // When scaling by width, the width is fixed and height varies + halfWidth = targetWidth / 2f; + // Use the main camera's actual orthographic size for the height + halfHeight = mainCamera.orthographicSize; + } + else // ScalingMode.Height + { + // When scaling by height, the height is fixed and width varies + halfHeight = targetHeight / 2f; + // Calculate width based on camera's aspect ratio + float screenAspect = (float)Screen.width / Screen.height; + halfWidth = halfHeight * screenAspect; + } } else { // 2. Use Game/Simulator window resolution float gameViewAspect = (float)Screen.height / Screen.width; - halfHeight = halfWidth * gameViewAspect; + + if (scalingMode == ScalingMode.Width) + { + halfWidth = targetWidth / 2f; + halfHeight = halfWidth * gameViewAspect; + } + else // ScalingMode.Height + { + halfHeight = targetHeight / 2f; + halfWidth = halfHeight / gameViewAspect; + } // 3. Fallback to the scene view camera if needed UnityEditor.SceneView sceneView = UnityEditor.SceneView.lastActiveSceneView; @@ -86,10 +110,49 @@ namespace AppleHillsCamera { // Use the scene view camera's aspect ratio instead float sceneAspect = sceneView.camera.pixelHeight / (float)sceneView.camera.pixelWidth; - halfHeight = halfWidth * sceneAspect; + + if (scalingMode == ScalingMode.Width) + { + halfHeight = halfWidth * sceneAspect; + } + else // ScalingMode.Height + { + float sceneAspectInv = sceneView.camera.pixelWidth / (float)sceneView.camera.pixelHeight; + halfWidth = halfHeight * sceneAspectInv; + } } } + // Draw the reference dimension indicator based on scaling mode + if (scalingMode == ScalingMode.Width) + { + // Draw the width reference (horizontal line) + Vector3 left = position + Vector3.left * halfWidth; + Vector3 right = position + Vector3.right * halfWidth; + Gizmos.DrawLine(left, right); + + // Draw vertical endpoints + float endCapSize = 0.5f; + Gizmos.DrawLine(left, left + Vector3.up * endCapSize); + Gizmos.DrawLine(left, left + Vector3.down * endCapSize); + Gizmos.DrawLine(right, right + Vector3.up * endCapSize); + Gizmos.DrawLine(right, right + Vector3.down * endCapSize); + } + else // ScalingMode.Height + { + // Draw the height reference (vertical line) + Vector3 top = position + Vector3.up * halfHeight; + Vector3 bottom = position + Vector3.down * halfHeight; + Gizmos.DrawLine(top, bottom); + + // Draw horizontal endpoints + float endCapSize = 0.5f; + Gizmos.DrawLine(top, top + Vector3.left * endCapSize); + Gizmos.DrawLine(top, top + Vector3.right * endCapSize); + Gizmos.DrawLine(bottom, bottom + Vector3.left * endCapSize); + Gizmos.DrawLine(bottom, bottom + Vector3.right * endCapSize); + } + // Screen edge positions Vector3 topEdge = position + Vector3.up * halfHeight; Vector3 bottomEdge = position + Vector3.down * halfHeight;