using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.Serialization.Json; using System.Text; using System.Threading.Tasks; using Cysharp.Threading.Tasks; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using UnityEngine; using UnityEngine.UI; using VketCloudGUITools.Runtime; using VketCloudGUITools.Utilities; namespace VketCloudGUITools.Serialization { public class VCCanvasImporter { /// /// Import用タスクを生成します。 /// /// /// /// 進捗表示用オブザーバー /// public static async UniTask ImportAsync(string jsonData, Transform root, VCCanvasImporterSettings settings, Action getProgressObserver = null) { var progress = new ImportProgress("Importing Canvas", string.Empty, 1f); if (getProgressObserver != null) getProgressObserver(progress); return await DoImportAsync(progress, jsonData, root, settings); } /// /// Import処理を行います。 /// /// 進捗 /// CanvasJSONテキスト /// 生成されたCanvasのRoot /// インポート設定 /// static async UniTask DoImportAsync(ImportProgress progress, string jsonData, Transform root, VCCanvasImporterSettings settings) { VCCanvasDef canvasDef = null; try { // Jsonを読んでデシリアライズ用のインスタンスを生成する canvasDef = JsonConvert.DeserializeObject(jsonData); } catch (Exception e) { settings.logger.LogException(e); // Innerにしたいが、ログが異様に長くて読みにくいので要約を投げる throw new Exception("JSON Parse Failed."); } // Json読み取りに成功したので、Canvasを組み立てる var canvas = await ImportCanvasAsync(CreateChildProgress("Canvas", string.Empty, progress, 1f), canvasDef, root, settings); progress.Done(); return canvas; } /// /// Canvasをインポートする /// /// 進捗 /// キャンバス構造定義 /// キャンバス出力先ルート /// インポート設定 /// static async UniTask ImportCanvasAsync(ImportProgress progress, VCCanvasDef canvasDef, Transform root, VCCanvasImporterSettings settings) { var canvas = VCFactory.CreateCanvas(settings.determinateCanvasName()); var unityCanvas = canvas.GetComponent(); unityCanvas.renderMode = settings.canvasRenderMode; // Canvas親設定 canvas.transform.SetParent(root, worldPositionStays: false); canvas.transform.localPosition = Vector3.zero; canvas.transform.localRotation = Quaternion.identity; // 定義読み取り canvas.Version = canvasDef.Version; canvas.Z = canvasDef.Z; canvas.CanvasType = settings.determinateCanvasType(); // 読み取った数値をUnityに反映(座標系の変換など) canvas.ApplyValues(); // Scripts読み取り foreach (var script in canvasDef.Scripts) { await settings.onImportHeliodorScript(script, progress, settings); canvas.Scripts.Add(await settings.onLoadHeliodorScript(script, progress, settings)); } // LayerList個別に読み取り var layerDefs = canvasDef.Layout; float progressWeight = 1f / layerDefs.Count; for (int i = 0; i < layerDefs.Count; i++) { await ImportLayerListAsync(CreateChildProgress("LayerList", $"Element [{i}]", progress, progressWeight), layerDefs[i], canvas, settings); } progress.Done(); return canvas; } /// /// LayerListをインポートする /// /// 進捗 /// レイヤー構造定義 /// 親キャンバス /// インポート設定 /// public static async UniTask ImportLayerListAsync(ImportProgress progress, VCLayerDef layerDef, VCCanvas canvas, VCCanvasImporterSettings settings) { var layerList = VCFactory.CreateLayerList(layerDef.Name, canvas.CanvasType); layerList.transform.SetParent(canvas.transform, false); layerList.Show = layerDef.Show; layerList.Z = layerDef.Z; layerList.SpreadMode = layerDef.SpreadMode; layerList.AutoLoading = layerDef.AutoLoading; layerList.Components = layerDef.Components; if (layerDef.Mask != null) { await ImportLayerMaskAsync(progress, layerList, layerDef, settings); } // レイヤー内GUIコンテンツ別に読み取り var contentDefs = layerDef.Gui; float progressWeight = 1f / contentDefs.Count; for (int i = 0; i < contentDefs.Count; i++) { await ImportGUIContentAsync(CreateChildProgress("GUIContent", $"Element {i}", progress, progressWeight), contentDefs[i], layerList, settings); } progress.Done(); return layerList; } /// /// レイヤー内GUIコンテンツをインポートする /// /// 進捗 /// GUIコンテンツ構造定義 /// 親レイヤー /// インポート設定 /// static async UniTask ImportGUIContentAsync(ImportProgress progress, VCContentDef guiContentDef, VCLayerList layerList, VCCanvasImporterSettings settings) { switch (guiContentDef.Type) { case "button": await ImportButtonAsync(CreateChildProgress("Button", string.Empty, progress, 1f), guiContentDef, layerList, settings); break; case "image": await ImportImageAsync(CreateChildProgress("Image", string.Empty, progress, 1f), guiContentDef, layerList, settings); break; case "text": ImportText(CreateChildProgress("Text", string.Empty, progress, 1f), guiContentDef, layerList, settings); break; case "Slider": await ImportSliderAsync(CreateChildProgress("Slider", string.Empty, progress, 1f), guiContentDef, layerList, settings); break; case "html": ImportHtml(CreateChildProgress("Html", string.Empty, progress, 1f), guiContentDef, layerList, settings); break; default: { var childProgress = CreateChildProgress("Unknown", string.Empty, progress, 1f); CheckTypeUnknown(guiContentDef, layerList, settings); childProgress.Done(); } break; } progress.Done(); } static void CheckTypeUnknown(VCContentDef guiContentDef, VCLayerList layerList, VCCanvasImporterSettings settings) { // コメント行のみ専用処理。コメント行は(Jsonに直接、人間が書くため)Type情報が満たされないので、Type不明時に判断する if (!string.IsNullOrEmpty(guiContentDef.Comment)) { VCFactory.CreateComment(guiContentDef.Comment, layerList.transform); } else { // Type不明なので、代用としてUnknown出力する ImportUnknown(guiContentDef, layerList, settings); } } /// /// 不明なGUIコンテンツのインポート /// /// GUIコンテンツ構造定義 /// 親レイヤー /// インポート設定 static void ImportUnknown(VCContentDef guiContentDef, VCLayerList layerList, VCCanvasImporterSettings settings) { VCUnknown unknown = VCFactory.CreateUnknown(guiContentDef.Name); // 基本的にNameは実行時の構造解析に、Typeはインポート時の構造解析に必須 // 無いときは強く警告する if (guiContentDef.Name == null) { unknown.name = "###NAME_BROKEN###"; settings.logger.LogWarning(nameof(VCCanvasImporter), $"{unknown}[Unknown] Name要素が破損してるため、名前が決定できません。", unknown); } if (guiContentDef.Type == null) { settings.logger.LogWarning(nameof(VCCanvasImporter), $"{unknown}[Unknown] Type要素が破損してるため、種類が決定できません。", unknown); } // その他のパラメータは、読めたら幸運程度に考えて取り込む unknown.ToJson(guiContentDef, settings.logger); ImportTransform(unknown.GetComponent(), guiContentDef, layerList, settings); } /// /// スライダーをインポートする /// /// 進捗 /// GUIコンテンツ構造定義 /// 親レイヤー /// インポート設定 /// static async UniTask ImportSliderAsync(ImportProgress progress, VCContentDef guiContentDef, VCLayerList layerList, VCCanvasImporterSettings settings) { var slider = VCFactory.CreateSlider(guiContentDef.Name); float progressWeight = 1f / 8f; if (guiContentDef.ParamSlider != null) { // Import Base await ImportAssetSpriteAsync(CreateChildProgress("Import Sprite", "Slider.Base", progress, progressWeight), guiContentDef.ParamSlider.Base, settings); // Load Base slider.BaseSprite = await LoadAssetSpriteAsync(CreateChildProgress("Load Sprite", "Slider.Base", progress, progressWeight), guiContentDef.ParamSlider.Base, settings); // Import Front await ImportAssetSpriteAsync(CreateChildProgress("Import Sprite", "Slider.Front", progress, progressWeight), guiContentDef.ParamSlider.Front, settings); // Load Front slider.FrontSprite = await LoadAssetSpriteAsync(CreateChildProgress("Load Sprite", "Slider.Front", progress, progressWeight), guiContentDef.ParamSlider.Front, settings); // Import OnName await ImportAssetSpriteAsync(CreateChildProgress("Import Sprite", "Slider.OnName", progress, progressWeight), guiContentDef.ParamSlider.OnName, settings); // Load OnName slider.OnHandleSprite = await LoadAssetSpriteAsync(CreateChildProgress("Load Sprite", "Slider.OnName", progress, progressWeight), guiContentDef.ParamSlider.OnName, settings); // Import OnName await ImportAssetSpriteAsync(CreateChildProgress("Import Sprite", "Slider.OffName", progress, progressWeight), guiContentDef.ParamSlider.OffName, settings); // Load OnName slider.OffHandleSprite = await LoadAssetSpriteAsync(CreateChildProgress("Load Sprite", "Slider.OffName", progress, progressWeight), guiContentDef.ParamSlider.OffName, settings); slider.unityHandleImage.rectTransform.sizeDelta = new Vector3(guiContentDef.ParamSlider.OnSize[0], guiContentDef.ParamSlider.OnSize[1]); slider.DriveField = guiContentDef.ParamSlider.DriveField; } // Toggle if (guiContentDef.Toggle != null) { slider.ToggleList = new List(); for (int i = 0; i < guiContentDef.Toggle.Count; ++i) { var toggleDef = guiContentDef.Toggle[i]; var toggle = new Runtime.VCStateToggle() { Name = toggleDef.Name, State = toggleDef.State }; slider.ToggleList.Add(toggle); } } ImportTransform(slider.GetComponent(), guiContentDef, layerList, settings); progress.Done(); return slider; } /// /// テキストをインポートする /// /// 進捗 /// GUIコンテンツ構造定義 /// 親レイヤー /// インポート設定 /// static VCText ImportText(ImportProgress progress, VCContentDef guiContentDef, VCLayerList layerList, VCCanvasImporterSettings settings) { VCText vcguiText = VCFactory.CreateText(guiContentDef.Name); Text text = vcguiText.GetComponent(); if (guiContentDef.ParamText != null) { vcguiText.Text = guiContentDef.ParamText.Text; if (guiContentDef.ParamText.Color != null) { vcguiText.MulColor = new Color(guiContentDef.ParamText.Color[0], guiContentDef.ParamText.Color[1], guiContentDef.ParamText.Color[2], guiContentDef.ParamText.Color[3]); } else { vcguiText.MulColor = new Color(1.0f,1.0f,1.0f,1.0f); } vcguiText.FontSize = guiContentDef.ParamText.FontSize; vcguiText.TextEn = guiContentDef.ParamText.TextEn; if (!Enum.TryParse(guiContentDef.ParamText.Alignment, out vcguiText.Alignment)) { vcguiText.Alignment = ParamTextAlignment.LT; } vcguiText.FontFamily = guiContentDef.ParamText.FontFamily ?? ""; vcguiText.CharaSpace = guiContentDef.ParamText.CharaSpace; vcguiText.LineSpace = guiContentDef.ParamText.LineSpace; vcguiText.OverflowWrap = guiContentDef.ParamText.OverflowWrap; vcguiText.URLClickable = guiContentDef.ParamText.URLClickable; vcguiText.URLColor = guiContentDef.ParamText.URLColor; } text.supportRichText = false; ImportTransform(vcguiText.GetComponent(), guiContentDef, layerList, settings); progress.Done(); return vcguiText; } /// /// イメージをインポートする /// /// 進捗 /// GUIコンテンツ構造定義 /// 親レイヤー /// インポート設定 /// static async UniTask ImportImageAsync(ImportProgress progress, VCContentDef guiContentDef, VCLayerList layerList, VCCanvasImporterSettings settings) { VCImage image = VCFactory.CreateImage(guiContentDef.Name); var unityImage = image.GetComponent(); // Toggle if (guiContentDef.Toggle != null) { image.ToggleList = new List(); for (int i = 0; i < guiContentDef.Toggle.Count; ++i) { var toggleDef = guiContentDef.Toggle[i]; var toggle = new Runtime.VCStateToggle() { Name = toggleDef.Name, State = toggleDef.State }; image.ToggleList.Add(toggle); } } float progressWeight = 1f / 2f; // Image if (guiContentDef.ParamImage != null) { // Import FileName await ImportAssetSpriteAsync(CreateChildProgress("Import Sprite", "Image.Uri", progress, progressWeight), guiContentDef.ParamImage.Uri, settings); // Load FileName image.Sprite = await LoadAssetSpriteAsync(CreateChildProgress("Load Sprite", "Image.Sprite", progress, progressWeight), guiContentDef.ParamImage.Uri, settings); image.UVArea = guiContentDef.ParamImage.UVArea; image.UVAreaRate = guiContentDef.ParamImage.UVAreaRate; } ImportTransform(image.GetComponent(), guiContentDef, layerList, settings); progress.Done(); return image; } /// /// ボタンをインポートする /// /// 進捗 /// GUIコンテンツ構造定義 /// 親レイヤー /// インポート設定 /// static async UniTask ImportButtonAsync(ImportProgress progress, VCContentDef guiContentDef, VCLayerList layerList, VCCanvasImporterSettings settings) { var button = VCFactory.CreateButton(guiContentDef.Name); float progressWeight = 1f / 8f; if (guiContentDef.ParamButton != null) { // Import FileName await ImportAssetSpriteAsync(CreateChildProgress("Import Sprite", "Button.FileName", progress, progressWeight), guiContentDef.ParamButton.FileName, settings); // Load FileName button.DefaultImage = await LoadAssetSpriteAsync(CreateChildProgress("Load Sprite", "Button.FileName", progress, progressWeight), guiContentDef.ParamButton.FileName, settings); // Import OnCursorFileName await ImportAssetSpriteAsync(CreateChildProgress("Import Sprite", "Button.OnCursorFileName", progress, progressWeight), guiContentDef.ParamButton.OnCursorFileName, settings); // Load OnCursorFileName button.OnCursorImage = await LoadAssetSpriteAsync(CreateChildProgress("Load Sprite", "Button.OnCursorFileName", progress, progressWeight), guiContentDef.ParamButton.OnCursorFileName, settings); // Import DownFileName await ImportAssetSpriteAsync(CreateChildProgress("Import Sprite", "Button.DownFileName", progress, progressWeight), guiContentDef.ParamButton.DownFileName, settings); // Load DownFileName button.DownImage = await LoadAssetSpriteAsync(CreateChildProgress("Load Sprite", "Button.DownFileName", progress, progressWeight), guiContentDef.ParamButton.DownFileName, settings); // Toggle if (guiContentDef.Toggle != null) { button.ToggleList = new List(); for (int i = 0; i < guiContentDef.Toggle.Count; ++i) { var toggleDef = guiContentDef.Toggle[i]; var toggle = new Runtime.VCStateToggle() { Name = toggleDef.Name, State = toggleDef.State }; button.ToggleList.Add(toggle); } } button.UVArea = guiContentDef.ParamButton.UVArea; button.UVAreaRate = guiContentDef.ParamButton.UVAreaRate; button.ClickAreaSize = guiContentDef.ParamButton.ClickAreaSize; button.LTRB = guiContentDef.ParamButton.LTRB; button.ClickAreaImage = string.IsNullOrEmpty(guiContentDef.ParamButton.ClickAreaFileName) ? null : await LoadAssetSpriteAsync(CreateChildProgress("Load Sprite", "Button.ClickAreaFileName", progress, progressWeight), guiContentDef.ParamButton.ClickAreaFileName, settings); button.Flick = guiContentDef.ParamButton.Flick; button.OnKeyDownMulColor = guiContentDef.ParamButton.OnKeyDownMulColor; progress.SelfProgress = 7f / 8f; // GUIAction if (guiContentDef.GUIAction != null) { foreach (var actions in guiContentDef.GUIAction) { if (actions.Any()) { var v = actions.First(); ImportGUIActionItemList(button, v); } } } progress.SelfProgress = 8f / 8f; } ImportTransform(button.GetComponent(), guiContentDef, layerList, settings); progress.Done(); return button; } /// /// 汎用Transformインポート /// /// 出力先Transform /// GUIコンテンツ構造定義 /// 親レイヤー static void ImportTransform(RectTransform rectTransform, VCContentDef guiContentDef, VCLayerList parentLayerList, VCCanvasImporterSettings settings) { rectTransform.SetParent(parentLayerList.transform, false); rectTransform.gameObject.SetActive(guiContentDef.Show); var itemGUIContent = rectTransform.GetComponent(); itemGUIContent.Language = guiContentDef.Language; itemGUIContent.Portrait = guiContentDef.Portrait; itemGUIContent.Platform = guiContentDef.Platform; itemGUIContent.RaycastTarget = guiContentDef.RaycastTarget; var itemTransform = rectTransform.GetComponent(); // UIとして必須の位置情報の破損を伝える if (!Enum.TryParse(guiContentDef.Anchor, out itemTransform.Anchor)) settings.logger.LogError(nameof(VCCanvasImporter), $"{rectTransform}[VCGUITransform]は、Anchorが破損しています。\nレイアウト破損の恐れがあるため、手動確認してください。", rectTransform); // 配列数がnull、もしくは2つに満たないとき、フォールバックとして0を代入する if (!TryReadVector2Int(ref itemTransform.Pos, guiContentDef.Pos)) settings.logger.LogError(nameof(VCCanvasImporter), $"{rectTransform}[VCGUITransform]は、Posが破損しています。\nレイアウト破損の恐れがあるため、手動確認してください。", rectTransform); if (!TryReadVector2(ref itemTransform.Pivot, guiContentDef.Pivot)) settings.logger.LogError(nameof(VCCanvasImporter), $"{rectTransform}[VCGUITransform]は、Pivotが破損しています。\nレイアウト破損の恐れがあるため、手動確認してください。", rectTransform); if (!TryReadVector2Int(ref itemTransform.Size, guiContentDef.Size)) settings.logger.LogError(nameof(VCCanvasImporter), $"{rectTransform}[VCGUITransform]は、Sizeが破損しています。\nレイアウト破損の恐れがあるため、手動確認してください。", rectTransform); itemTransform.Z = guiContentDef.Z; itemTransform.ApplyTransform(); } /// /// int配列のをVector2として読み込みます。
/// sourceArrayの要素数が2以上なら、に代入しします。
/// 要素数が2未満のとき、にVector2Int.zeroを代入します。
/// 要素数が2のとき、trueを返します。
/// それ以外のとき、falseを返します。
///
/// /// に出力されたかどうかと戻り値は直接関係がないことに注意してください。 /// 「要素数を間違いなく解釈できた」ときのみtrueを返します。 /// 読めないnull, 0, 1のときや、取りこぼした3以上のときfalseを返します。 /// /// 出力先 /// /// 正常に読み込めたときtrue、それ以外のときfalse static bool TryReadVector2Int(ref Vector2Int v, int[] sourceArray) { bool success = false; if (sourceArray == null || sourceArray.Length < 2) { v = Vector2Int.zero; } else if (sourceArray.Length >= 2) { v.x = sourceArray[0]; v.y = sourceArray[1]; success = sourceArray.Length == 2; } else { v = Vector2Int.zero; } return success; } /// /// float配列のをVector2として読み込みます。
/// sourceArrayの要素数が2以上なら、に代入しします。
/// 要素数が2未満のとき、にVector2Int.zeroを代入します。
/// 要素数が2のとき、trueを返します。
/// それ以外のとき、falseを返します。
///
/// /// に出力されたかどうかと戻り値は直接関係がないことに注意してください。 /// 「要素数を間違いなく解釈できた」ときのみtrueを返します。 /// 読めないnull, 0, 1のときや、取りこぼした3以上のときfalseを返します。 /// /// 出力先 /// /// 正常に読み込めたときtrue、それ以外のときfalse static bool TryReadVector2(ref Vector2 v, float[] sourceArray) { bool success = false; if (sourceArray == null || sourceArray.Length < 2) { v = Vector2.zero; } else if (sourceArray.Length >= 2) { v.x = sourceArray[0]; v.y = sourceArray[1]; success = sourceArray.Length == 2; } else { v = Vector2.zero; } return success; } /// /// ボタン押下イベントのGUIActionItemListをインポートする /// /// 出力先ボタン /// イベント定義Json static void ImportGUIActionItemList(VCButton itemButton, KeyValuePair> jsonParams) { // イベント構造は、かなり種類が多い // ここで大分類を確定してから詳細を読み込む Runtime.GUIActionListItem guiActionListItem = null; if (jsonParams.Key == "Func") { if (jsonParams.Value.ContainsValue("callscript")) { guiActionListItem = ScriptableObject.CreateInstance(); ImportCallScriptGUIAction(jsonParams, guiActionListItem); } else if (jsonParams.Value.ContainsValue("DebugLog")) { guiActionListItem = ScriptableObject.CreateInstance(); ImportDebugLogGUIAction(jsonParams, guiActionListItem); } else { guiActionListItem = ScriptableObject.CreateInstance(); ImportFuncGUIAction(jsonParams, guiActionListItem); } } else if (jsonParams.Key == "Flag") { guiActionListItem = ScriptableObject.CreateInstance(); ImportFlagGUIAction(jsonParams, guiActionListItem); } else if (jsonParams.Key == "Index") { guiActionListItem = ScriptableObject.CreateInstance(); ImportIndexGUIAction(jsonParams, guiActionListItem); } else if (jsonParams.Value.Count == 2 && jsonParams.Value.ContainsKey("Value") && jsonParams.Value["Value"] is string) { guiActionListItem = ScriptableObject.CreateInstance(); ImportStringGUIAction(jsonParams, guiActionListItem); } else if (jsonParams.Key == "S2DI") { guiActionListItem = ScriptableObject.CreateInstance(); ImportS2DIGUIAction(jsonParams, guiActionListItem); } else if (jsonParams.Key == "SetShowGUI") { guiActionListItem = ScriptableObject.CreateInstance(); ImportSetShowGUIGUIAction(jsonParams, guiActionListItem); } else if (jsonParams.Key == "SetShowLayer") { guiActionListItem = ScriptableObject.CreateInstance(); ImportSetShowLayerGUIAction(jsonParams, guiActionListItem); }else if (jsonParams.Key == "Func" && jsonParams.Value.ContainsValue("calljs")) { guiActionListItem = ScriptableObject.CreateInstance(); ImportCallJSGUIAction(jsonParams, guiActionListItem); } else if ( jsonParams.Key == "Master" || jsonParams.Key == "World" || jsonParams.Key == "Voice" || jsonParams.Key == "SE" || jsonParams.Key == "SystemSE" || jsonParams.Key == "Video") { guiActionListItem = ScriptableObject.CreateInstance(); ImportSoundMixerGUIAction(jsonParams, guiActionListItem); } else { guiActionListItem = ScriptableObject.CreateInstance(); ImportUnknownGUIAction(jsonParams, guiActionListItem); } if (guiActionListItem != null) itemButton.GUIActions.Add(guiActionListItem); } /// /// ImportProgressの子を設定して詳細を入れる /// /// デバッグ表示用タグ /// デバッグ表示用詳細 /// 親 /// 親にとっての子の進捗の重み /// static ImportProgress CreateChildProgress(string tag, string detail, ImportProgress parent, float progressWeight) { var child = new ImportProgress(tag, detail, 1f); parent.ChildProgressWeight = progressWeight; child.SetParent(parent); return child; } /// /// 不明なGUIAction /// エクスポート時の不備か、本ツールが未対応の新イベントか /// /// /// static void ImportUnknownGUIAction(KeyValuePair> jsonParams, Runtime.GUIActionListItem guiActionListItem) { var guiAction = ScriptableObject.CreateInstance(); guiActionListItem.GUIActionType = Runtime.GUIAction.FuncType.Unknown; guiActionListItem.GUIAction = guiAction; guiAction.SetFuncName(jsonParams.Key); foreach (var param in jsonParams.Value) { guiAction.UnknownParams.Add(param.Key, param.Value); } guiAction.UnknownParams.ForceSerialize(); } /// /// SoundMixer系イベント定義 /// おもにミュートのON/OFF /// /// /// static void ImportSoundMixerGUIAction(KeyValuePair> jsonParams, Runtime.GUIActionListItem guiActionListItem) { var guiAction = ScriptableObject.CreateInstance(); guiActionListItem.GUIActionType = (GUIAction.FuncType)Enum.Parse(typeof(GUIAction.FuncType), jsonParams.Key); guiActionListItem.GUIAction = guiAction; guiAction.FuncName = jsonParams.Key; guiAction.VolumeMuteFlag = jsonParams.Value["VolumeMuteFlag"] as bool? ?? false; } /// /// SetShowLayerイベント定義 /// レイヤー個別にON/OFFする /// /// /// static void ImportSetShowLayerGUIAction(KeyValuePair> jsonParams, Runtime.GUIActionListItem guiActionListItem) { var guiAction = ScriptableObject.CreateInstance(); guiActionListItem.GUIActionType = Runtime.GUIAction.FuncType.SetShowLayer; guiActionListItem.GUIAction = guiAction; guiAction.LayerName = jsonParams.Value["Name"].ToString(); guiAction.Show = jsonParams.Value["Show"] as bool? ?? false; } /// /// SetShowGUIイベント定義 /// ボタンや画像など個別にON/OFFする /// /// /// static void ImportSetShowGUIGUIAction(KeyValuePair> jsonParams, Runtime.GUIActionListItem guiActionListItem) { var guiAction = ScriptableObject.CreateInstance(); guiActionListItem.GUIActionType = Runtime.GUIAction.FuncType.SetShowGUI; guiActionListItem.GUIAction = guiAction; guiAction.GuiName = jsonParams.Value["Name"].ToString(); guiAction.Show = jsonParams.Value["Show"] as bool? ?? false; } /// /// S2DI引数イベント定義 /// 2次元整数ベクトルを引数に持つイベント /// 関数型ベースなので、実行内容は多岐にわたる /// /// /// static void ImportS2DIGUIAction(KeyValuePair> jsonParams, Runtime.GUIActionListItem guiActionListItem) { var guiAction = ScriptableObject.CreateInstance(); guiActionListItem.GUIActionType = Runtime.GUIAction.FuncType.S2DI; guiActionListItem.GUIAction = guiAction; guiAction.ActionName = jsonParams.Value["Name"].ToString(); var jArray = jsonParams.Value["Value"] as JArray; Vector2Int value = new Vector2Int(); if (jArray != null) { var intArray = jArray.ToObject(); TryReadVector2Int(ref value, intArray); } guiAction.Value = value; } /// /// String引数イベント定義 /// Stringを引数に持つイベント /// 関数型ベースなので、実行内容は多岐にわたる /// /// /// static void ImportStringGUIAction(KeyValuePair> jsonParams, Runtime.GUIActionListItem guiActionListItem) { var guiAction = ScriptableObject.CreateInstance(); guiActionListItem.GUIActionType = Runtime.GUIAction.FuncType.String; guiActionListItem.GUIAction = guiAction; guiAction.ActionName = jsonParams.Value["Name"].ToString(); guiAction.Value = jsonParams.Value["Value"].ToString(); } /// /// Index引数イベント定義 /// intを引数に持つイベント /// 関数型ベースなので、実行内容は多岐にわたる /// /// /// static void ImportIndexGUIAction(KeyValuePair> jsonParams, Runtime.GUIActionListItem guiActionListItem) { var guiAction = ScriptableObject.CreateInstance(); guiActionListItem.GUIActionType = Runtime.GUIAction.FuncType.Index; guiActionListItem.GUIAction = guiAction; guiAction.ActionName = jsonParams.Value["Name"].ToString(); guiAction.Value = jsonParams.Value["Value"] as int? ?? 0; } /// /// Flag引数イベント定義 /// boolを引数に持つイベント /// 関数型ベースなので、実行内容は多岐にわたる /// /// /// static void ImportFlagGUIAction(KeyValuePair> jsonParams, Runtime.GUIActionListItem guiActionListItem) { var guiAction = ScriptableObject.CreateInstance(); guiActionListItem.GUIActionType = Runtime.GUIAction.FuncType.Flag; guiActionListItem.GUIAction = guiAction; guiAction.ActionName = jsonParams.Value["Name"].ToString(); guiAction.Enable = jsonParams.Value["Enable"] as bool? ?? false; } /// /// Func引数イベント定義 /// 引数を持たないイベント /// 関数型ベースなので、実行内容は多岐にわたる /// /// /// static void ImportFuncGUIAction(KeyValuePair> jsonParams, Runtime.GUIActionListItem guiActionListItem) { var guiAction = ScriptableObject.CreateInstance(); guiActionListItem.GUIActionType = Runtime.GUIAction.FuncType.Func; guiActionListItem.GUIAction = guiAction; guiAction.ActionName = jsonParams.Value["Name"].ToString(); } private static void ImportCallJSGUIAction(KeyValuePair> jsonParams, Runtime.GUIActionListItem guiActionListItem) { var guiAction = ScriptableObject.CreateInstance(); guiActionListItem.GUIActionType = GUIAction.FuncType.calljs; guiActionListItem.GUIAction = guiAction; guiAction.ActionName= jsonParams.Value["Name"].ToString(); guiAction.Type = jsonParams.Value["Type"].ToString(); guiAction.Param = jsonParams.Value["Param"].ToString(); } private static void ImportCallScriptGUIAction(KeyValuePair> jsonParams, Runtime.GUIActionListItem guiActionListItem) { var guiAction = ScriptableObject.CreateInstance(); guiActionListItem.GUIActionType = GUIAction.FuncType.callscript; guiActionListItem.GUIAction = guiAction; guiAction.ActionName = jsonParams.Value["Name"].ToString(); guiAction.Category = jsonParams.Value["Category"].ToString(); guiAction.Param = jsonParams.Value["Param"].ToString(); } private static void ImportDebugLogGUIAction(KeyValuePair> jsonParams, Runtime.GUIActionListItem guiActionListItem) { var guiAction = ScriptableObject.CreateInstance(); guiActionListItem.GUIActionType = GUIAction.FuncType.DebugLog; guiActionListItem.GUIAction = guiAction; guiAction.ActionName = jsonParams.Value["Name"].ToString(); guiAction.Param = jsonParams.Value["Param"].ToString(); } /// /// アセットのインポート処理 /// /// /// /// /// static async UniTask ImportAssetSpriteAsync(ImportProgress progress, string path, VCCanvasImporterSettings settings) { return await settings.onImportSprite(path, progress, settings); } /// /// アセットのロード処理 /// /// /// /// /// static async UniTask LoadAssetSpriteAsync(ImportProgress progress, string path, VCCanvasImporterSettings settings) { return await settings.onLoadSprite(path, progress, settings); } static async UniTask ImportLayerMaskAsync(ImportProgress progress, VCLayerList layerList, VCLayerDef layerDef, VCCanvasImporterSettings settings) { if (layerDef.Mask == null) { layerList.Mask.Initialize(false); return; } layerList.Mask.Initialize(true); if (layerDef.Mask.URI != null) { await ImportAssetSpriteAsync(progress, layerDef.Mask.URI, settings); layerList.Mask.URI = await LoadAssetSpriteAsync(progress, layerDef.Mask.URI, settings); } layerList.Mask.Show = layerDef.Mask.Show; var pos = new Vector2(); if (!TryReadVector2(ref pos, layerDef.Mask.Pos)) settings.logger.LogError(nameof(VCCanvasImporter), $"{layerDef.Name}[Layer] MaskのPosが破損しています。\nレイアウト破損の恐れがあるため、手動確認してください。"); layerList.Mask.Pos = pos; var size = new Vector2(); if (!TryReadVector2(ref size, layerDef.Mask.Size)) settings.logger.LogError(nameof(VCCanvasImporter), $"{layerDef.Name}[Layer] MaskのSizeが破損しています。\nレイアウト破損の恐れがあるため、手動確認してください。"); layerList.Mask.Size = size; layerList.Mask.Z = layerDef.Mask.Z; var pivot = new Vector2(); if (!TryReadVector2(ref pivot, layerDef.Mask.Size)) settings.logger.LogError(nameof(VCCanvasImporter), $"{layerDef.Name}[Layer] MaskのPivotが破損しています。\nレイアウト破損の恐れがあるため、手動確認してください。"); layerList.Mask.Pivot = pivot; if (!Enum.TryParse(layerDef.Mask.Anchor, out AnchorType anchor)) settings.logger.LogError(nameof(VCCanvasImporter), $"{layerDef.Name}[Layer] MaskのAnchorが破損しています。\nレイアウト破損の恐れがあるため、手動確認してください。"); layerList.Mask.Anchor = anchor; var Color = new Color(); if (layerDef.Mask.Color != null && layerDef.Mask.Color.Length == 4) { Color.r = layerDef.Mask.Color[0]; Color.g = layerDef.Mask.Color[1]; Color.b = layerDef.Mask.Color[2]; Color.a = layerDef.Mask.Color[3]; } else { settings.logger.LogError(nameof(VCCanvasImporter), $"{layerDef.Name}[Layer] MaskのColorが破損しています。\nレイアウト破損の恐れがあるため、手動確認してください。"); } layerList.Mask.Color = Color; layerList.Mask.Vertical = layerDef.Mask.Vertical; layerList.Mask.FreeSlide = layerDef.Mask.FreeSlide; layerList.Mask.WheelTravel = layerDef.Mask.WheelTravel; if (layerDef.Mask.SeekBar != null) { var vertical = await ImportLayerMaskSeekBarItemAsync(progress, layerDef.Mask.SeekBar.Vertical, layerDef.Name, "Vertical", settings); var horizontal = await ImportLayerMaskSeekBarItemAsync(progress, layerDef.Mask.SeekBar.Horizontal, layerDef.Name, "Horizontal", settings); layerList.Mask.SeekBar.Initialize(vertical, horizontal); } else { layerList.Mask.SeekBar.Initialize(null, null); } } static async UniTask ImportLayerMaskSeekBarItemAsync(ImportProgress progress, VCLayerMaskSeekBarItemDef itemDef, string layerName, string type, VCCanvasImporterSettings settings) { if (itemDef == null) { return null; } var result = new VCLayerMaskSeekBarItem(); if (itemDef.Base != null) { await ImportAssetSpriteAsync(progress, itemDef.Base, settings); result.Base = await LoadAssetSpriteAsync(progress, itemDef.Base, settings); } if (itemDef.Front != null) { await ImportAssetSpriteAsync(progress, itemDef.Front, settings); result.Front = await LoadAssetSpriteAsync(progress, itemDef.Front, settings); } if (itemDef.On != null) { await ImportAssetSpriteAsync(progress, itemDef.On, settings); result.On = await LoadAssetSpriteAsync(progress, itemDef.On, settings); } if (itemDef.Off != null) { await ImportAssetSpriteAsync(progress, itemDef.Off, settings); result.Off = await LoadAssetSpriteAsync(progress, itemDef.Off, settings); } result.BarWidth = itemDef.BarWidth; var OnSize = new Vector2Int(); if (!TryReadVector2Int(ref OnSize, itemDef.OnSize)) settings.logger.LogError(nameof(VCCanvasImporter), $"{layerName}[Layer] MaskのSeekBar {type} のOnSizeが破損しています。\nレイアウト破損の恐れがあるため、手動確認してください。"); result.OnSize = OnSize; var OffSize = new Vector2Int(); if (!TryReadVector2Int(ref OffSize, itemDef.OffSize)) settings.logger.LogError(nameof(VCCanvasImporter), $"{layerName}[Layer] MaskのSeekBar {type} のOffSizeが破損しています。\nレイアウト破損の恐れがあるため、手動確認してください。"); result.OffSize = OffSize; return result; } static VCHtml ImportHtml(ImportProgress progress, VCContentDef guiContentDef, VCLayerList layerList, VCCanvasImporterSettings settings) { VCHtml vcguiHtml = VCFactory.CreateHtml(guiContentDef.Name); if (guiContentDef.ParamHtml != null) { vcguiHtml.FontSize = guiContentDef.ParamHtml.FontSize; } ImportTransform(vcguiHtml.GetComponent(), guiContentDef, layerList, settings); progress.Done(); return vcguiHtml; } } }