2020-02-17 11:22:12 +08:00
using UnityEditor ;
2018-06-22 18:48:14 +08:00
using UnityEditor.UI ;
using UnityEngine ;
2018-11-28 18:55:56 +08:00
using System.Collections.Generic ;
2020-09-01 13:27:06 +08:00
using UnityEditor.Experimental.SceneManagement ;
2020-08-28 13:38:13 +08:00
using UnityEditorInternal ;
using UnityEngine.UI ;
2018-06-22 18:48:14 +08:00
namespace Coffee.UIExtensions
{
2020-02-12 20:38:06 +08:00
[CustomEditor(typeof(UIParticle))]
[CanEditMultipleObjects]
2020-08-20 03:42:16 +08:00
internal class UIParticleEditor : GraphicEditor
2020-02-12 20:38:06 +08:00
{
//################################
// Constant or Static Members.
//################################
2020-08-31 08:28:38 +08:00
private static readonly GUIContent s_ContentRenderingOrder = new GUIContent ( "Rendering Order" ) ;
private static readonly GUIContent s_ContentRefresh = new GUIContent ( "Refresh" ) ;
2020-09-01 12:50:54 +08:00
private static readonly GUIContent s_ContentFix = new GUIContent ( "Fix" ) ;
private static readonly List < UIParticle > s_TempParents = new List < UIParticle > ( ) ;
private static readonly List < UIParticle > s_TempChildren = new List < UIParticle > ( ) ;
2020-08-20 03:42:16 +08:00
2020-08-28 13:38:13 +08:00
private SerializedProperty _spScale ;
2020-08-20 03:42:16 +08:00
private SerializedProperty _spIgnoreCanvasScaler ;
private SerializedProperty _spAnimatableProperties ;
2020-08-28 13:38:13 +08:00
private ReorderableList _ro ;
2020-08-20 03:42:16 +08:00
private static readonly List < string > s_MaskablePropertyNames = new List < string >
2020-02-12 20:38:06 +08:00
{
"_Stencil" ,
"_StencilComp" ,
"_StencilOp" ,
"_StencilWriteMask" ,
"_StencilReadMask" ,
"_ColorMask" ,
} ;
2020-08-20 03:42:16 +08:00
2020-02-12 20:38:06 +08:00
//################################
// Public/Protected Members.
//################################
/// <summary>
/// This function is called when the object becomes enabled and active.
/// </summary>
protected override void OnEnable ( )
{
base . OnEnable ( ) ;
2020-08-28 13:38:13 +08:00
_spScale = serializedObject . FindProperty ( "m_Scale" ) ;
2020-08-20 03:42:16 +08:00
_spIgnoreCanvasScaler = serializedObject . FindProperty ( "m_IgnoreCanvasScaler" ) ;
2020-02-12 20:38:06 +08:00
_spAnimatableProperties = serializedObject . FindProperty ( "m_AnimatableProperties" ) ;
2020-08-28 13:38:13 +08:00
var sp = serializedObject . FindProperty ( "m_Particles" ) ;
_ro = new ReorderableList ( sp . serializedObject , sp , true , true , false , false ) ;
_ro . elementHeight = EditorGUIUtility . singleLineHeight + 4 ;
_ro . drawElementCallback = ( rect , index , active , focused ) = >
{
rect . y + = 1 ;
rect . height = EditorGUIUtility . singleLineHeight ;
2020-08-31 08:28:38 +08:00
EditorGUI . ObjectField ( rect , sp . GetArrayElementAtIndex ( index ) , GUIContent . none ) ;
2020-08-28 13:38:13 +08:00
} ;
_ro . drawHeaderCallback + = rect = >
{
2020-08-31 08:28:38 +08:00
EditorGUI . LabelField ( new Rect ( rect . x , rect . y , 150 , rect . height ) , s_ContentRenderingOrder ) ;
2020-08-28 13:38:13 +08:00
2020-08-31 08:28:38 +08:00
if ( GUI . Button ( new Rect ( rect . width - 80 , rect . y - 1 , 80 , rect . height ) , s_ContentRefresh , EditorStyles . miniButton ) )
2020-08-28 13:38:13 +08:00
{
2020-08-31 08:28:38 +08:00
foreach ( UIParticle t in targets )
{
t . RefreshParticles ( ) ;
}
2020-08-28 13:38:13 +08:00
}
} ;
2020-02-12 20:38:06 +08:00
}
/// <summary>
/// Implement this function to make a custom inspector.
/// </summary>
public override void OnInspectorGUI ( )
{
2020-08-20 03:42:16 +08:00
var current = target as UIParticle ;
if ( current = = null ) return ;
2020-02-12 20:38:06 +08:00
serializedObject . Update ( ) ;
2020-08-28 13:38:13 +08:00
// IgnoreCanvasScaler
2020-09-01 12:50:54 +08:00
using ( var ccs = new EditorGUI . ChangeCheckScope ( ) )
{
EditorGUILayout . PropertyField ( _spIgnoreCanvasScaler ) ;
if ( ccs . changed )
{
foreach ( UIParticle p in targets )
{
p . ignoreCanvasScaler = _spIgnoreCanvasScaler . boolValue ;
}
}
}
2020-02-12 20:38:06 +08:00
2020-08-28 13:38:13 +08:00
// Scale
EditorGUILayout . PropertyField ( _spScale ) ;
2020-02-12 20:38:06 +08:00
// AnimatableProperties
AnimatedPropertiesEditor . DrawAnimatableProperties ( _spAnimatableProperties , current . material ) ;
2020-08-28 13:38:13 +08:00
_ro . DoLayoutList ( ) ;
2020-02-12 20:38:06 +08:00
2020-09-01 12:50:54 +08:00
serializedObject . ApplyModifiedProperties ( ) ;
2020-08-20 03:42:16 +08:00
// Does the shader support UI masks?
2020-08-28 13:38:13 +08:00
if ( current . maskable & & current . GetComponentInParent < Mask > ( ) )
2020-02-12 20:38:06 +08:00
{
2020-08-28 13:38:13 +08:00
foreach ( var mat in current . materials )
2020-02-12 20:38:06 +08:00
{
2020-08-31 08:28:38 +08:00
if ( ! mat | | ! mat . shader ) continue ;
2020-08-28 13:38:13 +08:00
var shader = mat . shader ;
foreach ( var propName in s_MaskablePropertyNames )
{
if ( mat . HasProperty ( propName ) ) continue ;
2020-08-20 03:42:16 +08:00
2020-08-28 13:38:13 +08:00
EditorGUILayout . HelpBox ( string . Format ( "Shader '{0}' doesn't have '{1}' property. This graphic cannot be masked." , shader . name , propName ) , MessageType . Warning ) ;
break ;
}
2020-02-12 20:38:06 +08:00
}
2020-08-12 01:10:22 +08:00
}
2020-02-12 20:38:06 +08:00
2020-09-01 12:50:54 +08:00
// Does the shader support UI masks?
if ( FixButton ( current . m_IsTrail , "This UIParticle component should be removed. The UIParticle for trails is no longer needed." ) )
{
DestroyUIParticle ( current ) ;
return ;
}
current . GetComponentsInParent ( true , s_TempParents ) ;
if ( FixButton ( 1 < s_TempParents . Count , "This UIParticle component should be removed. The parent UIParticle exists." ) )
{
DestroyUIParticle ( current ) ;
return ;
}
current . GetComponentsInChildren ( true , s_TempChildren ) ;
if ( FixButton ( 1 < s_TempChildren . Count , "The children UIParticle component should be removed." ) )
{
s_TempChildren . ForEach ( child = > DestroyUIParticle ( child , true ) ) ;
}
}
void DestroyUIParticle ( UIParticle p , bool ignoreCurrent = false )
{
if ( ! p | | ignoreCurrent & & target = = p ) return ;
var cr = p . canvasRenderer ;
DestroyImmediate ( p ) ;
DestroyImmediate ( cr ) ;
2020-09-01 13:27:06 +08:00
var stage = PrefabStageUtility . GetCurrentPrefabStage ( ) ;
if ( stage ! = null & & stage . scene . isLoaded )
{
PrefabUtility . SaveAsPrefabAsset ( stage . prefabContentsRoot , stage . prefabAssetPath ) ;
}
2020-09-01 12:50:54 +08:00
}
bool FixButton ( bool show , string text )
{
if ( ! show ) return false ;
using ( new EditorGUILayout . HorizontalScope ( GUILayout . ExpandWidth ( true ) ) )
{
EditorGUILayout . HelpBox ( text , MessageType . Warning , true ) ;
using ( new EditorGUILayout . VerticalScope ( ) )
{
return GUILayout . Button ( s_ContentFix , GUILayout . Width ( 30 ) ) ;
}
}
2020-02-12 20:38:06 +08:00
}
}
}