using System.Collections.Generic; using System.Linq; using UnityEngine; using static StageStatic; /// <summary> /// Attached to prefab Def_Stage /// </summary> public class StageBehaviour : MonoBehaviour { /// <summary> /// Re-loads <see cref="StageStatic.stage"/> to display all <see cref="Fact">Facts</see>. /// </summary> void Start() { StageStatic.LoadInitStage(true /*StageStatic.stage.player_record.solved*/, gameObject); GenerateMMTCollider(gameObject); } public static List<TriangleFact> GenerateMMTCollider(GameObject obj = null) { bool debug = false; var t0 = System.DateTime.Now; List<TriangleFact> tris = new(); foreach (BoxCollider coll in FindObjectsOfType<BoxCollider>()) { if (!UseMe(coll)) continue; Vector3[] minmax = new Vector3[] { coll.center - coll.size/2, coll.center + coll.size/2, }; _QuadAdd(0, 1, 3, 2); _QuadAdd(1, 5, 7, 3); _QuadAdd(5, 4, 6, 7); _QuadAdd(4, 0, 2, 6); _QuadAdd(2, 3, 7, 6); _QuadAdd(0, 4, 5, 1); void _QuadAdd(uint i, uint j, uint k, uint l) { _TrisAdd(i, k, j); _TrisAdd(k, i, l); } void _TrisAdd(uint i, uint j, uint k) { tris.Add(new( new[] { _Transform(new Vector3(minmax[i>>0&1][0], minmax[i>>1&1][1], minmax[i>>2&1][2]), coll.transform.localToWorldMatrix), _Transform(new Vector3(minmax[j>>0&1][0], minmax[j>>1&1][1], minmax[j>>2&1][2]), coll.transform.localToWorldMatrix), _Transform(new Vector3(minmax[k>>0&1][0], minmax[k>>1&1][1], minmax[k>>2&1][2]), coll.transform.localToWorldMatrix), })); } } //foreach (MeshCollider coll in FindObjectsOfType<MeshCollider>()) //{ // if (!UseMe(coll) // || !coll.sharedMesh.isReadable) // continue; // for (int i = 0; i < coll.sharedMesh.triangles.Length; i += 3) // { // tris.Add(new( // new[] { // _Transform(coll.sharedMesh.vertices[coll.sharedMesh.triangles[i + 0]], coll.transform.localToWorldMatrix), // _Transform(coll.sharedMesh.vertices[coll.sharedMesh.triangles[i + 1]], coll.transform.localToWorldMatrix), // _Transform(coll.sharedMesh.vertices[coll.sharedMesh.triangles[i + 2]], coll.transform.localToWorldMatrix), // }) // ); // } //} if (debug && obj != null) { var t1 = System.DateTime.Now - t0; Debug.Log($"{tris.Count} Tris in {t1.Milliseconds}ms"); Mesh mesh = new() { indexFormat = UnityEngine.Rendering.IndexFormat.UInt32, vertices = tris.SelectMany(t => t.Verticies).ToArray(), triangles = Enumerable.Range(0, tris.Count * 3).ToArray(), }; mesh.RecalculateNormals(); mesh.Optimize(); MeshFilter filter = obj.GetComponent<MeshFilter>(); filter.sharedMesh = mesh; } return tris; Vector3 _Transform(Vector3 vert, Matrix4x4 toworld) { Vector4 h = toworld * new Vector4(vert.x, vert.y, vert.z, 1f); return new Vector3(h.x, h.y, h.z); } bool UseMe(Collider coll) => true; //TODO: filter for what we want } /// <summary> /// Resets changes made by <see cref="StageStatic.stage"/> and frees ressources. /// </summary> private void OnDestroy() { StageStatic.SetMode(Mode.Play); // no Mode.Create // StageStatic.stage.solution.hardreset(invoke_event: false); NO! keep in memory! // StageStatic.stage?.factState.hardreset(invoke_event: false); also keep? } /// <summary> /// Wrapps <see cref="SetMode(Mode, GameObject)"/>. Needed as endpoint for unity buttons. /// </summary> /// <param name="create"><c>SetMode(create ? Mode.Create : Mode.Play);</c></param> public void SetMode(bool create) { SetMode(create ? Mode.Create : Mode.Play); } /// <summary> /// Wrapps <see cref="StageStatic.SetMode(Mode, GameObject)"/>. Defaulting <paramref name="obj"/> to <see cref="this.gameObject"/>. /// </summary> /// \copydetails StageStatic.SetMode(Mode, GameObject) public void SetMode(Mode mode, GameObject obj = null) { obj ??= gameObject; StageStatic.SetMode(mode, obj); } }