using System; using UnityEditor; using UnityEditor.UI; using UnityEngine; using UnityEngine.UI; using Object = UnityEngine.Object; namespace MPUIKIT.Editor { [CustomEditor(typeof(MPImage), true)] [CanEditMultipleObjects] public class MPImageEditor : ImageEditor { private SerializedProperty spSprite; private SerializedProperty spCircle, spTriangle, spRectangle, spPentagon, spHexagon, spNStarPolygon; private SerializedProperty spPreserveAspect; private SerializedProperty spFillMethod, spFillOrigin, spFillAmount, spFillClockwise; private SerializedProperty spShape; private SerializedProperty spStrokeWidth, spOutlineWidth, spOutlineColor, spFalloffDistance; private SerializedProperty spConstrainRotation, spShapeRotation, spFlipHorizontal, spFlipVertical; private SerializedProperty spMaterialSettings, spMaterial, spImageType; private SerializedProperty spGradient; private bool gsInitialized, shaderChannelsNeedUpdate; protected override void OnEnable() { foreach (Object obj in serializedObject.targetObjects) { ((MPImage) obj).UpdateSerializedValuesFromSharedMaterial(); } base.OnEnable(); spSprite = serializedObject.FindProperty("m_Sprite"); spShape = serializedObject.FindProperty("m_DrawShape"); spStrokeWidth = serializedObject.FindProperty("m_StrokeWidth"); spOutlineWidth = serializedObject.FindProperty("m_OutlineWidth"); spOutlineColor = serializedObject.FindProperty("m_OutlineColor"); spFalloffDistance = serializedObject.FindProperty("m_FalloffDistance"); spMaterialSettings = serializedObject.FindProperty("m_MaterialMode"); spMaterial = serializedObject.FindProperty("m_Material"); spImageType = serializedObject.FindProperty("m_ImageType"); spFillMethod = serializedObject.FindProperty("m_FillMethod"); spFillOrigin = serializedObject.FindProperty("m_FillOrigin"); spFillAmount = serializedObject.FindProperty("m_FillAmount"); spFillClockwise = serializedObject.FindProperty("m_FillClockwise"); spConstrainRotation = serializedObject.FindProperty("m_ConstrainRotation"); spShapeRotation = serializedObject.FindProperty("m_ShapeRotation"); spFlipHorizontal = serializedObject.FindProperty("m_FlipHorizontal"); spFlipVertical = serializedObject.FindProperty("m_FlipVertical"); spCircle = serializedObject.FindProperty("m_Circle"); spRectangle = serializedObject.FindProperty("m_Rectangle"); spTriangle = serializedObject.FindProperty("m_Triangle"); spPentagon = serializedObject.FindProperty("m_Pentagon"); spHexagon = serializedObject.FindProperty("m_Hexagon"); spNStarPolygon = serializedObject.FindProperty("m_NStarPolygon"); spPreserveAspect = serializedObject.FindProperty("m_PreserveAspect"); spGradient = serializedObject.FindProperty("m_GradientEffect"); } public override void OnInspectorGUI() { serializedObject.Update(); FixShaderChannelGUI(); RaycastControlsGUI(); EditorGUILayout.PropertyField(m_Color); EditorGUILayout.Space(); EditorGUILayout.PropertyField(spShape); if (spShape.enumValueIndex != (int) DrawShape.None) { EditorGUILayout.BeginVertical("Box"); if (!spShape.hasMultipleDifferentValues) { switch ((DrawShape) spShape.enumValueIndex) { case DrawShape.Circle: EditorGUILayout.PropertyField(spCircle); break; case DrawShape.Rectangle: EditorGUILayout.PropertyField(spRectangle); break; case DrawShape.Pentagon: EditorGUILayout.PropertyField(spPentagon); break; case DrawShape.Triangle: EditorGUILayout.PropertyField(spTriangle); break; case DrawShape.Hexagon: EditorGUILayout.PropertyField(spHexagon); break; case DrawShape.NStarPolygon: EditorGUILayout.PropertyField(spNStarPolygon); break; default: throw new ArgumentOutOfRangeException(); } } EditorGUILayout.Space(); if (spShape.enumValueIndex != (int) DrawShape.None) { AdditionalShapeDataGUI(); } EditorGUILayout.EndVertical(); } EditorGUILayout.Space(); ImageTypeGUI(); SpriteGUI(); if (!spSprite.hasMultipleDifferentValues && spSprite.objectReferenceValue != null) { EditorGUILayout.PropertyField(spPreserveAspect); } SetShowNativeSize(spSprite.objectReferenceValue != null, true); NativeSizeButtonGUI(); EditorGUILayout.Space(); SharedMaterialGUI(); EditorGUILayout.Space(); EditorGUILayout.BeginVertical("Box"); { EditorGUILayout.PropertyField(spGradient); } EditorGUILayout.EndVertical(); serializedObject.ApplyModifiedProperties(); serializedObject.Update(); Repaint(); } private void AdditionalShapeDataGUI() { EditorGUILayout.Space(); float strokeWidth = spStrokeWidth.floatValue; float outlineWidth = spOutlineWidth.floatValue; float falloff = spFalloffDistance.floatValue; Color outlineColor = spOutlineColor.colorValue; Rect r = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 2 + EditorGUIUtility.standardVerticalSpacing); Rect line = r; line.height = EditorGUIUtility.singleLineHeight; float x = (line.width - 10f) / 2; float fieldWidth = x / 2 - 10f; float labelWidth = x - fieldWidth; line.width = labelWidth; EditorGUI.LabelField(line, "Stroke"); Rect dragZone = line; line.x += labelWidth; line.width = fieldWidth; EditorGUI.BeginChangeCheck(); { EditorGUI.showMixedValue = spStrokeWidth.hasMultipleDifferentValues; strokeWidth = EditorGUILayoutExtended.FloatFieldExtended(line, spStrokeWidth.floatValue, dragZone); EditorGUI.showMixedValue = false; } if (EditorGUI.EndChangeCheck()) { spStrokeWidth.floatValue = strokeWidth; } line.x += fieldWidth + 10; line.width = labelWidth; EditorGUI.LabelField(line, "Falloff"); dragZone = line; line.x += labelWidth; line.width = fieldWidth; EditorGUI.BeginChangeCheck(); { EditorGUI.showMixedValue = spFalloffDistance.hasMultipleDifferentValues; falloff = EditorGUILayoutExtended.FloatFieldExtended(line, spFalloffDistance.floatValue, dragZone); EditorGUI.showMixedValue = false; } if (EditorGUI.EndChangeCheck()) { spFalloffDistance.floatValue = falloff; } line.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; line.x = r.x; line.width = labelWidth; EditorGUI.LabelField(line, "Outline Width"); dragZone = line; line.x += labelWidth; line.width = fieldWidth; EditorGUI.BeginChangeCheck(); { EditorGUI.showMixedValue = spOutlineWidth.hasMultipleDifferentValues; outlineWidth = EditorGUILayoutExtended.FloatFieldExtended(line, spOutlineWidth.floatValue, dragZone); EditorGUI.showMixedValue = false; } if (EditorGUI.EndChangeCheck()) { spOutlineWidth.floatValue = outlineWidth; } line.x += fieldWidth + 10; line.width = labelWidth; EditorGUI.LabelField(line, "Outline Color"); dragZone = line; line.width = fieldWidth; line.x += labelWidth; EditorGUI.BeginChangeCheck(); { EditorGUI.showMixedValue = spOutlineColor.hasMultipleDifferentValues; outlineColor = EditorGUI.ColorField(line, spOutlineColor.colorValue); EditorGUI.showMixedValue = false; } if (EditorGUI.EndChangeCheck()) { spOutlineColor.colorValue = outlineColor; } EditorGUILayout.Space(); RotationGUI(); } private void RotationGUI() { Rect r =EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight + 24 + EditorGUIUtility.standardVerticalSpacing); Rect line = r; line.height = EditorGUIUtility.singleLineHeight; float x = (line.width - 10f) / 2; float fieldWidth = x / 2 - 10f; float labelWidth = x - fieldWidth; line.width = labelWidth; EditorGUI.LabelField(line, "Rotation"); line.x += labelWidth; line.width = r.width - labelWidth - 78; string[] options = spConstrainRotation.hasMultipleDifferentValues? new []{ "---", "---" } : new []{"Free", "Constrained"}; bool boolVal = spConstrainRotation.boolValue; EditorGUI.BeginChangeCheck(); { boolVal = GUI.Toolbar(line, boolVal ? 1 : 0, options) == 1; } if (EditorGUI.EndChangeCheck()) { spConstrainRotation.boolValue = boolVal; GUI.FocusControl(null); } line.x += line.width + 14; line.width = 64; EditorGUI.LabelField(line, "Flip"); line.y += EditorGUIUtility.standardVerticalSpacing + EditorGUIUtility.singleLineHeight; line.x = r.x + 10; line.height = EditorGUIUtility.singleLineHeight; line.width = labelWidth - 10; EditorGUI.BeginDisabledGroup(spConstrainRotation.boolValue); { Rect dragZone = line; EditorGUI.LabelField(line, "Angle"); line.x = r.x + labelWidth; line.width = r.width - labelWidth - 148; float rotationValue = spShapeRotation.floatValue; EditorGUI.BeginChangeCheck(); { EditorGUI.showMixedValue = spShapeRotation.hasMultipleDifferentValues; rotationValue = EditorGUILayoutExtended.FloatFieldExtended(line, spShapeRotation.floatValue, dragZone); EditorGUI.showMixedValue = false; } if (EditorGUI.EndChangeCheck()) { spShapeRotation.floatValue = rotationValue; } } EditorGUI.EndDisabledGroup(); EditorGUI.BeginDisabledGroup(!spConstrainRotation.boolValue); { line.x += line.width + 4; line.width = 30; line.height = 24; if (GUI.Button(line, MPEditorContents.RotateLeftNormal)) { float rotation = spShapeRotation.floatValue; float remainder = rotation % 90; if (Mathf.Abs(remainder) <= 0) { rotation += 90; } else { rotation = rotation - remainder + 90; } if (Math.Abs(rotation) >= 360) rotation = 0; spShapeRotation.floatValue = rotation; } line.x += 34; if (GUI.Button(line, MPEditorContents.RotateRightNormal)) { float rotation = spShapeRotation.floatValue; float remainder = rotation % 90; if (Mathf.Abs(remainder) <= 0) { rotation -= 90; } else { rotation -= remainder; } if (Math.Abs(rotation) >= 360) rotation = 0; spShapeRotation.floatValue = rotation; } } EditorGUI.EndDisabledGroup(); line.x += 46; bool flipH = spFlipHorizontal.boolValue; bool flipV = spFlipVertical.boolValue; EditorGUI.BeginChangeCheck(); { EditorGUI.BeginDisabledGroup(spFlipHorizontal.hasMultipleDifferentValues || spFlipVertical.hasMultipleDifferentValues); flipH = GUI.Toggle(line, spFlipHorizontal.boolValue, spFlipHorizontal.boolValue ? MPEditorContents.FlipHorizontalActive:MPEditorContents.FlipHorizontalNormal, "button"); line.x += 34; flipV = GUI.Toggle(line, spFlipVertical.boolValue, spFlipVertical.boolValue?MPEditorContents.FlipVerticalActive:MPEditorContents.FlipVerticalNormal, "button"); EditorGUI.EndDisabledGroup(); } if (EditorGUI.EndChangeCheck()) { spFlipHorizontal.boolValue = flipH; spFlipVertical.boolValue = flipV; } } private void FixShaderChannelGUI() { if (!shaderChannelsNeedUpdate) return; EditorGUILayout.HelpBox( "Parent Canvas needs to have these additional shader channels : Texcoord1, Texcoord2", MessageType.Error); EditorGUILayout.BeginHorizontal(); { GUILayout.FlexibleSpace(); if (GUILayout.Button("Fix", GUILayout.Width(100))) { Canvas canvas = (target as MPImage)?.GetComponentInParent(); if (canvas != null) { MPEditorUtility.AddAdditionalShaderChannelsToCanvas(canvas); shaderChannelsNeedUpdate = false; } } } EditorGUILayout.EndHorizontal(); } private new void SpriteGUI() { EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(spSprite, new GUIContent("Sprite")); if (EditorGUI.EndChangeCheck()) { Sprite newSprite = spSprite.objectReferenceValue as Sprite; if (newSprite) { Image.Type oldType = (Image.Type) spImageType.enumValueIndex; if (newSprite.border.SqrMagnitude() > 0) { spImageType.enumValueIndex = (int) Image.Type.Sliced; } else if (oldType == Image.Type.Sliced) { spImageType.enumValueIndex = (int) Image.Type.Simple; } } (serializedObject.targetObject as Image)?.DisableSpriteOptimizations(); } } private void ImageTypeGUI() { int selectedIndex = spImageType.enumValueIndex == (int) Image.Type.Simple ? 0 : 1; Rect imageTypeRect = EditorGUILayout.GetControlRect(); EditorGUI.BeginChangeCheck(); { EditorGUI.LabelField( new Rect(imageTypeRect.x, imageTypeRect.y, EditorGUIUtility.labelWidth, imageTypeRect.height), "Type"); imageTypeRect.x += EditorGUIUtility.labelWidth + 2; imageTypeRect.width -= EditorGUIUtility.labelWidth + 2; selectedIndex = EditorGUI.Popup(imageTypeRect, selectedIndex, new[] {"Simple", "Filled"}); } if (EditorGUI.EndChangeCheck()) { spImageType.enumValueIndex = (int) (selectedIndex == 0 ? Image.Type.Simple : Image.Type.Filled); } if (!spImageType.hasMultipleDifferentValues && spImageType.enumValueIndex == (int) Image.Type.Filled) { ++EditorGUI.indentLevel; EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(spFillMethod); if (EditorGUI.EndChangeCheck()) { spFillOrigin.intValue = 0; } switch ((Image.FillMethod) spFillMethod.enumValueIndex) { case Image.FillMethod.Horizontal: spFillOrigin.intValue = (int) (Image.OriginHorizontal) EditorGUILayout.EnumPopup("Fill Origin", (Image.OriginHorizontal) spFillOrigin.intValue); break; case Image.FillMethod.Vertical: spFillOrigin.intValue = (int) (Image.OriginVertical) EditorGUILayout.EnumPopup("Fill Origin", (Image.OriginVertical) spFillOrigin.intValue); break; case Image.FillMethod.Radial90: spFillOrigin.intValue = (int) (Image.Origin90) EditorGUILayout.EnumPopup("Fill Origin", (Image.Origin90) spFillOrigin.intValue); break; case Image.FillMethod.Radial180: spFillOrigin.intValue = (int) (Image.Origin180) EditorGUILayout.EnumPopup("Fill Origin", (Image.Origin180) spFillOrigin.intValue); break; case Image.FillMethod.Radial360: spFillOrigin.intValue = (int) (Image.Origin360) EditorGUILayout.EnumPopup("Fill Origin", (Image.Origin360) spFillOrigin.intValue); break; } EditorGUILayout.PropertyField(spFillAmount); if ((Image.FillMethod) spFillMethod.enumValueIndex > Image.FillMethod.Vertical) { EditorGUILayout.PropertyField(spFillClockwise, new GUIContent("Clockwise")); } --EditorGUI.indentLevel; } } private void SharedMaterialGUI() { Rect rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing); int matSett = spMaterialSettings.enumValueIndex; Rect labelRect = rect; labelRect.width = EditorGUIUtility.labelWidth; EditorGUI.LabelField(labelRect, "Material Mode"); rect.x += labelRect.width; rect.width -= labelRect.width; EditorGUI.BeginChangeCheck(); EditorGUI.showMixedValue = spMaterialSettings.hasMultipleDifferentValues; string[] options = new[] {"Dynamic", "Shared"}; if (EditorGUI.showMixedValue) options = new[] {"---", "---"}; matSett = GUI.Toolbar(rect, matSett, options); if (EditorGUI.EndChangeCheck()) { spMaterialSettings.enumValueIndex = matSett; foreach (Object obj in targets) { ((MPImage) obj).MaterialMode = (MaterialMode) matSett; EditorUtility.SetDirty(obj); } } EditorGUI.showMixedValue = false; EditorGUI.BeginDisabledGroup(spMaterialSettings.enumValueIndex == (int) MaterialMode.Dynamic); { rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing); Object matObj = spMaterial.objectReferenceValue; EditorGUI.BeginChangeCheck(); { EditorGUI.showMixedValue = spMaterialSettings.hasMultipleDifferentValues; matObj = (Material) EditorGUI.ObjectField( new Rect(rect.x, rect.y, rect.width - 60, EditorGUIUtility.singleLineHeight), matObj, typeof(Material), false); EditorGUI.showMixedValue = false; } if (EditorGUI.EndChangeCheck()) { spMaterial.objectReferenceValue = matObj; foreach (Object obj in targets) { ((MPImage) obj).material = (Material) matObj; EditorUtility.SetDirty(obj); } } EditorGUI.BeginDisabledGroup(spMaterial.objectReferenceValue != null); { if (GUI.Button(new Rect(rect.x + rect.width - 55, rect.y, 55, EditorGUIUtility.singleLineHeight), "Create")) { Material mat = ((MPImage) target).CreateMaterialAssetFromComponentSettings(); spMaterial.objectReferenceValue = mat; foreach (Object obj in targets) { ((MPImage) obj).material = mat; EditorUtility.SetDirty(obj); } } } EditorGUI.EndDisabledGroup(); } EditorGUI.EndDisabledGroup(); } } }