浏览代码
Scene/Project Comments (#23)
Scene/Project Comments (#23)
* Base Work * Comments in scene base work * Comments Browser Window * Updated Icon / List / Editor * Filtering Comments + UsePOV * GUI Styling * Tweak Priorities * Work on Labels * Code cleanup * Comment Editor * Work on threads * Formatting/Editring Messages * Polishing UI * Refactor comments to fix serialization * Better property management, added filtering by name * Refactored focus * String filter * Message UI fixes + edit button fix * Handled Scene Change * Updated Changelog * Align with view button * Add new Comment Button + Manage on Delete * Toggle Preferences * Comments are displayed as edit mode upon creation. * Comment Assets * Fixed Accessibility / Script Compilation * Sorting Columns * Added Priority Column/main
GitHub
4 年前
当前提交
a25caceb
共有 30 个文件被更改,包括 1764 次插入 和 4 次删除
-
1CHANGELOG.md
-
12Editor/AdvancedHierarchyView/AdvancedHierarchyView.cs
-
20Editor/SceneViewToolbar.cs
-
8Editor/Comments.meta
-
34Editor/GUIUtils.cs
-
11Editor/GUIUtils.cs.meta
-
4Icons/GUI/edit.png
-
116Icons/GUI/edit.png.meta
-
4Icons/GUI/reply.png
-
116Icons/GUI/reply.png.meta
-
46Icons/Misc/ic-comment.png
-
116Icons/Misc/ic-comment.png.meta
-
9Icons/Misc/ic-comment.png~
-
8Runtime/Comments.meta
-
41Editor/Comments/CommentAsset.cs
-
11Editor/Comments/CommentAsset.cs.meta
-
57Editor/Comments/CommentAssetEditor.cs
-
11Editor/Comments/CommentAssetEditor.cs.meta
-
434Editor/Comments/CommentEditor.cs
-
11Editor/Comments/CommentEditor.cs.meta
-
423Editor/Comments/CommentsWindow.cs
-
11Editor/Comments/CommentsWindow.cs.meta
-
73Editor/Comments/SceneCommentEditor.cs
-
11Editor/Comments/SceneCommentEditor.cs.meta
-
130Runtime/Comments/Comment.cs
-
11Runtime/Comments/Comment.cs.meta
-
28Runtime/Comments/SceneComment.cs
-
11Runtime/Comments/SceneComment.cs.meta
|
|||
fileFormatVersion: 2 |
|||
guid: a42fe31621978284c8c2c0c11c8516d5 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
using UnityEditor; |
|||
|
|||
namespace GameplayIngredients |
|||
{ |
|||
static class GUIUtils |
|||
{ |
|||
public static void ColoredLabel(string text, Color color) |
|||
{ |
|||
GUIContent label = new GUIContent(text); |
|||
Rect r = GUILayoutUtility.GetRect(label, Styles.coloredLabel); |
|||
EditorGUI.DrawRect(r, color); |
|||
var r2 = new RectOffset(1, 1, 1, 1).Remove(r); |
|||
EditorGUI.DrawRect(r2, color * new Color(.5f, .5f, .5f, 1f)); |
|||
GUI.contentColor = color * 2; |
|||
GUI.Label(r, label, Styles.coloredLabel); |
|||
GUI.contentColor = Color.white; |
|||
} |
|||
|
|||
static class Styles |
|||
{ |
|||
public static GUIStyle coloredLabel; |
|||
static Styles() |
|||
{ |
|||
coloredLabel = new GUIStyle(EditorStyles.label); |
|||
coloredLabel.fontStyle = FontStyle.Bold; |
|||
coloredLabel.fontSize = 10; |
|||
coloredLabel.padding = new RectOffset(6, 6, 2, 2); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|
|||
fileFormatVersion: 2 |
|||
guid: e9a280e27f38ebe4984b39d341cacd4f |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 98d201cc66f05344ebd036a7a493e5c7 |
|||
TextureImporter: |
|||
internalIDToNameTable: [] |
|||
externalObjects: {} |
|||
serializedVersion: 11 |
|||
mipmaps: |
|||
mipMapMode: 0 |
|||
enableMipMap: 0 |
|||
sRGBTexture: 1 |
|||
linearTexture: 0 |
|||
fadeOut: 0 |
|||
borderMipMap: 0 |
|||
mipMapsPreserveCoverage: 0 |
|||
alphaTestReferenceValue: 0.5 |
|||
mipMapFadeDistanceStart: 1 |
|||
mipMapFadeDistanceEnd: 3 |
|||
bumpmap: |
|||
convertToNormalMap: 0 |
|||
externalNormalMap: 0 |
|||
heightScale: 0.25 |
|||
normalMapFilter: 0 |
|||
isReadable: 0 |
|||
streamingMipmaps: 0 |
|||
streamingMipmapsPriority: 0 |
|||
grayScaleToAlpha: 0 |
|||
generateCubemap: 6 |
|||
cubemapConvolution: 0 |
|||
seamlessCubemap: 0 |
|||
textureFormat: 1 |
|||
maxTextureSize: 2048 |
|||
textureSettings: |
|||
serializedVersion: 2 |
|||
filterMode: -1 |
|||
aniso: 1 |
|||
mipBias: -100 |
|||
wrapU: 1 |
|||
wrapV: 1 |
|||
wrapW: -1 |
|||
nPOTScale: 0 |
|||
lightmap: 0 |
|||
compressionQuality: 50 |
|||
spriteMode: 0 |
|||
spriteExtrude: 1 |
|||
spriteMeshType: 1 |
|||
alignment: 0 |
|||
spritePivot: {x: 0.5, y: 0.5} |
|||
spritePixelsToUnits: 100 |
|||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} |
|||
spriteGenerateFallbackPhysicsShape: 1 |
|||
alphaUsage: 1 |
|||
alphaIsTransparency: 1 |
|||
spriteTessellationDetail: -1 |
|||
textureType: 2 |
|||
textureShape: 1 |
|||
singleChannelComponent: 0 |
|||
maxTextureSizeSet: 0 |
|||
compressionQualitySet: 0 |
|||
textureFormatSet: 0 |
|||
applyGammaDecoding: 0 |
|||
platformSettings: |
|||
- serializedVersion: 3 |
|||
buildTarget: DefaultTexturePlatform |
|||
maxTextureSize: 2048 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 0 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Standalone |
|||
maxTextureSize: 2048 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 0 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Android |
|||
maxTextureSize: 2048 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 0 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
spriteSheet: |
|||
serializedVersion: 2 |
|||
sprites: [] |
|||
outline: [] |
|||
physicsShape: [] |
|||
bones: [] |
|||
spriteID: |
|||
internalID: 0 |
|||
vertices: [] |
|||
indices: |
|||
edges: [] |
|||
weights: [] |
|||
secondaryTextures: [] |
|||
spritePackingTag: |
|||
pSDRemoveMatte: 0 |
|||
pSDShowRemoveMatteOption: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 773f17336a081c741a9568d4b2fe5867 |
|||
TextureImporter: |
|||
internalIDToNameTable: [] |
|||
externalObjects: {} |
|||
serializedVersion: 11 |
|||
mipmaps: |
|||
mipMapMode: 0 |
|||
enableMipMap: 0 |
|||
sRGBTexture: 1 |
|||
linearTexture: 0 |
|||
fadeOut: 0 |
|||
borderMipMap: 0 |
|||
mipMapsPreserveCoverage: 0 |
|||
alphaTestReferenceValue: 0.5 |
|||
mipMapFadeDistanceStart: 1 |
|||
mipMapFadeDistanceEnd: 3 |
|||
bumpmap: |
|||
convertToNormalMap: 0 |
|||
externalNormalMap: 0 |
|||
heightScale: 0.25 |
|||
normalMapFilter: 0 |
|||
isReadable: 0 |
|||
streamingMipmaps: 0 |
|||
streamingMipmapsPriority: 0 |
|||
grayScaleToAlpha: 0 |
|||
generateCubemap: 6 |
|||
cubemapConvolution: 0 |
|||
seamlessCubemap: 0 |
|||
textureFormat: 1 |
|||
maxTextureSize: 2048 |
|||
textureSettings: |
|||
serializedVersion: 2 |
|||
filterMode: -1 |
|||
aniso: 1 |
|||
mipBias: -100 |
|||
wrapU: 1 |
|||
wrapV: 1 |
|||
wrapW: -1 |
|||
nPOTScale: 0 |
|||
lightmap: 0 |
|||
compressionQuality: 50 |
|||
spriteMode: 0 |
|||
spriteExtrude: 1 |
|||
spriteMeshType: 1 |
|||
alignment: 0 |
|||
spritePivot: {x: 0.5, y: 0.5} |
|||
spritePixelsToUnits: 100 |
|||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} |
|||
spriteGenerateFallbackPhysicsShape: 1 |
|||
alphaUsage: 1 |
|||
alphaIsTransparency: 1 |
|||
spriteTessellationDetail: -1 |
|||
textureType: 2 |
|||
textureShape: 1 |
|||
singleChannelComponent: 0 |
|||
maxTextureSizeSet: 0 |
|||
compressionQualitySet: 0 |
|||
textureFormatSet: 0 |
|||
applyGammaDecoding: 0 |
|||
platformSettings: |
|||
- serializedVersion: 3 |
|||
buildTarget: DefaultTexturePlatform |
|||
maxTextureSize: 2048 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 0 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Standalone |
|||
maxTextureSize: 2048 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 0 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Android |
|||
maxTextureSize: 2048 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 0 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
spriteSheet: |
|||
serializedVersion: 2 |
|||
sprites: [] |
|||
outline: [] |
|||
physicsShape: [] |
|||
bones: [] |
|||
spriteID: |
|||
internalID: 0 |
|||
vertices: [] |
|||
indices: |
|||
edges: [] |
|||
weights: [] |
|||
secondaryTextures: [] |
|||
spritePackingTag: |
|||
pSDRemoveMatte: 0 |
|||
pSDShowRemoveMatteOption: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 2db418d0b9151704f87ace549b922c16 |
|||
TextureImporter: |
|||
internalIDToNameTable: [] |
|||
externalObjects: {} |
|||
serializedVersion: 11 |
|||
mipmaps: |
|||
mipMapMode: 0 |
|||
enableMipMap: 0 |
|||
sRGBTexture: 1 |
|||
linearTexture: 0 |
|||
fadeOut: 0 |
|||
borderMipMap: 0 |
|||
mipMapsPreserveCoverage: 0 |
|||
alphaTestReferenceValue: 0.5 |
|||
mipMapFadeDistanceStart: 1 |
|||
mipMapFadeDistanceEnd: 3 |
|||
bumpmap: |
|||
convertToNormalMap: 0 |
|||
externalNormalMap: 0 |
|||
heightScale: 0.25 |
|||
normalMapFilter: 0 |
|||
isReadable: 0 |
|||
streamingMipmaps: 0 |
|||
streamingMipmapsPriority: 0 |
|||
grayScaleToAlpha: 0 |
|||
generateCubemap: 6 |
|||
cubemapConvolution: 0 |
|||
seamlessCubemap: 0 |
|||
textureFormat: 1 |
|||
maxTextureSize: 2048 |
|||
textureSettings: |
|||
serializedVersion: 2 |
|||
filterMode: -1 |
|||
aniso: 1 |
|||
mipBias: -100 |
|||
wrapU: 1 |
|||
wrapV: 1 |
|||
wrapW: -1 |
|||
nPOTScale: 0 |
|||
lightmap: 0 |
|||
compressionQuality: 50 |
|||
spriteMode: 0 |
|||
spriteExtrude: 1 |
|||
spriteMeshType: 1 |
|||
alignment: 0 |
|||
spritePivot: {x: 0.5, y: 0.5} |
|||
spritePixelsToUnits: 100 |
|||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} |
|||
spriteGenerateFallbackPhysicsShape: 1 |
|||
alphaUsage: 1 |
|||
alphaIsTransparency: 1 |
|||
spriteTessellationDetail: -1 |
|||
textureType: 2 |
|||
textureShape: 1 |
|||
singleChannelComponent: 0 |
|||
maxTextureSizeSet: 0 |
|||
compressionQualitySet: 0 |
|||
textureFormatSet: 0 |
|||
applyGammaDecoding: 0 |
|||
platformSettings: |
|||
- serializedVersion: 3 |
|||
buildTarget: DefaultTexturePlatform |
|||
maxTextureSize: 2048 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 0 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Standalone |
|||
maxTextureSize: 2048 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 0 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Android |
|||
maxTextureSize: 2048 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 0 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
spriteSheet: |
|||
serializedVersion: 2 |
|||
sprites: [] |
|||
outline: [] |
|||
physicsShape: [] |
|||
bones: [] |
|||
spriteID: |
|||
internalID: 0 |
|||
vertices: [] |
|||
indices: |
|||
edges: [] |
|||
weights: [] |
|||
secondaryTextures: [] |
|||
spritePackingTag: |
|||
pSDRemoveMatte: 0 |
|||
pSDShowRemoveMatteOption: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 0f301a8303ad194429c4dccd1ba83a6b |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using GameplayIngredients.Editor; |
|||
using UnityEngine; |
|||
using UnityEditor; |
|||
|
|||
namespace GameplayIngredients.Comments.Editor |
|||
{ |
|||
class CommentAsset : ScriptableObject |
|||
{ |
|||
public Comment comment => m_Comment; |
|||
|
|||
[SerializeField] |
|||
Comment m_Comment; |
|||
|
|||
[SerializeField, HideInInspector] |
|||
public bool firstTimeEdit; |
|||
|
|||
private void Reset() |
|||
{ |
|||
SetDefault(); |
|||
firstTimeEdit = true; |
|||
} |
|||
|
|||
public void SetDefault() |
|||
{ |
|||
m_Comment.title = "New Comment"; |
|||
m_Comment.message.body = "This is a new Comment, it can describe a problem in the scene, a note to the attention of other user, or a bug encountered."; |
|||
m_Comment.message.from = Comment.currentUser; |
|||
m_Comment.message.type = CommentType.Info; |
|||
m_Comment.message.priority = CommentPriority.Low; |
|||
m_Comment.message.state = CommentState.Open; |
|||
} |
|||
|
|||
[MenuItem("Assets/Create/Comment")] |
|||
static void CreateAsset() |
|||
{ |
|||
AssetFactory.CreateAssetInProjectWindow<CommentAsset>("Packages/net.peeweek.gameplay-ingredients/Icons/Misc/ic-comment.png", "New Comment.asset"); |
|||
} |
|||
|
|||
} |
|||
} |
|||
|
|
|||
fileFormatVersion: 2 |
|||
guid: 953948be2cd259646acba568317eaf8c |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {fileID: 2800000, guid: 2db418d0b9151704f87ace549b922c16, type: 3} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEditor; |
|||
using UnityEngine; |
|||
|
|||
namespace GameplayIngredients.Comments.Editor |
|||
{ |
|||
[CustomEditor(typeof(CommentAsset))] |
|||
public class CommentAssetEditor : UnityEditor.Editor |
|||
{ |
|||
[SerializeField] |
|||
CommentAsset commentAsset; |
|||
[SerializeField] |
|||
SerializedProperty m_Comment; |
|||
|
|||
[SerializeField] |
|||
CommentEditor m_CommentEditor; |
|||
|
|||
public static void RequestEdit() { m_NeedEditNext = true; } |
|||
public static bool m_NeedEditNext = false; |
|||
|
|||
private void OnEnable() |
|||
{ |
|||
UpdateComment(); |
|||
if (commentAsset.comment.focus) |
|||
EditorGUIUtility.PingObject(commentAsset); |
|||
} |
|||
|
|||
void UpdateComment() |
|||
{ |
|||
if (m_Comment == null) |
|||
m_Comment = serializedObject.FindProperty("m_Comment"); |
|||
|
|||
if (m_CommentEditor == null) |
|||
m_CommentEditor = new CommentEditor(serializedObject, m_Comment, true); |
|||
|
|||
commentAsset = (serializedObject.targetObject as CommentAsset); |
|||
|
|||
if (commentAsset.firstTimeEdit) |
|||
RequestEdit(); |
|||
} |
|||
|
|||
public override void OnInspectorGUI() |
|||
{ |
|||
UpdateComment(); |
|||
GUILayout.Space(4); |
|||
m_CommentEditor.DrawComment(commentAsset.comment, m_NeedEditNext); |
|||
|
|||
if (m_NeedEditNext) |
|||
{ |
|||
m_NeedEditNext = false; |
|||
commentAsset.firstTimeEdit = false; |
|||
} |
|||
|
|||
GUILayout.Space(16); |
|||
} |
|||
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 59a242602deca20438f9668ce3b67225 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
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; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|
|||
fileFormatVersion: 2 |
|||
guid: c6a9a77cca5b7ac4ba42c73ad1cc400a |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using GameplayIngredients.Editor; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEditor; |
|||
using UnityEditor.SceneManagement; |
|||
using UnityEngine; |
|||
using UnityEngine.SceneManagement; |
|||
|
|||
namespace GameplayIngredients.Comments.Editor |
|||
{ |
|||
public class CommentsWindow : EditorWindow |
|||
{ |
|||
static CommentsWindow s_Instance; |
|||
|
|||
[MenuItem("Window/Gameplay Ingredients/Comments")] |
|||
public static void Open() |
|||
{ |
|||
s_Instance = EditorWindow.GetWindow<CommentsWindow>(); |
|||
} |
|||
|
|||
private void OnEnable() |
|||
{ |
|||
titleContent = EditorGUIUtility.IconContent("console.infoicon.inactive.sml"); |
|||
titleContent.text = "Comments"; |
|||
minSize = new Vector2(680, 180); |
|||
Refresh(); |
|||
EditorSceneManager.sceneOpened += EditorSceneManager_sceneOpened; |
|||
EditorSceneManager.sceneClosed += EditorSceneManager_sceneClosed; |
|||
EditorSceneSetup.onSetupLoaded += EditorSceneSetup_onSetupLoaded; |
|||
EditorSceneManager.sceneLoaded += SceneManager_sceneLoaded; |
|||
EditorSceneManager.sceneUnloaded += SceneManager_sceneUnloaded; |
|||
} |
|||
|
|||
private void EditorSceneSetup_onSetupLoaded(EditorSceneSetup setup) |
|||
{ |
|||
Refresh(); |
|||
} |
|||
|
|||
private void EditorSceneManager_sceneClosed(Scene scene) |
|||
{ |
|||
Refresh(); |
|||
} |
|||
|
|||
private void EditorSceneManager_sceneOpened(Scene scene, OpenSceneMode mode) |
|||
{ |
|||
Refresh(); |
|||
} |
|||
|
|||
private void SceneManager_sceneUnloaded(Scene arg0) |
|||
{ |
|||
Refresh(); |
|||
} |
|||
|
|||
private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1) |
|||
{ |
|||
Refresh(); |
|||
} |
|||
|
|||
private void OnDisable() |
|||
{ |
|||
EditorSceneManager.sceneOpened -= EditorSceneManager_sceneOpened; |
|||
EditorSceneManager.sceneClosed -= EditorSceneManager_sceneClosed; |
|||
EditorSceneSetup.onSetupLoaded -= EditorSceneSetup_onSetupLoaded; |
|||
EditorSceneManager.sceneLoaded -= SceneManager_sceneLoaded; |
|||
EditorSceneManager.sceneUnloaded -= SceneManager_sceneUnloaded; |
|||
} |
|||
|
|||
enum SortMode |
|||
{ |
|||
None, |
|||
Name, |
|||
Description, |
|||
Location, |
|||
From, |
|||
Type, |
|||
Priority, |
|||
State |
|||
} |
|||
|
|||
SortMode sortMode = SortMode.None; |
|||
|
|||
public enum UserFilter |
|||
{ |
|||
MyComments, |
|||
AllComments, |
|||
} |
|||
|
|||
const string kPrefixPreference = "GameplayIngredients.Comments."; |
|||
static readonly string kUserFilterPreference = $"{kPrefixPreference}UserFilter"; |
|||
static readonly string kUserPreference = $"{kPrefixPreference}User"; |
|||
|
|||
static UserFilter userFilter |
|||
{ |
|||
get { return (UserFilter)EditorPrefs.GetInt(kUserFilterPreference, 0); } |
|||
set { EditorPrefs.SetInt(kUserFilterPreference, (int)value); } |
|||
} |
|||
|
|||
[InitializeOnLoadMethod] |
|||
static void SetDefaultUser() |
|||
{ |
|||
var user = EditorPrefs.GetString(kUserPreference, ""); |
|||
if(user == "") |
|||
{ |
|||
user = System.Security.Principal.WindowsIdentity.GetCurrent().Name; |
|||
} |
|||
} |
|||
|
|||
public static string user |
|||
{ |
|||
get { return EditorPrefs.GetString(kUserPreference, ""); } |
|||
set { EditorPrefs.SetString(kUserPreference, value); } |
|||
} |
|||
|
|||
bool GetShowPref(Enum item) |
|||
{ |
|||
string name = $"{kPrefixPreference}.Show.{item.GetType().Name}.{item}"; |
|||
return EditorPrefs.GetBool(name, true); |
|||
} |
|||
|
|||
void SetShowPref(Enum item, bool value) |
|||
{ |
|||
EditorPrefs.SetBool($"{kPrefixPreference}.Show.{item.GetType().Name}.{item}", value); |
|||
} |
|||
|
|||
void ToggleShowPref(Enum item) |
|||
{ |
|||
SetShowPref(item, !GetShowPref(item)); |
|||
} |
|||
|
|||
void MenuToggleShowPref(object item) |
|||
{ |
|||
ToggleShowPref(item as Enum); |
|||
} |
|||
|
|||
int highCount => results == null ? 0 : results.Count(o => o.Item1.computedPriority == CommentPriority.High); |
|||
int mediumCount => results == null ? 0 : results.Count(o => o.Item1.computedPriority == CommentPriority.Medium); |
|||
int lowCount => results == null ? 0 : results.Count(o => o.Item1.computedPriority == CommentPriority.Low); |
|||
|
|||
string searchFilter; |
|||
Vector2 scrollPosition; |
|||
|
|||
bool MatchFilter(UnityEngine.Object obj, Comment comment, string filter) |
|||
{ |
|||
filter = filter.ToLowerInvariant(); |
|||
return obj.name.Contains(filter) |
|||
|| MatchFilter(comment, filter) |
|||
; |
|||
} |
|||
|
|||
bool MatchFilter(Comment comment, string filter) |
|||
{ |
|||
return comment.title.ToLowerInvariant().Contains(filter) |
|||
|| comment.users.Any(o => o.ToLowerInvariant().Contains(filter)) |
|||
|| MatchFilter(comment.message, filter) |
|||
|| comment.replies.Any(m => MatchFilter(m, filter)) |
|||
; |
|||
} |
|||
|
|||
bool MatchFilter(CommentMessage message, string filter) |
|||
{ |
|||
return message.body.ToLowerInvariant().Contains(filter) |
|||
|| message.from.ToLowerInvariant().Contains(filter) |
|||
|| message.attachedObjects.Any(o => o.name.ToLowerInvariant().Contains(filter)) |
|||
|| message.URL.ToLowerInvariant().Contains(filter) |
|||
; |
|||
} |
|||
|
|||
private void OnGUI() |
|||
{ |
|||
// Toolbar
|
|||
using (new GUILayout.HorizontalScope(EditorStyles.toolbar)) |
|||
{ |
|||
if (GUILayout.Button("+", EditorStyles.toolbarButton, GUILayout.Width(24))) |
|||
{ |
|||
SceneCommentEditor.CreateComment(); |
|||
Refresh(); |
|||
} |
|||
|
|||
if (GUILayout.Button(EditorGUIUtility.IconContent("Refresh"), EditorStyles.toolbarButton, GUILayout.Width(24))) |
|||
Refresh(); |
|||
|
|||
searchFilter = EditorGUILayout.DelayedTextField(searchFilter, EditorStyles.toolbarSearchField, GUILayout.ExpandWidth(true)); |
|||
userFilter = (UserFilter)EditorGUILayout.EnumPopup(userFilter, EditorStyles.toolbarDropDown, GUILayout.Width(128)); |
|||
if (GUILayout.Button("Type", EditorStyles.toolbarDropDown, GUILayout.Width(64))) |
|||
{ |
|||
var menu = new GenericMenu(); |
|||
menu.AddItem(new GUIContent(CommentType.Bug.ToString()), GetShowPref(CommentType.Bug), MenuToggleShowPref, CommentType.Bug); |
|||
menu.AddItem(new GUIContent(CommentType.Info.ToString()), GetShowPref(CommentType.Info), MenuToggleShowPref, CommentType.Info); |
|||
menu.AddItem(new GUIContent(CommentType.Request.ToString()), GetShowPref(CommentType.Request), MenuToggleShowPref, CommentType.Request); |
|||
menu.AddItem(new GUIContent(CommentType.ToDo.ToString()), GetShowPref(CommentType.ToDo), MenuToggleShowPref, CommentType.ToDo); |
|||
menu.DropDown(new Rect(position.width - 240, 10, 12, 12)); |
|||
} |
|||
if (GUILayout.Button("State", EditorStyles.toolbarDropDown, GUILayout.Width(64))) |
|||
{ |
|||
var menu = new GenericMenu(); |
|||
menu.AddItem(new GUIContent(CommentState.Open.ToString()), GetShowPref(CommentState.Open), MenuToggleShowPref, CommentState.Open); |
|||
menu.AddItem(new GUIContent(CommentState.Resolved.ToString()), GetShowPref(CommentState.Resolved), MenuToggleShowPref, CommentState.Resolved); |
|||
menu.AddItem(new GUIContent(CommentState.Closed.ToString()), GetShowPref(CommentState.Closed), MenuToggleShowPref, CommentState.Closed); |
|||
menu.AddItem(new GUIContent(CommentState.WontFix.ToString()), GetShowPref(CommentState.WontFix), MenuToggleShowPref, CommentState.WontFix); |
|||
menu.AddItem(new GUIContent(CommentState.Blocked.ToString()), GetShowPref(CommentState.Blocked), MenuToggleShowPref, CommentState.Blocked); |
|||
menu.DropDown(new Rect(position.width - 176, 10, 12, 12)); |
|||
} |
|||
GUILayout.Space(16); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
bool showHigh = GUILayout.Toggle(GetShowPref(CommentPriority.High), CommentEditor.GetPriorityContent(highCount.ToString(), CommentPriority.High), EditorStyles.toolbarButton, GUILayout.Width(32)); |
|||
bool showMedium = GUILayout.Toggle(GetShowPref(CommentPriority.Medium), CommentEditor.GetPriorityContent(mediumCount.ToString(), CommentPriority.Medium), EditorStyles.toolbarButton, GUILayout.Width(32)); |
|||
bool showLow = GUILayout.Toggle(GetShowPref(CommentPriority.Low), CommentEditor.GetPriorityContent(lowCount.ToString(), CommentPriority.Low), EditorStyles.toolbarButton, GUILayout.Width(32)); |
|||
if(EditorGUI.EndChangeCheck()) |
|||
{ |
|||
SetShowPref(CommentPriority.High, showHigh); |
|||
SetShowPref(CommentPriority.Medium, showMedium); |
|||
SetShowPref(CommentPriority.Low, showMedium); |
|||
} |
|||
} |
|||
|
|||
GUI.backgroundColor = Color.white * 1.25f; |
|||
|
|||
// Header
|
|||
using (new GUILayout.HorizontalScope(EditorStyles.toolbar)) |
|||
{ |
|||
SortButton("Commment", SortMode.Name, 180); |
|||
SortButton("Description", SortMode.Description, position.width - 541); |
|||
SortButton("Location", SortMode.Location, 100); |
|||
SortButton("From", SortMode.From, 80); |
|||
SortButton("Type", SortMode.Type, 50); |
|||
SortButton("Priority", SortMode.Priority, 60); |
|||
SortButton("State", SortMode.State, 70); |
|||
} |
|||
GUI.backgroundColor = Color.white; |
|||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); |
|||
|
|||
|
|||
|
|||
int i = 0; |
|||
// Lines
|
|||
foreach (var comment in results) |
|||
{ |
|||
if(comment.Item2 == null) |
|||
{ |
|||
Refresh(); |
|||
break; |
|||
} |
|||
|
|||
if(comment.Item2 is SceneComment) |
|||
{ |
|||
|
|||
if (!DrawComment(comment.Item1, i, (comment.Item2 as SceneComment).gameObject)) |
|||
continue; |
|||
} |
|||
else |
|||
{ |
|||
if (!DrawComment(comment.Item1, i, comment.Item2 as CommentAsset)) |
|||
continue; |
|||
} |
|||
i++; |
|||
} |
|||
|
|||
EditorGUILayout.EndScrollView(); |
|||
} |
|||
|
|||
void SortButton(string label, SortMode mode, float width) |
|||
{ |
|||
if (GUILayout.Button(label, sortMode == mode ? Styles.sortHeader : Styles.header, GUILayout.Width(width))) |
|||
{ |
|||
if(Event.current.shift) |
|||
sortMode = SortMode.None; |
|||
else if (sortMode != mode) |
|||
sortMode = mode; |
|||
} |
|||
SortResults(); |
|||
} |
|||
|
|||
bool DrawComment(Comment comment, int index, UnityEngine.Object parent) |
|||
{ |
|||
if (comment.computedState == CommentState.Open && !GetShowPref(CommentState.Open)) return false; |
|||
if (comment.computedState == CommentState.Resolved && !GetShowPref(CommentState.Resolved)) return false; |
|||
if (comment.computedState == CommentState.Blocked && !GetShowPref(CommentState.Blocked)) return false; |
|||
if (comment.computedState == CommentState.WontFix && !GetShowPref(CommentState.WontFix)) return false; |
|||
if (comment.computedState == CommentState.Closed && !GetShowPref(CommentState.Closed)) return false; |
|||
|
|||
if (comment.computedType == CommentType.Bug && !GetShowPref(CommentType.Bug)) return false; |
|||
if (comment.computedType == CommentType.Info && !GetShowPref(CommentType.Info)) return false; |
|||
if (comment.computedType == CommentType.Request && !GetShowPref(CommentType.Request)) return false; |
|||
if (comment.computedType == CommentType.ToDo && !GetShowPref(CommentType.ToDo)) return false; |
|||
|
|||
if (comment.computedPriority == CommentPriority.High && !GetShowPref(CommentPriority.High)) return false; |
|||
if (comment.computedPriority == CommentPriority.Medium && !GetShowPref(CommentPriority.Medium)) return false; |
|||
if (comment.computedPriority == CommentPriority.Low && !GetShowPref(CommentPriority.Low)) return false; |
|||
|
|||
if (userFilter == UserFilter.MyComments && !comment.users.Contains(user)) |
|||
return false; |
|||
|
|||
if (!string.IsNullOrEmpty(searchFilter) && !MatchFilter(parent, comment, searchFilter)) |
|||
return false; |
|||
|
|||
GUI.backgroundColor = (index % 2 == 0) ? Color.white : Color.white * 0.9f; |
|||
using (new GUILayout.HorizontalScope(EditorStyles.toolbar)) |
|||
{ |
|||
if (GUILayout.Button(CommentEditor.GetPriorityContent(comment.title, comment.computedPriority), Styles.line, GUILayout.Width(180))) |
|||
Selection.activeObject = parent; |
|||
|
|||
GUILayout.Label(comment.message.body, Styles.line, GUILayout.Width(position.width - 541)); |
|||
if(parent is GameObject) |
|||
GUILayout.Label((parent as GameObject).scene.name, Styles.line, GUILayout.Width(100)); |
|||
else |
|||
GUILayout.Label((parent as CommentAsset).name, Styles.line, GUILayout.Width(100)); |
|||
|
|||
GUILayout.Label(comment.message.from, Styles.line, GUILayout.Width(80)); |
|||
GUILayout.Label(comment.computedType.ToString(), Styles.line, GUILayout.Width(50)); |
|||
GUILayout.Label(comment.computedPriority.ToString(), Styles.line, GUILayout.Width(60)); |
|||
GUILayout.Label(comment.computedState.ToString(), Styles.line, GUILayout.Width(70)); |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
|
|||
|
|||
List<Tuple<Comment, UnityEngine.Object>> results; |
|||
|
|||
public static void RequestRefresh() |
|||
{ |
|||
if (s_Instance != null) |
|||
s_Instance.Refresh(); |
|||
|
|||
} |
|||
|
|||
void Refresh() |
|||
{ |
|||
if (results == null) |
|||
results = new List<Tuple<Comment, UnityEngine.Object>>(); |
|||
else |
|||
results.Clear(); |
|||
|
|||
foreach(var obj in Resources.FindObjectsOfTypeAll(typeof(SceneComment))) |
|||
{ |
|||
results.Add(new Tuple<Comment, UnityEngine.Object>((obj as SceneComment).comment, obj)); |
|||
} |
|||
foreach (var guid in AssetDatabase.FindAssets($"t:{typeof(CommentAsset).Name}")) |
|||
{ |
|||
CommentAsset ca = AssetDatabase.LoadAssetAtPath<CommentAsset>(AssetDatabase.GUIDToAssetPath(guid)); |
|||
results.Add(new Tuple<Comment, UnityEngine.Object>(ca.comment, ca)); |
|||
} |
|||
SortResults(); |
|||
Repaint(); |
|||
} |
|||
|
|||
void SortResults() |
|||
{ |
|||
if (results == null) |
|||
return; |
|||
switch (sortMode) |
|||
{ |
|||
case SortMode.None: |
|||
break; |
|||
case SortMode.Name: |
|||
results = results.OrderBy(o => o.Item2.name).ToList(); |
|||
break; |
|||
case SortMode.Description: |
|||
results = results.OrderBy(o => o.Item1.title).ToList(); |
|||
break; |
|||
case SortMode.Location: |
|||
results = results.OrderBy(o => o.Item2 is GameObject ? (o.Item2 as GameObject).scene.name : o.Item2.name ).ToList(); |
|||
break; |
|||
case SortMode.From: |
|||
results = results.OrderBy(o => o.Item1.message.from).ToList(); |
|||
break; |
|||
case SortMode.Type: |
|||
results = results.OrderBy(o => o.Item1.computedType).ToList(); |
|||
break; |
|||
case SortMode.Priority: |
|||
results = results.OrderBy(o => o.Item1.computedPriority).ToList(); |
|||
break; |
|||
case SortMode.State: |
|||
results = results.OrderBy(o => o.Item1.computedState).ToList(); |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
static class Styles |
|||
{ |
|||
public static GUIStyle header; |
|||
public static GUIStyle sortHeader; |
|||
public static GUIStyle line; |
|||
static Styles() |
|||
{ |
|||
header = new GUIStyle(EditorStyles.toolbarButton); |
|||
header.alignment = TextAnchor.MiddleLeft; |
|||
header.fontStyle = FontStyle.Bold; |
|||
|
|||
sortHeader = new GUIStyle(EditorStyles.toolbarDropDown); |
|||
sortHeader.alignment = TextAnchor.MiddleLeft; |
|||
sortHeader.fontStyle = FontStyle.Bold; |
|||
|
|||
line = new GUIStyle(EditorStyles.toolbarButton); |
|||
line.padding = new RectOffset(); |
|||
line.contentOffset = new Vector2(6, 2); |
|||
line.alignment = TextAnchor.UpperLeft; |
|||
line.wordWrap = false; |
|||
} |
|||
} |
|||
|
|||
|
|||
[SettingsProvider] |
|||
public static SettingsProvider CommentsPreferences() |
|||
{ |
|||
return new SettingsProvider("Preferences/Gameplay Ingredients/Comments", SettingsScope.User) |
|||
{ |
|||
label = "Comments", |
|||
guiHandler = (searchContext) => |
|||
{ |
|||
user = EditorGUILayout.DelayedTextField("Project User Nickname", user); |
|||
} |
|||
}; |
|||
|
|||
|
|||
} |
|||
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 40737dcad5a16c842aab1be8a72b04ce |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEditor; |
|||
using UnityEngine; |
|||
|
|||
namespace GameplayIngredients.Comments.Editor |
|||
{ |
|||
[CustomEditor(typeof(SceneComment))] |
|||
public class SceneCommentEditor : UnityEditor.Editor |
|||
{ |
|||
[SerializeField] |
|||
SceneComment sceneComment; |
|||
[SerializeField] |
|||
SerializedProperty m_Comment; |
|||
|
|||
[SerializeField] |
|||
CommentEditor m_CommentEditor; |
|||
|
|||
|
|||
public static void RequestEdit() { m_NeedEditNext = true; } |
|||
public static bool m_NeedEditNext = false; |
|||
|
|||
|
|||
private void OnEnable() |
|||
{ |
|||
UpdateComment(); |
|||
if(sceneComment.comment.focus && SceneView.lastActiveSceneView != null) |
|||
SceneView.lastActiveSceneView.AlignViewToObject(sceneComment.transform); |
|||
} |
|||
|
|||
void UpdateComment() |
|||
{ |
|||
if (m_Comment == null) |
|||
m_Comment = serializedObject.FindProperty("m_Comment"); |
|||
|
|||
if (m_CommentEditor == null) |
|||
m_CommentEditor = new CommentEditor(serializedObject, m_Comment); |
|||
|
|||
sceneComment = (serializedObject.targetObject as SceneComment); |
|||
} |
|||
|
|||
public override void OnInspectorGUI() |
|||
{ |
|||
UpdateComment(); |
|||
GUILayout.Space(4); |
|||
m_CommentEditor.DrawComment(sceneComment.comment, m_NeedEditNext); |
|||
|
|||
if (m_NeedEditNext) |
|||
m_NeedEditNext = false; |
|||
|
|||
GUILayout.Space(16); |
|||
} |
|||