You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

292 lines
13 KiB

  1. using UnityEngine;
  2. using UnityEditor;
  3. using UnityEngine.UI;
  4. using UnityEngine.EventSystems;
  5. namespace TMPro.EditorUtilities
  6. {
  7. public static class TMPro_CreateObjectMenu
  8. {
  9. /// <summary>
  10. /// Create a TextMeshPro object that works with the Mesh Renderer
  11. /// </summary>
  12. /// <param name="command"></param>
  13. [MenuItem("GameObject/3D Object/TextMeshPro - Text", false, 30)]
  14. static void CreateTextMeshProObjectPerform(MenuCommand command)
  15. {
  16. GameObject go = new GameObject("TextMeshPro");
  17. TextMeshPro textMeshPro = go.AddComponent<TextMeshPro>();
  18. textMeshPro.text = "Sample text";
  19. textMeshPro.alignment = TextAlignmentOptions.TopLeft;
  20. Undo.RegisterCreatedObjectUndo((Object)go, "Create " + go.name);
  21. GameObject contextObject = command.context as GameObject;
  22. if (contextObject != null)
  23. {
  24. GameObjectUtility.SetParentAndAlign(go, contextObject);
  25. Undo.SetTransformParent(go.transform, contextObject.transform, "Parent " + go.name);
  26. }
  27. Selection.activeGameObject = go;
  28. }
  29. /// <summary>
  30. /// Create a TextMeshPro object that works with the CanvasRenderer
  31. /// </summary>
  32. /// <param name="command"></param>
  33. [MenuItem("GameObject/UI/TextMeshPro - Text", false, 2001)]
  34. static void CreateTextMeshProGuiObjectPerform(MenuCommand command)
  35. {
  36. // Check if there is a Canvas in the scene
  37. Canvas canvas = Object.FindObjectOfType<Canvas>();
  38. if (canvas == null)
  39. {
  40. // Create new Canvas since none exists in the scene.
  41. GameObject canvasObject = new GameObject("Canvas");
  42. canvas = canvasObject.AddComponent<Canvas>();
  43. canvas.renderMode = RenderMode.ScreenSpaceOverlay;
  44. // Add a Graphic Raycaster Component as well
  45. canvas.gameObject.AddComponent<GraphicRaycaster>();
  46. Undo.RegisterCreatedObjectUndo(canvasObject, "Create " + canvasObject.name);
  47. }
  48. // Create the TextMeshProUGUI Object
  49. GameObject go = new GameObject("TextMeshPro Text");
  50. RectTransform goRectTransform = go.AddComponent<RectTransform>();
  51. Undo.RegisterCreatedObjectUndo((Object)go, "Create " + go.name);
  52. // Check if object is being create with left or right click
  53. GameObject contextObject = command.context as GameObject;
  54. if (contextObject == null)
  55. {
  56. //goRectTransform.sizeDelta = new Vector2(200f, 50f);
  57. GameObjectUtility.SetParentAndAlign(go, canvas.gameObject);
  58. TextMeshProUGUI textMeshPro = go.AddComponent<TextMeshProUGUI>();
  59. textMeshPro.text = "New Text";
  60. textMeshPro.alignment = TextAlignmentOptions.TopLeft;
  61. }
  62. else
  63. {
  64. if (contextObject.GetComponent<Button>() != null)
  65. {
  66. goRectTransform.sizeDelta = Vector2.zero;
  67. goRectTransform.anchorMin = Vector2.zero;
  68. goRectTransform.anchorMax = Vector2.one;
  69. GameObjectUtility.SetParentAndAlign(go, contextObject);
  70. TextMeshProUGUI textMeshPro = go.AddComponent<TextMeshProUGUI>();
  71. textMeshPro.text = "Button";
  72. textMeshPro.fontSize = 24;
  73. textMeshPro.alignment = TextAlignmentOptions.Center;
  74. }
  75. else
  76. {
  77. //goRectTransform.sizeDelta = new Vector2(200f, 50f);
  78. GameObjectUtility.SetParentAndAlign(go, contextObject);
  79. TextMeshProUGUI textMeshPro = go.AddComponent<TextMeshProUGUI>();
  80. textMeshPro.text = "New Text";
  81. textMeshPro.alignment = TextAlignmentOptions.TopLeft;
  82. }
  83. }
  84. // Check if an event system already exists in the scene
  85. if (!Object.FindObjectOfType<EventSystem>())
  86. {
  87. GameObject eventObject = new GameObject("EventSystem", typeof(EventSystem));
  88. eventObject.AddComponent<StandaloneInputModule>();
  89. Undo.RegisterCreatedObjectUndo(eventObject, "Create " + eventObject.name);
  90. }
  91. Selection.activeGameObject = go;
  92. }
  93. [MenuItem("GameObject/UI/TextMeshPro - Input Field", false, 2037)]
  94. static void AddTextMeshProInputField(MenuCommand menuCommand)
  95. {
  96. GameObject go = TMP_DefaultControls.CreateInputField(GetStandardResources());
  97. PlaceUIElementRoot(go, menuCommand);
  98. }
  99. [MenuItem("GameObject/UI/TextMeshPro - Dropdown", false, 2036)]
  100. static public void AddDropdown(MenuCommand menuCommand)
  101. {
  102. GameObject go = TMP_DefaultControls.CreateDropdown(GetStandardResources());
  103. PlaceUIElementRoot(go, menuCommand);
  104. }
  105. private const string kUILayerName = "UI";
  106. private const string kStandardSpritePath = "UI/Skin/UISprite.psd";
  107. private const string kBackgroundSpritePath = "UI/Skin/Background.psd";
  108. private const string kInputFieldBackgroundPath = "UI/Skin/InputFieldBackground.psd";
  109. private const string kKnobPath = "UI/Skin/Knob.psd";
  110. private const string kCheckmarkPath = "UI/Skin/Checkmark.psd";
  111. private const string kDropdownArrowPath = "UI/Skin/DropdownArrow.psd";
  112. private const string kMaskPath = "UI/Skin/UIMask.psd";
  113. static private TMP_DefaultControls.Resources s_StandardResources;
  114. static private TMP_DefaultControls.Resources GetStandardResources()
  115. {
  116. if (s_StandardResources.standard == null)
  117. {
  118. s_StandardResources.standard = AssetDatabase.GetBuiltinExtraResource<Sprite>(kStandardSpritePath);
  119. s_StandardResources.background = AssetDatabase.GetBuiltinExtraResource<Sprite>(kBackgroundSpritePath);
  120. s_StandardResources.inputField = AssetDatabase.GetBuiltinExtraResource<Sprite>(kInputFieldBackgroundPath);
  121. s_StandardResources.knob = AssetDatabase.GetBuiltinExtraResource<Sprite>(kKnobPath);
  122. s_StandardResources.checkmark = AssetDatabase.GetBuiltinExtraResource<Sprite>(kCheckmarkPath);
  123. s_StandardResources.dropdown = AssetDatabase.GetBuiltinExtraResource<Sprite>(kDropdownArrowPath);
  124. s_StandardResources.mask = AssetDatabase.GetBuiltinExtraResource<Sprite>(kMaskPath);
  125. }
  126. return s_StandardResources;
  127. }
  128. private static void SetPositionVisibleinSceneView(RectTransform canvasRTransform, RectTransform itemTransform)
  129. {
  130. // Find the best scene view
  131. SceneView sceneView = SceneView.lastActiveSceneView;
  132. if (sceneView == null && SceneView.sceneViews.Count > 0)
  133. sceneView = SceneView.sceneViews[0] as SceneView;
  134. // Couldn't find a SceneView. Don't set position.
  135. if (sceneView == null || sceneView.camera == null)
  136. return;
  137. // Create world space Plane from canvas position.
  138. Vector2 localPlanePosition;
  139. Camera camera = sceneView.camera;
  140. Vector3 position = Vector3.zero;
  141. if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRTransform, new Vector2(camera.pixelWidth / 2, camera.pixelHeight / 2), camera, out localPlanePosition))
  142. {
  143. // Adjust for canvas pivot
  144. localPlanePosition.x = localPlanePosition.x + canvasRTransform.sizeDelta.x * canvasRTransform.pivot.x;
  145. localPlanePosition.y = localPlanePosition.y + canvasRTransform.sizeDelta.y * canvasRTransform.pivot.y;
  146. localPlanePosition.x = Mathf.Clamp(localPlanePosition.x, 0, canvasRTransform.sizeDelta.x);
  147. localPlanePosition.y = Mathf.Clamp(localPlanePosition.y, 0, canvasRTransform.sizeDelta.y);
  148. // Adjust for anchoring
  149. position.x = localPlanePosition.x - canvasRTransform.sizeDelta.x * itemTransform.anchorMin.x;
  150. position.y = localPlanePosition.y - canvasRTransform.sizeDelta.y * itemTransform.anchorMin.y;
  151. Vector3 minLocalPosition;
  152. minLocalPosition.x = canvasRTransform.sizeDelta.x * (0 - canvasRTransform.pivot.x) + itemTransform.sizeDelta.x * itemTransform.pivot.x;
  153. minLocalPosition.y = canvasRTransform.sizeDelta.y * (0 - canvasRTransform.pivot.y) + itemTransform.sizeDelta.y * itemTransform.pivot.y;
  154. Vector3 maxLocalPosition;
  155. maxLocalPosition.x = canvasRTransform.sizeDelta.x * (1 - canvasRTransform.pivot.x) - itemTransform.sizeDelta.x * itemTransform.pivot.x;
  156. maxLocalPosition.y = canvasRTransform.sizeDelta.y * (1 - canvasRTransform.pivot.y) - itemTransform.sizeDelta.y * itemTransform.pivot.y;
  157. position.x = Mathf.Clamp(position.x, minLocalPosition.x, maxLocalPosition.x);
  158. position.y = Mathf.Clamp(position.y, minLocalPosition.y, maxLocalPosition.y);
  159. }
  160. itemTransform.anchoredPosition = position;
  161. itemTransform.localRotation = Quaternion.identity;
  162. itemTransform.localScale = Vector3.one;
  163. }
  164. private static void PlaceUIElementRoot(GameObject element, MenuCommand menuCommand)
  165. {
  166. GameObject parent = menuCommand.context as GameObject;
  167. if (parent == null || parent.GetComponentInParent<Canvas>() == null)
  168. {
  169. parent = GetOrCreateCanvasGameObject();
  170. }
  171. string uniqueName = GameObjectUtility.GetUniqueNameForSibling(parent.transform, element.name);
  172. element.name = uniqueName;
  173. Undo.RegisterCreatedObjectUndo(element, "Create " + element.name);
  174. Undo.SetTransformParent(element.transform, parent.transform, "Parent " + element.name);
  175. GameObjectUtility.SetParentAndAlign(element, parent);
  176. if (parent != menuCommand.context) // not a context click, so center in sceneview
  177. SetPositionVisibleinSceneView(parent.GetComponent<RectTransform>(), element.GetComponent<RectTransform>());
  178. Selection.activeGameObject = element;
  179. }
  180. static public GameObject CreateNewUI()
  181. {
  182. // Root for the UI
  183. var root = new GameObject("Canvas");
  184. root.layer = LayerMask.NameToLayer(kUILayerName);
  185. Canvas canvas = root.AddComponent<Canvas>();
  186. canvas.renderMode = RenderMode.ScreenSpaceOverlay;
  187. root.AddComponent<CanvasScaler>();
  188. root.AddComponent<GraphicRaycaster>();
  189. Undo.RegisterCreatedObjectUndo(root, "Create " + root.name);
  190. // if there is no event system add one...
  191. CreateEventSystem(false);
  192. return root;
  193. }
  194. private static void CreateEventSystem(bool select)
  195. {
  196. CreateEventSystem(select, null);
  197. }
  198. private static void CreateEventSystem(bool select, GameObject parent)
  199. {
  200. var esys = Object.FindObjectOfType<EventSystem>();
  201. if (esys == null)
  202. {
  203. var eventSystem = new GameObject("EventSystem");
  204. GameObjectUtility.SetParentAndAlign(eventSystem, parent);
  205. esys = eventSystem.AddComponent<EventSystem>();
  206. eventSystem.AddComponent<StandaloneInputModule>();
  207. Undo.RegisterCreatedObjectUndo(eventSystem, "Create " + eventSystem.name);
  208. }
  209. if (select && esys != null)
  210. {
  211. Selection.activeGameObject = esys.gameObject;
  212. }
  213. }
  214. static public GameObject GetOrCreateCanvasGameObject()
  215. {
  216. GameObject selectedGo = Selection.activeGameObject;
  217. // Try to find a gameobject that is the selected GO or one if its parents.
  218. Canvas canvas = (selectedGo != null) ? selectedGo.GetComponentInParent<Canvas>() : null;
  219. if (canvas != null && canvas.gameObject.activeInHierarchy)
  220. return canvas.gameObject;
  221. // No canvas in selection or its parents? Then use just any canvas..
  222. canvas = Object.FindObjectOfType(typeof(Canvas)) as Canvas;
  223. if (canvas != null && canvas.gameObject.activeInHierarchy)
  224. return canvas.gameObject;
  225. // No canvas in the scene at all? Then create a new one.
  226. return CreateNewUI();
  227. }
  228. }
  229. }