Gameplay Ingredients是一组用于 Unity 游戏的运行时和编辑器工具:一组脚本的集合,可在制作游戏和原型时简化简单的任务。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

434 行
17 KiB

using GameplayIngredients.Editor;
using UnityEditor;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
namespace GameplayIngredients.Comments.Editor
{
public class CommentEditor
{
SerializedObject serializedObject;
SerializedProperty rootMessage;
SerializedProperty replies;
SerializedProperty title;
SerializedProperty focus;
string editMessagePath;
bool editRoot => editMessagePath == rootMessage.propertyPath;
bool m_IsAsset;
public CommentEditor(SerializedObject serializedObject, SerializedProperty comment, bool isAsset = false)
{
this.serializedObject = serializedObject;
title = comment.FindPropertyRelative("title");
rootMessage = comment.FindPropertyRelative("message");
replies = comment.FindPropertyRelative("replies");
focus = comment.FindPropertyRelative("focus");
m_IsAsset = isAsset;
}
public bool DrawEditButton(bool edit)
{
return GUILayout.Toggle(edit, edit ? "Close" : "Edit", EditorStyles.miniButton, GUILayout.Width(64));
}
public void DrawComment(Comment comment, bool requireEdit = false)
{
if(requireEdit)
{
editMessagePath = rootMessage.propertyPath;
requireEdit = false;
}
using (new GUILayout.HorizontalScope())
{
TypeLabel(comment.computedType);
StateLabel(comment.computedState);
PriorityLabel(comment.computedPriority);
GUILayout.FlexibleSpace();
EditorGUI.BeginChangeCheck();
EditorGUI.BeginDisabledGroup(comment.message.from != CommentsWindow.user);
bool editRoot = DrawEditButton(this.editRoot);
EditorGUI.EndDisabledGroup();
if(EditorGUI.EndChangeCheck())
{
if (editRoot)
editMessagePath = rootMessage.propertyPath;
else
editMessagePath = string.Empty;
}
}
GUILayout.Space(6);
if(editRoot)
{
serializedObject.Update();
EditorGUILayout.PropertyField(title);
using(new GUILayout.HorizontalScope())
{
EditorGUILayout.PropertyField(focus);
if(!m_IsAsset && GUILayout.Button("Align to SceneView", GUILayout.ExpandWidth(true)))
{
focus.boolValue = true;
if(SceneView.lastActiveSceneView != null)
{
SceneComment c = serializedObject.targetObject as SceneComment;
c.gameObject.transform.position = SceneView.lastActiveSceneView.camera.transform.position;
c.gameObject.transform.rotation = SceneView.lastActiveSceneView.camera.transform.rotation;
}
}
}
serializedObject.ApplyModifiedProperties();
CommentsWindow.RequestRefresh();
}
else
{
GUILayout.Space(8);
using (new GUILayout.HorizontalScope())
{
GUILayout.Label(CommentEditor.GetPriorityContent(" " + title.stringValue, comment.computedPriority), Styles.title);
GUILayout.FlexibleSpace();
}
}
GUILayout.Space(6);
DrawMessage(rootMessage, -1);
int replyCount = replies.arraySize;
using(new GUILayout.HorizontalScope())
{
GUILayout.Space(16);
using(new GUILayout.VerticalScope())
{
for (int i = 0; i < replyCount; i++)
{
DrawMessage(replies.GetArrayElementAtIndex(i), i);
}
}
}
}
void DrawMessage(SerializedProperty message, int replyIndex)
{
using(new EditorGUILayout.VerticalScope(Styles.message))
{
SerializedProperty body = message.FindPropertyRelative("body");
SerializedProperty URL = message.FindPropertyRelative("URL");
SerializedProperty from = message.FindPropertyRelative("from");
SerializedProperty targets = message.FindPropertyRelative("attachedObjects");
SerializedProperty changeType = message.FindPropertyRelative("changeType");
SerializedProperty changeState = message.FindPropertyRelative("changeState");
SerializedProperty changePriority = message.FindPropertyRelative("changePriority");
SerializedProperty type = message.FindPropertyRelative("type");
SerializedProperty state = message.FindPropertyRelative("state");
SerializedProperty priority = message.FindPropertyRelative("priority");
if (editMessagePath == message.propertyPath)
{
message.serializedObject.Update();
EditorGUILayout.LabelField("Edit Message", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(body);
EditorGUILayout.PropertyField(URL);
EditorGUILayout.PropertyField(from);
using (new EditorGUI.IndentLevelScope(1))
{
EditorGUILayout.PropertyField(targets);
}
if(replyIndex >= 0)
{
EditorGUILayout.PropertyField(changeType);
EditorGUILayout.PropertyField(changeState);
EditorGUILayout.PropertyField(changePriority);
}
if(changeType.boolValue || replyIndex == -1)
EditorGUILayout.PropertyField(type);
if (changeState.boolValue || replyIndex == -1)
EditorGUILayout.PropertyField(state);
if (changePriority.boolValue || replyIndex == -1)
EditorGUILayout.PropertyField(priority);
using (new GUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
if (editMessagePath == message.propertyPath && GUILayout.Button("Apply", Styles.miniButton))
{
editMessagePath = string.Empty;
}
if (replyIndex == replies.arraySize - 1 && from.stringValue == CommentsWindow.user && GUILayout.Button("Delete", Styles.miniButton))
{
replies.serializedObject.Update();
replies.DeleteArrayElementAtIndex(replyIndex);
replies.serializedObject.ApplyModifiedProperties();
CommentsWindow.RequestRefresh();
}
}
GUILayout.Space(2);
message.serializedObject.ApplyModifiedProperties();
CommentsWindow.RequestRefresh();
}
else // Display Message
{
using (new GUILayout.HorizontalScope())
{
GUILayout.Label($"<b>From:</b> <color={(from.stringValue == CommentsWindow.user ? "lime" : "white")}><b>{from.stringValue}</b></color>", Styles.from);
GUILayout.FlexibleSpace();
if (replyIndex > -1 && from.stringValue == CommentsWindow.user
&& GUILayout.Button(Styles.edit, Styles.miniButton, GUILayout.Width(32)))
{
editMessagePath = message.propertyPath;
}
if (GUILayout.Button(Styles.reply, Styles.miniButton, GUILayout.Width(32)))
{
replies.serializedObject.Update();
int index = replies.arraySize;
replies.InsertArrayElementAtIndex(index);
var reply = replies.GetArrayElementAtIndex(index);
editMessagePath = reply.propertyPath;
reply.FindPropertyRelative("body").stringValue = string.Empty;
reply.FindPropertyRelative("URL").stringValue = string.Empty;
reply.FindPropertyRelative("from").stringValue = CommentsWindow.user;
reply.FindPropertyRelative("attachedObjects").ClearArray();
replies.serializedObject.ApplyModifiedProperties();
CommentsWindow.RequestRefresh();
}
}
EditorGUILayout.Space();
EditorGUILayout.LabelField(body.stringValue, Styles.multiline);
if (!string.IsNullOrEmpty(URL.stringValue))
{
GUILayout.Space(12);
GUILayout.Label("URL:", EditorStyles.boldLabel, GUILayout.Width(32));
Color b = GUI.backgroundColor;
GUI.backgroundColor = new Color(0, 0, 0, 0.2f);
if (GUILayout.Button($"<color=#44AAFFFF>{URL.stringValue}</color>", Styles.link))
{
Application.OpenURL(URL.stringValue);
}
GUI.backgroundColor = b;
}
if (targets.arraySize > 0)
{
GUILayout.Space(12);
EditorGUILayout.LabelField("Attached Objects:", EditorStyles.boldLabel);
EditorGUI.BeginDisabledGroup(true);
for (int i = 0; i < targets.arraySize; i++)
{
EditorGUILayout.ObjectField(targets.GetArrayElementAtIndex(i));
}
EditorGUI.EndDisabledGroup();
}
if(replyIndex == -1
|| changeType.boolValue
|| changeState.boolValue
|| changePriority.boolValue)
{
GUILayout.Space(12);
using (new GUILayout.HorizontalScope())
{
GUILayout.Label("<b>Set Properties :</b>", Styles.multiline);
if (replyIndex == -1 || changeType.boolValue)
TypeLabel((CommentType)type.intValue);
if (replyIndex == -1 || changeState.boolValue)
StateLabel((CommentState)state.intValue);
if (replyIndex == -1 || changePriority.boolValue)
PriorityLabel((CommentPriority)priority.intValue);
GUILayout.FlexibleSpace();
}
}
}
}
GUI.contentColor = Color.white;
}
void Separator()
{
Rect r = GUILayoutUtility.GetRect(0, 1, GUILayout.ExpandWidth(true));
EditorGUI.DrawRect(r, Color.gray);
}
public static Color GetTypeColor(CommentType type)
{
float sat = 0.3f;
float v = 1f;
switch (type)
{
default:
case CommentType.Info:
return Color.HSVToRGB(0.4f, 0, v);
case CommentType.Bug:
return Color.HSVToRGB(0.05f, sat, v);
case CommentType.Request:
return Color.HSVToRGB(0.15f, sat, v);
case CommentType.ToDo:
return Color.HSVToRGB(0.25f, sat, v);
}
}
public static Color GetStateColor(CommentState state)
{
float sat = 0.8f;
float v = 1f;
switch (state)
{
default:
case CommentState.Open:
return Color.HSVToRGB(0.3f, sat, v);
case CommentState.Blocked:
return Color.HSVToRGB(0.05f, sat, v);
case CommentState.Resolved:
return Color.HSVToRGB(0.5f, sat, v);
case CommentState.WontFix:
return Color.HSVToRGB(0.05f, sat, v);
case CommentState.Closed:
return Color.HSVToRGB(0.7f, 0f, v);
}
}
public static Color GetPriorityColor(CommentPriority priority)
{
float sat = 0.9f;
float v = 1f;
switch (priority)
{
default:
case CommentPriority.High:
return Color.HSVToRGB(0.02f, sat, v);
case CommentPriority.Medium:
return Color.HSVToRGB(0.15f, sat, v);
case CommentPriority.Low:
return Color.HSVToRGB(0.3f, sat, v);
}
}
public static void TypeLabel(CommentType value)
{
GUIUtils.ColoredLabel(value.ToString(), GetTypeColor(value));
}
public static void StateLabel(CommentState value)
{
GUIUtils.ColoredLabel(value.ToString(), GetStateColor(value));
}
public static void PriorityLabel(CommentPriority value)
{
GUIUtils.ColoredLabel(value.ToString(), GetPriorityColor(value));
}
public static GUIContent GetPriorityContent(string text, CommentPriority priority)
{
return new GUIContent(text, GetPriorityTexture(priority));
}
public static Texture GetPriorityTexture(CommentPriority priority)
{
switch (priority)
{
case CommentPriority.High:
return CheckResult.GetIcon(CheckResult.Result.Failed);
case CommentPriority.Medium:
return CheckResult.GetIcon(CheckResult.Result.Warning);
default:
case CommentPriority.Low:
return CheckResult.GetIcon(CheckResult.Result.Notice);
}
}
static class Styles
{
public static GUIStyle title;
public static GUIStyle from;
public static GUIStyle link;
public static GUIStyle multiline;
public static GUIStyle coloredLabel;
public static GUIStyle message;
public static GUIStyle miniButton;
public static GUIContent reply;
public static GUIContent edit;
static Styles()
{
title = new GUIStyle(EditorStyles.boldLabel);
title.fontSize = 16;
from = new GUIStyle(EditorStyles.label);
from.fontSize = 12;
from.richText = true;
link = new GUIStyle(EditorStyles.label);
link.fontSize = 12;
link.richText = true;
link.margin = new RectOffset(0, 0, 4, 4);
link.padding = new RectOffset(2, 2, 2, 2);
SetWhiteBG(link);
multiline = new GUIStyle(EditorStyles.label);
multiline.wordWrap = true;
multiline.richText = true;
multiline.fontSize = 13;
coloredLabel = new GUIStyle(EditorStyles.label);
coloredLabel.fontSize = 12;
coloredLabel.padding = new RectOffset(12, 12, 2, 2);
message = new GUIStyle(EditorStyles.helpBox);
SetWhiteBG(message);
miniButton = new GUIStyle(EditorStyles.miniButton);
miniButton.fontSize = 10;
miniButton.fixedHeight = 16;
SetWhiteBG(miniButton);
edit = new GUIContent(EditorGUIUtility.Load("Packages/net.peeweek.gameplay-ingredients/Icons/GUI/edit.png") as Texture);
reply = new GUIContent(EditorGUIUtility.Load("Packages/net.peeweek.gameplay-ingredients/Icons/GUI/reply.png") as Texture);
}
static Texture2D flat;
static void SetWhiteBG(GUIStyle style)
{
if(flat == null)
{
flat = new Texture2D(1, 1, DefaultFormat.LDR, TextureCreationFlags.None);
flat.SetPixel(0, 0, new Color(0.5f, 0.5f, 0.5f, 0.3f));
flat.Apply();
}
SetBGTexture(style, flat);
}
static void SetBGTexture(GUIStyle style, Texture2D texture)
{
style.onActive.background = texture;
style.active.background = texture;
style.onFocused.background = texture;
style.focused.background = texture;
style.onHover.background = texture;
style.hover.background = texture;
style.onNormal.background = texture;
style.normal.background = texture;
}
}
}
}