From 96839e0e8266fda2c3f873be0ce139e87aee8bf2 Mon Sep 17 00:00:00 2001 From: henrisel Date: Wed, 14 Jan 2026 14:02:10 +0200 Subject: [PATCH] ShapeScanner multiple configurations, configurable in editor --- Assets/Editor/BoolMatrixDrawer.cs | 144 +++++++++++++ Assets/Editor/BoolMatrixDrawer.cs.meta | 11 + .../ModelGeneration/ShapeScanner.prefab | 198 ++++++++++++++++-- .../ModelGeneration/ShapeScannerRay.prefab | 9 +- .../_PROJECT/Scenes/DeltaBuilding_base.unity | 4 +- .../ArcheryRange/MicrophoneStand.cs | 1 + .../ShapeDetectionMinigameController.cs | 2 + .../ShapeDetection/ShapeScanner.cs | 130 ++++++++---- .../com.unity.probuilder/Settings.json | 19 +- 9 files changed, 448 insertions(+), 70 deletions(-) create mode 100644 Assets/Editor/BoolMatrixDrawer.cs create mode 100644 Assets/Editor/BoolMatrixDrawer.cs.meta diff --git a/Assets/Editor/BoolMatrixDrawer.cs b/Assets/Editor/BoolMatrixDrawer.cs new file mode 100644 index 00000000..5659d95c --- /dev/null +++ b/Assets/Editor/BoolMatrixDrawer.cs @@ -0,0 +1,144 @@ + +#if UNITY_EDITOR +using UnityEditor; +using UnityEngine; + + +[CustomPropertyDrawer(typeof(ShapeScannerConfiguration))] +public class BoolMatrixDrawer : PropertyDrawer +{ + private const float ToggleSize = 18f; + private const float RowLabelWidth = 24f; + private const float Padding = 2f; + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + var rowsProp = property.FindPropertyRelative("rows"); + var columnsProp = property.FindPropertyRelative("columns"); + int rows = rowsProp != null ? rowsProp.arraySize : 0; + int cols = Mathf.Max(0, columnsProp != null ? columnsProp.intValue : 0); + + // Header (one line), columns field (one line), buttons (one line), then one line per row + int totalLines = 1 + 1 + 1 + Mathf.Max(1, rows); + float lineHeight = EditorGUIUtility.singleLineHeight + Padding; + return totalLines * lineHeight + Padding; + } + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + EditorGUI.BeginProperty(position, label, property); + + var rowsProp = property.FindPropertyRelative("rows"); + var columnsProp = property.FindPropertyRelative("columns"); + + if (rowsProp == null || columnsProp == null) + { + EditorGUI.HelpBox(position, "BoolMatrix is missing 'rows' or 'columns' properties.", MessageType.Error); + EditorGUI.EndProperty(); + return; + } + + // Layout helper + float lineHeight = EditorGUIUtility.singleLineHeight; + Rect line = new Rect(position.x, position.y, position.width, lineHeight); + + // Header + EditorGUI.LabelField(line, label, EditorStyles.boldLabel); + line.y += lineHeight + Padding; + + // Draw requiredCorrectPercentage + var requiredCorrectProp = property.FindPropertyRelative("requiredCorrectPercentage"); + EditorGUI.PropertyField(line, requiredCorrectProp, new GUIContent("Required Correct Percentage")); + line.y += lineHeight + Padding; + + // Columns field + EditorGUI.BeginChangeCheck(); + int cols = Mathf.Max(0, EditorGUI.IntField(line, "Columns", columnsProp.intValue)); + if (EditorGUI.EndChangeCheck()) + { + columnsProp.intValue = cols; + // Resize each row to match new column count + for (int r = 0; r < rowsProp.arraySize; r++) + { + var rowProp = rowsProp.GetArrayElementAtIndex(r); + var cellsProp = rowProp.FindPropertyRelative("cells"); + ResizeBoolArray(cellsProp, cols); + } + } + line.y += lineHeight + Padding; + + // Row controls (Add/Remove) + using (new EditorGUI.IndentLevelScope()) + { + Rect left = new Rect(line.x, line.y, 120, lineHeight); + if (GUI.Button(left, "Add Row")) + { + int newIndex = rowsProp.arraySize; + rowsProp.InsertArrayElementAtIndex(newIndex); + var rowProp = rowsProp.GetArrayElementAtIndex(newIndex); + var cellsProp = rowProp.FindPropertyRelative("cells"); + ResizeBoolArray(cellsProp, columnsProp.intValue); + } + + Rect right = new Rect(line.x + 130, line.y, 140, lineHeight); + if (GUI.Button(right, "Remove Last Row") && rowsProp.arraySize > 0) + { + rowsProp.DeleteArrayElementAtIndex(rowsProp.arraySize - 1); + } + } + line.y += lineHeight + Padding; + + // Draw grid + int rowCount = rowsProp.arraySize; + int colCount = Mathf.Max(0, columnsProp.intValue); + + for (int r = 0; r < rowCount; r++) + { + var rowProp = rowsProp.GetArrayElementAtIndex(r); + var cellsProp = rowProp.FindPropertyRelative("cells"); + + // Ensure row width + if (cellsProp.arraySize != colCount) + ResizeBoolArray(cellsProp, colCount); + + // Row label + Rect rowLabel = new Rect(line.x, line.y, RowLabelWidth, lineHeight); + EditorGUI.LabelField(rowLabel, $"R{r}"); + + // Toggle strip + float startX = rowLabel.x + RowLabelWidth + Padding; + for (int c = 0; c < colCount; c++) + { + Rect toggleRect = new Rect(startX + c * (ToggleSize + 2), line.y, ToggleSize, lineHeight); + var cellProp = cellsProp.GetArrayElementAtIndex(c); + bool newVal = EditorGUI.Toggle(toggleRect, GUIContent.none, cellProp.boolValue); + if (newVal != cellProp.boolValue) cellProp.boolValue = newVal; + } + + line.y += lineHeight + Padding; + } + + EditorGUI.EndProperty(); + } + + private void ResizeBoolArray(SerializedProperty listProp, int newSize) + { + if (listProp == null) return; + newSize = Mathf.Max(0, newSize); + + // Grow + while (listProp.arraySize < newSize) + { + int i = listProp.arraySize; + listProp.InsertArrayElementAtIndex(i); + var elem = listProp.GetArrayElementAtIndex(i); + elem.boolValue = false; + } + // Shrink + while (listProp.arraySize > newSize) + { + listProp.DeleteArrayElementAtIndex(listProp.arraySize - 1); + } + } +} +#endif diff --git a/Assets/Editor/BoolMatrixDrawer.cs.meta b/Assets/Editor/BoolMatrixDrawer.cs.meta new file mode 100644 index 00000000..e284d9ae --- /dev/null +++ b/Assets/Editor/BoolMatrixDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e3da5d98c11c1b54fb05eda4624de9e3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_PROJECT/Prefabs/ModelGeneration/ShapeScanner.prefab b/Assets/_PROJECT/Prefabs/ModelGeneration/ShapeScanner.prefab index 5e402762..b0ce4223 100644 --- a/Assets/_PROJECT/Prefabs/ModelGeneration/ShapeScanner.prefab +++ b/Assets/_PROJECT/Prefabs/ModelGeneration/ShapeScanner.prefab @@ -27,8 +27,8 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1013838101896458198} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -0.21589, z: 0} - m_LocalScale: {x: 0.64645, y: 0.029855646, z: 0.64645} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.6, y: 0.03, z: 0.6} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8294461198356057691} @@ -105,6 +105,146 @@ BoxCollider: serializedVersion: 3 m_Size: {x: 1, y: 1, z: 1} m_Center: {x: 0, y: 0, z: 0} +--- !u!1 &1231701550042884109 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8594417542550664647} + - component: {fileID: 7869926060146003813} + - component: {fileID: 5476518908687164580} + m_Layer: 0 + m_Name: CurrentConfigurationDisplay + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8594417542550664647 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1231701550042884109} + 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: 6932860525531626823} + m_RootOrder: -1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 0.5, y: 0} + m_AnchoredPosition: {x: 0, y: 22.45} + m_SizeDelta: {x: 50, y: 14} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7869926060146003813 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1231701550042884109} + m_CullTransparentMesh: 1 +--- !u!114 &5476518908687164580 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1231701550042884109} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: '0 / 2 + +' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 254d33525bc3919439f569ea33703c5b, type: 2} + m_sharedMaterial: {fileID: 4369893532151414794, guid: 254d33525bc3919439f569ea33703c5b, + type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 12 + m_fontSizeBase: 12 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 0 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!1 &1374309978863673311 GameObject: m_ObjectHideFlags: 0 @@ -129,7 +269,7 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1374309978863673311} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0.3, y: 0, z: 0.3} + m_LocalPosition: {x: 0.275, y: 0, z: 0.275} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] @@ -160,7 +300,7 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1598434951760464124} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: -0.416, z: 0} + m_LocalPosition: {x: 0, y: -0.225, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: @@ -199,6 +339,7 @@ RectTransform: m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: + - {fileID: 8594417542550664647} - {fileID: 6492405423818451632} m_Father: {fileID: 5335160954898573969} m_RootOrder: -1 @@ -273,8 +414,8 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 3769602036287398038} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -0.61411, z: 0} - m_LocalScale: {x: 0.64645, y: 0.029855646, z: 0.64645} + m_LocalPosition: {x: 0, y: -0.5, z: 0} + m_LocalScale: {x: 0.6, y: 0.03, z: 0.6} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8294461198356057691} @@ -375,7 +516,7 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 5358414661713154358} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -0.3, y: 0, z: -0.3} + m_LocalPosition: {x: -0.275, y: 0, z: -0.275} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] @@ -394,7 +535,7 @@ GameObject: - component: {fileID: 489185111762359262} - component: {fileID: 7443612957244256760} m_Layer: 0 - m_Name: Text + m_Name: CorrectPercentageDisplay m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -415,9 +556,9 @@ RectTransform: m_Father: {fileID: 6932860525531626823} m_RootOrder: -1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 0.5, y: 0} + m_AnchoredPosition: {x: 0, y: 7} m_SizeDelta: {x: 50, y: 14} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &489185111762359262 @@ -570,25 +711,38 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: b2226de466bbe814d8bfe0cb0fce83f6, type: 3} m_Name: m_EditorClassIdentifier: - configuration: - - cells: 010001010000 - - cells: 000101010000 - - cells: 010101010101 - - cells: 000000000000 - - cells: 000000000000 - - cells: 000000000000 + configurations: + - columns: 6 + requiredCorrectPercentage: 80 + rows: + - cells: 000000000000 + - cells: 000001010000 + - cells: 000001010000 + - cells: 000101010100 + - cells: 010101010101 + - cells: 000000000000 + - columns: 6 + requiredCorrectPercentage: 80 + rows: + - cells: 000001000000 + - cells: 000101010100 + - cells: 000101010101 + - cells: 010101010100 + - cells: 000101010100 + - cells: 000000010000 rayPrefab: {fileID: 1303694035827653214, guid: dfe698ad960ffbd47a7d0ff8f6b5baa3, type: 3} raySpawnCorner1: {fileID: 4055409281532582849} raySpawnCorner2: {fileID: 8025195334996356355} rayParent: {fileID: 4362133469817120903} + currentConfigurationDisplay: {fileID: 5476518908687164580} + correctPercentageDisplay: {fileID: 7443612957244256760} requiredAndActive: {fileID: 2100000, guid: dccb608b252977047bd5848d6a497bfb, type: 2} requiredAndPassive: {fileID: 2100000, guid: c0707507abffb6149b19e60299403e82, type: 2} notRequiredAndActive: {fileID: 2100000, guid: c7aad7ea05b9332478242744c9de52b9, type: 2} notRequiredAndPassive: {fileID: 2100000, guid: 991fa2870324ba04aba7bec9e1168afa, type: 2} - displayText: {fileID: 7443612957244256760} --- !u!54 &6146655625910388013 Rigidbody: m_ObjectHideFlags: 0 @@ -707,7 +861,7 @@ MonoBehaviour: m_Calls: [] m_AttachTransform: {fileID: 0} m_SecondaryAttachTransform: {fileID: 0} - m_UseDynamicAttach: 0 + m_UseDynamicAttach: 1 m_MatchAttachPosition: 1 m_MatchAttachRotation: 1 m_SnapToColliderVolume: 1 @@ -788,8 +942,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 50, y: 20} + m_AnchoredPosition: {x: 0, y: 0.16} + m_SizeDelta: {x: 50, y: 30} m_Pivot: {x: 0.5, y: 0.5} --- !u!223 &2825347825077556369 Canvas: diff --git a/Assets/_PROJECT/Prefabs/ModelGeneration/ShapeScannerRay.prefab b/Assets/_PROJECT/Prefabs/ModelGeneration/ShapeScannerRay.prefab index f4972bf1..5fececc3 100644 --- a/Assets/_PROJECT/Prefabs/ModelGeneration/ShapeScannerRay.prefab +++ b/Assets/_PROJECT/Prefabs/ModelGeneration/ShapeScannerRay.prefab @@ -29,11 +29,11 @@ Transform: m_GameObject: {fileID: 8688612914795219519} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.259, y: 0.012, z: -0.26886} - m_LocalScale: {x: 0.035900656, y: 0.45784503, z: 0.035900656} + m_LocalScale: {x: 0.035, y: 0.5, z: 0.035} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: -1 + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &8730629787356023745 MeshFilter: @@ -118,5 +118,6 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: db942dc95bda5a149b7e9358de43a923, type: 3} m_Name: m_EditorClassIdentifier: - activeMaterial: {fileID: 0} - passiveMaterial: {fileID: 0} + _activeMaterial: {fileID: 0} + _passiveMaterial: {fileID: 0} + scannableTag: ShapeScannable diff --git a/Assets/_PROJECT/Scenes/DeltaBuilding_base.unity b/Assets/_PROJECT/Scenes/DeltaBuilding_base.unity index 1997accd..6aef7a14 100644 --- a/Assets/_PROJECT/Scenes/DeltaBuilding_base.unity +++ b/Assets/_PROJECT/Scenes/DeltaBuilding_base.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c77e82a1e194d016fc4cde74c15b48b7b9b5a54d8f1dcfce4b155b7c342fd41 -size 67860614 +oid sha256:5cb70d3f641c5491e6d2b2c98ad2399fa7650033ed3a9aca15944e96377e6d72 +size 68524704 diff --git a/Assets/_PROJECT/Scripts/ModeGeneration/ArcheryRange/MicrophoneStand.cs b/Assets/_PROJECT/Scripts/ModeGeneration/ArcheryRange/MicrophoneStand.cs index dd6a9b88..bc868408 100644 --- a/Assets/_PROJECT/Scripts/ModeGeneration/ArcheryRange/MicrophoneStand.cs +++ b/Assets/_PROJECT/Scripts/ModeGeneration/ArcheryRange/MicrophoneStand.cs @@ -12,6 +12,7 @@ public class MicrophoneStand : MonoBehaviour private WhisperStream stream; + [SerializeField] private string textOutput; public GameObject microphoneOffStatus; diff --git a/Assets/_PROJECT/Scripts/ModeGeneration/ShapeDetection/ShapeDetectionMinigameController.cs b/Assets/_PROJECT/Scripts/ModeGeneration/ShapeDetection/ShapeDetectionMinigameController.cs index 06602b25..78358aaa 100644 --- a/Assets/_PROJECT/Scripts/ModeGeneration/ShapeDetection/ShapeDetectionMinigameController.cs +++ b/Assets/_PROJECT/Scripts/ModeGeneration/ShapeDetection/ShapeDetectionMinigameController.cs @@ -76,6 +76,8 @@ public class ShapeDetectionMinigameController : MonoBehaviour //spawnedObject.AddComponent(); //spawnedObject.AddComponent(); + MeshCollider spawnedObjectCollider = spawnedObject.GetComponent(); + spawnedObjectCollider.convex = false; spawnedObject.transform.parent = spawnedObjectParent.transform; spawnedObject.transform.position = spawnedObjectParent.transform.position; spawnedObject.tag = shapeScannerTag; diff --git a/Assets/_PROJECT/Scripts/ModeGeneration/ShapeDetection/ShapeScanner.cs b/Assets/_PROJECT/Scripts/ModeGeneration/ShapeDetection/ShapeScanner.cs index 87ef8140..fad1a6f6 100644 --- a/Assets/_PROJECT/Scripts/ModeGeneration/ShapeDetection/ShapeScanner.cs +++ b/Assets/_PROJECT/Scripts/ModeGeneration/ShapeDetection/ShapeScanner.cs @@ -1,68 +1,57 @@ +using System; using System.Collections.Generic; +using System.Linq; using TMPro; using UnityEngine; -[System.Serializable] +[Serializable] public class BoolRow { - public bool[] cells; + public List cells = new List(); +} + +[Serializable] +public class ShapeScannerConfiguration +{ + public int columns = 6; + public float requiredCorrectPercentage = 80.0f; + public List rows = new List(); } public class ShapeScanner : MonoBehaviour { - public List configuration; + public List configurations = new List(); public ShapeScannerRay rayPrefab; public Transform raySpawnCorner1; public Transform raySpawnCorner2; public Transform rayParent; + public TextMeshProUGUI currentConfigurationDisplay; + public TextMeshProUGUI correctPercentageDisplay; public Material requiredAndActive; public Material requiredAndPassive; public Material notRequiredAndActive; public Material notRequiredAndPassive; - public TextMeshProUGUI displayText; + private List existingRays; + private float raySpawnDistanceX; + private float raySpawnDistanceZ; + private int currentConfiguration; private int rayCount; private int correctRayStates; - private void Awake() - { - correctRayStates = 0; - } // Start is called before the first frame update void Start() { - float raySpawnDistanceX = raySpawnCorner2.localPosition.x - raySpawnCorner1.localPosition.x; - float raySpawnDistanceZ = raySpawnCorner2.localPosition.z - raySpawnCorner1.localPosition.z; + existingRays = new List(); + raySpawnDistanceX = raySpawnCorner2.localPosition.x - raySpawnCorner1.localPosition.x; + raySpawnDistanceZ = raySpawnCorner2.localPosition.z - raySpawnCorner1.localPosition.z; - int rayRowCount = configuration.Count; - for (int i = 0; i < rayRowCount; i++) - { - float rayPosX = raySpawnCorner1.localPosition.x + i * raySpawnDistanceX / (rayRowCount - 1); - for (int j = 0; j < rayRowCount; j++) - { - rayCount++; - - // Local position - float rayPosZ = raySpawnCorner1.localPosition.z + j * raySpawnDistanceZ / (rayRowCount - 1); - Vector3 rayPos = new Vector3(rayPosX, 0, rayPosZ); - ShapeScannerRay ray = Instantiate(rayPrefab, rayParent); - ray.transform.localPosition = rayPos; - - bool rayCollisionRequired = configuration[i].cells[j]; - if (rayCollisionRequired) - { - ray.Initialize(this, rayCollisionRequired, requiredAndActive, requiredAndPassive); - } else - { - ray.Initialize(this, rayCollisionRequired, notRequiredAndActive, notRequiredAndPassive); - IncrementCorrectRayCount(); - } - } - } + currentConfiguration = 0; + InitializeConfiguration(); } // Update is called once per frame @@ -71,21 +60,82 @@ public class ShapeScanner : MonoBehaviour } + private void InitializeConfiguration() + { + // Delete all existing rays first + foreach (GameObject ray in existingRays) + { + Destroy(ray); + } + + ShapeScannerConfiguration configuration = configurations[currentConfiguration]; + int rayRowCount = configuration.rows.Count; + for (int i = 0; i < rayRowCount; i++) + { + float rayPosX = raySpawnCorner1.localPosition.x + i * raySpawnDistanceX / (rayRowCount - 1); + for (int j = 0; j < rayRowCount; j++) + { + // Local position + float rayPosZ = raySpawnCorner1.localPosition.z + j * raySpawnDistanceZ / (rayRowCount - 1); + Vector3 rayPos = new Vector3(rayPosX, 0, rayPosZ); + ShapeScannerRay ray = Instantiate(rayPrefab, rayParent); + ray.transform.localPosition = rayPos; + existingRays.Add(ray.gameObject); + + bool rayCollisionRequired = configuration.rows[i].cells[j]; + if (rayCollisionRequired) + { + ray.Initialize(this, rayCollisionRequired, requiredAndActive, requiredAndPassive); + } + else + { + ray.Initialize(this, rayCollisionRequired, notRequiredAndActive, notRequiredAndPassive); + } + } + } + // Count total rays and required collision rays + rayCount = configuration.rows.SelectMany(row => row.cells).Count(); + correctRayStates = configuration.rows.SelectMany(row => row.cells).Count(cell => !cell); + UpdateDisplay(calculateCorrectPercentage()); + } + + private float calculateCorrectPercentage() + { + return Mathf.RoundToInt((float)correctRayStates / rayCount * 100); + } + public void IncrementCorrectRayCount() { correctRayStates++; - UpdateDisplay(); + float correctPercentage = calculateCorrectPercentage(); + if (correctPercentage >= configurations[currentConfiguration].requiredCorrectPercentage) + { + UpdateCurrentConfigurationDisplay(currentConfiguration + 1); + if (currentConfiguration + 1 < configurations.Count) + { + currentConfiguration++; + InitializeConfiguration(); + } else + { + Debug.Log("Shape checker completed"); + } + } + UpdateDisplay(correctPercentage); } public void DecrementCorrectRayCount() { correctRayStates--; - UpdateDisplay(); + UpdateDisplay(calculateCorrectPercentage()); } - private void UpdateDisplay() + private void UpdateDisplay(float percentage) { - int percentage = Mathf.RoundToInt((float) correctRayStates / rayCount * 100); - displayText.text = percentage.ToString() + " %"; + correctPercentageDisplay.text = Mathf.Round(percentage).ToString() + " %"; + } + + private void UpdateCurrentConfigurationDisplay(int confNumber) + { + currentConfigurationDisplay.text = confNumber.ToString() + " / " + configurations.Count; } } diff --git a/ProjectSettings/Packages/com.unity.probuilder/Settings.json b/ProjectSettings/Packages/com.unity.probuilder/Settings.json index fbd629d2..a13a6763 100644 --- a/ProjectSettings/Packages/com.unity.probuilder/Settings.json +++ b/ProjectSettings/Packages/com.unity.probuilder/Settings.json @@ -169,7 +169,7 @@ { "type": "System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "key": "ShapeBuilder.ActiveShapeIndex", - "value": "{\"m_Value\":2}" + "value": "{\"m_Value\":11}" }, { "type": "System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", @@ -189,7 +189,7 @@ { "type": "UnityEngine.Vector3, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "key": "ShapeBuilder.LastSize", - "value": "{\"m_Value\":{\"x\":49.08480453491211,\"y\":0.10000000149011612,\"z\":-30.85292625427246}}" + "value": "{\"m_Value\":{\"x\":1.3506088256835938,\"y\":0.41489124298095705,\"z\":1.3857231140136719}}" }, { "type": "UnityEngine.Vector3, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", @@ -246,6 +246,21 @@ "key": "ShapeBuilder.Plane", "value": "{}" }, + { + "type": "UnityEngine.ProBuilder.Shapes.Shape, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", + "key": "ShapeBuilder.Prism", + "value": "{}" + }, + { + "type": "UnityEngine.ProBuilder.Shapes.Shape, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", + "key": "ShapeBuilder.Torus", + "value": "{}" + }, + { + "type": "UnityEngine.ProBuilder.Shapes.Shape, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", + "key": "ShapeBuilder.Pipe", + "value": "{}" + }, { "type": "System.Single, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "key": "uv.uvEditorGridSnapIncrement",