MPImageEditor.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. using System;
  2. using UnityEditor;
  3. using UnityEditor.UI;
  4. using UnityEngine;
  5. using UnityEngine.UI;
  6. using Object = UnityEngine.Object;
  7. namespace MPUIKIT.Editor {
  8. [CustomEditor(typeof(MPImage), true)]
  9. [CanEditMultipleObjects]
  10. public class MPImageEditor : ImageEditor {
  11. private SerializedProperty spSprite;
  12. private SerializedProperty spCircle, spTriangle, spRectangle, spPentagon, spHexagon, spNStarPolygon;
  13. private SerializedProperty spPreserveAspect;
  14. private SerializedProperty spFillMethod, spFillOrigin, spFillAmount, spFillClockwise;
  15. private SerializedProperty spShape;
  16. private SerializedProperty spStrokeWidth, spOutlineWidth, spOutlineColor, spFalloffDistance;
  17. private SerializedProperty spConstrainRotation, spShapeRotation, spFlipHorizontal, spFlipVertical;
  18. private SerializedProperty spMaterialSettings, spMaterial, spImageType;
  19. private SerializedProperty spGradient;
  20. private bool gsInitialized, shaderChannelsNeedUpdate;
  21. protected override void OnEnable() {
  22. foreach (Object obj in serializedObject.targetObjects) {
  23. ((MPImage) obj).UpdateSerializedValuesFromSharedMaterial();
  24. }
  25. base.OnEnable();
  26. spSprite = serializedObject.FindProperty("m_Sprite");
  27. spShape = serializedObject.FindProperty("m_DrawShape");
  28. spStrokeWidth = serializedObject.FindProperty("m_StrokeWidth");
  29. spOutlineWidth = serializedObject.FindProperty("m_OutlineWidth");
  30. spOutlineColor = serializedObject.FindProperty("m_OutlineColor");
  31. spFalloffDistance = serializedObject.FindProperty("m_FalloffDistance");
  32. spMaterialSettings = serializedObject.FindProperty("m_MaterialMode");
  33. spMaterial = serializedObject.FindProperty("m_Material");
  34. spImageType = serializedObject.FindProperty("m_ImageType");
  35. spFillMethod = serializedObject.FindProperty("m_FillMethod");
  36. spFillOrigin = serializedObject.FindProperty("m_FillOrigin");
  37. spFillAmount = serializedObject.FindProperty("m_FillAmount");
  38. spFillClockwise = serializedObject.FindProperty("m_FillClockwise");
  39. spConstrainRotation = serializedObject.FindProperty("m_ConstrainRotation");
  40. spShapeRotation = serializedObject.FindProperty("m_ShapeRotation");
  41. spFlipHorizontal = serializedObject.FindProperty("m_FlipHorizontal");
  42. spFlipVertical = serializedObject.FindProperty("m_FlipVertical");
  43. spCircle = serializedObject.FindProperty("m_Circle");
  44. spRectangle = serializedObject.FindProperty("m_Rectangle");
  45. spTriangle = serializedObject.FindProperty("m_Triangle");
  46. spPentagon = serializedObject.FindProperty("m_Pentagon");
  47. spHexagon = serializedObject.FindProperty("m_Hexagon");
  48. spNStarPolygon = serializedObject.FindProperty("m_NStarPolygon");
  49. spPreserveAspect = serializedObject.FindProperty("m_PreserveAspect");
  50. spGradient = serializedObject.FindProperty("m_GradientEffect");
  51. }
  52. public override void OnInspectorGUI() {
  53. serializedObject.Update();
  54. FixShaderChannelGUI();
  55. RaycastControlsGUI();
  56. EditorGUILayout.PropertyField(m_Color);
  57. EditorGUILayout.Space();
  58. EditorGUILayout.PropertyField(spShape);
  59. if (spShape.enumValueIndex != (int) DrawShape.None) {
  60. EditorGUILayout.BeginVertical("Box");
  61. if (!spShape.hasMultipleDifferentValues) {
  62. switch ((DrawShape) spShape.enumValueIndex) {
  63. case DrawShape.Circle:
  64. EditorGUILayout.PropertyField(spCircle);
  65. break;
  66. case DrawShape.Rectangle:
  67. EditorGUILayout.PropertyField(spRectangle);
  68. break;
  69. case DrawShape.Pentagon:
  70. EditorGUILayout.PropertyField(spPentagon);
  71. break;
  72. case DrawShape.Triangle:
  73. EditorGUILayout.PropertyField(spTriangle);
  74. break;
  75. case DrawShape.Hexagon:
  76. EditorGUILayout.PropertyField(spHexagon);
  77. break;
  78. case DrawShape.NStarPolygon:
  79. EditorGUILayout.PropertyField(spNStarPolygon);
  80. break;
  81. default:
  82. throw new ArgumentOutOfRangeException();
  83. }
  84. }
  85. EditorGUILayout.Space();
  86. if (spShape.enumValueIndex != (int) DrawShape.None) {
  87. AdditionalShapeDataGUI();
  88. }
  89. EditorGUILayout.EndVertical();
  90. }
  91. EditorGUILayout.Space();
  92. ImageTypeGUI();
  93. SpriteGUI();
  94. if (!spSprite.hasMultipleDifferentValues && spSprite.objectReferenceValue != null) {
  95. EditorGUILayout.PropertyField(spPreserveAspect);
  96. }
  97. SetShowNativeSize(spSprite.objectReferenceValue != null, true);
  98. NativeSizeButtonGUI();
  99. EditorGUILayout.Space();
  100. SharedMaterialGUI();
  101. EditorGUILayout.Space();
  102. EditorGUILayout.BeginVertical("Box");
  103. {
  104. EditorGUILayout.PropertyField(spGradient);
  105. }
  106. EditorGUILayout.EndVertical();
  107. serializedObject.ApplyModifiedProperties();
  108. serializedObject.Update();
  109. Repaint();
  110. }
  111. private void AdditionalShapeDataGUI() {
  112. EditorGUILayout.Space();
  113. float strokeWidth = spStrokeWidth.floatValue;
  114. float outlineWidth = spOutlineWidth.floatValue;
  115. float falloff = spFalloffDistance.floatValue;
  116. Color outlineColor = spOutlineColor.colorValue;
  117. Rect r = EditorGUILayout.GetControlRect(true,
  118. EditorGUIUtility.singleLineHeight * 2 + EditorGUIUtility.standardVerticalSpacing);
  119. Rect line = r;
  120. line.height = EditorGUIUtility.singleLineHeight;
  121. float x = (line.width - 10f) / 2;
  122. float fieldWidth = x / 2 - 10f;
  123. float labelWidth = x - fieldWidth;
  124. line.width = labelWidth;
  125. EditorGUI.LabelField(line, "Stroke");
  126. Rect dragZone = line;
  127. line.x += labelWidth;
  128. line.width = fieldWidth;
  129. EditorGUI.BeginChangeCheck();
  130. {
  131. EditorGUI.showMixedValue = spStrokeWidth.hasMultipleDifferentValues;
  132. strokeWidth =
  133. EditorGUILayoutExtended.FloatFieldExtended(line, spStrokeWidth.floatValue, dragZone);
  134. EditorGUI.showMixedValue = false;
  135. }
  136. if (EditorGUI.EndChangeCheck())
  137. {
  138. spStrokeWidth.floatValue = strokeWidth;
  139. }
  140. line.x += fieldWidth + 10;
  141. line.width = labelWidth;
  142. EditorGUI.LabelField(line, "Falloff");
  143. dragZone = line;
  144. line.x += labelWidth;
  145. line.width = fieldWidth;
  146. EditorGUI.BeginChangeCheck();
  147. {
  148. EditorGUI.showMixedValue = spFalloffDistance.hasMultipleDifferentValues;
  149. falloff =
  150. EditorGUILayoutExtended.FloatFieldExtended(line, spFalloffDistance.floatValue, dragZone);
  151. EditorGUI.showMixedValue = false;
  152. }
  153. if (EditorGUI.EndChangeCheck())
  154. {
  155. spFalloffDistance.floatValue = falloff;
  156. }
  157. line.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
  158. line.x = r.x;
  159. line.width = labelWidth;
  160. EditorGUI.LabelField(line, "Outline Width");
  161. dragZone = line;
  162. line.x += labelWidth;
  163. line.width = fieldWidth;
  164. EditorGUI.BeginChangeCheck();
  165. {
  166. EditorGUI.showMixedValue = spOutlineWidth.hasMultipleDifferentValues;
  167. outlineWidth =
  168. EditorGUILayoutExtended.FloatFieldExtended(line, spOutlineWidth.floatValue, dragZone);
  169. EditorGUI.showMixedValue = false;
  170. }
  171. if (EditorGUI.EndChangeCheck())
  172. {
  173. spOutlineWidth.floatValue = outlineWidth;
  174. }
  175. line.x += fieldWidth + 10;
  176. line.width = labelWidth;
  177. EditorGUI.LabelField(line, "Outline Color");
  178. dragZone = line;
  179. line.width = fieldWidth;
  180. line.x += labelWidth;
  181. EditorGUI.BeginChangeCheck();
  182. {
  183. EditorGUI.showMixedValue = spOutlineColor.hasMultipleDifferentValues;
  184. outlineColor = EditorGUI.ColorField(line, spOutlineColor.colorValue);
  185. EditorGUI.showMixedValue = false;
  186. }
  187. if (EditorGUI.EndChangeCheck())
  188. {
  189. spOutlineColor.colorValue = outlineColor;
  190. }
  191. EditorGUILayout.Space();
  192. RotationGUI();
  193. }
  194. private void RotationGUI() {
  195. Rect r =EditorGUILayout.GetControlRect(true,
  196. EditorGUIUtility.singleLineHeight + 24 + EditorGUIUtility.standardVerticalSpacing);
  197. Rect line = r;
  198. line.height = EditorGUIUtility.singleLineHeight;
  199. float x = (line.width - 10f) / 2;
  200. float fieldWidth = x / 2 - 10f;
  201. float labelWidth = x - fieldWidth;
  202. line.width = labelWidth;
  203. EditorGUI.LabelField(line, "Rotation");
  204. line.x += labelWidth;
  205. line.width = r.width - labelWidth - 78;
  206. string[] options = spConstrainRotation.hasMultipleDifferentValues? new []{ "---", "---" } : new []{"Free", "Constrained"};
  207. bool boolVal = spConstrainRotation.boolValue;
  208. EditorGUI.BeginChangeCheck();
  209. {
  210. boolVal = GUI.Toolbar(line, boolVal ? 1 : 0, options) == 1;
  211. }
  212. if (EditorGUI.EndChangeCheck()) {
  213. spConstrainRotation.boolValue = boolVal;
  214. GUI.FocusControl(null);
  215. }
  216. line.x += line.width + 14;
  217. line.width = 64;
  218. EditorGUI.LabelField(line, "Flip");
  219. line.y += EditorGUIUtility.standardVerticalSpacing + EditorGUIUtility.singleLineHeight;
  220. line.x = r.x + 10;
  221. line.height = EditorGUIUtility.singleLineHeight;
  222. line.width = labelWidth - 10;
  223. EditorGUI.BeginDisabledGroup(spConstrainRotation.boolValue);
  224. {
  225. Rect dragZone = line;
  226. EditorGUI.LabelField(line, "Angle");
  227. line.x = r.x + labelWidth;
  228. line.width = r.width - labelWidth - 148;
  229. float rotationValue = spShapeRotation.floatValue;
  230. EditorGUI.BeginChangeCheck();
  231. {
  232. EditorGUI.showMixedValue = spShapeRotation.hasMultipleDifferentValues;
  233. rotationValue = EditorGUILayoutExtended.FloatFieldExtended(line, spShapeRotation.floatValue, dragZone);
  234. EditorGUI.showMixedValue = false;
  235. }
  236. if (EditorGUI.EndChangeCheck()) {
  237. spShapeRotation.floatValue = rotationValue;
  238. }
  239. }
  240. EditorGUI.EndDisabledGroup();
  241. EditorGUI.BeginDisabledGroup(!spConstrainRotation.boolValue);
  242. {
  243. line.x += line.width + 4;
  244. line.width = 30;
  245. line.height = 24;
  246. if (GUI.Button(line, MPEditorContents.RotateLeftNormal)) {
  247. float rotation = spShapeRotation.floatValue;
  248. float remainder = rotation % 90;
  249. if (Mathf.Abs(remainder) <= 0) {
  250. rotation += 90;
  251. }
  252. else {
  253. rotation = rotation - remainder + 90;
  254. }
  255. if (Math.Abs(rotation) >= 360) rotation = 0;
  256. spShapeRotation.floatValue = rotation;
  257. }
  258. line.x += 34;
  259. if (GUI.Button(line, MPEditorContents.RotateRightNormal)) {
  260. float rotation = spShapeRotation.floatValue;
  261. float remainder = rotation % 90;
  262. if (Mathf.Abs(remainder) <= 0) {
  263. rotation -= 90;
  264. }
  265. else {
  266. rotation -= remainder;
  267. }
  268. if (Math.Abs(rotation) >= 360) rotation = 0;
  269. spShapeRotation.floatValue = rotation;
  270. }
  271. }
  272. EditorGUI.EndDisabledGroup();
  273. line.x += 46;
  274. bool flipH = spFlipHorizontal.boolValue;
  275. bool flipV = spFlipVertical.boolValue;
  276. EditorGUI.BeginChangeCheck();
  277. {
  278. EditorGUI.BeginDisabledGroup(spFlipHorizontal.hasMultipleDifferentValues || spFlipVertical.hasMultipleDifferentValues);
  279. flipH = GUI.Toggle(line, spFlipHorizontal.boolValue, spFlipHorizontal.boolValue ? MPEditorContents.FlipHorizontalActive:MPEditorContents.FlipHorizontalNormal, "button");
  280. line.x += 34;
  281. flipV = GUI.Toggle(line, spFlipVertical.boolValue, spFlipVertical.boolValue?MPEditorContents.FlipVerticalActive:MPEditorContents.FlipVerticalNormal, "button");
  282. EditorGUI.EndDisabledGroup();
  283. }
  284. if (EditorGUI.EndChangeCheck()) {
  285. spFlipHorizontal.boolValue = flipH;
  286. spFlipVertical.boolValue = flipV;
  287. }
  288. }
  289. private void FixShaderChannelGUI() {
  290. if (!shaderChannelsNeedUpdate) return;
  291. EditorGUILayout.HelpBox(
  292. "Parent Canvas needs to have these additional shader channels : Texcoord1, Texcoord2",
  293. MessageType.Error);
  294. EditorGUILayout.BeginHorizontal();
  295. {
  296. GUILayout.FlexibleSpace();
  297. if (GUILayout.Button("Fix", GUILayout.Width(100))) {
  298. Canvas canvas = (target as MPImage)?.GetComponentInParent<Canvas>();
  299. if (canvas != null) {
  300. MPEditorUtility.AddAdditionalShaderChannelsToCanvas(canvas);
  301. shaderChannelsNeedUpdate = false;
  302. }
  303. }
  304. }
  305. EditorGUILayout.EndHorizontal();
  306. }
  307. private new void SpriteGUI() {
  308. EditorGUI.BeginChangeCheck();
  309. EditorGUILayout.PropertyField(spSprite, new GUIContent("Sprite"));
  310. if (EditorGUI.EndChangeCheck()) {
  311. Sprite newSprite = spSprite.objectReferenceValue as Sprite;
  312. if (newSprite) {
  313. Image.Type oldType = (Image.Type) spImageType.enumValueIndex;
  314. if (newSprite.border.SqrMagnitude() > 0) {
  315. spImageType.enumValueIndex = (int) Image.Type.Sliced;
  316. }
  317. else if (oldType == Image.Type.Sliced) {
  318. spImageType.enumValueIndex = (int) Image.Type.Simple;
  319. }
  320. }
  321. (serializedObject.targetObject as Image)?.DisableSpriteOptimizations();
  322. }
  323. }
  324. private void ImageTypeGUI() {
  325. int selectedIndex = spImageType.enumValueIndex == (int) Image.Type.Simple ? 0 : 1;
  326. Rect imageTypeRect = EditorGUILayout.GetControlRect();
  327. EditorGUI.BeginChangeCheck();
  328. {
  329. EditorGUI.LabelField(
  330. new Rect(imageTypeRect.x, imageTypeRect.y, EditorGUIUtility.labelWidth, imageTypeRect.height),
  331. "Type");
  332. imageTypeRect.x += EditorGUIUtility.labelWidth + 2;
  333. imageTypeRect.width -= EditorGUIUtility.labelWidth + 2;
  334. selectedIndex = EditorGUI.Popup(imageTypeRect, selectedIndex, new[] {"Simple", "Filled"});
  335. }
  336. if (EditorGUI.EndChangeCheck()) {
  337. spImageType.enumValueIndex = (int) (selectedIndex == 0 ? Image.Type.Simple : Image.Type.Filled);
  338. }
  339. if (!spImageType.hasMultipleDifferentValues && spImageType.enumValueIndex == (int) Image.Type.Filled) {
  340. ++EditorGUI.indentLevel;
  341. EditorGUI.BeginChangeCheck();
  342. EditorGUILayout.PropertyField(spFillMethod);
  343. if (EditorGUI.EndChangeCheck()) {
  344. spFillOrigin.intValue = 0;
  345. }
  346. switch ((Image.FillMethod) spFillMethod.enumValueIndex) {
  347. case Image.FillMethod.Horizontal:
  348. spFillOrigin.intValue = (int) (Image.OriginHorizontal) EditorGUILayout.EnumPopup("Fill Origin",
  349. (Image.OriginHorizontal) spFillOrigin.intValue);
  350. break;
  351. case Image.FillMethod.Vertical:
  352. spFillOrigin.intValue = (int) (Image.OriginVertical) EditorGUILayout.EnumPopup("Fill Origin",
  353. (Image.OriginVertical) spFillOrigin.intValue);
  354. break;
  355. case Image.FillMethod.Radial90:
  356. spFillOrigin.intValue =
  357. (int) (Image.Origin90) EditorGUILayout.EnumPopup("Fill Origin",
  358. (Image.Origin90) spFillOrigin.intValue);
  359. break;
  360. case Image.FillMethod.Radial180:
  361. spFillOrigin.intValue =
  362. (int) (Image.Origin180) EditorGUILayout.EnumPopup("Fill Origin",
  363. (Image.Origin180) spFillOrigin.intValue);
  364. break;
  365. case Image.FillMethod.Radial360:
  366. spFillOrigin.intValue =
  367. (int) (Image.Origin360) EditorGUILayout.EnumPopup("Fill Origin",
  368. (Image.Origin360) spFillOrigin.intValue);
  369. break;
  370. }
  371. EditorGUILayout.PropertyField(spFillAmount);
  372. if ((Image.FillMethod) spFillMethod.enumValueIndex > Image.FillMethod.Vertical) {
  373. EditorGUILayout.PropertyField(spFillClockwise, new GUIContent("Clockwise"));
  374. }
  375. --EditorGUI.indentLevel;
  376. }
  377. }
  378. private void SharedMaterialGUI() {
  379. Rect rect = EditorGUILayout.GetControlRect(true,
  380. EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing);
  381. int matSett = spMaterialSettings.enumValueIndex;
  382. Rect labelRect = rect;
  383. labelRect.width = EditorGUIUtility.labelWidth;
  384. EditorGUI.LabelField(labelRect, "Material Mode");
  385. rect.x += labelRect.width;
  386. rect.width -= labelRect.width;
  387. EditorGUI.BeginChangeCheck();
  388. EditorGUI.showMixedValue = spMaterialSettings.hasMultipleDifferentValues;
  389. string[] options = new[] {"Dynamic", "Shared"};
  390. if (EditorGUI.showMixedValue) options = new[] {"---", "---"};
  391. matSett = GUI.Toolbar(rect, matSett, options);
  392. if (EditorGUI.EndChangeCheck()) {
  393. spMaterialSettings.enumValueIndex = matSett;
  394. foreach (Object obj in targets) {
  395. ((MPImage) obj).MaterialMode = (MaterialMode) matSett;
  396. EditorUtility.SetDirty(obj);
  397. }
  398. }
  399. EditorGUI.showMixedValue = false;
  400. EditorGUI.BeginDisabledGroup(spMaterialSettings.enumValueIndex == (int) MaterialMode.Dynamic);
  401. {
  402. rect = EditorGUILayout.GetControlRect(true,
  403. EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing);
  404. Object matObj = spMaterial.objectReferenceValue;
  405. EditorGUI.BeginChangeCheck();
  406. {
  407. EditorGUI.showMixedValue = spMaterialSettings.hasMultipleDifferentValues;
  408. matObj = (Material) EditorGUI.ObjectField(
  409. new Rect(rect.x, rect.y, rect.width - 60, EditorGUIUtility.singleLineHeight),
  410. matObj, typeof(Material), false);
  411. EditorGUI.showMixedValue = false;
  412. }
  413. if (EditorGUI.EndChangeCheck()) {
  414. spMaterial.objectReferenceValue = matObj;
  415. foreach (Object obj in targets) {
  416. ((MPImage) obj).material = (Material) matObj;
  417. EditorUtility.SetDirty(obj);
  418. }
  419. }
  420. EditorGUI.BeginDisabledGroup(spMaterial.objectReferenceValue != null);
  421. {
  422. if (GUI.Button(new Rect(rect.x + rect.width - 55, rect.y, 55, EditorGUIUtility.singleLineHeight),
  423. "Create")) {
  424. Material mat = ((MPImage) target).CreateMaterialAssetFromComponentSettings();
  425. spMaterial.objectReferenceValue = mat;
  426. foreach (Object obj in targets) {
  427. ((MPImage) obj).material = mat;
  428. EditorUtility.SetDirty(obj);
  429. }
  430. }
  431. }
  432. EditorGUI.EndDisabledGroup();
  433. }
  434. EditorGUI.EndDisabledGroup();
  435. }
  436. }
  437. }