/* * ExternalReceiver * https://sabowl.sakura.ne.jp/gpsnmeajp/ * * MIT License * * Copyright (c) 2020-2022 gpsnmeajp * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #pragma warning disable CS0162 using System; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; using UnityEngine; using UnityEditor; using UnityEditor.AnimatedValues; using UnityEngine.Events; using System.Linq; namespace EVMC4U { public class Tutorial : EditorWindow { const bool check = false; //バージョンチェック条件式があったが、バージョン番号がなくなったので無効化 const int window_w = 400; const int window_h = 400; //ページ名 static string page = ""; //ボタン押下アニメーション static AnimFloat anim = new AnimFloat(0.001f); static string animTargetName = ""; //1つのボタンだけアニメさせる識別名 static string jsonError = ""; static TutorialJson tutorialJson = null; static Dictionary tutorialPages = new Dictionary(); //JSON設定ファイル定義 [Serializable] private class TutorialJson { public bool debug; public TutorialPage[] pages; public override string ToString() { return "TutorialJson debug:" + debug + " pages:" + pages.Length; } } //JSONページ定義 [Serializable] private class TutorialPage { public string name = ""; public string text = ""; public string image = ""; public TutorialButton[] buttons = new TutorialButton[0]; public override string ToString() { return "TutorialPage name:" + name + " text:" + text + " iamge:" + image + " buttons:" + buttons.Length; } } //JSONボタン定義 [Serializable] private class TutorialButton { public int x = 0; public int y = 0; public int w = 0; public int h = 0; public string text = ""; public string image = ""; public string uri = ""; //"page://" = page, "http://" or "https://" = url public string fire = ""; //event public override string ToString() { return "TutorialButton (" + x + "," + y + "," + w + "," + h + ") text:" + text + " image:" + image + " uri:" + uri; } } [InitializeOnLoadMethod] static void InitializeOnLoad() { //一度も開いたことない場合は、ここで開く if (EditorUserSettings.GetConfigValue("Opened") != "1" || (check && EditorUserSettings.GetConfigValue("VRMCheckCaution") != "1")) { Open(); } } [MenuItem("EVMC4U/Oepn Tutorial")] public static void Open() { //ウィンドウサイズを固定 var window = GetWindow(); window.maxSize = new Vector2(window_w, window_h - 6); window.minSize = window.maxSize; //アニメーション定義 anim.value = 0.001f; anim.speed = 10f; anim.target = 0.001f; anim.valueChanged = null; if (Resources.Load("tutorial/define") == null) { //読み込み準備ができていない return; } //ページを初期位置に設定 page = "start"; if (EditorUserSettings.GetConfigValue("Language") == "ja") { page = "start_ja"; } if (EditorUserSettings.GetConfigValue("Language") == "en") { page = "start_en"; } //データを読み込む tutorialPages = new Dictionary(); try { jsonError = ""; var r = Resources.Load("tutorial/define"); tutorialJson = JsonUtility.FromJson(r.text); if (tutorialJson.debug) { Debug.Log(tutorialJson); } //各ページのデータを読み込む foreach (var p in tutorialJson.pages) { tutorialPages.Add(p.name, p); if (tutorialJson.debug) { Debug.Log(p); } } //一度開いたのを覚えておく EditorUserSettings.SetConfigValue("Opened", "1"); } catch (ArgumentException e) { //Debug.LogError(e); jsonError = e.ToString(); tutorialJson = null; } //バージョンチェック(失敗したら失敗ページに飛ばす) if (check) { EditorUserSettings.SetConfigValue("VRMCheckCaution", "1"); page = "versionCheckFailed"; } else { EditorUserSettings.SetConfigValue("VRMCheckCaution", "0"); } } [MenuItem("EVMC4U/Reset Language")] public static void ResetLanguage() { EditorUserSettings.SetConfigValue("Language", ""); Open(); } void OnGUI() { //ページを開いたまま初期化されたら、初期ロード処理に飛ばす if (page == "") { GUI.Label(new Rect(10, 10, window_w, window_h), "INVALID STATE\n\nチュートリアルの読み込みに失敗しました。Unityを再起動してください。\nそれでもダメな場合は、UnityPackageの導入からやり直してみてください\n\nTutorial load failed.\nPlease restart Unity.\nor Please re-import UnityPackage."); Open(); return; } //アニメーションを立ち上げる if (anim.valueChanged == null) { var repaintEvent = new UnityEvent(); repaintEvent.AddListener(() => Repaint()); anim.valueChanged = repaintEvent; } //アニメーション折り返し if (anim.value > anim.target - 0.1f) { anim.target = 0.001f; } //ページの表示処理を開始 TutorialPage tutorialPage; if (!tutorialPages.TryGetValue(page, out tutorialPage)) { //JSONが多分バグってるときに表示 GUI.Label(new Rect(10, 10, window_w - 20, window_h), "JSON LOAD FAILED\n" + jsonError + "\n\nチュートリアルの読み込みに失敗しました。Unityを再起動してください。\nそれでもダメな場合は、UnityPackageの導入からやり直してみてください\n\nTutorial load failed.\nPlease restart Unity.\nor Please re-import UnityPackage."); if (GUI.Button(new Rect(0, window_h - 30, window_w, 30), "Reload")) { Open(); } return; } //デバッグログ if (tutorialJson.debug) { Debug.Log("OnGUI: " + anim.value); Debug.Log(tutorialPage); } //背景画像があれば表示 if (tutorialPage.image != "") { var bgtexture = Resources.Load("tutorial/" + tutorialPage.image); EditorGUI.DrawPreviewTexture(new Rect(0, 0, window_w, window_h), bgtexture); } //ページのテキストを表示(代替テキスト) GUI.Label(new Rect(0, 0, window_w, window_h), tutorialPage.text); //ボタンを1つずつ表示 foreach (var b in tutorialPage.buttons) { if (tutorialJson.debug) { Debug.Log(b); } //ボタンに画像があればそれを表示 if (b.image != "") { //画像を読み込む var texture = Resources.Load("tutorial/" + b.image); //位置情報がない場合、下端として扱う if (b.x == 0 && b.y == 0 && b.w == 0 && b.h == 0) { b.y = window_h - window_w * texture.height / texture.width; b.w = window_w; } string buttonName = "btn#" + page + "#" + b.x + "-" + b.y + "-" + b.w + "-" + b.h; float height = b.w * texture.height / texture.width; Rect r = new Rect(b.x, b.y, b.w, height); //アニメ対象の場合だけ動く if (buttonName == animTargetName) { r = new Rect(b.x + anim.value, b.y + anim.value, b.w, height); } //ボタンを表示 if (GUI.Button(r, texture, new GUIStyle())) { //アニメーション処理と、遷移を実行 buttonFireProcess(b.fire); buttonUriProcess(b.uri); animTargetName = buttonName; anim.target = 2f; } } else { //テキストボタンを表示 if (GUI.Button(new Rect(b.x, b.y, b.w, b.h), b.text)) { buttonFireProcess(b.fire); buttonUriProcess(b.uri); } } } //デバッグ再読み込みボタン if (tutorialJson.debug) { if (GUI.Button(new Rect(0, window_h - 30, 30, 30), "#")) { Open(); } } } void buttonUriProcess(string uri) { if (tutorialJson.debug) { Debug.LogWarning("buttonProcess: " + uri); } if (uri == null) { return; } if (uri.StartsWith("page://")) { page = uri.Replace("page://", ""); } if (uri.StartsWith("http://") || uri.StartsWith("https://")) { System.Diagnostics.Process.Start(uri); } } void buttonFireProcess(string fire) { switch (fire) { case "SaveLanguageJa": { EditorUserSettings.SetConfigValue("Language", "ja"); var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone).Split(';').ToList(); if (symbols.Contains("EVMC4U_EN")) { symbols.Remove("EVMC4U_EN"); } if (!symbols.Contains("EVMC4U_JA")) { symbols.Add("EVMC4U_JA"); } PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone, String.Join(";", symbols.ToArray())); break; } case "SaveLanguageEn": { EditorUserSettings.SetConfigValue("Language", "en"); var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone).Split(';').ToList(); if (symbols.Contains("EVMC4U_JA")) { symbols.Remove("EVMC4U_JA"); } if (!symbols.Contains("EVMC4U_EN")) { symbols.Add("EVMC4U_EN"); } PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone, String.Join(";", symbols.ToArray())); break; } default: break; } } } }