// Helper function that returns a Canvas GameObject; preferably a parent of the selection, or other existing Canvas. static public GameObject GetOrCreateCanvasGameObject() { GameObject selectedGo = Selection.activeGameObject; // Try to find a gameobject that is the selected GO or one if its parents. Canvas canvas = (selectedGo != null) ? selectedGo.GetComponentInParent <Canvas>() : null; if (IsValidCanvas(canvas)) { return(canvas.gameObject); } // No canvas in selection or its parents? Then use any valid canvas. // We have to find all loaded Canvases, not just the ones in main scenes. Canvas[] canvasArray = StageUtility.GetCurrentStageHandle().FindComponentsOfType <Canvas>(); for (int i = 0; i < canvasArray.Length; i++) { if (IsValidCanvas(canvasArray[i])) { return(canvasArray[i].gameObject); } } // No canvas in the scene at all? Then create a new one. return(MenuOptionsOverwrite.CreateNewUI()); }
private static void PlaceUIElementRoot(GameObject element, MenuCommand menuCommand) { GameObject parent = menuCommand.context as GameObject; bool explicitParentChoice = true; if (parent == null) { parent = GetOrCreateCanvasGameObject(); explicitParentChoice = false; // If in Prefab Mode, Canvas has to be part of Prefab contents, // otherwise use Prefab root instead. PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null && !prefabStage.IsPartOfPrefabContents(parent)) { parent = prefabStage.prefabContentsRoot; } } if (parent.GetComponentInParent <Canvas>() == null) { // Create canvas under context GameObject, // and make that be the parent which UI element is added under. GameObject canvas = MenuOptionsOverwrite.CreateNewUI(); canvas.transform.SetParent(parent.transform, false); parent = canvas; } // Setting the element to be a child of an element already in the scene should // be sufficient to also move the element to that scene. // However, it seems the element needs to be already in its destination scene when the // RegisterCreatedObjectUndo is performed; otherwise the scene it was created in is dirtied. SceneManager.MoveGameObjectToScene(element, parent.scene); Undo.RegisterCreatedObjectUndo(element, "Create " + element.name); if (element.transform.parent == null) { Undo.SetTransformParent(element.transform, parent.transform, "Parent " + element.name); } GameObjectUtility.EnsureUniqueNameForSibling(element); // We have to fix up the undo name since the name of the object was only known after reparenting it. Undo.SetCurrentGroupName("Create " + element.name); GameObjectUtility.SetParentAndAlign(element, parent); if (!explicitParentChoice) // not a context click, so center in sceneview { SetPositionVisibleinSceneView(parent.GetComponent <RectTransform>(), element.GetComponent <RectTransform>()); } Selection.activeGameObject = element; }