using System.Threading;
using Cysharp.Threading.Tasks;
using Speckle.ConnectorUnity.Args;
using Speckle.ConnectorUnity.Models;
using Speckle.Core.Api;
using Speckle.Core.Credentials;
using Speckle.Core.Logging;
using Speckle.Core.Models;
using UnityEngine;
using UnityEngine.Events;
namespace Speckle.ConnectorUnity.Ops
{
///
/// A Speckle Sender, it's a wrapper around a basic Speckle Client
/// that handles conversions for you
///
[AddComponentMenu(SpeckleUnity.NAMESPACE + "/Sender")]
[ExecuteAlways]
public class Sender : ClientBehaviour
{
[SerializeField] string _message;
Base _data;
///
/// Ignores any speckle node values and sends the loaded
///
///
/// Commit message to add
/// Cancellation token. Will default to attached source token
///
public async UniTask Run(Base @base, string message = null, CancellationTokenSource tokenSource = null)
{
_data = @base;
return await Run(message, tokenSource);
}
///
/// Converts and sends the speckle node to the active stream of this client
///
/// Top level object to send
/// Commit message
/// Cancellation token
///
public async UniTask Run(SpeckleObjectBehaviour obj, string message = null, CancellationTokenSource tokenSource = null)
{
if (obj != null) _root = obj;
return await Run(message, tokenSource);
}
///
/// Converts all objects attached to the speckle node and sends it to the active stream in this client object
///
/// Commit message to add
/// Cancellation token. Will default to attached source token
///
public async UniTask Run(string message, CancellationTokenSource tokenSource = null)
{
token = tokenSource?.Token ?? this.GetCancellationTokenOnDestroy();
_message = message.Valid() ? message : string.Empty;
return await Run();
}
///
/// A Unity friendly wrapper to send a Base object to the active stream of this client
///
/// with values of the url of the commit and the operation result
public override async UniTask Run()
{
var args = new SendWorkArgs()
{
message = "",
url = "",
client = this,
success = false
};
try
{
SpeckleUnity.Console.Log("Send started");
if (!IsValid())
{
args.message = "Invalid Client";
SpeckleUnity.Console.Warn($"{args.client}-" + args.message);
return args;
}
SpeckleUnity.Console.Log("Converting data");
if (_root == null && _data == null)
{
args.message = $"No objects were found in {nameof(SpeckleNode)} to send. Stopping call";
SpeckleUnity.Console.Warn(args.message);
return args;
}
_data ??= _root.SceneToData(converter, token);
if (_data == null)
{
args.message = "There is no data in this commit to send. Stopping call";
SpeckleUnity.Console.Warn(args.message);
return args;
}
var objectId = await SpeckleOps.Send(_client, _data, _stream.id, HandleProgress, HandleError);
var count = _data.GetTotalChildrenCount();
var commitId = await _client.CommitCreate(
new CommitCreateInput
{
objectId = objectId,
streamId = _stream.id,
branchName = branch.name,
message = _message.Valid() ? _message : $"Objects from Unity {count}",
sourceApplication = SpeckleUnity.APP,
totalChildrenCount = (int)count
});
args.success = true;
args.commitId = commitId;
args.message = $"Commit sent to {branch}! ({objectId})";
args.url = SpeckleUnity.GetUrl(false, _client.account.serverInfo.url, _stream.id, StreamWrapperType.Commit, commitId);
onDataSent?.Invoke(objectId);
}
catch (SpeckleException e)
{
SpeckleUnity.Console.Warn(e.Message);
}
finally
{
_data = null;
await UniTask.Yield();
HandleRefresh();
}
return args;
}
public event UnityAction onDataSent;
}
}