using System; using System.Collections.Generic; using Newtonsoft.Json.Linq; using SLZ.Serialize; using SLZ.Marrow.Utilities; using UnityEngine; using UnityEngine.Serialization; using Object = UnityEngine.Object; #if UNITY_EDITOR using UnityEditor; #endif namespace SLZ.Marrow.Warehouse { public class GameObjectCrate : CrateT { [FormerlySerializedAs("_assetReference")] [SerializeField] private MarrowGameObject _mainAsset; public override MarrowAsset MainAsset { get => _mainAsset; set { if (value != null && value.GetType() == typeof(MarrowAsset)) { _mainAsset = new MarrowGameObject(value.AssetGUID); } else { _mainAsset = (MarrowGameObject)value; } } } public MarrowGameObject MainGameObject { get => _mainAsset; set => _mainAsset = value; } [SerializeField] private MarrowAssetT _previewMesh = new MarrowAssetT(); public MarrowAssetT PreviewMesh { get => _previewMesh; set => _previewMesh = value; } [SerializeField] private bool _customQuality = false; public bool CustomQuality { get => _customQuality; set => _customQuality = value; } [SerializeField] [Range(0f, 1f)] private float _previewMeshQuality = 0.5f; public float PreviewMeshQuality { get => _previewMeshQuality; set => _previewMeshQuality = value; } [SerializeField] [Range(0f, 5f)] private int _maxLODLevel = 0; public int MaxLODLevel { get => _maxLODLevel; set => _maxLODLevel = value; } [SerializeField] public Bounds _colliderBounds; public Bounds ColliderBounds { get => _colliderBounds; set => _colliderBounds = value; } public override void ImportPackedAssets(Dictionary packedAssets) { base.ImportPackedAssets(packedAssets); if (packedAssets.TryGetValue("PreviewMesh", out var packedAsset)) PreviewMesh = new MarrowMesh(packedAsset.marrowAsset.AssetGUID); } public override List ExportPackedAssets() { base.ExportPackedAssets(); PackedAssets.Add(new PackedAsset("PreviewMesh", PreviewMesh, PreviewMesh.AssetType, "previewMesh")); return PackedAssets; } #if UNITY_EDITOR public override void GeneratePackedAssets(bool saveAsset = true) { base.GeneratePackedAssets(); GenerateColliderBounds(); GeneratePreviewMesh(); EditorUtility.SetDirty(this); if (saveAsset) { AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } } protected void GenerateColliderBounds() { this.ColliderBounds = GenerateColliderBounds(MainGameObject.EditorAsset); } public static Bounds GenerateColliderBounds(GameObject targetGameObject) { Bounds bounds = new Bounds(); if (targetGameObject != null) { PreviewRenderUtility fakeScene = new PreviewRenderUtility(); var parentGO = new GameObject("root"); fakeScene.AddSingleGO(parentGO); var go = Object.Instantiate(targetGameObject, Vector3.zero, Quaternion.identity, parentGO.transform); Collider[] cols = go.GetComponentsInChildren(); bool isFirst = true; for (int j = 0; j < cols.Length; j++) { if (cols[j].isTrigger) continue; if (isFirst) bounds = cols[j].bounds; else bounds.Encapsulate(cols[j].bounds); isFirst = false; } bounds.center -= go.transform.position; DestroyImmediate(go); DestroyImmediate(parentGO); fakeScene.Cleanup(); } return bounds; } protected virtual void GeneratePreviewMesh() { if (MainGameObject.EditorAsset != null) { Mesh mesh; if (CustomQuality) mesh = MeshCroncher.CronchMesh(MainGameObject.EditorAsset, MaxLODLevel, PreviewMeshQuality, CustomQuality); else mesh = MeshCroncher.CronchMesh(MainGameObject.EditorAsset, MaxLODLevel); if (mesh != null) { if (!AssetDatabase.IsValidFolder(MarrowSDK.GetMarrowAssetsPath())) { AssetDatabase.CreateFolder("Assets", MarrowSDK.EDITOR_ASSETS_FOLDER); } if (!AssetDatabase.IsValidFolder(MarrowSDK.GetMarrowAssetsPath("PackedAssets"))) { AssetDatabase.CreateFolder(MarrowSDK.GetMarrowAssetsPath(), "PackedAssets"); } if (!AssetDatabase.IsValidFolder(MarrowSDK.GetMarrowAssetsPath("PackedAssets", Pallet.Barcode.ToString()))) { AssetDatabase.CreateFolder(MarrowSDK.GetMarrowAssetsPath("PackedAssets"), Pallet.Barcode.ToString()); } if (!AssetDatabase.IsValidFolder(MarrowSDK.GetMarrowAssetsPath("PackedAssets", Pallet.Barcode.ToString(), "PreviewMesh"))) { AssetDatabase.CreateFolder(MarrowSDK.GetMarrowAssetsPath("PackedAssets", Pallet.Barcode.ToString()), "PreviewMesh"); } string path = MarrowSDK.GetMarrowAssetsPath("PackedAssets", Pallet.Barcode.ToString(), "PreviewMesh", $"{MarrowSDK.SanitizeName(Title)} PreviewMesh.mesh"); if (System.IO.File.Exists(path)) AssetDatabase.DeleteAsset(path); AssetDatabase.Refresh(); AssetDatabase.CreateAsset(mesh, path); AssetDatabase.Refresh(); var meshAsset = AssetDatabase.LoadAssetAtPath(path); PreviewMesh.SetEditorAsset(meshAsset); } } } #endif public override void Pack(ObjectStore store, JObject json) { base.Pack(store, json); json.Add(new JProperty("colliderBounds", new JObject { { "center", new JObject { { "x", _colliderBounds.center.x }, { "y", _colliderBounds.center.y }, { "z", _colliderBounds.center.z } } }, { "extents", new JObject { { "x", _colliderBounds.extents.x }, { "y", _colliderBounds.extents.y }, { "z", _colliderBounds.extents.z } } } })); } public override void Unpack(ObjectStore store, string objectId) { base.Unpack(store, objectId); if (store.TryGetJSON("colliderBounds", objectId, out JToken colliderBoundsToken)) { _colliderBounds = colliderBoundsToken.ToObject(); } } } }