diff --git a/AnimationCurvePopupMenu/.gitignore b/AnimationCurvePopupMenu/.gitignore
new file mode 100644
index 0000000..933a9f0
--- /dev/null
+++ b/AnimationCurvePopupMenu/.gitignore
@@ -0,0 +1,2 @@
+/Library/
+/Temp/
diff --git a/AnimationCurvePopupMenu/Assets/Editor.meta b/AnimationCurvePopupMenu/Assets/Editor.meta
new file mode 100644
index 0000000..ed0d894
--- /dev/null
+++ b/AnimationCurvePopupMenu/Assets/Editor.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 7e121d2db1b5f6a46a3a29ebffb3a894
+folderAsset: yes
+timeCreated: 1467200556
+licenseType: Pro
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/AnimationCurvePopupMenu/Assets/Editor/AnimationCurveDrawer.cs b/AnimationCurvePopupMenu/Assets/Editor/AnimationCurveDrawer.cs
new file mode 100644
index 0000000..a6d7e30
--- /dev/null
+++ b/AnimationCurvePopupMenu/Assets/Editor/AnimationCurveDrawer.cs
@@ -0,0 +1,11 @@
+using UnityEngine;
+using UnityEditor;
+
+[CustomPropertyDrawer(typeof(AnimationCurve))]
+public class AnimationCurveDrawer : PropertyDrawer
+{
+ public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
+ {
+ AnimationCurveGUI.OnGUI(position, property, label);
+ }
+}
diff --git a/AnimationCurvePopupMenu/Assets/Editor/AnimationCurveDrawer.cs.meta b/AnimationCurvePopupMenu/Assets/Editor/AnimationCurveDrawer.cs.meta
new file mode 100644
index 0000000..12671cd
--- /dev/null
+++ b/AnimationCurvePopupMenu/Assets/Editor/AnimationCurveDrawer.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 51fc08f728922d94b804b10d0dddf893
+timeCreated: 1467200556
+licenseType: Pro
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/AnimationCurvePopupMenu/Assets/Editor/AnimationCurveGUI.cs b/AnimationCurvePopupMenu/Assets/Editor/AnimationCurveGUI.cs
new file mode 100644
index 0000000..dbd02f1
--- /dev/null
+++ b/AnimationCurvePopupMenu/Assets/Editor/AnimationCurveGUI.cs
@@ -0,0 +1,72 @@
+using UnityEngine;
+using UnityEditor;
+
+public class AnimationCurveGUI
+{
+ private static Rect SubtractPopupWidth(Rect position)
+ {
+ position.width -= 18f;
+ return position;
+ }
+
+ private static Rect GetPopupRect(Rect position)
+ {
+ position.xMin = position.xMax - 13f;
+ return position;
+ }
+
+ #region EditorGUILayout
+ public static AnimationCurve CurveField(AnimationCurve value, params GUILayoutOption[] options)
+ {
+ Rect position = EditorGUILayout.GetControlRect(false, 16f, EditorStyles.colorField, options);
+ return CurveField(position, value);
+ }
+
+ public static AnimationCurve CurveField(string label, AnimationCurve value, params GUILayoutOption[] options)
+ {
+ Rect position = EditorGUILayout.GetControlRect(true, 16f, EditorStyles.colorField, options);
+ return CurveField(position, label, value);
+ }
+
+ public static AnimationCurve CurveField(GUIContent label, AnimationCurve value, params GUILayoutOption[] options)
+ {
+ Rect position = EditorGUILayout.GetControlRect(true, 16f, EditorStyles.colorField, options);
+ return CurveField(position, label, value);
+ }
+ #endregion
+
+ #region EditorGUI
+ public static AnimationCurve CurveField(Rect position, AnimationCurve value)
+ {
+ AnimationCurve animationCurve = EditorGUI.CurveField(SubtractPopupWidth(position), value);
+ AnimationCurvePopupMenu.Show(GetPopupRect(position), animationCurve, null);
+ return animationCurve;
+ }
+
+ public static AnimationCurve CurveField(Rect position, string label, AnimationCurve value)
+ {
+ return CurveField(position, new GUIContent(label), value);
+ }
+
+ public static AnimationCurve CurveField(Rect position, GUIContent label, AnimationCurve value)
+ {
+ AnimationCurve animationCurve = EditorGUI.CurveField(SubtractPopupWidth(position), label, value);
+ AnimationCurvePopupMenu.Show(GetPopupRect(position), animationCurve, null);
+ return animationCurve;
+ }
+ #endregion
+
+ ///
+ /// 默认属性字段的绘制,也会为PropertyField自动绘制
+ ///
+ ///
+ ///
+ ///
+ public static void OnGUI(Rect position, SerializedProperty property, GUIContent label)
+ {
+ label = EditorGUI.BeginProperty(position, label, property);
+ EditorGUI.CurveField(EditorGUI.PrefixLabel(SubtractPopupWidth(position), label), property, Color.green, default(Rect));
+ AnimationCurvePopupMenu.Show(GetPopupRect(position), null, property);
+ EditorGUI.EndProperty();
+ }
+}
diff --git a/AnimationCurvePopupMenu/Assets/Editor/AnimationCurveGUI.cs.meta b/AnimationCurvePopupMenu/Assets/Editor/AnimationCurveGUI.cs.meta
new file mode 100644
index 0000000..3066383
--- /dev/null
+++ b/AnimationCurvePopupMenu/Assets/Editor/AnimationCurveGUI.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 677915183234a3c40bff720f40d27e22
+timeCreated: 1467200556
+licenseType: Pro
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/AnimationCurvePopupMenu/Assets/Editor/AnimationCurvePopupMenu.cs b/AnimationCurvePopupMenu/Assets/Editor/AnimationCurvePopupMenu.cs
new file mode 100644
index 0000000..1aac08e
--- /dev/null
+++ b/AnimationCurvePopupMenu/Assets/Editor/AnimationCurvePopupMenu.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Reflection;
+using UnityEngine;
+using UnityEditor;
+using UnityEditorInternal;
+
+public class AnimationCurvePopupMenu
+{
+ private static AnimationCurve s_ClipBoardAnimationCurve;
+
+ public static void Show(Rect popupRect, AnimationCurve animationCurve, SerializedProperty property)
+ {
+ if (GUI.Button(popupRect, GUIContent.none, "ShurikenDropdown"))
+ {
+ GUIContent content = new GUIContent("Copy");
+ GUIContent content2 = new GUIContent("Paste");
+ GUIContent content3 = new GUIContent("Clear");
+ GenericMenu genericMenu = new GenericMenu();
+
+ if (property != null)
+ {
+ genericMenu.AddItem(content, false, AnimationCurveCallbackCopy, property);
+ genericMenu.AddItem(content2, false, AnimationCurveCallbackPaste, property);
+ genericMenu.AddItem(content3, false, AnimationCurveCallbackClear, property);
+ }
+ else
+ {
+ genericMenu.AddItem(content, false, AnimationCurveCallback2Copy, animationCurve);
+ genericMenu.AddItem(content2, false, AnimationCurveCallback2Paste, animationCurve);
+ genericMenu.AddItem(content3, false, AnimationCurveCallback2Clear, animationCurve);
+ }
+
+ if (!HasClipBoardAnimationCurve())
+ {
+ genericMenu.AddDisabledItem(content2);
+ }
+ genericMenu.DropDown(popupRect);
+ Event.current.Use();
+ }
+ }
+
+ ///
+ /// 清除检视器界面的曲线缓存,才能刷新新的值
+ ///
+ public static void AnimationCurvePreviewCacheClearCache()
+ {
+ Assembly assembly = Assembly.GetAssembly(typeof(ReorderableList));
+ Type type = assembly.GetType("UnityEditorInternal.AnimationCurvePreviewCache");
+ MethodInfo clearCache = type.GetMethod("ClearCache", BindingFlags.Static | BindingFlags.Public);
+ if (clearCache != null)
+ {
+ clearCache.Invoke(null, null);
+ }
+ }
+
+ private static bool HasClipBoardAnimationCurve()
+ {
+ return s_ClipBoardAnimationCurve != null;
+ }
+
+ private static void AnimationCurveCallbackCopy(object obj)
+ {
+ SerializedProperty property = (SerializedProperty)obj;
+ s_ClipBoardAnimationCurve = property.animationCurveValue;
+ }
+
+ private static void AnimationCurveCallbackPaste(object obj)
+ {
+ if (s_ClipBoardAnimationCurve == null)
+ {
+ return;
+ }
+ SerializedProperty property = (SerializedProperty)obj;
+ property.serializedObject.Update();
+ property.animationCurveValue = s_ClipBoardAnimationCurve;
+ property.serializedObject.ApplyModifiedProperties();
+ }
+
+ private static void AnimationCurveCallbackClear(object obj)
+ {
+ SerializedProperty property = (SerializedProperty)obj;
+ property.serializedObject.Update();
+ property.animationCurveValue = new AnimationCurve();
+ property.serializedObject.ApplyModifiedProperties();
+ }
+
+ private static void AnimationCurveCallback2Copy(object obj)
+ {
+ AnimationCurve animationCurve = (AnimationCurve)obj;
+ s_ClipBoardAnimationCurve = animationCurve;
+ }
+
+ private static void AnimationCurveCallback2Paste(object obj)
+ {
+ if (s_ClipBoardAnimationCurve == null)
+ {
+ return;
+ }
+ AnimationCurve animationCurve = (AnimationCurve)obj;
+ animationCurve.keys = s_ClipBoardAnimationCurve.keys;
+ animationCurve.postWrapMode = s_ClipBoardAnimationCurve.postWrapMode;
+ animationCurve.preWrapMode = s_ClipBoardAnimationCurve.preWrapMode;
+ AnimationCurvePreviewCacheClearCache();
+ }
+
+ private static void AnimationCurveCallback2Clear(object obj)
+ {
+ AnimationCurve animationCurve = (AnimationCurve)obj;
+ if (animationCurve != null)
+ {
+ for (int i = animationCurve.length - 1; i >= 0; i--)
+ {
+ animationCurve.RemoveKey(i);
+ }
+ AnimationCurvePreviewCacheClearCache();
+ }
+ }
+}
diff --git a/AnimationCurvePopupMenu/Assets/Editor/AnimationCurvePopupMenu.cs.meta b/AnimationCurvePopupMenu/Assets/Editor/AnimationCurvePopupMenu.cs.meta
new file mode 100644
index 0000000..0397452
--- /dev/null
+++ b/AnimationCurvePopupMenu/Assets/Editor/AnimationCurvePopupMenu.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a489e6d3b58df6a46bc47348469a40e5
+timeCreated: 1467200556
+licenseType: Pro
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/AnimationCurvePopupMenu/Assets/Editor/TestCurveEditor.cs b/AnimationCurvePopupMenu/Assets/Editor/TestCurveEditor.cs
new file mode 100644
index 0000000..4c5a9e6
--- /dev/null
+++ b/AnimationCurvePopupMenu/Assets/Editor/TestCurveEditor.cs
@@ -0,0 +1,32 @@
+using UnityEngine;
+using UnityEditor;
+
+[CustomEditor(typeof(TestCurve))]
+public class TestCurveEditor : Editor
+{
+ SerializedProperty curveProp;
+ SerializedProperty curveProp2;
+ private AnimationCurve m_TestAnimCurve = new AnimationCurve();
+ private AnimationCurve m_TestAnimCurve2 = new AnimationCurve();
+
+ void OnEnable()
+ {
+ curveProp = serializedObject.FindProperty("curve");
+ curveProp2 = serializedObject.FindProperty("curve2");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(curveProp);
+ EditorGUILayout.PropertyField(curveProp2, new GUIContent("Curve2 Object"));
+
+ m_TestAnimCurve = AnimationCurveGUI.CurveField("扩展曲线", m_TestAnimCurve);
+ m_TestAnimCurve2 = EditorGUILayout.CurveField("默认曲线", m_TestAnimCurve2);
+
+ //EditorGUILayout.TextField("abc");
+
+ serializedObject.ApplyModifiedProperties();
+ }
+}
diff --git a/AnimationCurvePopupMenu/Assets/Editor/TestCurveEditor.cs.meta b/AnimationCurvePopupMenu/Assets/Editor/TestCurveEditor.cs.meta
new file mode 100644
index 0000000..3391d7e
--- /dev/null
+++ b/AnimationCurvePopupMenu/Assets/Editor/TestCurveEditor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 60ff6bafc5d32db4b87abf5dc2159d9d
+timeCreated: 1467200556
+licenseType: Pro
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/AnimationCurvePopupMenu/Assets/Test.unity b/AnimationCurvePopupMenu/Assets/Test.unity
new file mode 100644
index 0000000..cac3448
Binary files /dev/null and b/AnimationCurvePopupMenu/Assets/Test.unity differ
diff --git a/AnimationCurvePopupMenu/Assets/Test.unity.meta b/AnimationCurvePopupMenu/Assets/Test.unity.meta
new file mode 100644
index 0000000..7d3369e
--- /dev/null
+++ b/AnimationCurvePopupMenu/Assets/Test.unity.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: da67d09a4f151594ca7fb2dd4e2e85b7
+timeCreated: 1467200688
+licenseType: Pro
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/AnimationCurvePopupMenu/Assets/TestCurve.cs b/AnimationCurvePopupMenu/Assets/TestCurve.cs
new file mode 100644
index 0000000..1f9f38a
--- /dev/null
+++ b/AnimationCurvePopupMenu/Assets/TestCurve.cs
@@ -0,0 +1,8 @@
+using UnityEngine;
+using System.Collections;
+
+public class TestCurve : MonoBehaviour
+{
+ public AnimationCurve curve; // for preview
+ public AnimationCurve curve2; // for preview
+}
diff --git a/AnimationCurvePopupMenu/Assets/TestCurve.cs.meta b/AnimationCurvePopupMenu/Assets/TestCurve.cs.meta
new file mode 100644
index 0000000..c254e16
--- /dev/null
+++ b/AnimationCurvePopupMenu/Assets/TestCurve.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 079fcfcf76d5a204f9af86781d95edac
+timeCreated: 1467200556
+licenseType: Pro
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/AnimationCurvePopupMenu/ProjectSettings/AudioManager.asset b/AnimationCurvePopupMenu/ProjectSettings/AudioManager.asset
new file mode 100644
index 0000000..1a76003
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/AudioManager.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/ClusterInputManager.asset b/AnimationCurvePopupMenu/ProjectSettings/ClusterInputManager.asset
new file mode 100644
index 0000000..4b124b6
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/ClusterInputManager.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/DynamicsManager.asset b/AnimationCurvePopupMenu/ProjectSettings/DynamicsManager.asset
new file mode 100644
index 0000000..2d634db
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/DynamicsManager.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/EditorBuildSettings.asset b/AnimationCurvePopupMenu/ProjectSettings/EditorBuildSettings.asset
new file mode 100644
index 0000000..1574502
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/EditorBuildSettings.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/EditorSettings.asset b/AnimationCurvePopupMenu/ProjectSettings/EditorSettings.asset
new file mode 100644
index 0000000..a7b221f
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/EditorSettings.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/GraphicsSettings.asset b/AnimationCurvePopupMenu/ProjectSettings/GraphicsSettings.asset
new file mode 100644
index 0000000..ed6c17f
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/GraphicsSettings.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/InputManager.asset b/AnimationCurvePopupMenu/ProjectSettings/InputManager.asset
new file mode 100644
index 0000000..a12aa70
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/InputManager.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/NavMeshAreas.asset b/AnimationCurvePopupMenu/ProjectSettings/NavMeshAreas.asset
new file mode 100644
index 0000000..2ccaab7
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/NavMeshAreas.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/NetworkManager.asset b/AnimationCurvePopupMenu/ProjectSettings/NetworkManager.asset
new file mode 100644
index 0000000..6700c35
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/NetworkManager.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/Physics2DSettings.asset b/AnimationCurvePopupMenu/ProjectSettings/Physics2DSettings.asset
new file mode 100644
index 0000000..d2fda8b
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/Physics2DSettings.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/ProjectSettings.asset b/AnimationCurvePopupMenu/ProjectSettings/ProjectSettings.asset
new file mode 100644
index 0000000..31c0cb3
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/ProjectSettings.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/ProjectVersion.txt b/AnimationCurvePopupMenu/ProjectSettings/ProjectVersion.txt
new file mode 100644
index 0000000..c35bf9d
--- /dev/null
+++ b/AnimationCurvePopupMenu/ProjectSettings/ProjectVersion.txt
@@ -0,0 +1,2 @@
+m_EditorVersion: 5.3.4p5
+m_StandardAssetsVersion: 0
diff --git a/AnimationCurvePopupMenu/ProjectSettings/QualitySettings.asset b/AnimationCurvePopupMenu/ProjectSettings/QualitySettings.asset
new file mode 100644
index 0000000..d83c764
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/QualitySettings.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/TagManager.asset b/AnimationCurvePopupMenu/ProjectSettings/TagManager.asset
new file mode 100644
index 0000000..e68f8fc
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/TagManager.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/TimeManager.asset b/AnimationCurvePopupMenu/ProjectSettings/TimeManager.asset
new file mode 100644
index 0000000..b8ff322
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/TimeManager.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/UnityAdsSettings.asset b/AnimationCurvePopupMenu/ProjectSettings/UnityAdsSettings.asset
new file mode 100644
index 0000000..532825c
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/UnityAdsSettings.asset differ
diff --git a/AnimationCurvePopupMenu/ProjectSettings/UnityConnectSettings.asset b/AnimationCurvePopupMenu/ProjectSettings/UnityConnectSettings.asset
new file mode 100644
index 0000000..1447c4a
Binary files /dev/null and b/AnimationCurvePopupMenu/ProjectSettings/UnityConnectSettings.asset differ
diff --git a/README.md b/README.md
index 8de8c82..89afe05 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,55 @@
-# UnityAnimationCurvePopupMenu
-Unity AnimationCurvePopupMenu (Copy, Paste)
+# Unity AnimationCurvePopupMenu
+Unity 曲线编辑扩展菜单功能
+
+# 原因
+默认的 AnimationCurve 字段曲线编辑,不支持复制粘贴到另一个 AnimationCurve 字段,亦不支持关键帧的清空。所以扩展 AnimationCurve 的绘制,在右侧添加下拉菜单,以扩展功能。
+
+# 功能
+* 复制曲线
+* 粘贴曲线
+* 清空曲线
+
+# 截图
+点击右侧下拉按钮,点击 Copy 复制:
+
+在另一个曲线,右侧菜单点击 Paste 粘贴:
+
+清空曲线的关键帧值,点击 Clear 清空:
+
+
+# 使用说明
+代码放进工程里面,对于默认的脚本,会自动调用扩展的曲线绘制方式:
+默认的脚本类似:
+```
+public class TestCurve : MonoBehaviour
+{
+ public AnimationCurve curve;
+}
+```
+高级方式,要对默认脚本进行自定义绘制的话,创建 Editor 类。接着,对于属性值,调用 Unity 自带的接口 `EditorGUILayout.PropertyField` 即可。对于非属性值,可通过 AnimationCurveGUI 接口来替换 EditorGUILayout 和 EditorGUI 来绘制曲线:
+```
+using UnityEngine;
+using UnityEditor;
+
+[CustomEditor(typeof(TestCurve))]
+public class TestCurveEditor : Editor
+{
+ private SerializedProperty curveProp;
+ private AnimationCurve m_TestAnimCurve = new AnimationCurve();
+
+ void OnEnable()
+ {
+ curveProp = serializedObject.FindProperty("curve");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(curveProp);
+ m_TestAnimCurve = AnimationCurveGUI.CurveField("扩展曲线", m_TestAnimCurve);
+
+ serializedObject.ApplyModifiedProperties();
+ }
+}
+```
diff --git a/Screenshots/screenshot_clear.png b/Screenshots/screenshot_clear.png
new file mode 100644
index 0000000..e561987
Binary files /dev/null and b/Screenshots/screenshot_clear.png differ
diff --git a/Screenshots/screenshot_copy.png b/Screenshots/screenshot_copy.png
new file mode 100644
index 0000000..18ca338
Binary files /dev/null and b/Screenshots/screenshot_copy.png differ
diff --git a/Screenshots/screenshot_paste.png b/Screenshots/screenshot_paste.png
new file mode 100644
index 0000000..4cedd04
Binary files /dev/null and b/Screenshots/screenshot_paste.png differ