Reputation: 4177
For instance, I found out that the Unity plugin "Octave3d Level Design" has this feature
I hope to make my own prefab manager, since Octave3d prefab manager is not fit for my need. So the question is: when mouse is overlapping Scene View, how to make mouse seize a object and put it in Scene View?
Upvotes: 1
Views: 4986
Reputation: 307
In Octave3d
, they implemented this function by:
preview
gameobject of the prefab in Scene, the preview gameobject will follow the mouse (by their custom raycast detection). The preview gameobject's parent is the octave manager or something like this.And I think it was a bit overkill, something like Unity's own DragAndDrop is enough: a prefab can be drag from custom editorwindow, and drop on sceneview, hierarchy or object field. And this CUSTOM drag and drop can be implement like this:
MouseDownEvent
to start the DragAndDropDragUpdatedEvent
to move the dragging objectDropping
on SceneView or Hierarchy, listen to DragPerform
and DragExited
in there ongui callback.Code is here:
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
public class MyWindow : EditorWindow
{
[MenuItem("Window/MyWindow")]
private static void ShowWindow()
{
GetWindow<MyWindow>("MyWindow");
}
private GameObject prefab;
private bool m_IsDragPerformed = false;
private bool m_IsDragging = false;
private void OnEnable()
{
prefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Cube.prefab");
var box = new VisualElement();
box.style.backgroundColor = Color.red;
box.style.flexGrow = 1f;
box.RegisterCallback<MouseDownEvent>(evt =>
{
DragAndDrop.PrepareStartDrag();
DragAndDrop.StartDrag("Dragging");
DragAndDrop.objectReferences = new Object[] { prefab };
Selection.activeGameObject = null;
m_IsDragPerformed = false;
m_IsDragging = true;
});
box.RegisterCallback<DragUpdatedEvent>(evt =>
{
DragAndDrop.visualMode = DragAndDropVisualMode.Move;
});
rootVisualElement.Add(box);
SceneView.duringSceneGui += sv => OnDragEnd();
EditorApplication.hierarchyWindowItemOnGUI += (id, rect) => OnDragEnd();
}
private void OnDragEnd()
{
if (Event.current.type == EventType.DragPerform)
{
m_IsDragPerformed = true;
}
if (Event.current.type == EventType.DragExited)
{
if (m_IsDragging && m_IsDragPerformed)
{
m_IsDragging = false;
m_IsDragPerformed = false;
var go = Selection.activeGameObject;
// Do your **OnDragEnd callback on go** here
}
}
}
private void OnDestroy()
{
SceneView.duringSceneGui -= sv => OnDragEnd();
EditorApplication.hierarchyWindowItemOnGUI -= (id, rect) => OnDragEnd();
}
}
Reference is here, this guy is a genius: How to start DragAndDrop action so that SceneView and Hierarchy accept it like with prefabs
Upvotes: 0
Reputation: 31
Edit: Actually found out that you'll need to use SceneView.lastActiveSceneView.camera as your camera, and you can use Gizmos.DrawMesh() to draw the mesh instead of instantiating..
There's also SceneView.OnSceneGUIDelegate that can help you access the scene view.
here's some sample code on how to set that up
void OnGUI() {
if (objectThatFollowsMouse != null) {
SceneView.onSceneGUIDelegate -= OnSceneGUI;
SceneView.onSceneGUIDelegate += OnSceneGUI;
}
else { SceneView.onSceneGUIDelegate -= OnSceneGUI; }
}
void OnSceneGUI(SceneView sceneView) {
...
}
with some additional editor scripting, you can do something like this
Vector3 mousePoint = Camera.main.ViewportToWorldPoint(Input.mousePosition);
if (objectShouldFollowMouse) {
objectThatFollowsMouse.transform.position = mousePoint;
if (Event.current.type == EventType.MouseUp) {
objectShouldFollowMouse = false;
objectThatFollowsMouse = null;
}
}
if (prefabGotClicked) {
GameObject obj = Object.Instantiate(someObject,mousePoint,Quaternion.identity) as GameObject;
objectShouldFollowMouse = true;
objectThatFollowsMouse = obj;
}
Upvotes: 2