using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Cysharp.Threading.Tasks;
using Speckle.Core.Api;
using Speckle.Core.Models;
using UnityEngine;
using UnityEngine.Events;
namespace Speckle.ConnectorUnity.Models
{
///
/// This class gets attached to GOs and is used to store Speckle's metadata when sending / receiving
///
[Serializable]
public class SpeckleProperties
{
public SpeckleProperties()
{
_observableConcurrentDict = new ObservableConcurrentDictionary();
_observableConcurrentDict.CollectionChanged += (_, args) => OnCollectionChange?.Invoke(args);
}
[SerializeField] [HideInInspector] string _jsonString = "";
public event UnityAction OnCollectionChange;
HashSet _excludedProps;
public HashSet excludedProps
{
get
{
return _excludedProps ??= new HashSet(
typeof(Base).GetProperties().Select(x => x.Name));
}
private set => _excludedProps = value;
}
ObservableConcurrentDictionary _observableConcurrentDict;
public IDictionary Data
{
get => _observableConcurrentDict;
set
{
((ICollection>)_observableConcurrentDict).Clear();
foreach (var kvp in value) _observableConcurrentDict.Add(kvp.Key, kvp.Value);
}
}
public UniTask Serialize(Base @base, HashSet props)
{
if (props != null) excludedProps = props;
return Serialize(@base);
}
public UniTask Serialize(Base @base)
{
Data = @base.GetMembers().Where(x => !excludedProps.Contains(x.Key)).ToDictionary(x => x.Key, x => x.Value);
_jsonString = Operations.Serialize(@base);
return UniTask.CompletedTask;
}
public UniTask Serialize(IDictionary objectProps)
{
Data = objectProps;
_jsonString = Operations.Serialize(new BasePropsWrapper(Data));
return UniTask.CompletedTask;
}
///
/// Serializes the stored properties in
///
///
public UniTask Serialize()
{
var tData = new Base();
foreach (var d in Data)
tData[d.Key] = d.Value;
_jsonString = Operations.Serialize(new BasePropsWrapper(Data));
return UniTask.CompletedTask;
}
public async UniTask Test_Serialize(Base @base)
{
var watch = Stopwatch.StartNew();
await UniTask.Create(() =>
{
_jsonString = Operations.Serialize(@base);
return UniTask.CompletedTask;
});
SpeckleUnity.Console.Log($"Step 1: Serialize to string with Operations-{watch.Elapsed}");
await UniTask.Yield();
watch.Restart();
await UniTask.Create(() =>
{
Data = @base.GetMembers().Where(x => !excludedProps.Contains(x.Key)).ToDictionary(x => x.Key, x => x.Value);
return UniTask.CompletedTask;
});
SpeckleUnity.Console.Log($"Step 2: Serialize dictionary of props-{watch.Elapsed}");
await UniTask.Yield();
watch.Restart();
await UniTask.Create(() =>
{
var speckleData = Operations.Deserialize(_jsonString);
SpeckleUnity.Console.Log(speckleData.speckle_type);
SpeckleUnity.Console.Log(speckleData.id);
return UniTask.CompletedTask;
});
SpeckleUnity.Console.Log($"Step 4: DeSerializing string-{watch.Elapsed}");
await UniTask.Yield();
watch.Stop();
}
[Serializable]
internal sealed class BasePropsWrapper : Base
{
public BasePropsWrapper(IDictionary data)
{
foreach (var v in data) this[v.Key] = v.Value;
}
}
}
}