This repository has been archived on 2025-04-28. You can view files and clone it, but cannot push or open issues or pull requests.
ARPlusSystem/ARPlusSystem-250418/Assets/ARLocation/Experimental/World Builder/WorldBuilder.cs

201 lines
5.2 KiB
C#
Raw Normal View History

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace ARLocation
{
public class WorldBuilder : MonoBehaviour
{
public PrefabDatabase PrefabDatabase;
public string Id = "World";
public bool UseLocalStorage;
[System.Serializable]
public class Entry
{
public Location Location;
public float Rotation;
public string MeshId;
[System.NonSerialized]
public GameObject Instance;
}
[System.Serializable]
public class World
{
public List<Entry> Entries = new List<Entry>();
}
class State
{
public World World = new World();
}
private readonly State state = new State();
public World GetWorld()
{
return state.World;
}
private bool initialized;
public bool Initialized => initialized;
IEnumerator Start()
{
yield return StartCoroutine(WaitForLocationServices());
if (UseLocalStorage)
{
RestoreWorldFromLocalStorage();
}
initialized = true;
}
IEnumerator WaitForLocationServices()
{
while (!ARLocationProvider.Instance.IsEnabled)
{
yield return new WaitForSeconds(0.1f);
}
}
public void AddEntry(string meshId, Vector3 worldPosition, float rotation = 0)
{
var location = ARLocationManager.Instance.GetLocationForWorldPosition(worldPosition);
var entry = new Entry { Location = location, MeshId = meshId, Rotation = rotation };
state.World.Entries.Add(entry);
PlaceEntryAtLocation(entry);
}
void OnDestroy()
{
SaveWorld();
}
void OnApplicationPause(bool pause)
{
if (pause) SaveWorld();
}
void PlaceWorld()
{
state.World.Entries.ForEach(PlaceEntryAtLocation);
}
void PlaceEntryAtLocation(Entry entry)
{
var prefab = PrefabDatabase.GetEntryById(entry.MeshId);
if (prefab == null)
{
Debug.LogWarning($"Invalid prefab '{entry.MeshId}'");
return;
}
var location = entry.Location;
var options = new PlaceAtLocation.PlaceAtOptions { };
entry.Instance = PlaceAtLocation.CreatePlacedInstance(prefab, location, options, false);
entry.Instance.transform.localEulerAngles = new Vector3(0, entry.Rotation, 0);
}
public string ToJson()
{
return JsonUtility.ToJson(state.World);
}
public void FromJson(string json)
{
ClearWorld();
state.World = JsonUtility.FromJson<World>(json);
PlaceWorld();
}
string GetJsonFilename()
{
var s = Id.Trim();
if (s == "") s = "World";
return Application.persistentDataPath + "/" + s + ".json";
}
public void SaveWorld()
{
if (!UseLocalStorage) return;
string json = JsonUtility.ToJson(state.World);
Debug.Log(json);
try
{
System.IO.File.WriteAllText(GetJsonFilename(), json);
}
catch
{
Debug.Log("[ARLocation::WorldBuilder::SaveWorld]: Failed to open json file for writing.");
return;
}
Debug.Log($"Written to json file '{GetJsonFilename()}'");
}
public void RestoreWorldFromLocalStorage()
{
if (!UseLocalStorage) return;
string json = "";
try
{
json = System.IO.File.ReadAllText(GetJsonFilename(), System.Text.Encoding.UTF8);
}
catch
{
Debug.Log("[ARLocation::WorldBuilder::RestoreWorld]: Failed to open json file for reading.");
return;
}
state.World = JsonUtility.FromJson<World>(json);
PlaceWorld();
Debug.Log($"Restored world from json file '{GetJsonFilename()}'");
}
public void ClearWorld()
{
state.World.Entries.ForEach(e => {
if (e.Instance != null)
{
Destroy(e.Instance);
}
});
state.World = new World();
}
internal void MoveEntry(Entry entry, Vector3 point)
{
var location = ARLocationManager.Instance.GetLocationForWorldPosition(point);
entry.Location = location;
if (entry.Instance != null)
{
var placeAt = entry.Instance.GetComponent<PlaceAtLocation>();
if (placeAt != null)
{
placeAt.Location = location;
}
}
}
public void RemoveEntry(Entry entry)
{
Destroy(entry.Instance);
state.World.Entries.Remove(entry);
}
}
}