using Thousandto.Code.Logic; using Thousandto.Core.Asset; using Thousandto.SkillEditor; using Thousandto.SkillEditor.DIY; using Thousandto.SkillEditor.Support; using System; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; using UnityEditor; using UnityEngine; namespace Thousandto.SkillEditor.DIY { public class SkillEditor : EditorWindow { #region//入口 [MenuItem("Ares/SkillEditor")] static void OpenSkillEditor() { var curScenes = EditorBuildSettings.scenes; var needSet = true; var allScenes = new List(); for (int i = 0; i < curScenes.Length; ++i) { allScenes.Add(new EditorBuildSettingsScene(curScenes[i].path, true)); if (curScenes[i].path == "Assets/SkillEditor/EditorRes/Scene/EditorScene.unity") { needSet = false; } } if (needSet) { allScenes.Add(new EditorBuildSettingsScene("Assets/SkillEditor/EditorRes/Scene/EditorScene.unity", true)); EditorBuildSettings.scenes = allScenes.ToArray(); EditorUtility.DisplayDialog("提示", "自动将EditorScene场景添加到BuildSetting,请重新启动!", "确定"); EditorApplication.isPlaying = false; return; } if (!EditorApplication.isPlaying) { EditorUtility.DisplayDialog("提示", "播放状态下才能打开技能编辑器!", "确定"); return; } SkillResPathEditor.InitResPath(); var win = (SkillEditor)EditorWindow.GetWindow(typeof(SkillEditor), true); win.wantsMouseMove = true; win.minSize = new Vector2(1860, 960); win.maxSize = new Vector2(1860, 960); win.Show(); win.Init(); IsOpen = true; } #endregion #region//界面渲染 bool OnEditorModeGUI() { SkillEditorScene.OnGUI(); bool isLeftMouseDown = false; bool isRightMouseUP = false; switch (Event.current.type) { case EventType.ScrollWheel: { if (_buttomRect.Contains(Event.current.mousePosition)) { float oldScale = _curFrameWidthScale; _curFrameWidthScale -= Event.current.delta.y * 0.05f; if (_curFrameWidthScale > FrameWidthMaxScale) { _curFrameWidthScale = FrameWidthMaxScale; } if (_curFrameWidthScale < FrameWidthMinScale) { _curFrameWidthScale = FrameWidthMinScale; } } } break; case EventType.MouseDown: { if (_buttomRect.Contains(Event.current.mousePosition)) { if (Event.current.button == 0) { //左键 isLeftMouseDown = true; _draging = true; } else if (Event.current.button == 1) { //右键 isRightMouseUP = false; } } if (SkillEventEditor.IsOpen) { SkillEventEditor.Hide(); } } break; case EventType.MouseUp: { if (Event.current.button == 0) { //左键 isLeftMouseDown = false; _curDragEvent = null; _draging = false; } else if (Event.current.button == 1) { //右键 if (_buttomRect.Contains(Event.current.mousePosition)) { isRightMouseUP = true; } } } break; } #region//左侧操作面板 GUILayout.BeginArea(_leftRect); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("载入", GUILayout.Width(60))) { SkillEditorData.Load(); Init(); } bool bSave = false; if (GUILayout.Button("保存", GUILayout.Width(60))) { bSave = true; } if (GUILayout.Button("新技能", GUILayout.Width(60))) { SkillCreateAndChangeEditor.OpenCreate(this); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginVertical(); GUILayout.Space(20); GUILayout.Label("筛选技能"); EditorGUILayout.BeginHorizontal(); if (SkillFilterEditor.FilterKeys != null) { var newSelect = EditorGUILayout.Popup(_selectFilter, SkillFilterEditor.FilterKeys, GUILayout.Width(100)); if (newSelect != _selectFilter) { _limitSkillName = SkillFilterEditor.GetFilterText(SkillFilterEditor.FilterKeys[newSelect]); _selectFilter = newSelect; ResetSkillList(_limitSkillName); SetSelectSkill(_curSelectSkillName); } } if (GUILayout.Button("编辑筛选器", GUILayout.Width(90), GUILayout.Height(16))) { SkillFilterEditor.Open(); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); string tmpFindName = EditorGUILayout.TextField(_limitSkillName, GUILayout.Width(180)); if (_limitSkillName != tmpFindName) { ResetSkillList(tmpFindName); SetSelectSkill(_curSelectSkillName); } if (GUILayout.Button("X", GUILayout.Width(16), GUILayout.Height(16))) { ResetSkillList(""); SetSelectSkill(_curSelectSkillName); } EditorGUILayout.EndHorizontal(); GUILayout.Label("技能列表"); if (_showSkillList.Count > 0) { int nowSelect = EditorGUILayout.Popup(_curSelectSkillIndex, _showSkillList.ToArray(), GUILayout.Width(200)); if (nowSelect != _curSelectSkillIndex) { //刷新界面 SetSelectSkill(_showSkillList[nowSelect]); _curSelectSkillIndex = nowSelect; } } else { GUILayout.Label("没有符合筛选文本的技能!"); } GUILayout.Space(50); var curSkill = SkillEditorData.FindSkill(_curSelectSkillName); if (curSkill != null) { EditorGUILayout.BeginHorizontal(); GUILayout.Label("技能名字", GUILayout.Width(90)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.TextField(curSkill.Name, GUILayout.Width(160)); if (GUILayout.Button("修改", GUILayout.Width(36))) { SkillCreateAndChangeEditor.OpenChange(this, curSkill); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("是否是召唤对象", GUILayout.Width(110)); curSkill.IsSkillObject = EditorGUILayout.Toggle(curSkill.IsSkillObject, GUILayout.Width(20)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("受击效果对玩家有效", GUILayout.Width(110)); curSkill.IsPlayerValid = EditorGUILayout.Toggle(curSkill.IsPlayerValid, GUILayout.Width(20)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("结束清除特效", GUILayout.Width(110)); curSkill.EndClearVfx = EditorGUILayout.Toggle(curSkill.EndClearVfx, GUILayout.Width(20)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("等待服务器返回后再执行", GUILayout.Width(110)); curSkill.WaitServerResult = EditorGUILayout.Toggle(curSkill.WaitServerResult, GUILayout.Width(20)); EditorGUILayout.EndHorizontal(); if (GUILayout.Button("复制技能", GUILayout.Width(200), GUILayout.Height(20))) { CopySkill(curSkill); } if (GUILayout.Button("删除技能", GUILayout.Width(200))) { DeleteSkill(curSkill.Name); EditorGUILayout.EndVertical(); GUILayout.EndArea(); return true; } } EditorGUILayout.EndVertical(); GUILayout.EndArea(); if(bSave) { SkillEditorData.Save(); SkillEditorData.SaveBinary(); } #endregion #region//下侧播放面板 if (curSkill != null) { GUILayout.BeginArea(_buttomRect); EditorGUILayout.BeginHorizontal(); curSkill.FrameCount = EditorGUILayout.IntField("技能帧数", curSkill.FrameCount, GUILayout.Width(200)); GUILayout.Space(30); if (GUILayout.Button("播放", GUILayout.Width(100))) { if (Application.isPlaying) { SkillEditorScene.UseSkill(curSkill); //SkillEditorPlayerUI.PlaySkill(curSkill.Name); } else { EditorUtility.DisplayDialog("提示", "在Unity播放模式下才能使用技能播放功能", "确定"); } } GUILayout.Space(30); GUILayout.Label("显示走跑动作对比", GUILayout.Width(110)); _showPauseContrast = EditorGUILayout.Toggle(_showPauseContrast, GUILayout.Width(30)); GUILayout.Space(30); GUILayout.Label("显示技能范围", GUILayout.Width(110)); EditorBaseObject.ShowSkillRange = EditorGUILayout.Toggle(EditorBaseObject.ShowSkillRange, GUILayout.Width(30)); EditorGUILayout.EndHorizontal(); _scrollPos = GUILayout.BeginScrollView(_scrollPos, true, false, GUILayout.Width(1820)); int drawFrameCount = Math.Max(PageFrameCount, curSkill.FrameCount); var spaceCount = (int)(CurFrameWidth * drawFrameCount); GUILayout.Box("", GUILayout.Width(spaceCount + 30)); Vector2 size = new Vector2(2, 50); Vector2 pos = Vector2.zero; Rect boxRect = new Rect(); Rect textRect = new Rect(); textRect.size = new Vector2(30, 20); GUIStyle textStyle = new GUIStyle(); textStyle.alignment = TextAnchor.MiddleCenter; GUIStyle eventStyle = new GUIStyle(); eventStyle.alignment = TextAnchor.MiddleCenter; eventStyle.fontSize = 10; float frontY = 0f; int frontEventIndex = 0; int diffIndex = Mathf.RoundToInt(24f / CurFrameWidth); bool isShowEventMenu = false; for (int i = 0; i < drawFrameCount; ++i) { pos.x = i * CurFrameWidth + 10; textRect.position = new Vector2(pos.x - 15, 0); if (i % 5 == 0) { GUI.Label(textRect, i.ToString(), textStyle); boxRect.size = new Vector2(2, 240); pos.y = 20; boxRect.position = pos; } else { pos.y = 25; boxRect.size = new Vector2(2, 230); boxRect.position = pos; } if (i < curSkill.FrameCount) { GUI.color = Color.white; } else { GUI.color = Color.black; } GUI.Box(boxRect, string.Empty); var eventList = curSkill.FindEventByFrame(i); boxRect.size = new Vector2(24, 16); if (i - frontEventIndex >= diffIndex) { frontY = 0; } int j = 0; for (; j < eventList.Count; ++j) { GUI.color = Color.white; boxRect.position = new Vector2(i * CurFrameWidth, frontY + 25 + j * 18); frontEventIndex = i; if (isLeftMouseDown && boxRect.Contains(Event.current.mousePosition)) { _curDragEvent = eventList[j]; } if (SkillEventEditor.IsOpen && SkillEventEditor.EventInfo == eventList[j]) { GUI.color = Color.red; } if (GUI.Button(boxRect, GetEventName(eventList[j].EventType))) { if (isRightMouseUP) { _curDragEvent = null; if (!isShowEventMenu) { var mousePos = Event.current.mousePosition; _skillEventGo.name = string.Format("edit;{0};{1}", curSkill.Name, eventList[j].EventID); EditorUtility.DisplayPopupMenu(new Rect(mousePos.x, mousePos.y, 0, 0), "CONTEXT/SkillEvent/", new MenuCommand(_skillEventGo)); isShowEventMenu = true; } } else { //连续两次点击,打开编辑界面 SkillEventEditor.Open(eventList[j]); } } } GUI.color = Color.white; frontY += j * 18; pos.x -= (CurFrameWidth / 2 - 4); boxRect.position = pos; boxRect.size = new Vector2(CurFrameWidth, 200); if (_draging && boxRect.Contains(Event.current.mousePosition)) { _curSelectFrame = i; if (_curDragEvent != null && i < curSkill.FrameCount) { _curDragEvent.EventFrame = i; } SkillEditorScene.DoPauseAnim(curSkill, _curSelectFrame, _showPauseContrast); } if (isRightMouseUP && boxRect.Contains(Event.current.mousePosition) && i < curSkill.FrameCount) { if (!isShowEventMenu) { var mousePos = Event.current.mousePosition; _skillEventGo.name = string.Format("create;{0};{1}", curSkill.Name, i); EditorUtility.DisplayPopupMenu(new Rect(mousePos.x, mousePos.y, 0, 0), "CONTEXT/SkillEvent/", new MenuCommand(_skillEventGo)); isShowEventMenu = true; } } } if (SkillEditorScene.LocalUser != null && SkillEditorScene.LocalUser.SkillManager.IsUsing && SkillEditorScene.LocalUser.SkillManager.CurSkill != null) { _curSelectFrame = SkillEditorScene.LocalUser.SkillManager.CurSkill.CurFrame; if(SkillEditorScene.LocalUser.SkillManager.CurSkill.VisualInfo != curSkill) { curSkill = SkillEditorScene.LocalUser.SkillManager.CurSkill.VisualInfo; } } GUI.color = Color.red; boxRect.position = new Vector2(_curSelectFrame * CurFrameWidth + 10, 0); boxRect.size = new Vector2(2, 280); GUI.Box(boxRect, string.Empty); GUI.color = Color.white; GUILayout.EndScrollView(); GUILayout.EndArea(); } #endregion #region//右侧操作面板 GUILayout.BeginArea(_rightRect); EditorGUILayout.BeginVertical(); SkillEditorPlayerUI.OnGUI(); EditorGUILayout.EndVertical(); GUILayout.EndArea(); #endregion return true; } void OnGUI() { if (OnEditorModeGUI()) { Repaint(); } } private void Update() { if (Application.isPlaying) { AudioPlayer.Update(); EditorVFXPlayer.Instance.Update(); SkillEditorScene.Update(); } else { Close(); } } #endregion #region//私有变量 private const float FrameWidthMaxScale = 1f; private const float FrameWidthMinScale = 0.3f; private Rect _leftRect = new Rect(10, 0, 200, 600); private Rect _rightRect = new Rect(1650, 0, 200, 800); private Rect _buttomRect = new Rect(10, 720, 1820, 240); private float _curFrameWidthScale = 1f; private int _curSelectFrame = 0; private List _showSkillList = new List(); private int _curSelectSkillIndex = 0; private string _curSelectSkillName = string.Empty; private string _limitSkillName = string.Empty; private SkillBaseEventInfo _curDragEvent = null; private bool _draging = false; private bool _frontPlayingState = false; private float _sliderValue = 0f; private const int PageFrameCount = 301; private Vector2 _scrollPos = Vector2.zero; private GameObject _skillEventGo = null; private int _selectFilter = 0; private bool _showPauseContrast = false; #endregion #region//属性 private float CurFrameWidth { get { return _curFrameWidthScale * 20; } } public string CurSelectSkillName { get { return _curSelectSkillName; } } public static bool IsOpen { get; private set; } #endregion #region//私有函数 //初始化 private void Init() { SkillFilterEditor.Init(); SkillEditorScene.Load(); _curFrameWidthScale = FrameWidthMaxScale; _curSelectFrame = 0; SkillEditorData.Load(); _limitSkillName = string.Empty; ResetSkillList(_limitSkillName); SetSelectSkill(string.Empty); _draging = false; _skillEventGo = new GameObject("SkillEditorTmp"); GameObject.DontDestroyOnLoad(_skillEventGo); } //创建新技能 public bool CreateNewSkill(string name) { if (SkillEditorData.CreateNewSkill(name)) { _showSkillList.Add(name); SetSelectSkill(name); Repaint(); return true; } else { return false; } } //删除技能 private void DeleteSkill(string name) { SkillEditorData.RemoveSkill(name); ResetSkillList(_limitSkillName); if (_showSkillList.Count <= 0) { //如果当前查找选项里边已经没有技能了,清空查找选项重新查找 ResetSkillList(string.Empty); } SetSelectSkill(string.Empty); } //复制技能 private void CopySkill(SkillVisualInfo skill) { var name = SkillEditorData.CopyNewSkill(skill); _showSkillList.Add(name); SetSelectSkill(name); } //修改名字 public bool ChangeSkillName(SkillVisualInfo skill, string newName) { for (int i = 0; i < SkillEditorData.SkillList.Count; ++i) { if (SkillEditorData.SkillList[i].Name == newName) { return false; } } for (int i = 0; i < _showSkillList.Count; ++i) { if (_showSkillList[i] == skill.Name) { _showSkillList[i] = newName; } } if (_curSelectSkillName == skill.Name) { _curSelectSkillName = newName; } skill.Name = newName; Repaint(); return true; } string GetEventName(SkillEventDefine type) { string result = "None"; switch (type) { case SkillEventDefine.PlayAnimation: result = "A"; break; case SkillEventDefine.PlayVfx: result = "V"; break; case SkillEventDefine.PlaySfx: result = "S"; break; case SkillEventDefine.PlayCameraShake: result = "K"; break; case SkillEventDefine.PlayBlur: result = "B"; break; case SkillEventDefine.PlaySlow: result = "L"; break; case SkillEventDefine.PlayLockTrajectory: result = "lt"; break; case SkillEventDefine.DisableMove: result = "dr"; break; case SkillEventDefine.DisableChangeDir: result = "dc"; break; case SkillEventDefine.PlaySimpleSkillObject: result = "so"; break; case SkillEventDefine.PlaySkillObject: result = "O"; break; case SkillEventDefine.PlayHit: result = "H"; break; case SkillEventDefine.PlaySelfMove: result = "M"; break; case SkillEventDefine.PlayHideWeapon: result = "W"; break; case SkillEventDefine.PlayLinkDamage: result = "L"; break; } return result; } public void OnDestroy() { IsOpen = false; GameObject.DestroyImmediate(_skillEventGo, true); SkillEventEditor.Hide(); SkillCreateAndChangeEditor.Hide(); SkillFilterEditor.Hide(); SkillEditorScene.UnLoad(); } #endregion #region//公有函数 //重新设置技能列表 public void ResetSkillList(string nameLimit) { _limitSkillName = nameLimit; var skillList = SkillEditorData.SkillList; _showSkillList.Clear(); for (int i = 0; i < skillList.Count; ++i) { if (string.IsNullOrEmpty(nameLimit) || skillList[i].Name.IndexOf(nameLimit) >= 0) { _showSkillList.Add(skillList[i].Name); } } } //设置选择的技能 public void SetSelectSkill(string skillName) { _curDragEvent = null; SkillEventEditor.Hide(); if (_showSkillList.Count > 0) { _curSelectSkillIndex = 0; _curSelectSkillName = _showSkillList[0]; } for (int i = 0; i < _showSkillList.Count; ++i) { if (_showSkillList[i] == skillName) { _curSelectSkillIndex = i; _curSelectSkillName = skillName; } } } #endregion } }