您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
471 行
16 KiB
471 行
16 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using System.Threading.Tasks;
|
|
using System.Net.Http.Headers;
|
|
using System.Text;
|
|
using COSXML;
|
|
using COSXML.Model.Object;
|
|
using COSXML.Transfer;
|
|
using MetaCity.BundleKit.Editor.Utils;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace MetaCity.BundleKit.Editor
|
|
{
|
|
public enum ServerType
|
|
{
|
|
None, // no need server
|
|
Official, // use official server
|
|
Customize // use customize server
|
|
}
|
|
|
|
public delegate void FailedCallBack();
|
|
|
|
public class MetacityBuildWindow : EditorWindow
|
|
{
|
|
|
|
private FailedCallBack _failedCallBack;
|
|
|
|
private Config _config = new Config();
|
|
private SerializedObject _portObject;
|
|
private SerializedProperty _portsProperty;
|
|
private SerializedProperty _envVerbsProperty;
|
|
|
|
private float _process = 0;
|
|
private string _processNote = "";
|
|
private bool _showProcessBar = false;
|
|
|
|
private bool _isPublishClick = false;
|
|
private PutObjectRequest _request;
|
|
private COSXMLUploadTask _uploadTask;
|
|
|
|
protected virtual void OnEnable()
|
|
{
|
|
_failedCallBack = CloseProcessBar;
|
|
|
|
_portObject = new SerializedObject(this);
|
|
_envVerbsProperty = _portObject.FindProperty("environmentVariables");
|
|
_portsProperty = _portObject.FindProperty("gameServerPorts");
|
|
|
|
_isPublishClick = false;
|
|
|
|
LoadConfig();
|
|
}
|
|
|
|
protected void OnDestroy() {
|
|
|
|
SaveConfig();
|
|
}
|
|
|
|
private void LoadConfig()
|
|
{
|
|
if (!Directory.Exists(Constants.TokenConfigPath))
|
|
{
|
|
Directory.CreateDirectory(Constants.TokenConfigPath);
|
|
}
|
|
var path=Path.Combine(Constants.TokenConfigPath,"config.json");
|
|
if (!System.IO.File.Exists(path))
|
|
{
|
|
_config = new Config();
|
|
var fs = System.IO.File.Create(path);
|
|
var json = JsonConvert.SerializeObject(_config);
|
|
byte[] array = Encoding.UTF8.GetBytes(json);
|
|
fs.Write(array);
|
|
fs.Close();
|
|
fs.Dispose();
|
|
return;
|
|
}
|
|
|
|
Config localConfig = JsonTools.FromFile<Config>(path);
|
|
if (localConfig != null)
|
|
{
|
|
_config = localConfig;
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("failed to deserialize config data");
|
|
}
|
|
}
|
|
|
|
private void SaveConfig()
|
|
{
|
|
if (!Directory.Exists(Constants.TokenConfigPath))
|
|
{
|
|
Directory.CreateDirectory(Constants.TokenConfigPath);
|
|
}
|
|
var path=Path.Combine(Constants.TokenConfigPath,"config.json");
|
|
if (!System.IO.File.Exists(path))
|
|
{
|
|
var fs = System.IO.File.Create(path);
|
|
var json = JsonConvert.SerializeObject(_config);
|
|
byte[] array = Encoding.UTF8.GetBytes(json);
|
|
fs.Write(array);
|
|
fs.Close();
|
|
fs.Dispose();
|
|
return;
|
|
}
|
|
JsonTools.ToFile(_config, path);
|
|
}
|
|
|
|
#region render UI
|
|
|
|
protected virtual void OnGUI()
|
|
{
|
|
EditorGUILayout.BeginVertical();
|
|
|
|
// RenderHelper();
|
|
//
|
|
// EditorGUILayout.Space(10);
|
|
//
|
|
// RenderPublishInfo();
|
|
//
|
|
// EditorGUILayout.Space(10);
|
|
|
|
RenderActions();
|
|
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
private void RenderHelper()
|
|
{
|
|
EditorGUILayout.HelpBox("\n" +
|
|
"Publish your cloudrendering build zip to metacity platform.\n" +
|
|
"\n"
|
|
, MessageType.Info);
|
|
}
|
|
|
|
private void RenderPublishInfo()
|
|
{
|
|
_config.templateName = EditorGUILayout.TextField(new GUIContent("Template Name"), _config.templateName);
|
|
_config.thumbnail = EditorGUILayout.TextField(new GUIContent("Template Thumbnail"), _config.thumbnail);
|
|
_config.memberLimit =
|
|
EditorGUILayout.IntSlider(new GUIContent("Template Member Limit"), _config.memberLimit, 5, 8);
|
|
|
|
EditorGUILayout.Space(10);
|
|
|
|
EditorGUILayout.LabelField("Template Description");
|
|
_config.description =
|
|
EditorGUILayout.TextArea(_config.description, EditorStyles.textArea, GUILayout.Height(50));
|
|
|
|
EditorGUILayout.Space(10);
|
|
|
|
EditorGUILayout.HelpBox("\n" +
|
|
"If you need to add/update build content, please export the build file in advance and compress it into zip.\n" +
|
|
"\n"
|
|
, MessageType.Warning);
|
|
_config.buildNeeded = EditorGUILayout.Toggle(new GUIContent("create/update Build"), _config.buildNeeded);
|
|
|
|
EditorGUI.indentLevel++;
|
|
}
|
|
|
|
private void RenderActions()
|
|
{
|
|
MetacityTokenWindow.Validate();
|
|
if (_isPublishClick)
|
|
{
|
|
_isPublishClick = false;
|
|
_showProcessBar = true;
|
|
Publish();
|
|
}
|
|
|
|
if (MetacityTokenWindow.IsAccessTokenValid)
|
|
{
|
|
if (GUILayout.Button($"Publish"))
|
|
{
|
|
_isPublishClick = true;
|
|
EditorUtility.SetDirty(this);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EditorGUILayout.HelpBox("\n" +
|
|
"Your access token is invalid. \n" +
|
|
"Please update your access token.\n" +
|
|
"\n", MessageType.Warning);
|
|
if (GUILayout.Button("Update Access Token"))
|
|
{
|
|
MetacityTokenWindow.OpenTokenWindow();
|
|
}
|
|
}
|
|
|
|
if (_showProcessBar)
|
|
{
|
|
Repaint();
|
|
if (EditorUtility.DisplayCancelableProgressBar("Upload File to COS", _processNote, _process))
|
|
{
|
|
_request?.Cancel();
|
|
_uploadTask?.Cancel();
|
|
CloseProcessBar();
|
|
Debug.Log("Publish canceled");
|
|
}
|
|
}
|
|
}
|
|
|
|
private async void Publish()
|
|
{
|
|
bool isValid = await MetacityClient.CheckAccessToken();
|
|
if (!isValid)
|
|
{
|
|
EditorUtility.SetDirty(this);
|
|
CloseProcessBar();
|
|
return;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(_config.templateId))
|
|
{
|
|
var result = await CreateNewTemplateByConfig(_failedCallBack);
|
|
if(!result) return;
|
|
}
|
|
else
|
|
{
|
|
var template = await MetacityClient.GetTemplateById(_config.templateId);
|
|
if (template == null)
|
|
{
|
|
var result = await CreateNewTemplateByConfig(_failedCallBack);
|
|
if(!result) return;
|
|
}
|
|
|
|
var templateResponse = await MetacityClient.UpdateTemplateById(template, _config.templateId, _config.templateName, _config.description,
|
|
_config.thumbnail, _config.buildId);
|
|
if (templateResponse == null)
|
|
{
|
|
CloseProcessBar();
|
|
}
|
|
}
|
|
|
|
SaveConfig();
|
|
Debug.Log("Template info has been updated.");
|
|
|
|
if (_config.buildNeeded)
|
|
{
|
|
var bundles = BuildEntry.LoadLastBuiltCatalog();
|
|
_config.assetBundles.Clear();
|
|
for (int i = 0; i < bundles.Count; i++)
|
|
{
|
|
_config.assetBundles.Add(new AssetBundle()
|
|
{
|
|
bundlePath = bundles[i].bundleLocalPath,
|
|
bundleName = bundles[i].bundleName,
|
|
bundleType = bundles[i].bundleType,
|
|
bundleHash = bundles[i].bundleHash,
|
|
bundleDependencies = bundles[i].bundleDependencies,
|
|
platform = bundles[i].bundlePlatform
|
|
});
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(_config.buildId))
|
|
{
|
|
var result = await CreateNewCloudrenderingByConfig(_failedCallBack);
|
|
if (!result) return;
|
|
}
|
|
else
|
|
{
|
|
var cr = await MetacityClient.GetCloudrenderingById(_config.buildId);
|
|
if (cr == null)
|
|
{
|
|
var result = await CreateNewCloudrenderingByConfig(_failedCallBack);
|
|
if (!result) return;
|
|
}
|
|
}
|
|
|
|
_processNote = "Start upload ...";
|
|
|
|
var isSuccess = await UploadBundles(_config.assetBundles, _failedCallBack);
|
|
if (!isSuccess)
|
|
{
|
|
return;
|
|
}
|
|
|
|
bool isPublish = await MetacityClient.Publish(
|
|
_config.templateId,
|
|
_config.buildId,
|
|
_config.serverType.ToString(),
|
|
_config.assetBundles
|
|
);
|
|
|
|
if (isPublish)
|
|
{
|
|
Debug.Log("Publish successful.");
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Publish Failed");
|
|
}
|
|
}
|
|
|
|
CloseProcessBar();
|
|
}
|
|
|
|
private void CloseProcessBar()
|
|
{
|
|
EditorUtility.ClearProgressBar();
|
|
_showProcessBar = false;
|
|
EditorUtility.SetDirty(this);
|
|
}
|
|
|
|
private async Task<bool> CreateNewTemplateByConfig(FailedCallBack callBack)
|
|
{
|
|
var template = await MetacityClient.CreateTemplate(_config.templateName, _config.description, _config.thumbnail);
|
|
if (template == null)
|
|
{
|
|
callBack.Invoke();
|
|
return false;
|
|
}
|
|
|
|
_config.templateId = template.id;
|
|
_config.templateName = template.name;
|
|
_config.description = template.description;
|
|
_config.thumbnail = template.banner;
|
|
|
|
return true;
|
|
}
|
|
|
|
private async Task<bool> CreateNewCloudrenderingByConfig(FailedCallBack callBack)
|
|
{
|
|
var cr = await MetacityClient.CreateCloudrendering(_config.templateName, _config.description,
|
|
_config.templateName);
|
|
|
|
if (cr == null)
|
|
{
|
|
callBack.Invoke();
|
|
return false;
|
|
}
|
|
|
|
_config.buildId = cr.id;
|
|
|
|
var template = await MetacityClient.GetTemplateById(_config.templateId);
|
|
|
|
if (template == null)
|
|
{
|
|
callBack.Invoke();
|
|
return false;
|
|
}
|
|
|
|
var templateResponse = await MetacityClient.UpdateTemplateById(template, _config.templateId, _config.templateName, _config.description,
|
|
_config.thumbnail, _config.buildId);
|
|
|
|
if (templateResponse == null)
|
|
{
|
|
callBack.Invoke();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private async void UpdateConfig()
|
|
{
|
|
_config.userId = await MetacityClient.GetUserId();
|
|
|
|
if(string.IsNullOrEmpty(_config.templateId)) return;
|
|
var template = await MetacityClient.GetTemplateById(_config.templateId);
|
|
_config.templateName = template.name;
|
|
_config.thumbnail = template.banner;
|
|
_config.description = template.description;
|
|
|
|
var assetBundles = await MetacityClient.GetAssetBundleByTemplateId(_config.templateId);
|
|
if (assetBundles.Count > 0)
|
|
{
|
|
_config.assetBundles.Clear();
|
|
foreach (var ab in assetBundles)
|
|
{
|
|
AssetBundle assetBundle = new AssetBundle()
|
|
{
|
|
bundleName = ab.bundleName,
|
|
bundlePath = ab.bundlePath,
|
|
bundleType = ab.bundleType,
|
|
bundleHash = ab.bundleHash,
|
|
bundleDependencies = ab.bundleDependencies,
|
|
platform = ab.platform,
|
|
extraInfo = ab.extraInfo
|
|
};
|
|
_config.assetBundles.Add(assetBundle);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Upload cos
|
|
|
|
private async Task<bool> UploadBundles(List<AssetBundle> assetBundles, FailedCallBack onFailed)
|
|
{
|
|
CosXmlConfig config = new CosXmlConfig.Builder()
|
|
.SetRegion("ap-shanghai")
|
|
.SetDebugLog(true)
|
|
.Build();
|
|
var cosXml = new CosXmlServer(config, null);
|
|
|
|
int totalCount = assetBundles.Count;
|
|
int count = 1;
|
|
|
|
foreach (var assetBundle in assetBundles)
|
|
{
|
|
if (!File.Exists(assetBundle.bundlePath))
|
|
{
|
|
onFailed.Invoke();
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
|
|
var cosPath = $"{assetBundle.bundleName}-{assetBundle.bundleHash}";
|
|
string requestSignURL = await MetacityClient.GetUploadUrlAsync(cosPath);
|
|
_request = new PutObjectRequest(null, null, assetBundle.bundlePath);
|
|
_request.RequestURLWithSign = requestSignURL;
|
|
_request.SetCosProgressCallback(delegate(long completed, long total)
|
|
{
|
|
_process = (float) completed / total;
|
|
_processNote = string.Format("Upload({0}/{1})\n" +
|
|
"uploaded {2} of {3} bytes. {4:##.##} % complete...",
|
|
count,
|
|
totalCount,
|
|
completed,
|
|
total,
|
|
completed * 100.0 / total);
|
|
});
|
|
PutObjectResult result = cosXml.PutObject(_request);
|
|
|
|
if (result.IsSuccessful())
|
|
{
|
|
count++;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
catch (COSXML.CosException.CosClientException clientEx)
|
|
{
|
|
Debug.LogException(clientEx);
|
|
}
|
|
catch (COSXML.CosException.CosServerException serverEx)
|
|
{
|
|
Debug.LogException(serverEx);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
private async Task<bool> PublishAssetBundles(List<AssetBundle> assetBundles)
|
|
{
|
|
bool upload = await UploadBundles(assetBundles, _failedCallBack);
|
|
if (upload)
|
|
{
|
|
return await MetacityClient.PublishAssetBundles(assetBundles);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|