initial upload
This commit is contained in:
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3e21c62030a49848f0630c7404e2d7f
|
||||
timeCreated: 1729858716
|
||||
@ -0,0 +1,72 @@
|
||||
using Convai.Scripts.Editor.Setup.ServerAnimation.Model;
|
||||
using Convai.Scripts.Editor.Setup.ServerAnimation.View;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace Convai.Scripts.Editor.Setup.ServerAnimation.Controller {
|
||||
|
||||
internal class ServerAnimationItemController {
|
||||
internal ServerAnimationItemController( ServerAnimationItemView view, ServerAnimationItemData itemData, ServerAnimationPageController controller ) {
|
||||
Data = itemData;
|
||||
View = view;
|
||||
Controller = controller;
|
||||
view.UpdateToggleState( Data.IsSelected, Data.ItemResponse.Status );
|
||||
view.SetAnimationName( Data.ItemResponse.AnimationName );
|
||||
Data.CanBeSelected = Data.IsSuccess;
|
||||
view.Card.RegisterCallback<ClickEvent>( OnCardClicked );
|
||||
UpdateThumbnail();
|
||||
}
|
||||
|
||||
internal ServerAnimationItemData Data { get; }
|
||||
private ServerAnimationItemView View { get; }
|
||||
|
||||
private ServerAnimationPageController Controller { get; }
|
||||
|
||||
private async void UpdateThumbnail() {
|
||||
|
||||
if( Controller.Data.Thumbnails.TryGetValue( Data.ItemResponse.AnimationID, out Texture2D cacheTexture2D ) ) {
|
||||
View.Thumbnail.style.backgroundImage = new StyleBackground {
|
||||
value = new Background {
|
||||
texture = cacheTexture2D
|
||||
}
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ( string.IsNullOrEmpty( Data.ItemResponse.ThumbnailURL ) ) return;
|
||||
Texture2D texture = await ServerAnimationAPI.GetThumbnail( Data.ItemResponse.ThumbnailURL );
|
||||
View.Thumbnail.style.backgroundImage = new StyleBackground {
|
||||
value = new Background {
|
||||
texture = texture
|
||||
}
|
||||
};
|
||||
Controller.Data.Thumbnails.Add( Data.ItemResponse.AnimationID, texture );
|
||||
}
|
||||
|
||||
~ServerAnimationItemController() {
|
||||
View.Card.UnregisterCallback<ClickEvent>( OnCardClicked );
|
||||
}
|
||||
|
||||
private void OnCardClicked( ClickEvent evt ) {
|
||||
if ( !Data.CanBeSelected ) return;
|
||||
ToggleSelect();
|
||||
}
|
||||
|
||||
internal void UpdateCanBeSelected( bool newValue ) {
|
||||
Data.CanBeSelected = newValue;
|
||||
}
|
||||
|
||||
internal void Reset() {
|
||||
Data.CanBeSelected = Data.IsSuccess;
|
||||
Data.IsSelected = false;
|
||||
View.UpdateToggleState( Data.IsSelected, Data.ItemResponse.Status );
|
||||
}
|
||||
|
||||
private void ToggleSelect() {
|
||||
Data.IsSelected = !Data.IsSelected;
|
||||
View.UpdateToggleState( Data.IsSelected, Data.ItemResponse.Status );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5430fefd15c7f04d81ae43d70bf5768
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,166 @@
|
||||
using Convai.Scripts.Editor.Setup.ServerAnimation.Model;
|
||||
using Convai.Scripts.Editor.Setup.ServerAnimation.View;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace Convai.Scripts.Editor.Setup.ServerAnimation.Controller
|
||||
{
|
||||
|
||||
internal class ServerAnimationPageController
|
||||
{
|
||||
private readonly ServerAnimationPageView _ui;
|
||||
|
||||
|
||||
internal ServerAnimationPageController(ServerAnimationPageView view)
|
||||
{
|
||||
Data = new ServerAnimationPageData();
|
||||
_ui = view;
|
||||
if (ConvaiSDKSetupEditorWindow.IsApiKeySet)
|
||||
{
|
||||
InjectData();
|
||||
}
|
||||
else
|
||||
{
|
||||
ConvaiSDKSetupEditorWindow.OnAPIKeySet += () =>
|
||||
{
|
||||
if (ConvaiSDKSetupEditorWindow.IsApiKeySet)
|
||||
{
|
||||
InjectData();
|
||||
}
|
||||
};
|
||||
}
|
||||
_ui.RefreshBtn.clicked += RefreshBtnOnClicked;
|
||||
_ui.ImportBtn.clicked += ImportBtnOnClicked;
|
||||
_ui.NextPageBtn.clicked += NextPageBtnOnClicked;
|
||||
_ui.PreviousPageBtn.clicked += PreviousPageBtnOnClicked;
|
||||
}
|
||||
|
||||
|
||||
internal ServerAnimationPageData Data { get; }
|
||||
private List<ServerAnimationItemController> Items { get; set; } = new();
|
||||
|
||||
|
||||
~ServerAnimationPageController()
|
||||
{
|
||||
_ui.RefreshBtn.clicked -= RefreshBtnOnClicked;
|
||||
_ui.ImportBtn.clicked -= ImportBtnOnClicked;
|
||||
}
|
||||
|
||||
private async void ImportBtnOnClicked()
|
||||
{
|
||||
List<ServerAnimationItemResponse> selectedAnimations = Items.FindAll(x => x.Data.IsSelected).Select(x => x.Data.ItemResponse).ToList();
|
||||
if (selectedAnimations.Count == 0)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "No animations selected!", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable Refresh and Import buttons
|
||||
_ui.RefreshBtn.SetEnabled(false);
|
||||
_ui.ImportBtn.SetEnabled(false);
|
||||
|
||||
Items.ForEach(x => x.UpdateCanBeSelected(false));
|
||||
|
||||
try
|
||||
{
|
||||
Task importTask = ServerAnimationService.ImportAnimations(selectedAnimations);
|
||||
|
||||
// Show progress bar
|
||||
float progress = 0f;
|
||||
while (!importTask.IsCompleted)
|
||||
{
|
||||
EditorUtility.DisplayProgressBar("Importing Animations", $"Progress: {progress:P0}", progress);
|
||||
await Task.Delay(100); // Update every 100ms
|
||||
progress += 0.01f; // Increment progress (you may want to adjust this based on actual progress)
|
||||
if (progress > 0.99f)
|
||||
progress = Random.value; // Set it to random value
|
||||
}
|
||||
|
||||
// Ensure task is completed and handle any exceptions
|
||||
await importTask;
|
||||
|
||||
EditorUtility.DisplayProgressBar("Importing Animations", "Complete!", 1f);
|
||||
await Task.Delay(500); // Show 100% for half a second
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Import Error", $"An error occurred during import: {e.Message}", "OK");
|
||||
}
|
||||
finally
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
|
||||
// Re-enable Refresh and Import buttons
|
||||
_ui.RefreshBtn.SetEnabled(true);
|
||||
_ui.ImportBtn.SetEnabled(true);
|
||||
|
||||
Items.ForEach(x => x.Reset());
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshBtnOnClicked()
|
||||
{
|
||||
InjectData();
|
||||
}
|
||||
|
||||
private async void InjectData()
|
||||
{
|
||||
_ui.PreviousPageBtn.SetEnabled(false);
|
||||
_ui.NextPageBtn.SetEnabled(false);
|
||||
_ui.RefreshBtn.SetEnabled(false);
|
||||
_ui.ImportBtn.SetEnabled(false);
|
||||
List<ServerAnimationItemData> list = new();
|
||||
await foreach (ServerAnimationItemResponse serverAnimationItemResponse in Data.GetAnimationItems())
|
||||
list.Add(new ServerAnimationItemData
|
||||
{
|
||||
ItemResponse = serverAnimationItemResponse
|
||||
});
|
||||
list = list.OrderBy(item =>
|
||||
{
|
||||
return item.ItemResponse.Status.ToLower() switch
|
||||
{
|
||||
"success" => 0,
|
||||
"pending" or "processing" => 1,
|
||||
"failed" => 2,
|
||||
_ => 3
|
||||
};
|
||||
}).ToList();
|
||||
Items = _ui.ShowAnimationList(list);
|
||||
_ui.PreviousPageBtn.SetEnabled(Data.CurrentPage > 1);
|
||||
_ui.NextPageBtn.SetEnabled(Data.CurrentPage < Data.TotalPages - 1);
|
||||
_ui.RefreshBtn.SetEnabled(true);
|
||||
_ui.ImportBtn.SetEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
private void PreviousPageBtnOnClicked()
|
||||
{
|
||||
Data.CurrentPage--;
|
||||
Data.CurrentPage = Math.Max(Data.CurrentPage, 1);
|
||||
_ui.PreviousPageBtn.SetEnabled(false);
|
||||
_ui.NextPageBtn.SetEnabled(false);
|
||||
InjectData();
|
||||
}
|
||||
|
||||
private void NextPageBtnOnClicked()
|
||||
{
|
||||
if (Data.CurrentPage < Data.TotalPages - 1)
|
||||
{
|
||||
Data.CurrentPage++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Data.CurrentPage = 1;
|
||||
}
|
||||
_ui.PreviousPageBtn.SetEnabled(false);
|
||||
_ui.NextPageBtn.SetEnabled(false);
|
||||
InjectData();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cde2cc1e43134111918c555b5cb19ae6
|
||||
timeCreated: 1729858864
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 972b84739ae24eee9b6c60299a9f554e
|
||||
timeCreated: 1729858708
|
||||
@ -0,0 +1,13 @@
|
||||
namespace Convai.Scripts.Editor.Setup.ServerAnimation.Model {
|
||||
|
||||
internal class ServerAnimationItemData {
|
||||
public bool CanBeSelected;
|
||||
public bool IsSelected;
|
||||
public ServerAnimationItemResponse ItemResponse;
|
||||
|
||||
public bool IsPending => ItemResponse.Status == "pending";
|
||||
public bool IsSuccess => ItemResponse.Status == "success";
|
||||
public bool IsFailed => ItemResponse.Status == "failed";
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5059b3cdb59a8274ab89a0a0c3877a1e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Convai.Scripts.Editor.Setup.ServerAnimation.Model {
|
||||
|
||||
internal class ServerAnimationPageData {
|
||||
private ServerAnimationListResponse _animationListResponse;
|
||||
|
||||
public Dictionary<string, Texture2D> Thumbnails { get; } = new();
|
||||
|
||||
public int TotalPages => _animationListResponse.TotalPages;
|
||||
|
||||
public int CurrentPage { get; set; } = 1;
|
||||
|
||||
public async IAsyncEnumerable<ServerAnimationItemResponse> GetAnimationItems() {
|
||||
if ( !ConvaiAPIKeySetup.GetAPIKey( out string apiKey ) ) yield break;
|
||||
_animationListResponse = await ServerAnimationAPI.GetAnimationList( apiKey, CurrentPage );
|
||||
if ( _animationListResponse == null || _animationListResponse.Animations == null ) yield break;
|
||||
foreach ( ServerAnimationItemResponse serverAnimationItemResponse in _animationListResponse.Animations ) yield return serverAnimationItemResponse;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b5384b14e205e34e98769b8d2e38030
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,191 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Convai.Scripts.Editor.Setup.ServerAnimation
|
||||
{
|
||||
|
||||
public static class ServerAnimationAPI
|
||||
{
|
||||
private const string BASE_URL = "https://api.convai.com/";
|
||||
private const string GET_ANIMATION_LIST = "animations/list";
|
||||
private const string GET_ANIMATION = "animations/get";
|
||||
|
||||
public static async Task<ServerAnimationListResponse> GetAnimationList(string apiKey, int page)
|
||||
{
|
||||
HttpClient client = CreateHttpClient(apiKey);
|
||||
HttpContent content = CreateHttpContent(new Dictionary<string, object> {
|
||||
{ "status", "success" },
|
||||
{ "generate_signed_urls", true },
|
||||
{ "page", page }
|
||||
});
|
||||
string response = await SendPostRequestAsync(GetEndPoint(GET_ANIMATION_LIST), client, content);
|
||||
ServerAnimationListResponse serverAnimationListResponse = JsonConvert.DeserializeObject<ServerAnimationListResponse>(response);
|
||||
return serverAnimationListResponse;
|
||||
}
|
||||
|
||||
public static async Task<bool> DownloadAnimation(string animationID, string apiKey, string saveDirectory, string newFileName)
|
||||
{
|
||||
HttpClient client = CreateHttpClient(apiKey);
|
||||
HttpContent content = CreateHttpContent(new Dictionary<string, object> {
|
||||
{ "animation_id", animationID },
|
||||
{ "generate_upload_video_urls", false }
|
||||
});
|
||||
string response = await SendPostRequestAsync(GetEndPoint(GET_ANIMATION), client, content);
|
||||
dynamic animation = JsonConvert.DeserializeObject(response);
|
||||
if (animation == null)
|
||||
return false;
|
||||
string gcpLink = animation.animation.fbx_gcp_file;
|
||||
|
||||
using HttpClient downloadClient = new();
|
||||
try
|
||||
{
|
||||
byte[] fileBytes = await downloadClient.GetByteArrayAsync(gcpLink);
|
||||
|
||||
// Ensure the save directory exists
|
||||
if (!Directory.Exists(saveDirectory))
|
||||
Directory.CreateDirectory(saveDirectory);
|
||||
|
||||
// Construct the full file path with the new name and .fbx extension
|
||||
string filePath = Path.Combine(saveDirectory, $"{newFileName}.fbx");
|
||||
int counter = 1;
|
||||
|
||||
while (File.Exists(filePath))
|
||||
{
|
||||
filePath = Path.Combine(saveDirectory, $"{newFileName}_{counter}.fbx");
|
||||
counter++;
|
||||
}
|
||||
|
||||
// Write the file
|
||||
await File.WriteAllBytesAsync(filePath, fileBytes);
|
||||
string relativePath = filePath.Substring(Application.dataPath.Length + 1).Replace('\\', '/');
|
||||
relativePath = "Assets/" + relativePath;
|
||||
//AssetDatabase.ImportAsset(relativePath);
|
||||
AssetDatabase.Refresh();
|
||||
ModelImporter importer = AssetImporter.GetAtPath(relativePath) as ModelImporter;
|
||||
if (importer != null)
|
||||
{
|
||||
importer.animationType = ModelImporterAnimationType.Human;
|
||||
importer.importAnimatedCustomProperties = true;
|
||||
importer.materialLocation = ModelImporterMaterialLocation.External;
|
||||
importer.SaveAndReimport();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"Error downloading file: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<Texture2D> GetThumbnail(string thumbnailURL)
|
||||
{
|
||||
using HttpClient client = new();
|
||||
try
|
||||
{
|
||||
byte[] fileBytes = await client.GetByteArrayAsync(thumbnailURL);
|
||||
Texture2D texture = new(256, 256);
|
||||
texture.LoadImage(fileBytes);
|
||||
return texture;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"Error downloading thumbnail: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static string GetEndPoint(string endpoint)
|
||||
{
|
||||
return BASE_URL + endpoint;
|
||||
}
|
||||
|
||||
|
||||
private static HttpClient CreateHttpClient(string apiKey)
|
||||
{
|
||||
if (string.IsNullOrEmpty(apiKey))
|
||||
return new HttpClient();
|
||||
HttpClient httpClient = new()
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(30),
|
||||
DefaultRequestHeaders = {
|
||||
Accept = {
|
||||
new MediaTypeWithQualityHeaderValue( "application/json" )
|
||||
}
|
||||
}
|
||||
};
|
||||
httpClient.DefaultRequestHeaders.Add("CONVAI-API-KEY", apiKey);
|
||||
httpClient.DefaultRequestHeaders.Add("Source", "convaiUI");
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
private static HttpContent CreateHttpContent(Dictionary<string, object> dataToSend)
|
||||
{
|
||||
// Serialize the dictionary to JSON
|
||||
string json = JsonConvert.SerializeObject(dataToSend);
|
||||
|
||||
// Convert JSON to HttpContent
|
||||
return new StringContent(json, Encoding.UTF8, "application/json");
|
||||
}
|
||||
|
||||
private static HttpContent CreateHttpContent(string json)
|
||||
{
|
||||
// Convert JSON to HttpContent
|
||||
return new StringContent(json, Encoding.UTF8, "application/json");
|
||||
}
|
||||
|
||||
private static async Task<string> SendPostRequestAsync(string endpoint, HttpClient httpClient, HttpContent content)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpResponseMessage response = await httpClient.PostAsync(endpoint, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
string responseContent = await response.Content.ReadAsStringAsync();
|
||||
return responseContent;
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
Debug.Log($"Request to {endpoint} failed: {e.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Serializable]
|
||||
public class ServerAnimationListResponse
|
||||
{
|
||||
[JsonProperty("animations")] public List<ServerAnimationItemResponse> Animations { get; private set; }
|
||||
[JsonProperty("transaction_id")] public string TransactionID { get; private set; }
|
||||
[JsonProperty("total_pages")] public int TotalPages { get; private set; }
|
||||
[JsonProperty("page")] public int CurrentPage { get; private set; }
|
||||
[JsonProperty("total")] public int TotalItems { get; private set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ServerAnimationItemResponse
|
||||
{
|
||||
public ServerAnimationItemResponse(string animationID, string animationName, string status, string thumbnailURL)
|
||||
{
|
||||
AnimationID = animationID;
|
||||
AnimationName = animationName;
|
||||
Status = status;
|
||||
ThumbnailURL = thumbnailURL;
|
||||
}
|
||||
|
||||
[JsonProperty("animation_id")] public string AnimationID { get; private set; }
|
||||
[JsonProperty("animation_name")] public string AnimationName { get; private set; }
|
||||
[JsonProperty("status")] public string Status { get; private set; }
|
||||
[JsonProperty("thumbnail_gcp_file")] public string ThumbnailURL { get; private set; }
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3163b8ff3c034b878e606e4924a02172
|
||||
timeCreated: 1734419624
|
||||
@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Convai.Scripts.Editor.Setup.ServerAnimation {
|
||||
|
||||
internal static class ServerAnimationService {
|
||||
private const string DIRECTORY_SAVE_KEY = "CONVAI_SERVER_ANIMATION_SAVE_PATH";
|
||||
|
||||
public static async Task ImportAnimations( List<ServerAnimationItemResponse> animations ) {
|
||||
if ( !ConvaiAPIKeySetup.GetAPIKey( out string apiKey ) ) return;
|
||||
if ( animations.Count == 0 ) {
|
||||
EditorUtility.DisplayDialog( "Import Animation Process", "Cannot start import process since no animations are selected", "Ok" );
|
||||
return;
|
||||
}
|
||||
|
||||
string savePath = UpdateAnimationSavePath();
|
||||
if ( string.IsNullOrEmpty( savePath ) ) {
|
||||
EditorUtility.DisplayDialog( "Failed", "Import Operation Cancelled", "Ok" );
|
||||
return;
|
||||
}
|
||||
|
||||
List<string> allAnimations = animations.Select( x => x.AnimationName ).ToList();
|
||||
List<string> successfulImports = new();
|
||||
foreach ( ServerAnimationItemResponse anim in animations ) {
|
||||
bool result = await ServerAnimationAPI.DownloadAnimation( anim.AnimationID, apiKey, savePath, anim.AnimationName );
|
||||
if ( result ) successfulImports.Add( anim.AnimationName );
|
||||
}
|
||||
|
||||
LogResult( successfulImports, allAnimations );
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
private static void LogResult( List<string> successfulImports, List<string> animPaths ) {
|
||||
string dialogMessage = $"Successfully Imported{Environment.NewLine}";
|
||||
successfulImports.ForEach( x => dialogMessage += x + Environment.NewLine );
|
||||
List<string> unSuccessFullImports = animPaths.Except( successfulImports ).ToList();
|
||||
if ( unSuccessFullImports.Count > 0 ) {
|
||||
dialogMessage += $"Could not import{Environment.NewLine}";
|
||||
unSuccessFullImports.ForEach( x => dialogMessage += x + Environment.NewLine );
|
||||
}
|
||||
|
||||
EditorUtility.DisplayDialog( "Import Animation Result", dialogMessage, "Ok" );
|
||||
}
|
||||
|
||||
private static string UpdateAnimationSavePath() {
|
||||
string selectedPath;
|
||||
string currentPath = EditorPrefs.GetString( DIRECTORY_SAVE_KEY, Application.dataPath );
|
||||
while ( true ) {
|
||||
selectedPath = EditorUtility.OpenFolderPanel( "Select folder within project", currentPath, "" );
|
||||
if ( string.IsNullOrEmpty( selectedPath ) ) {
|
||||
selectedPath = string.Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !IsSubfolder( selectedPath, Application.dataPath ) ) {
|
||||
EditorUtility.DisplayDialog( "Invalid Folder Selected", "Please select a folder within the project", "Ok" );
|
||||
continue;
|
||||
}
|
||||
|
||||
EditorPrefs.SetString( DIRECTORY_SAVE_KEY, selectedPath );
|
||||
break;
|
||||
}
|
||||
|
||||
return selectedPath;
|
||||
}
|
||||
|
||||
private static bool IsSubfolder( string pathA, string pathB ) {
|
||||
// Get full paths to handle any relative path issues
|
||||
string fullPathA = Path.GetFullPath( pathA );
|
||||
string fullPathB = Path.GetFullPath( pathB );
|
||||
|
||||
// Create URI objects for the paths
|
||||
Uri uriA = new(fullPathA);
|
||||
Uri uriB = new(fullPathB);
|
||||
|
||||
// Check if pathA is under pathB
|
||||
return uriB.IsBaseOf( uriA );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36e144b353be7034ab9b83f184c24288
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1d8ed8a29394a5a8d502a4e32314afd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,66 @@
|
||||
using Convai.Scripts.Editor.Setup.ServerAnimation.Controller;
|
||||
using Convai.Scripts.Editor.Setup.ServerAnimation.Model;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace Convai.Scripts.Editor.Setup.ServerAnimation.View {
|
||||
|
||||
internal class ServerAnimationItemView : VisualElement {
|
||||
private readonly Color _animationProcessFailure = new(1f, 131f / 255f, 131f / 255f, 1f); //rgb(255,131,131)
|
||||
private readonly Color _animationProcessPending = new(1f, 245f / 255f, 116f / 255f, 1f);
|
||||
private readonly Color _animationProcessSuccess = new(0, 0, 0, 0.25f);
|
||||
private readonly Color _selectedColor = new(11f / 255, 96f / 255, 73f / 255);
|
||||
internal readonly ServerAnimationItemController Controller;
|
||||
private Label _nameLabel;
|
||||
|
||||
internal ServerAnimationItemView( ServerAnimationItemData itemData, ServerAnimationPageController controller ) {
|
||||
AddUI();
|
||||
InitializeUI();
|
||||
Controller = new ServerAnimationItemController( this, itemData, controller );
|
||||
}
|
||||
|
||||
public VisualElement Card { get; private set; }
|
||||
public VisualElement Thumbnail { get; private set; }
|
||||
|
||||
private void InitializeUI() {
|
||||
_nameLabel = contentContainer.Q<Label>( "name" );
|
||||
Card = contentContainer.Q<VisualElement>( "server-animation-card" );
|
||||
Thumbnail = Card.Q<VisualElement>( "thumbnail" );
|
||||
}
|
||||
|
||||
|
||||
internal void SetAnimationName( string animationName ) {
|
||||
_nameLabel.text = animationName;
|
||||
}
|
||||
|
||||
internal void UpdateToggleState( bool isSelected, string status ) {
|
||||
Card.style.borderTopColor = GetColor( isSelected, status );
|
||||
Card.style.borderBottomColor = GetColor( isSelected, status );
|
||||
Card.style.borderLeftColor = GetColor( isSelected, status );
|
||||
Card.style.borderRightColor = GetColor( isSelected, status );
|
||||
}
|
||||
|
||||
private Color GetColor( bool isSelected, string status ) {
|
||||
if ( isSelected ) return _selectedColor;
|
||||
return status switch {
|
||||
"success" => _animationProcessSuccess,
|
||||
"pending" => _animationProcessPending,
|
||||
"processing" => _animationProcessPending,
|
||||
"failed" => _animationProcessFailure,
|
||||
_ => Color.white
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private void AddUI() {
|
||||
VisualTreeAsset treeAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>( "Assets/Convai/Art/UI/Editor/server-animation-card.uxml" );
|
||||
TemplateContainer child = treeAsset.CloneTree();
|
||||
child.style.width = new Length( 100, LengthUnit.Percent );
|
||||
child.style.height = new Length( 100, LengthUnit.Percent );
|
||||
child.style.justifyContent = Justify.Center;
|
||||
contentContainer.Add( child );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: effbae7421a30734d9dea85f5bda3927
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
using Convai.Scripts.Editor.Setup.ServerAnimation.Controller;
|
||||
using Convai.Scripts.Editor.Setup.ServerAnimation.Model;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace Convai.Scripts.Editor.Setup.ServerAnimation.View {
|
||||
|
||||
internal class ServerAnimationPageView {
|
||||
private ServerAnimationPageController _controller;
|
||||
private VisualElement _listContainer;
|
||||
|
||||
private VisualElement _uiContainer;
|
||||
|
||||
internal Button ImportBtn;
|
||||
internal Button NextPageBtn;
|
||||
internal Button PreviousPageBtn;
|
||||
internal Button RefreshBtn;
|
||||
|
||||
|
||||
internal ServerAnimationPageView( VisualElement root ) {
|
||||
Initialize( root );
|
||||
_controller = new ServerAnimationPageController( this );
|
||||
}
|
||||
|
||||
|
||||
private void Initialize( VisualElement root ) {
|
||||
_uiContainer = root.Q<VisualElement>( "content-container" ).Q<VisualElement>( "server-anim" );
|
||||
_listContainer = _uiContainer.Q<ScrollView>( "container" ).Q<VisualElement>( "grid" );
|
||||
RefreshBtn = _uiContainer.Q<Button>( "refresh-btn" );
|
||||
ImportBtn = _uiContainer.Q<Button>( "import-btn" );
|
||||
NextPageBtn = _uiContainer.Q<Button>( "next-page-btn" );
|
||||
PreviousPageBtn = _uiContainer.Q<Button>( "previous-page-btn" );
|
||||
}
|
||||
|
||||
|
||||
internal List<ServerAnimationItemController> ShowAnimationList( List<ServerAnimationItemData> datas ) {
|
||||
List<ServerAnimationItemController> cards = new();
|
||||
_listContainer.Clear();
|
||||
foreach ( ServerAnimationItemData data in datas ) {
|
||||
ServerAnimationItemView animationItemView = new(data, _controller);
|
||||
cards.Add( animationItemView.Controller );
|
||||
_listContainer.Add( animationItemView );
|
||||
}
|
||||
|
||||
_listContainer.MarkDirtyRepaint();
|
||||
return cards;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff9e296b4c9673e4abf0b96166a17fef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user