166 lines
6.3 KiB
C#
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
|
|
} |