123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- using System.Text;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Networking;
- using UnityEngine.UI;
- using UnityEngine.XR.ARFoundation;
- namespace ARLocation
- {
- [RequireComponent(typeof(WorldBuilder))]
- public class WorldBuilderApplicationController : MonoBehaviour
- {
- [System.Serializable]
- public class UiElementsSettings
- {
- public Button CubeBtn;
- public Button CylinderBtn;
- public Button LogoBtn;
- public Button MoveBtn;
- public Button RotateBtn;
- public Button DeselectBtn;
- public Button ClearWorldBtn;
- public Button HeightBtn;
- public Button DeleteObjectBtn;
- public Text DebugText;
- }
- [System.Serializable]
- public class RaycastMarginSettings
- {
- public float Top;
- public float Bottom;
- public float Left;
- public float Right;
- }
- [System.Serializable]
- public class GeneralSettings
- {
- public float HeightAdjustmentSensitivity = 0.25f;
- public float RotationAdjustmentSensitivity = 1.0f;
- public string SaveWorldUrl;
- public string RestoreWorldUrl;
- public bool SaveToServer;
- }
- public UiElementsSettings UiElements;
- public RaycastMarginSettings RaycastMargins;
- public GeneralSettings Settings;
- private WorldBuilder worldBuilder;
- private PlaceAtLocation selectedObject;
- private WorldBuilder.Entry selectedObjectEntry;
- enum AppState
- {
- PlacementMode,
- MoveMode,
- RotateMode,
- HeightMode,
- IdleMode
- };
- class State
- {
- public string CurrentMeshId;
- public AppState AppState;
- }
- private readonly State state = new State();
- private void Awake()
- {
- worldBuilder = GetComponent<WorldBuilder>();
- if (Settings.SaveToServer)
- {
- worldBuilder.UseLocalStorage = false;
- }
- Debug.Assert(worldBuilder != null);
- Debug.Assert(worldBuilder.PrefabDatabase.Entries.Count > 0);
- state.CurrentMeshId = "Cube";
- UiElements.CubeBtn.image.color = UiElements.CubeBtn.colors.pressedColor;
- SetObjectSelectedUIVisible(false);
- InitListeners();
- }
- IEnumerator Start()
- {
- if (Settings.SaveToServer)
- {
- while (!worldBuilder.Initialized)
- {
- yield return new WaitForSeconds(0.1f);
- }
- yield return RestoreWorldFromServer();
- }
- }
- IEnumerator RestoreWorldFromServer()
- {
- var request = UnityWebRequest.Get($"{Settings.RestoreWorldUrl}{worldBuilder.Id}");
- yield return request.SendWebRequest();
- if (Utils.Misc.WebRequestResultIsError(request))
- {
- Debug.Log("Failed to restore world from server!");
- yield break;
- }
- Debug.Log(request.downloadHandler.text);
- Debug.Log(request.responseCode);
- worldBuilder.FromJson(request.downloadHandler.text);
- }
- IEnumerator SaveWorldToServer()
- {
- var request = new UnityWebRequest($"{Settings.SaveWorldUrl}{worldBuilder.Id}", "POST");
- byte[] bodyRaw = Encoding.UTF8.GetBytes(worldBuilder.ToJson());
- request.uploadHandler = (UploadHandler) new UploadHandlerRaw(bodyRaw);
- request.downloadHandler = (DownloadHandler) new DownloadHandlerBuffer();
- request.SetRequestHeader("Content-Type", "application/json");
- yield return request.SendWebRequest();
- if (Utils.Misc.WebRequestResultIsError(request))
- {
- Debug.LogWarning("Failed to save to server!");
- }
- }
- void SetObjectSelectedUIVisible(bool visible)
- {
- UiElements.MoveBtn.gameObject.SetActive(visible);
- UiElements.RotateBtn.gameObject.SetActive(visible);
- UiElements.DeselectBtn.gameObject.SetActive(visible);
- UiElements.HeightBtn.gameObject.SetActive(visible);
- UiElements.DeleteObjectBtn.gameObject.SetActive(visible);
- UiElements.CubeBtn.gameObject.SetActive(!visible);
- UiElements.CylinderBtn.gameObject.SetActive(!visible);
- UiElements.LogoBtn.gameObject.SetActive(!visible);
- UiElements.ClearWorldBtn.gameObject.SetActive(!visible);
- }
- void SetMoveMode()
- {
- UiElements.MoveBtn.image.color = UiElements.MoveBtn.colors.pressedColor;
- UiElements.RotateBtn.image.color = UiElements.MoveBtn.colors.normalColor;
- UiElements.DeselectBtn.image.color = UiElements.MoveBtn.colors.normalColor;
- UiElements.HeightBtn.image.color = UiElements.MoveBtn.colors.normalColor;
- state.AppState = AppState.MoveMode;
- }
- void SetRotateMode()
- {
- UiElements.MoveBtn.image.color = UiElements.MoveBtn.colors.normalColor;
- UiElements.RotateBtn.image.color = UiElements.MoveBtn.colors.pressedColor;
- UiElements.DeselectBtn.image.color = UiElements.MoveBtn.colors.normalColor;
- UiElements.HeightBtn.image.color = UiElements.MoveBtn.colors.normalColor;
- state.AppState = AppState.RotateMode;
- }
- private void SetHeightMode()
- {
- UiElements.MoveBtn.image.color = UiElements.MoveBtn.colors.normalColor;
- UiElements.RotateBtn.image.color = UiElements.MoveBtn.colors.normalColor;
- UiElements.DeselectBtn.image.color = UiElements.MoveBtn.colors.normalColor;
- UiElements.HeightBtn.image.color = UiElements.MoveBtn.colors.pressedColor;
- state.AppState = AppState.HeightMode;
- }
- void InitListeners()
- {
- UiElements.ClearWorldBtn.onClick.AddListener(() =>
- {
- worldBuilder.ClearWorld();
- SetObjectSelectedUIVisible(false);
- state.AppState = AppState.PlacementMode;
- });
- UiElements.CubeBtn.onClick.AddListener(() =>
- {
- UiElements.CubeBtn.image.color = UiElements.CubeBtn.colors.pressedColor;
- UiElements.CylinderBtn.image.color = UiElements.CylinderBtn.colors.normalColor;
- UiElements.LogoBtn.image.color = UiElements.LogoBtn.colors.normalColor;
- state.CurrentMeshId = "Cube";
- });
- UiElements.CylinderBtn.onClick.AddListener(() =>
- {
- UiElements.CubeBtn.image.color = UiElements.CubeBtn.colors.normalColor;
- UiElements.CylinderBtn.image.color = UiElements.CylinderBtn.colors.pressedColor;
- UiElements.LogoBtn.image.color = UiElements.LogoBtn.colors.normalColor;
- state.CurrentMeshId = "Cylinder";
- });
- UiElements.LogoBtn.onClick.AddListener(() =>
- {
- UiElements.CubeBtn.image.color = UiElements.CubeBtn.colors.normalColor;
- UiElements.CylinderBtn.image.color = UiElements.CylinderBtn.colors.normalColor;
- UiElements.LogoBtn.image.color = UiElements.LogoBtn.colors.pressedColor;
- state.CurrentMeshId = "Logo";
- });
- UiElements.DeselectBtn.onClick.AddListener(() =>
- {
- state.CurrentMeshId = "Cube";
- UiElements.CubeBtn.image.color = UiElements.CubeBtn.colors.pressedColor;
- UiElements.CylinderBtn.image.color = UiElements.CylinderBtn.colors.normalColor;
- UiElements.LogoBtn.image.color = UiElements.LogoBtn.colors.normalColor;
- state.AppState = AppState.PlacementMode;
- SetObjectSelectedUIVisible(false);
- selectedObjectEntry = null;
- });
- UiElements.RotateBtn.onClick.AddListener(() =>
- {
- SetRotateMode();
- });
- UiElements.MoveBtn.onClick.AddListener(() =>
- {
- SetMoveMode();
- });
- UiElements.HeightBtn.onClick.AddListener(() =>
- {
- SetHeightMode();
- });
- UiElements.DeleteObjectBtn.onClick.AddListener(() =>
- {
- worldBuilder.RemoveEntry(selectedObjectEntry);
- });
- }
- void DebugOutput(string text)
- {
- if (UiElements.DebugText)
- {
- UiElements.DebugText.text = text;
- }
- }
- void Update()
- {
- DebugOutput($" c = {ARLocationManager.Instance.MainCamera.transform.position}");
- if (Input.touchCount == 1)
- {
- var touch = Input.touches[0];
- if (state.AppState == AppState.RotateMode)
- {
- if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
- {
- float dx = Settings.RotationAdjustmentSensitivity * (180.0f / Mathf.PI) * touch.deltaPosition.x / Screen.width;
- DebugOutput($"dx = {dx}");
- if (selectedObjectEntry != null && selectedObjectEntry.Instance != null)
- {
- var euler = selectedObjectEntry.Instance.transform.localEulerAngles;
- selectedObjectEntry.Rotation = euler.y + dx;
- selectedObjectEntry.Instance.transform.localEulerAngles = new Vector3(euler.x, selectedObjectEntry.Rotation, euler.z);
- }
- }
- return;
- }
- else if (state.AppState == AppState.HeightMode)
- {
- if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
- {
- float dy = Settings.HeightAdjustmentSensitivity * (180.0f / Mathf.PI) * touch.deltaPosition.y / Screen.height;
- DebugOutput($"dy = {dy}");
- if (selectedObjectEntry != null && selectedObjectEntry.Instance != null)
- {
- var Location = selectedObjectEntry.Instance.GetComponent<PlaceAtLocation>().Location.Clone();
- Location.Altitude += dy;
- selectedObjectEntry.Location.Altitude += dy;
- selectedObjectEntry.Instance.GetComponent<PlaceAtLocation>().Location = Location;
- }
- }
- return;
- }
- else if (touch.phase == TouchPhase.Began)
- {
- if (UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject(0)) return;
- OnTouchOrClick(touch.position);
- }
- }
- if (Application.isEditor && Input.GetMouseButtonDown(0))
- {
- OnTouchOrClick(Input.mousePosition);
- }
- }
- private void OnTouchOrClick(Vector2 p)
- {
- float x = p.x / Screen.width;
- float y = p.y / Screen.height;
- if (x < RaycastMargins.Left || x > (1 - RaycastMargins.Right)) return;
- if (y < RaycastMargins.Bottom || y > (1 - RaycastMargins.Top)) return;
- var camera = Application.isEditor ? Camera.main : ARLocationManager.Instance.MainCamera;
- var ray = camera.ScreenPointToRay(p);
- if (state.AppState == AppState.PlacementMode)
- {
- RaycastHit hit;
- if (Physics.Raycast(ray, out hit))
- {
- GameObject go = null;
- WorldBuilder.Entry entry = null;
- var o = hit.collider.transform;
- while (o.parent)
- {
- Debug.Log(o.name);
- entry = worldBuilder.GetWorld().Entries.Find(e => e.Instance == o.gameObject);
- if (entry != null)
- {
- go = entry.Instance;
- break;
- }
- o = o.parent;
- }
- if (go != null && entry != null)
- {
- selectedObjectEntry = entry;
- SetObjectSelectedUIVisible(true);
- SetMoveMode();
- return;
- }
- }
- }
- float enter;
- if (RaycastGround(ray, out enter))
- {
- var point = ray.GetPoint(enter);
- switch (state.AppState)
- {
- case AppState.PlacementMode:
- OnPlacementRaycast(point);
- break;
- case AppState.MoveMode:
- OnMoveModeRaycast(point);
- break;
- }
- }
- }
- private bool RaycastGround(Ray ray, out float t)
- {
- var arRaycastManager = FindObjectOfType<ARRaycastManager>();
- if (Application.isEditor || arRaycastManager == null)
- {
- var camera = Application.isEditor ? Camera.main : ARLocationManager.Instance.MainCamera;
- var plane = new Plane(new Vector3(0, 1, 0), camera.transform.position - new Vector3(0, 1.4f, 0));
- return plane.Raycast(ray, out t);
- }
- else
- {
- List<ARRaycastHit> hits = new List<ARRaycastHit>();
- arRaycastManager.Raycast(ray, hits, trackableTypes: UnityEngine.XR.ARSubsystems.TrackableType.PlaneWithinInfinity);
- if (hits.Count > 0)
- {
- t = hits[0].distance;
- return true;
- }
- else
- {
- var camera = Application.isEditor ? Camera.main : ARLocationManager.Instance.MainCamera;
- var plane = new Plane(new Vector3(0, 1, 0), camera.transform.position - new Vector3(0, 1.4f, 0));
- return plane.Raycast(ray, out t);
- }
- }
- }
- private void OnMoveModeRaycast(Vector3 point)
- {
- worldBuilder.MoveEntry(selectedObjectEntry, point);
- }
- private void OnPlacementRaycast(Vector3 v)
- {
- Debug.Log("ok!");
- worldBuilder.AddEntry(state.CurrentMeshId, v);
- if (Settings.SaveToServer)
- {
- Debug.Log("ok2!");
- StartCoroutine(SaveWorldToServer());
- }
- }
- }
- }
|