Skip to content

Instantly share code, notes, and snippets.

@bzgeb
Last active October 19, 2021 16:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bzgeb/8dd186bbdd532f43fe6c7615f036cc19 to your computer and use it in GitHub Desktop.
Save bzgeb/8dd186bbdd532f43fe6c7615f036cc19 to your computer and use it in GitHub Desktop.
Quick and dirty Unity tool to place an object
using UnityEditor;
using UnityEditor.EditorTools;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
[EditorTool("Place Object Tool")]
public class PlaceObjectTool : EditorTool
{
[SerializeField] Texture2D m_ToolIcon;
GUIContent m_IconContent;
VisualElement toolRootElement;
Toggle useCurrentSelection;
ObjectField prefabObjectField;
bool receivedClickDownEvent;
bool receivedClickUpEvent;
public override GUIContent toolbarIcon => m_IconContent;
public override void OnActivated()
{
m_IconContent = new GUIContent
{
image = m_ToolIcon,
text = "Place Object Tool",
tooltip = "Place Object Tool"
};
var sv = SceneView.lastActiveSceneView;
SceneView.beforeSceneGui += BeforeSceneGUI;
toolRootElement = new VisualElement();
toolRootElement.style.width = 200;
var titleLabel = new Label("Place Object Tool");
toolRootElement.Add(titleLabel);
prefabObjectField = new ObjectField {allowSceneObjects = true, objectType = typeof(GameObject)};
useCurrentSelection = new Toggle {label = "Use Current Selection"};
useCurrentSelection.RegisterValueChangedCallback(evt => { prefabObjectField.visible = !evt.newValue; });
toolRootElement.Add(useCurrentSelection);
toolRootElement.Add(prefabObjectField);
sv.rootVisualElement.Add(toolRootElement);
sv.rootVisualElement.style.flexDirection = FlexDirection.ColumnReverse;
}
public override void OnWillBeDeactivated()
{
SceneView.beforeSceneGui -= BeforeSceneGUI;
toolRootElement?.RemoveFromHierarchy();
}
public void BeforeSceneGUI(SceneView sceneView)
{
if (ToolManager.IsActiveTool(this))
{
if (useCurrentSelection.value && Selection.activeGameObject == null)
{
receivedClickDownEvent = false;
receivedClickUpEvent = false;
return;
}
if (!useCurrentSelection.value && prefabObjectField?.value == null)
{
receivedClickDownEvent = false;
receivedClickUpEvent = false;
return;
}
if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
{
receivedClickDownEvent = true;
Event.current.Use();
}
if (receivedClickDownEvent && Event.current.type == EventType.MouseUp && Event.current.button == 0)
{
receivedClickDownEvent = false;
receivedClickUpEvent = true;
Event.current.Use();
}
}
}
public override void OnToolGUI(EditorWindow window)
{
if (!(window is SceneView sceneView))
return;
if (ToolManager.IsActiveTool(this))
{
if (useCurrentSelection.value && Selection.activeGameObject == null)
{
return;
}
if (!useCurrentSelection.value && prefabObjectField?.value == null)
{
return;
}
Handles.DrawWireDisc(GetCurrentMousePositionInScene(), Vector3.up, 1f);
if (receivedClickUpEvent)
{
var newObject = useCurrentSelection.value ? Selection.activeGameObject : prefabObjectField.value;
PrefabUtility.IsPartOfPrefabInstance(newObject);
var newPrefabInstance = (GameObject) PrefabUtility.InstantiatePrefab(newObject);
if (newPrefabInstance == null)
{
if (PrefabUtility.IsPartOfPrefabInstance(newObject))
{
var prefabPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(newObject);
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
newPrefabInstance = (GameObject) PrefabUtility.InstantiatePrefab(prefab);
}
else
{
newPrefabInstance = Instantiate((GameObject) newObject);
}
}
newPrefabInstance.transform.position = GetCurrentMousePositionInScene();
Event.current.Use();
Undo.RegisterCreatedObjectUndo(newPrefabInstance, "Place new object");
receivedClickUpEvent = false;
}
}
}
Vector3 GetCurrentMousePositionInScene()
{
Vector3 mousePosition = Event.current.mousePosition;
var placeObject = HandleUtility.PlaceObject(mousePosition, out var newPosition, out var normal);
return placeObject ? newPosition : HandleUtility.GUIPointToWorldRay(mousePosition).GetPoint(10);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment