一、框架视图
二、关键代码
//================================================================================================================================
//================================================================================================================================
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 balls = new List();
private void Awake()
{
vioCamera = Session.GetComponentInChildren();
dense = Session.GetComponentInChildren();
}
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();
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 Props = new List();
public MapMeta(SparseSpatialMapController.SparseSpatialMapInfo map, List 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 LoadAll()
{
var metas = new List();
var dirRoot = GetRootPath();
try
{
foreach (var path in Directory.GetFiles(dirRoot, "*.meta"))
{
try
{
metas.Add(JsonUtility.FromJson(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 Templets = new List();
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();
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("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();
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.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();
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 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("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 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 CreateObject;
public event Action DeleteObject;
private void Awake()
{
rectTransform = GetComponent();
dummy = GetComponentInChildren(true);
touchControl = GetComponentInChildren(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().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(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(true);
if (video) { video.Playable = true; }
}
var meshFilter = selection.GetComponentInChildren();
OutlinePrefab.SetActive(true);
OutlinePrefab.GetComponent().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(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(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(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 cells = new List();
private void Start()
{
layout = GetComponent();
rectTransform = GetComponent();
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();
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();
sprite = GetComponent();
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();
}
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 cells = new List();
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();
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();
rectTransform = GetComponent();
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
{
colors.normalColor,
colors.highlightedColor,
colors.pressedColor
};
var clist = new List();
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;
}
}
}