美文网首页
Unity3D开发技术研究-构建稀疏空间地图SparseSpat

Unity3D开发技术研究-构建稀疏空间地图SparseSpat

作者: TonyWan_AR | 来源:发表于2021-12-02 23:42 被阅读0次

    一、框架视图

    二、关键代码

    //================================================================================================================================
    
    //================================================================================================================================
    
    using easyar;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.EventSystems;
    using UnityEngine.UI;
    
    namespace SpatialMap_Dense_BallGame
    {
        public class UIController : MonoBehaviour
        {
            public Text Status;
            public ARSession Session;
            public GameObject Ball;
            public int MaxBallCount = 30;
            public float BallLifetime = 15;
    
            private Color meshColor;
            private VIOCameraDeviceUnion vioCamera;
            private DenseSpatialMapBuilderFrameFilter dense;
            private List<GameObject> balls = new List<GameObject>();
    
            private void Awake()
            {
                vioCamera = Session.GetComponentInChildren<VIOCameraDeviceUnion>();
                dense = Session.GetComponentInChildren<DenseSpatialMapBuilderFrameFilter>();
            }
    
            private void Start()
            {
                meshColor = dense.MeshColor;
            }
    
            private void Update()
            {
                Status.text = "VIO Device Type: " + (vioCamera.Device == null ? "-" : vioCamera.Device.DeviceType.ToString()) + Environment.NewLine +
                    "Tracking Status: " + (Session.WorldRootController == null ? "-" : Session.WorldRootController.TrackingStatus.ToString()) + Environment.NewLine +
                    "Dense Mesh Block Count: " + dense.MeshBlocks.Count + Environment.NewLine +
                    "Ball Count: " + balls.Count + "/" + MaxBallCount + Environment.NewLine +
                    Environment.NewLine +
                    "Gesture Instruction" + Environment.NewLine +
                    "\tShoot Ball: Tap Screen";
    
                if (Input.GetMouseButtonDown(0) && Input.touchCount > 0 && !EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
                {
                    Ray ray = Camera.main.ScreenPointToRay(Input.touches[0].position);
                    var launchPoint = Camera.main.transform;
                    var ball = Instantiate(Ball, launchPoint.position, launchPoint.rotation);
                    var rigid = ball.GetComponent<Rigidbody>();
                    rigid.velocity = Vector3.zero;
                    rigid.AddForce(ray.direction * 15f + Vector3.up * 5f);
                    if (balls.Count > 0 && balls.Count == MaxBallCount)
                    {
                        Destroy(balls[0]);
                        balls.RemoveAt(0);
                    }
                    balls.Add(ball);
                    StartCoroutine(Kill(ball, BallLifetime));
                }
            }
    
            public void RenderMesh(bool show)
            {
                if (!dense)
                {
                    return;
                }
                dense.RenderMesh = show;
            }
    
    
            public void TransparentMesh(bool trans)
            {
                if (!dense)
                {
                    return;
                }
                dense.MeshColor = trans ? Color.clear : meshColor;
            }
    
            private IEnumerator Kill(GameObject ball, float lifetime)
            {
                yield return new WaitForSeconds(lifetime);
                if (balls.Remove(ball)) { Destroy(ball); }
            }
        }
    }
    
    
    //================================================================================================================================
    //
    
    //================================================================================================================================
    
    using easyar;
    using System;
    using System.Collections.Generic;
    
    namespace SpatialMap_SparseSpatialMap
    {
        [Serializable]
        public class MapMeta
        {
            public SparseSpatialMapController.MapManagerSourceData Map = new SparseSpatialMapController.MapManagerSourceData();
            public List<PropInfo> Props = new List<PropInfo>();
    
            public MapMeta(SparseSpatialMapController.SparseSpatialMapInfo map, List<PropInfo> props)
            {
                Map = new SparseSpatialMapController.MapManagerSourceData() { Name = map.Name, ID = map.ID };
                Props = props;
            }
    
            [Serializable]
            public class PropInfo
            {
                public string Name = string.Empty;
                public float[] Position = new float[3];
                public float[] Rotation = new float[4];
                public float[] Scale = new float[3];
            }
        }
    }
    
    
    //================================================================================================================================
    //
    
    //================================================================================================================================
    
    using System.Collections.Generic;
    using System.IO;
    using UnityEngine;
    
    namespace SpatialMap_SparseSpatialMap
    {
        public class MapMetaManager
        {
            private static readonly string root = Application.persistentDataPath + "/SparseSpatialMap";
    
            public static List<MapMeta> LoadAll()
            {
                var metas = new List<MapMeta>();
                var dirRoot = GetRootPath();
                try
                {
                    foreach (var path in Directory.GetFiles(dirRoot, "*.meta"))
                    {
                        try
                        {
                            metas.Add(JsonUtility.FromJson<MapMeta>(File.ReadAllText(path)));
                        }
                        catch (System.Exception e)
                        {
                            Debug.LogError(e.Message);
                        }
                    }
                }
                catch (System.Exception e)
                {
                    Debug.LogError(e.Message);
                }
                return metas;
            }
    
            public static bool Save(MapMeta meta)
            {
                try
                {
                    File.WriteAllText(GetPath(meta.Map.ID), JsonUtility.ToJson(meta));
                }
                catch (System.Exception e)
                {
                    Debug.LogError(e.Message);
                    return false;
                }
                return true;
            }
    
            public static bool Delete(MapMeta meta)
            {
                if (!File.Exists(GetPath(meta.Map.ID)))
                {
                    return false;
                }
                try
                {
                    File.Delete(GetPath(meta.Map.ID));
                }
                catch (System.Exception e)
                {
                    Debug.LogError(e.Message);
                    return false;
                }
                return true;
            }
    
            private static string GetRootPath()
            {
                if (!File.Exists(root))
                {
                    Directory.CreateDirectory(root);
                }
                return root;
            }
    
            private static string GetPath(string id)
            {
                return GetRootPath() + "/" + id + ".meta";
            }
        }
    }
    
    
    //================================================================================================================================
    //
    
    //================================================================================================================================
    
    using System;
    using System.Collections.Generic;
    using UnityEngine;
    
    namespace SpatialMap_SparseSpatialMap
    {
        public class PropCollection : MonoBehaviour
        {
            public static PropCollection Instance;
            public List<Templet> Templets = new List<Templet>();
    
            private void Awake()
            {
                Instance = this;
            }
    
            [Serializable]
            public class Templet
            {
                public GameObject Object;
                public Sprite Icon;
            }
        }
    }
    
    
    //================================================================================================================================
    
    //================================================================================================================================
    
    using easyar;
    using System.Collections;
    using System.IO;
    using UnityEngine;
    using UnityEngine.Video;
    
    namespace SpatialMap_SparseSpatialMap
    {
        [RequireComponent(typeof(MeshRenderer), typeof(UnityEngine.Video.VideoPlayer))]
        public class VideoPlayerAgent : MonoBehaviour
        {
            public string VideoInStreamingAssets;
    
            private UnityEngine.Video.VideoPlayer player;
            private bool ready;
            private bool playable = true;
    
            public bool Playable
            {
                get { return playable; }
                set
                {
                    playable = value;
                    StatusChanged();
                }
            }
    
            private void OnEnable()
            {
                StatusChanged();
            }
    
            private void Start()
            {
                player = GetComponent<UnityEngine.Video.VideoPlayer>();
                player.source = VideoSource.Url;
    
                var path = Application.streamingAssetsPath + "/" + VideoInStreamingAssets;
                if (Application.platform == RuntimePlatform.Android)
                {
                    path = Application.persistentDataPath + "/" + VideoInStreamingAssets;
    
                    {
                        // Workaround Unity bug: https://issuetracker.unity3d.com/issues/android-video-player-cannot-play-files-located-in-the-persistent-data-directory-on-android-10
                        // more info in this thread: https://forum.unity.com/threads/error-videoplayer-on-android.742451/
                        // If you are using Unity versions with this issue fixed, you can safely skip this code block
                        int sdkVersion = 0;
    #if UNITY_ANDROID && !UNITY_EDITOR
                        using (var buildVersion = new AndroidJavaClass("android.os.Build$VERSION"))
                        {
                            sdkVersion = buildVersion.GetStatic<int>("SDK_INT");
                        }
    #endif
                        if (sdkVersion >= 29)
                        {
                            GUIPopup.EnqueueMessage("Use web video to workaround Unity VideoPlayer bug on Android Q\nthe video play may be slow", 5);
                            path = "https://staticfile-cdn.sightp.com/easyar/video/" + Path.GetFileName(VideoInStreamingAssets);
                        }
                    }
                }
    
                // Note: Use the Unity VideoPlayer in your own way.
                // We use video file in StreamingAssets in the samples only to keep compatiblity.
                // Some versions of Unity will have strange behaviors if video in resources.
                if (Application.platform == RuntimePlatform.Android && !File.Exists(path) && !path.StartsWith("https://"))
                {
                    StartCoroutine(FileUtil.LoadFile(VideoInStreamingAssets, PathType.StreamingAssets, (data) =>
                    {
                        StartCoroutine(WriteFile(path, data));
                    }));
                }
                else
                {
                    player.url = FileUtil.PathToUrl(path);
                    ready = true;
                    StatusChanged();
                }
            }
    
            private IEnumerator WriteFile(string path, byte[] data)
            {
                if (data == null || data.Length <= 0)
                {
                    yield break;
                }
    
                bool finished = false;
                EasyARController.Instance.Worker.Run(() =>
                {
                    var dir = Path.GetDirectoryName(path);
                    if (!Directory.Exists(dir))
                    {
                        Directory.CreateDirectory(dir);
                    }
                    if (!File.Exists(path))
                    {
                        File.WriteAllBytes(path, data);
                    }
                    finished = true;
                });
    
                while (!finished)
                {
                    yield return 0;
                }
                player.url = FileUtil.PathToUrl(path);
                ready = true;
                StatusChanged();
            }
    
            private void StatusChanged()
            {
                if (!ready)
                {
                    return;
                }
                if (playable)
                {
                    player.Play();
                }
                else
                {
                    player.Pause();
                }
            }
        }
    }
    
    
    //================================================================================================================================
    
    //================================================================================================================================
    
    using easyar;
    using System;
    using System.Collections;
    using UnityEngine;
    using UnityEngine.UI;
    
    namespace SpatialMap_SparseSpatialMap
    {
        public class CreateViewController : MonoBehaviour
        {
            public GameObject Tips;
            public GameObject UploadPopup;
            public GameObject InfoWithPreview;
            public GameObject InfoWithoutPreview;
            public InputField MapNameInput;
            public Button UploadOKButton;
            public Button UploadCancelButton;
            public Button SaveButton;
            public Button TipsButton;
            public Button SnapshotButton;
            public Toggle PreviewToggle;
            public RawImage PreviewImage;
            public UnityEngine.UI.Image PreviewImageBorder;
            public Text SaveStatus;
    
            private MapSession mapSession;
            private bool isTipsOn;
            private bool withPreview = true;
            private string mapName;
            private Texture2D capturedImage;
            private int uploadingTime;
    
            private void OnEnable()
            {
                TipsButton.gameObject.SetActive(true);
                SaveButton.gameObject.SetActive(true);
                SaveButton.interactable = false;
    
                PreviewToggle.isOn = true;
    
                isTipsOn = false;
                Tips.SetActive(false);
    
                StopUploadUI();
                UploadPopup.transform.localScale = Vector3.zero;
                UploadPopup.gameObject.SetActive(false);
                var buttonText = UploadOKButton.transform.Find("Text").GetComponent<Text>();
                buttonText.text = "OK";
            }
    
            private void Update()
            {
                if ((mapSession.MapWorker.LocalizedMap == null || mapSession.MapWorker.LocalizedMap.PointCloud.Count <= 20) && !Application.isEditor)
                {
                    SaveButton.interactable = false;
                }
                else
                {
                    SaveButton.interactable = true;
                }
            }
    
            private void OnDestroy()
            {
                if (capturedImage)
                {
                    Destroy(capturedImage);
                }
            }
    
            public void SetMapSession(MapSession session)
            {
                mapSession = session;
            }
    
            public void Save()
            {
                SaveButton.gameObject.SetActive(false);
                TipsButton.gameObject.SetActive(false);
                UploadPopup.gameObject.SetActive(true);
                MapNameInput.text = mapName = "Map_" + DateTime.Now.ToString("yyyy-MM-dd_HHmm");
                mapSession.MapWorker.enabled = false;
                Snapshot();
                StartCoroutine(ShowPopup(UploadPopup.transform, Vector3.one));
            }
    
            public void ShowTips()
            {
                isTipsOn = !isTipsOn;
                Tips.SetActive(isTipsOn);
            }
    
            public void Snapshot()
            {
                var oneShot = Camera.main.gameObject.AddComponent<OneShot>();
                oneShot.Shot(true, (texture) =>
                {
                    if (capturedImage)
                    {
                        Destroy(capturedImage);
                    }
                    capturedImage = texture;
                    PreviewImage.texture = capturedImage;
                });
            }
    
            public void TogglePreview(bool enable)
            {
                withPreview = enable;
                InfoWithPreview.SetActive(withPreview);
                InfoWithoutPreview.SetActive(!withPreview);
                PreviewImageBorder.gameObject.SetActive(withPreview);
            }
    
            public void TogglePreview()
            {
                if (!PreviewToggle.interactable)
                {
                    return;
                }
                PreviewToggle.isOn = !withPreview;
            }
    
            public void OnMapNameChange(string name)
            {
                UploadOKButton.interactable = !string.IsNullOrEmpty(name);
                mapName = name;
            }
    
            public void Upload()
            {
                using (var buffer = easyar.Buffer.wrapByteArray(capturedImage.GetRawTextureData()))
                using (var image = new easyar.Image(buffer, PixelFormat.RGB888, capturedImage.width, capturedImage.height))
                {
                    mapSession.Save(mapName, withPreview ? image : null);
                }
                StartUploadUI();
                StartCoroutine(SavingStatus());
                StartCoroutine(Saving());
            }
    
            private IEnumerator Saving()
            {
                while (mapSession.IsSaving)
                {
                    yield return 0;
                }
                if (mapSession.Saved)
                {
                    gameObject.SetActive(false);
                    ViewManager.Instance.LoadMainView();
                }
                else
                {
                    var buttonText = UploadOKButton.transform.Find("Text").GetComponent<Text>();
                    buttonText.text = "Retry";
                    StopUploadUI();
                }
            }
    
            private IEnumerator SavingStatus()
            {
                while (mapSession.IsSaving)
                {
                    SaveStatus.text = "Upload and Generate Map.";
                    for (int i = 0; i < uploadingTime; ++i)
                    {
                        SaveStatus.text += ".";
                    }
                    uploadingTime = (uploadingTime + 1) % 3;
                    yield return new WaitForSeconds(1);
                }
                SaveStatus.text = "Upload and Generate Map";
            }
    
            private static IEnumerator ShowPopup(Transform t, Vector3 scale)
            {
                while (t.transform.localScale.x < scale.x)
                {
                    t.transform.localScale += scale * 6 * Time.deltaTime;
                    if (t.transform.localScale.x > scale.x)
                    {
                        t.transform.localScale = scale;
                    }
                    yield return 0;
                }
            }
    
            private void StartUploadUI()
            {
                UploadOKButton.interactable = false;
                PreviewToggle.interactable = false;
                MapNameInput.interactable = false;
                UploadCancelButton.interactable = false;
                SnapshotButton.interactable = false;
                uploadingTime = 0;
            }
    
            private void StopUploadUI()
            {
                SaveStatus.text = "Upload and Generate Map";
                UploadOKButton.interactable = true;
                PreviewToggle.interactable = true;
                MapNameInput.interactable = true;
                UploadCancelButton.interactable = true;
                SnapshotButton.interactable = true;
                uploadingTime = 0;
            }
        }
    }
    
    
    //================================================================================================================================
    //
    
    //================================================================================================================================
    
    using System;
    using UnityEngine;
    
    namespace SpatialMap_SparseSpatialMap
    {
        public class OneShot : MonoBehaviour
        {
            private bool mirror;
            private Action<Texture2D> callback;
            private bool capturing;
    
            public void OnRenderImage(RenderTexture source, RenderTexture destination)
            {
                Graphics.Blit(source, destination);
                if (!capturing) { return; }
    
                var destTexture = new RenderTexture(Screen.width, Screen.height, 0);
                if (mirror)
                {
                    var mat = Instantiate(Resources.Load<Material>("Sample_MirrorTexture"));
                    mat.mainTexture = source;
                    Graphics.Blit(null, destTexture, mat);
                }
                else
                {
                    Graphics.Blit(source, destTexture);
                }
    
                RenderTexture.active = destTexture;
                var texture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
                texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
                texture.Apply();
                RenderTexture.active = null;
                Destroy(destTexture);
    
                callback(texture);
                Destroy(this);
            }
    
            public void Shot(bool mirror, Action<Texture2D> callback)
            {
                if (callback == null) { return; }
                this.mirror = mirror;
                this.callback = callback;
                capturing = true;
            }
        }
    }
    
    
    //================================================================================================================================
    //
    //
    //================================================================================================================================
    
    using Common;
    using System;
    using System.Collections;
    using UnityEngine;
    using UnityEngine.EventSystems;
    
    namespace SpatialMap_SparseSpatialMap
    {
        public class Dragger : MonoBehaviour
        {
            public GameObject OutlinePrefab;
            public GameObject FreeMove;
            public UnityEngine.UI.Toggle VideoPlayable;
    
            private RectTransform rectTransform;
            private UnityEngine.UI.Image dummy;
            private TouchController touchControl;
            private MapSession mapSession;
            private GameObject candidate;
            private GameObject selection;
            private bool isOnMap;
            private bool isMoveFree = true;
    
            public event Action<GameObject> CreateObject;
            public event Action<GameObject> DeleteObject;
    
            private void Awake()
            {
                rectTransform = GetComponent<RectTransform>();
                dummy = GetComponentInChildren<UnityEngine.UI.Image>(true);
                touchControl = GetComponentInChildren<TouchController>(true);
                OutlinePrefab = Instantiate(OutlinePrefab);
                OutlinePrefab.SetActive(false);
            }
    
            private void Update()
            {
                transform.position = Input.mousePosition;
                var isEditorOrStandalone = Application.isEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.OSXPlayer;
                var isPointerOverGameObject = (isEditorOrStandalone && EventSystem.current.IsPointerOverGameObject())
                    || (Input.touchCount > 0 && EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId));
    
                if (candidate)
                {
                    if (mapSession != null && !isPointerOverGameObject && Input.touchCount > 0)
                    {
                        var point = mapSession.HitTestOne(new Vector2(Input.touches[0].position.x / Screen.width, Input.touches[0].position.y / Screen.height));
                        if (point.OnSome)
                        {
                            candidate.transform.position = point.Value + Vector3.up * candidate.transform.localScale.y / 2;
                            isOnMap = true;
                        }
                    }
    
                    if (isPointerOverGameObject || !isOnMap)
                    {
                        HideCandidate();
                    }
                    else
                    {
                        ShowCandidate();
                    }
                }
                else
                {
                    if (!isPointerOverGameObject && ((isEditorOrStandalone && Input.GetMouseButtonDown(0)) || (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Began)))
                    {
                        var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                        RaycastHit hitInfo;
                        if (Physics.Raycast(ray, out hitInfo))
                        {
                            StopEdit();
                            StartEdit(hitInfo.collider.gameObject);
                        }
                    }
                }
    
                if (mapSession != null && selection && !isMoveFree)
                {
                    if (!isPointerOverGameObject && Input.touchCount == 1)
                    {
                        var point = mapSession.HitTestOne(new Vector2(Input.touches[0].position.x / Screen.width, Input.touches[0].position.y / Screen.height));
                        if (point.OnSome)
                        {
                            selection.transform.position = point.Value + Vector3.up * selection.transform.localScale.y / 2;
                        }
                    }
                }
            }
    
            private void OnDisable()
            {
                mapSession = null;
                StopEdit();
            }
    
            public void SetMapSession(MapSession session)
            {
                mapSession = session;
                if (mapSession.MapWorker)
                {
                    mapSession.MapWorker.MapLoad += (arg1, arg2, arg3, arg4) =>
                    {
                        StartCoroutine(CheckVideo());
                    };
                }
            }
    
            public void SetFreeMove(bool free)
            {
                isMoveFree = free;
                if (selection)
                {
                    if (free)
                    {
                        touchControl.TurnOn(selection.transform, Camera.main, true, true, true, true);
                    }
                    else
                    {
                        touchControl.TurnOn(selection.transform, Camera.main, false, false, true, true);
                    }
                }
            }
    
            public void StartCreate(PropCellController controller)
            {
                StopEdit();
                isOnMap = false;
                rectTransform.sizeDelta = controller.GetComponent<RectTransform>().sizeDelta;
                dummy.sprite = controller.Templet.Icon;
                dummy.color = Color.white;
                candidate = Instantiate(controller.Templet.Object);
                candidate.name = controller.Templet.Object.name;
                if (candidate)
                {
                    var video = candidate.GetComponentInChildren<VideoPlayerAgent>(true);
                    if (video) { video.Playable = false; }
                }
                FreeMove.SetActive(false);
                HideCandidate();
            }
    
            public void StopCreate()
            {
                if (candidate.activeSelf)
                {
                    if (CreateObject != null)
                    {
                        CreateObject(candidate);
                        StartEdit(candidate);
                    }
                }
                else
                {
                    Destroy(candidate);
                }
    
                dummy.gameObject.SetActive(false);
                FreeMove.SetActive(true);
                isOnMap = false;
                candidate = null;
            }
    
            public void StartEdit(GameObject obj)
            {
                selection = obj;
                if (selection && VideoPlayable.isOn)
                {
                    var video = selection.GetComponentInChildren<VideoPlayerAgent>(true);
                    if (video) { video.Playable = true; }
                }
    
                var meshFilter = selection.GetComponentInChildren<MeshFilter>();
                OutlinePrefab.SetActive(true);
                OutlinePrefab.GetComponent<MeshFilter>().mesh = meshFilter.mesh;
                OutlinePrefab.transform.parent = meshFilter.transform;
                OutlinePrefab.transform.localPosition = Vector3.zero;
                OutlinePrefab.transform.localRotation = Quaternion.identity;
                OutlinePrefab.transform.localScale = Vector3.one;
    
                SetFreeMove(isMoveFree);
            }
    
            public void StopEdit()
            {
                if (selection)
                {
                    var video = selection.GetComponentInChildren<VideoPlayerAgent>(true);
                    if (video) { video.Playable = false; }
                }
                selection = null;
                if (OutlinePrefab)
                {
                    OutlinePrefab.transform.parent = null;
                    OutlinePrefab.SetActive(false);
                }
                if (touchControl)
                {
                    touchControl.TurnOff();
                }
            }
    
            public void DeleteSelection()
            {
                if (!selection)
                {
                    return;
                }
                if (DeleteObject != null)
                {
                    DeleteObject(selection);
                }
                Destroy(selection);
                StopEdit();
            }
    
            public void ToggleVideoPlayable(bool playable)
            {
                if (selection)
                {
                    var video = selection.GetComponentInChildren<VideoPlayerAgent>(true);
                    if (video) { video.Playable = playable; }
                }
            }
    
            private void ShowCandidate()
            {
                dummy.gameObject.SetActive(false);
                candidate.SetActive(true);
            }
    
            private void HideCandidate()
            {
                candidate.SetActive(false);
                dummy.gameObject.SetActive(true);
            }
    
            private IEnumerator CheckVideo()
            {
                yield return new WaitForEndOfFrame();
                if (mapSession == null) { yield return 0; }
                foreach (var prop in mapSession.Maps[0].Props)
                {
                    if (prop)
                    {
                        var video = prop.GetComponentInChildren<VideoPlayerAgent>(true);
                        if (video) { video.Playable = false; }
                    }
                }
            }
        }
    }
    
    
    //================================================================================================================================
    
    //================================================================================================================================
    
    using System;
    using UnityEngine;
    using UnityEngine.UI;
    
    namespace SpatialMap_SparseSpatialMap
    {
        public class PropCellController : MonoBehaviour
        {
            public Image Icon;
    
            public event Action PointerDown;
            public event Action PointerUp;
    
            public PropCollection.Templet Templet { get; private set; }
    
            public void SetData(PropCollection.Templet templet)
            {
                Templet = templet;
                Icon.sprite = templet.Icon;
            }
    
            public void OnPointerDown()
            {
                Icon.color = Color.gray;
                if (PointerDown != null)
                {
                    PointerDown();
                }
            }
    
            public void OnPointerUp()
            {
                Icon.color = Color.white;
                if (PointerUp != null)
                {
                    PointerUp();
                }
            }
        }
    }
    
    
    //================================================================================================================================
    //
    //
    //================================================================================================================================
    
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    namespace SpatialMap_SparseSpatialMap
    {
        public class PropGridController : MonoBehaviour
        {
            public GameObject PropCellPrefab;
            public Dragger PropDragger;
    
            private GridLayoutGroup layout;
            private RectTransform rectTransform;
            private List<PropCellController> cells = new List<PropCellController>();
    
            private void Start()
            {
                layout = GetComponent<GridLayoutGroup>();
                rectTransform = GetComponent<RectTransform>();
    
                var cellHeight = rectTransform.rect.height * 0.7f;
                var padding = (int)(cellHeight * 0.1f);
                layout.padding.left = padding;
                layout.cellSize = new Vector2(cellHeight, cellHeight);
                layout.spacing = new Vector2(padding, padding);
    
                foreach (var templet in PropCollection.Instance.Templets)
                {
                    var cell = Instantiate(PropCellPrefab);
                    cell.transform.SetParent(transform);
                    var controller = cell.GetComponent<PropCellController>();
                    controller.SetData(templet);
                    controller.PointerDown += () =>
                    {
                        PropDragger.StartCreate(controller);
                    };
                    controller.PointerUp += PropDragger.StopCreate;
                    cells.Add(controller);
                }
            }
    
            private void Update()
            {
                var offset = rectTransform.childCount * (layout.cellSize.x + layout.padding.left) + layout.padding.left - rectTransform.rect.width;
                if (offset > 0)
                {
                    var offserMax = rectTransform.offsetMax;
                    offserMax.x = offset;
                    rectTransform.offsetMax = offserMax;
                }
            }
        }
    }
    
    
    //================================================================================================================================
    //
    
    //
    //================================================================================================================================
    
    using System;
    using UnityEngine;
    using UnityEngine.UI;
    
    namespace SpatialMap_SparseSpatialMap
    {
        public class MapCellController : MonoBehaviour
        {
            public Button DeleteButton;
    
            private Text text;
            private Image sprite;
    
            public event Action PointerDown;
            public event Action Delete;
    
            public bool Selected { get; private set; }
            public MapMeta MapMeta { get; private set; }
    
            public void Awake()
            {
                text = GetComponentInChildren<Text>();
                sprite = GetComponent<Image>();
                Cancel();
            }
    
            public void SetData(MapMeta meta)
            {
                MapMeta = meta;
                text.text = meta.Map.Name;
            }
    
            public void OnPointerDown()
            {
                if (Selected)
                {
                    Cancel();
                }
                else
                {
                    Selete();
                }
                if (PointerDown != null)
                {
                    PointerDown();
                }
            }
    
            public virtual void OnDelete()
            {
                if (Delete != null)
                {
                    Delete();
                }
            }
    
            private void Selete()
            {
                sprite.color = new Color(0.2f, 0.58f, 0.99f);
                text.color = new Color(1, 1, 1);
                DeleteButton.gameObject.SetActive(true);
                Selected = true;
            }
    
            private void Cancel()
            {
                sprite.color = new Color(1, 1, 1);
                text.color = new Color(0.2f, 0.58f, 0.99f);
                DeleteButton.gameObject.SetActive(false);
                Selected = false;
            }
        }
    }
    
    
    //================================================================================================================================
    //
    
    //
    //================================================================================================================================
    
    using System.Collections;
    using UnityEngine;
    using UnityEngine.EventSystems;
    using UnityEngine.UI;
    
    namespace SpatialMap_SparseSpatialMap
    {
        public class MapDockController : MonoBehaviour
        {
            public Button OpenButton;
    
            private RectTransform rectTransform;
    
            private void Awake()
            {
                rectTransform = GetComponent<RectTransform>();
            }
    
            private void Update()
            {
                if (((Application.isEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.OSXPlayer) && Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject())
                    || (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began && !EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)))
                {
                    ShowAndHide(OpenButton.gameObject.activeSelf);
                }
            }
    
            public void ShowAndHide(bool isShow)
            {
                StopAllCoroutines();
                if (isShow)
                {
                    StartCoroutine(Show());
                }
                else
                {
                    StartCoroutine(Hide());
                }
            }
    
            private IEnumerator Show()
            {
                var offsetMax = rectTransform.offsetMax;
                var offsetMin = rectTransform.offsetMin;
                OpenButton.gameObject.SetActive(false);
                while (offsetMax.x < 0)
                {
                    offsetMax.x += Screen.width * Time.deltaTime;
                    offsetMin.x += Screen.width * Time.deltaTime;
                    rectTransform.offsetMax = offsetMax;
                    rectTransform.offsetMin = offsetMin;
                    if (offsetMax.x > 0)
                    {
                        offsetMax.x = 0;
                        offsetMin.x = 0;
                        rectTransform.offsetMax = offsetMax;
                        rectTransform.offsetMin = offsetMin;
                    }
                    yield return 0;
                }
            }
    
            private IEnumerator Hide()
            {
                var offsetMax = rectTransform.offsetMax;
                var offsetMin = rectTransform.offsetMin;
                var width = rectTransform.rect.width + Screen.width * 0.01f;
                while (offsetMax.x > -width && offsetMin.x > -width)
                {
                    offsetMax.x -= Screen.width * Time.deltaTime;
                    offsetMin.x -= Screen.width * Time.deltaTime;
                    rectTransform.offsetMax = offsetMax;
                    rectTransform.offsetMin = offsetMin;
                    if (offsetMax.x < -width)
                    {
                        offsetMax.x = -width;
                        offsetMin.x = -width;
                        rectTransform.offsetMax = offsetMax;
                        rectTransform.offsetMin = offsetMin;
                    }
                    yield return 0;
                }
                OpenButton.gameObject.SetActive(true);
            }
        }
    }
    
    
    //================================================================================================================================
    //
    
    //
    //================================================================================================================================
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    using UnityEngine.UI;
    
    namespace SpatialMap_SparseSpatialMap
    {
        public class MapGridController : MonoBehaviour
        {
            public GameObject MapCellPrefab;
    
            private GridLayoutGroup layout;
            private RectTransform rectTransform;
            private List<MapCellController> cells = new List<MapCellController>();
    
            public int CellCount { get { return cells.Count; } }
    
            private void OnEnable()
            {
                foreach (var meta in MapMetaManager.LoadAll())
                {
                    var cell = Instantiate(MapCellPrefab);
                    cell.transform.SetParent(transform);
                    var controller = cell.GetComponent<MapCellController>();
                    controller.SetData(meta);
                    controller.PointerDown += OnCellChange;
                    controller.Delete += () =>
                    {
                        if (cells.Remove(controller))
                        {
                            MapMetaManager.Delete(controller.MapMeta);
                            Destroy(controller.gameObject);
                            OnCellChange();
                            easyar.GUIPopup.EnqueueMessage(
                                "DELETED: {(Sample) Meta Data}" + Environment.NewLine +
                                "NOT DELETED: {Map Cache, Map on Server}" + Environment.NewLine +
                                "Use recycle bin button to delete map cache" + Environment.NewLine +
                                "Use web develop center to manage maps on server", 5);
                        }
                    };
                    cells.Add(controller);
                }
            }
    
            private void Start()
            {
                layout = GetComponent<GridLayoutGroup>();
                rectTransform = GetComponent<RectTransform>();
                var cellWidth = rectTransform.rect.width * 0.9f;
                var padding = (int)(cellWidth * 0.1f);
                layout.padding.top = padding;
                layout.cellSize = new Vector2(cellWidth, cellWidth * 0.5f);
                layout.spacing = new Vector2(padding, padding);
            }
    
            private void Update()
            {
                var sizeDelta = rectTransform.sizeDelta;
                sizeDelta.y = rectTransform.childCount * (layout.cellSize.y + layout.padding.top) + layout.padding.top;
                rectTransform.sizeDelta = sizeDelta;
            }
    
            private void OnDisable()
            {
                foreach (var cell in cells)
                {
                    if (cell) { Destroy(cell.gameObject); }
                }
                cells.Clear();
            }
    
            public void ClearAll()
            {
                // Notice:
                //   a) When clear both map cache and map list,
                //      load map will not trigger a download (cache is build when upload),
                //      and statistical request count will not be increased in a subsequent load (when edit or preview).
                //   b) When clear map cache only,
                //      load map after clear (only the first time each map) will trigger a download,
                //      and statistical request count will be increased in a subsequent load (when edit or preview).
                //      Map cache is used after a successful download and will be cleared if SparseSpatialMapManager.clear is called or app uninstalled.
                //
                // More about the statistical request count and limitations for different subscription mode can be found at EasyAR website.
    
                if (!ViewManager.Instance.MainViewRecycleBinClearMapCacheOnly)
                {
                    // clear map meta and the list on UI
                    foreach (var cell in cells)
                    {
                        if (cell)
                        {
                            MapMetaManager.Delete(cell.MapMeta);
                            Destroy(cell.gameObject);
                        }
                    }
                    cells.Clear();
                }
    
                // clear map cache
                MapSession.ClearCache();
    
                // UI notification
                OnCellChange();
                if (!ViewManager.Instance.MainViewRecycleBinClearMapCacheOnly)
                {
                    easyar.GUIPopup.EnqueueMessage(
                        "DELETED: {(Sample) Meta Data, Map Cache}" + Environment.NewLine +
                        "NOT DELETED: {Map on Server}" + Environment.NewLine +
                        "Use web develop center to manage maps on server", 5);
                }
                else
                {
                    easyar.GUIPopup.EnqueueMessage(
                        "DELETED: {Map Cache}" + Environment.NewLine +
                        "NOT DELETED: {Map on Server, (Sample) Meta Data}" + Environment.NewLine +
                        "Use web develop center to manage maps on server", 5);
                }
            }
    
            private void OnCellChange()
            {
                ViewManager.Instance.SelectMaps(cells.Where(cell => cell && cell.Selected).Select(cell => cell.MapMeta).ToList());
            }
        }
    }
    
    
    //================================================================================================================================
    //
    
    //
    //================================================================================================================================
    
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    namespace SpatialMap_SparseSpatialMap
    {
        public class MainViewController : MonoBehaviour
        {
            public Button Edit;
            public Button Preview;
            public Button Create;
            public GameObject ClearPupup;
            public MapGridController MapGrid;
    
            private void OnEnable()
            {
                StopAllCoroutines();
                var colors = Create.colors;
                colors.normalColor = new Color(0.2f, 0.58f, 0.988f);
                colors.highlightedColor = new Color(0.192f, 0.557f, 0.949f);
                colors.pressedColor = new Color(0.157f, 0.455f, 0.773f);
                Create.colors = colors;
                ClearPupup.SetActive(false);
                StartCoroutine(Twinkle(Create));
            }
    
            public void EnableEdit(bool enable)
            {
                Edit.interactable = enable;
            }
    
            public void EnablePreview(bool enable)
            {
                Preview.interactable = enable;
            }
    
            private IEnumerator Twinkle(Button button)
            {
                if (MapGrid.CellCount > 0) { yield break; }
    
                var colors = button.colors;
                var olist = new List<Color>
                {
                    colors.normalColor,
                    colors.highlightedColor,
                    colors.pressedColor
                };
    
                var clist = new List<Vector3>();
                foreach (var color in olist)
                {
                    Vector3 hsv;
                    Color.RGBToHSV(color, out hsv.x, out hsv.y, out hsv.z);
                    clist.Add(hsv);
                }
    
                float smin = 0.2f;
                float smax = clist[0].y;
                bool increase = false;
    
                while (MapGrid.CellCount <= 0)
                {
                    for (int i = 0; i < clist.Count; ++i)
                    {
                        var hsv = clist[i];
                        hsv.y += increase ? 0.2f * Time.deltaTime : -0.2f * Time.deltaTime;
                        clist[i] = hsv;
                    }
                    if (clist[0].y >= smax)
                    {
                        for (int i = 0; i < clist.Count; ++i)
                        {
                            clist[i] = new Vector3(clist[i].x, smax, clist[i].z);
                        }
                        increase = false;
                    }
                    else if (clist[0].y < smin)
                    {
                        for (int i = 0; i < clist.Count; ++i)
                        {
                            clist[i] = new Vector3(clist[i].x, smin, clist[i].z);
                        }
                        increase = true;
                    }
                    colors.normalColor = Color.HSVToRGB(clist[0].x, clist[0].y, clist[0].z);
                    colors.highlightedColor = Color.HSVToRGB(clist[1].x, clist[1].y, clist[1].z);
                    colors.pressedColor = Color.HSVToRGB(clist[2].x, clist[2].y, clist[2].z);
                    button.colors = colors;
                    yield return 0;
                }
                colors.normalColor = olist[0];
                colors.highlightedColor = olist[1];
                colors.pressedColor = olist[2];
                button.colors = colors;
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:Unity3D开发技术研究-构建稀疏空间地图SparseSpat

          本文链接:https://www.haomeiwen.com/subject/tozuxrtx.html