Files
ApexSurgery/Assets/Oculus/SampleFramework/Usage/SceneManager/Scripts/FurnitureSpawner.cs
T
2025-07-04 20:33:06 +03:00

138 lines
4.2 KiB
C#

using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(OVRSceneAnchor))]
[DefaultExecutionOrder(30)]
public class FurnitureSpawner : MonoBehaviour
{
[Tooltip("Add a point at ceiling.")]
public GameObject RoomLightPrefab;
[Tooltip("This prefab will be used if the label is " +
"not in the SpawnablesPrefabs")]
public SimpleResizable FallbackPrefab;
public List<Spawnable> SpawnablePrefabs;
private OVRSceneAnchor _sceneAnchor;
private OVRSemanticClassification _classification;
private static GameObject _roomLightRef;
private int _frameCounter;
private void Start()
{
_sceneAnchor = GetComponent<OVRSceneAnchor>();
_classification = GetComponent<OVRSemanticClassification>();
AddRoomLight();
SpawnSpawnable();
}
private void SpawnSpawnable()
{
if (!FindValidSpawnable(out var currentSpawnable))
{
return;
}
// Get current anchor's information
Vector3 position = transform.position;
Quaternion rotation = transform.rotation;
Vector3 localScale = transform.localScale;
var plane = _sceneAnchor.GetComponent<OVRScenePlane>();
var volume = _sceneAnchor.GetComponent<OVRSceneVolume>();
var dimensions = volume ? volume.Dimensions : Vector3.one;
if (_classification && plane)
{
dimensions = plane.Dimensions;
dimensions.z = 1;
// Special case 01: Has only top plane
if (_classification.Contains(OVRSceneManager.Classification.Table) ||
_classification.Contains(OVRSceneManager.Classification.Couch))
{
GetVolumeFromTopPlane(
transform,
plane.Dimensions,
transform.position.y,
out position,
out rotation,
out localScale);
dimensions = localScale;
// The pivot for the resizer is at the top
position.y += localScale.y / 2.0f;
}
// Special case 02: Set wall thickness to something small instead of default value (1.0m)
if (_classification.Contains(OVRSceneManager.Classification.WallFace) ||
_classification.Contains(OVRSceneManager.Classification.Ceiling) ||
_classification.Contains(OVRSceneManager.Classification.Floor))
{
dimensions.z = 0.01f;
}
}
GameObject root = new GameObject("Root");
root.transform.parent = transform;
root.transform.SetPositionAndRotation(position, rotation);
SimpleResizer resizer = new SimpleResizer();
resizer.CreateResizedObject(dimensions, root, currentSpawnable);
}
private bool FindValidSpawnable(out SimpleResizable currentSpawnable)
{
currentSpawnable = null;
if (!_classification) return false;
var sceneManager = FindObjectOfType<OVRSceneManager>();
if (!sceneManager) return false;
foreach (var spawnable in SpawnablePrefabs)
{
if (_classification.Contains(spawnable.ClassificationLabel))
{
currentSpawnable = spawnable.ResizablePrefab;
return true;
}
}
if (FallbackPrefab != null)
{
currentSpawnable = FallbackPrefab;
return true;
}
return false;
}
private void AddRoomLight()
{
if (!RoomLightPrefab) return;
if (_classification && _classification.Contains(OVRSceneManager.Classification.Ceiling) &&
!_roomLightRef)
{
_roomLightRef = Instantiate(RoomLightPrefab, _sceneAnchor.transform);
}
}
private void GetVolumeFromTopPlane(
Transform plane,
Vector2 dimensions,
float height,
out Vector3 position,
out Quaternion rotation,
out Vector3 localScale)
{
float halfHeight = height / 2.0f;
position = plane.position - Vector3.up * halfHeight;
rotation = Quaternion.LookRotation(-plane.up, Vector3.up);
localScale = new Vector3(dimensions.x, halfHeight * 2.0f, dimensions.y);
}
}