using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Cysharp.Threading.Tasks;
using Speckle.ConnectorUnity.Converter;
using Speckle.ConnectorUnity.Models;
using Speckle.Core.Kits;
using Speckle.Core.Logging;
using Speckle.Core.Models;
using UnityEngine;
namespace Speckle.ConnectorUnity.Ops
{
public static partial class SpeckleOps
{
///
/// Setup the hierarchy for the commit coming in
///
/// Object to attach data to
/// The object to convert
/// Speckle Converter to parse objects with
/// Cancellation token
///
public static async UniTask DataToScene(this SpeckleObjectBehaviour speckleObject, Base data, ISpeckleConverter converter, CancellationToken token)
{
if (data == null)
{
SpeckleUnity.Console.Warn($"No valid {typeof(Base)} to use during conversion ");
return;
}
if (converter == null)
{
SpeckleUnity.Console.Warn("No valid converter to use during conversion ");
return;
}
speckleObject.hierarchy = new SpeckleObjectHierarchy();
var defaultLayer = new GameObject("Default").AddComponent();
await speckleObject.DeconstructObject(data, defaultLayer, converter, token);
if (defaultLayer.Layers.Any())
{
defaultLayer.SetObjectParent(speckleObject.transform);
speckleObject.hierarchy.Add(defaultLayer);
}
else
SpeckleUnity.SafeDestroy(defaultLayer.gameObject);
if (converter is ScriptableSpeckleConverter sc)
await sc.PostWork();
}
static async UniTask DeconstructObject(
this SpeckleObjectBehaviour speckleObj, Base data, SpeckleLayer defaultLayer, ISpeckleConverter converter, CancellationToken token
)
{
if (token.IsCancellationRequested) return;
// 1: Object is supported, so lets convert the object and it's data
if (converter.CanConvertToNative(data))
{
// NOTE: Object created in scene
// NOTE: This is where the game object instance could be captured and meta stored in each object
// NOTE: The converter should spawn a series of mono objects that will handle going through the list of objects to convert and send data to
var obj = CheckConvertedFormat(converter.ConvertToNative(data));
if (obj != null)
defaultLayer.Add(obj);
await UniTask.Yield();
}
// 2: Check for the properties of an object. There might be additional objects that we want to convert as well
foreach (var member in data.GetMemberNames())
{
if (token.IsCancellationRequested)
return;
// NOTE: we should only have to check for certain props and make sure to not duplicate any
var obj = data[member];
// 2a: A prop is a list! We create a special list object to store those items in
if (obj.IsList())
{
// create the list container
var layer = ListToLayer(member, ((IEnumerable)obj).Cast