2023-05-08 15:56:10 +03:00

166 lines
6.3 KiB
C#

using System.Collections.Generic;
using _PROJECT.Components.Portals2;
using Unity.XR.CoreUtils;
using UnityEngine;
using UnityEngine.Rendering;
#if (UNITY_EDITOR)
using static UnityEditor.GameObjectUtility;
#endif
public class PortalScene : MonoBehaviour
{
private StencilPortal _portal;
private StencilPortal _targetPortal;
private PortalScene _targetPortalScene;
public LayerMask defaultLayer;
public LayerMask portalLayer;
public BoxCollider boxCollider;
private GameObject _skybox;
#if (UNITY_EDITOR)
public void BuildPortalScene()
{
_portal = transform.parent.GetComponentInChildren<StencilPortal>();
_targetPortal = _portal.targetPortal;
_targetPortalScene = _targetPortal.portalScene;
boxCollider = GetComponent<BoxCollider>();
_skybox = transform.Find("Skybox").gameObject;
// Make skybox size slightly smaller than collider
_skybox.transform.localScale = _targetPortalScene.boxCollider.bounds.size * 0.999f;
_skybox.transform.position =
_targetPortalScene.boxCollider.bounds.center + _targetPortal.normalVisible.forward * -0.001f;
// Move skybox to this portal, but mirror the position
_skybox.transform.position =
StencilPortal.TransformPositionBetweenPortals(_targetPortal, _portal, _skybox.transform.position);
_skybox.transform.localRotation =
StencilPortal.TransformRotationBetweenPortals(_targetPortal, _portal, _skybox.transform.rotation);
// Get all gameobjects in target portal collider
var gameObjects = _targetPortalScene.getAllCollisions(defaultLayer);
// Clone all gameobjects found
var clonedGameObjects = CloneGameObjects(gameObjects, portalLayer);
// Add normalVector rotation to portalScene
transform.rotation = transform.rotation * Quaternion.Inverse(_portal.normalVisible.rotation);
}
private List<GameObject> getAllCollisions(LayerMask mask)
{
// Cast physics overlapbox
var colliders = Physics.OverlapBox(boxCollider.bounds.center, boxCollider.bounds.extents,
boxCollider.transform.rotation, mask);
// Make list of all gameobjects
var gameObjects = new List<GameObject>();
foreach (var collider in colliders)
{
if (collider.gameObject.GetComponent<StencilPortal>()) continue;
if (collider.gameObject.GetComponent<PortalScene>()) continue;
gameObjects.Add(collider.gameObject);
}
// Return list of gameobjects
return gameObjects;
}
private List<GameObject> CloneGameObjects(List<GameObject> gameObjects, LayerMask targetMask)
{
// Make list of cloned gameobjects
var clonedGameObjects = new List<GameObject>();
foreach (var gameObject in gameObjects)
{
// Clone gameobject without static flag
var clonedGameObject = Instantiate(gameObject, transform);
clonedGameObject.isStatic = false;
// Remove all children from cloned gameobject
foreach (Transform child in clonedGameObject.transform)
{
DestroyImmediate(child.gameObject);
}
var flags = GetStaticEditorFlags(gameObject);
SetStaticEditorFlags(clonedGameObject, flags);
// Make sure mesh is not shared
var meshFilter = clonedGameObject.GetComponent<MeshFilter>();
if (meshFilter)
{
meshFilter.mesh = Instantiate(meshFilter.sharedMesh);
}
// Make sure material is not shared
var originalMeshRenderer = gameObject.GetComponent<MeshRenderer>();
// Destroy cloned object if no mesh renderer is found
if (!originalMeshRenderer)
{
DestroyImmediate(clonedGameObject);
continue;
}
var clonedMeshRenderer = clonedGameObject.GetComponent<MeshRenderer>();
if (clonedMeshRenderer)
{
var materials = new Material[clonedMeshRenderer.sharedMaterials.Length];
for (var i = 0; i < originalMeshRenderer.sharedMaterials.Length; i++)
{
materials[i] = Instantiate(originalMeshRenderer.sharedMaterials[i]);
}
clonedMeshRenderer.materials = materials;
}
// Remove collider if exists
var collider = clonedGameObject.GetComponent<Collider>();
if (collider)
{
DestroyImmediate(collider);
}
// Add LightmapDataSync component
// Check if lightmap data is available
if (originalMeshRenderer.lightmapIndex >= 0)
{
var lightmapDataSync = clonedGameObject.AddComponent<LightmapDataSync>();
// Set lightmap data
lightmapDataSync.toCloneRenderer = originalMeshRenderer;
}
// Check if blend probes are enabled on original gameobject
if (originalMeshRenderer.lightProbeUsage == LightProbeUsage.BlendProbes)
{
// Use probes from original position
clonedMeshRenderer.lightProbeUsage = LightProbeUsage.BlendProbes;
clonedMeshRenderer.probeAnchor = originalMeshRenderer.transform;
}
// Set position and rotation of cloned gameobject
clonedGameObject.transform.position =
StencilPortal.TransformPositionBetweenPortals(_targetPortal, _portal, gameObject.transform.position);
// Move slightly up
clonedGameObject.transform.position += _targetPortal.normalVisible.up * 0.002f;
clonedGameObject.transform.rotation =
StencilPortal.TransformRotationBetweenPortals(_targetPortal, _portal, gameObject.transform.rotation);
// Set layer of cloned gameobject to target layer
clonedGameObject.layer = targetMask.GetFirstLayerIndex();
// Set parent of cloned gameobject to our portal scene
clonedGameObject.transform.parent = transform;
// Add cloned gameobject to list
clonedGameObjects.Add(clonedGameObject);
}
// Return list of cloned gameobjects
return clonedGameObjects;
}
#endif
}