using System.Collections.Generic; using System.Globalization; using System.Xml; using UnityEngine; namespace ARLocation { public class WebMapLoader : MonoBehaviour { public class DataEntry { public int id; public double lat; public double lng; public double altitude; public string altitudeMode; public string name; public string meshId; public float movementSmoothing; public int maxNumberOfLocationUpdates; public bool useMovingAverage; public bool hideObjectUtilItIsPlaced; public AltitudeMode getAltitudeMode() { if (altitudeMode == "GroundRelative") { return AltitudeMode.GroundRelative; } else if (altitudeMode == "DeviceRelative") { return AltitudeMode.DeviceRelative; } else if (altitudeMode == "Absolute") { return AltitudeMode.Absolute; } else { return AltitudeMode.Ignore; } } } /// /// The `PrefabDatabase` ScriptableObject, containing a dictionary of Prefabs with a string ID. /// public PrefabDatabase PrefabDatabase; /// /// The XML data file download from the Web Map Editor (htttps://editor.unity-ar-gps-location.com) /// public TextAsset XmlDataFile; /// /// If true, enable DebugMode on the `PlaceAtLocation` generated instances. /// public bool DebugMode; /// /// Returns a list of the `PlaceAtLocation` instances created by this compoonent. /// >/summary> public List Instances { get => _placeAtComponents; } private List _dataEntries = new List(); private List _placeAtComponents = new List(); // Start is called before the first frame update void Start() { LoadXmlFile(); BuildGameObjects(); } /// /// /// Calls `SetActive(value)` for each of the gameObjects created by this component. /// /// public void SetActiveGameObjects(bool value) { foreach (var i in _placeAtComponents) { i.gameObject.SetActive(value); } } /// /// /// Hides all the meshes contained on each of the gameObjects created /// by this component, but does not disable the gameObjects. /// /// public void HideMeshes() { foreach (var i in _placeAtComponents) { Utils.Misc.HideGameObject(i.gameObject); } } /// /// /// Makes all the gameObjects visible after calling `HideMeshes`. /// /// public void ShowMeshes() { foreach (var i in _placeAtComponents) { Utils.Misc.ShowGameObject(i.gameObject); } } void BuildGameObjects() { foreach (var entry in _dataEntries) { var Prefab = PrefabDatabase.GetEntryById(entry.meshId); if (!Prefab) { Debug.LogWarning($"[ARLocation#WebMapLoader]: Prefab {entry.meshId} not found."); continue; } var PlacementOptions = new PlaceAtLocation.PlaceAtOptions() { MovementSmoothing = entry.movementSmoothing, MaxNumberOfLocationUpdates = entry.maxNumberOfLocationUpdates, UseMovingAverage = entry.useMovingAverage, HideObjectUntilItIsPlaced = entry.hideObjectUtilItIsPlaced }; var location = new Location() { Latitude = entry.lat, Longitude = entry.lng, Altitude = entry.altitude, AltitudeMode = entry.getAltitudeMode(), Label = entry.name }; var instance = PlaceAtLocation.CreatePlacedInstance(Prefab, location, PlacementOptions, DebugMode); _placeAtComponents.Add(instance.GetComponent()); } } // Update is called once per frame void LoadXmlFile() { var xmlString = XmlDataFile.text; Debug.Log(xmlString); XmlDocument xmlDoc = new XmlDocument(); try { xmlDoc.LoadXml(xmlString); } catch (XmlException e) { Debug.LogError("[ARLocation#WebMapLoader]: Failed to parse XML file: " + e.Message); } var root = xmlDoc.FirstChild; var nodes = root.ChildNodes; foreach (XmlNode node in nodes) { Debug.Log(node.InnerXml); Debug.Log(node["id"].InnerText); int id = int.Parse(node["id"].InnerText); double lat = double.Parse(node["lat"].InnerText, CultureInfo.InvariantCulture); double lng = double.Parse(node["lng"].InnerText, CultureInfo.InvariantCulture); double altitude = double.Parse(node["altitude"].InnerText, CultureInfo.InvariantCulture); string altitudeMode = node["altitudeMode"].InnerText; string name = node["name"].InnerText; string meshId = node["meshId"].InnerText; float movementSmoothing = float.Parse(node["movementSmoothing"].InnerText, CultureInfo.InvariantCulture); int maxNumberOfLocationUpdates = int.Parse(node["maxNumberOfLocationUpdates"].InnerText); bool useMovingAverage = bool.Parse(node["useMovingAverage"].InnerText); bool hideObjectUtilItIsPlaced = bool.Parse(node["hideObjectUtilItIsPlaced"].InnerText); DataEntry entry = new DataEntry() { id = id, lat = lat, lng = lng, altitudeMode = altitudeMode, altitude = altitude, name = name, meshId = meshId, movementSmoothing = movementSmoothing, maxNumberOfLocationUpdates = maxNumberOfLocationUpdates, useMovingAverage = useMovingAverage, hideObjectUtilItIsPlaced = hideObjectUtilItIsPlaced }; _dataEntries.Add(entry); Debug.Log($"{id}, {lat}, {lng}, {altitude}, {altitudeMode}, {name}, {meshId}, {movementSmoothing}, {maxNumberOfLocationUpdates}, {useMovingAverage}, {hideObjectUtilItIsPlaced}"); } } } }