Writing an Editor Window that mimics the Scene View

I am writing an editor extension (let’s call it EE1) that involves the manipulation of a pattern. The pattern’s data is stored in a scriptable object and represented by game objects in the scene view, however, since the data is stored as a scriptable object, I don’t actually need to save any data to a scene object. The pattern is just a 2D or 3D array of cells, with some cells being active, and others inactive.

Currently I just open up a new scene, load the pattern, and the user can then manipulate/change the pattern. The scene is closed once pattern editing is finished.

The issue is, I have another editor extension (also which utilizes the scene view, let’s call it EE2) that uses the pattern, and it would be beneficial to allow both these editor extensions to run at once, as adjusting the pattern to fit the users needs would be easier if they could have EE2 open. Otherwise, to edit the pattern using EE1, I have to close the EE2 scene.

If the pattern were just two dimensional, I could build EE1 using an Editor Window, however the pattern can be three dimensional, which is why it is easier to use game objects to represent it and also make use of the rotatable camera.

So, what I really need, is a sort of dummy scene view that allows me to load game objects into it, but doesn’t actually utilize a scene asset. This dummy scene view would also need to be usable while an actual scene view is also open, in the same way you can open an editor window while a scene is open.

Does anyone have any experience with this?

Is there any reason you can’t have both of them in the same scene?

It would be basically impossible to do the pattern editing while the second editing process is underway. Sort of difficult to explain, but I did consider that possibility and it is not feasible. Thanks for the suggestion though!

I had an idea for an editor which was something similar, however I never implemented it. What I planned on doing was changing the culling mask on the scene view camera.

So in editor 1: it could see objects on layer A
and
editor 2: could not see objects on layer A

possibly you could do something similar?

Hmm, I suppose that should be possible, since each scene view should utilize its own camera. I will play around with this and see what I can come up with. Thanks for the suggestion!

You could still do that without culling masks. The scene is a large place. Just put the components far away from each other.

Yes, but since the scene in question could basically contain anything (i.e., when the ‘editor’ is launched, I’d just load it into whatever scene was currently open), calculating a “safe” place where no other objects appear may be ridiculously hard, if not impossible.

Or am I missing something?

Would it be possible to provide some more context (screenshots, etc.) as to what you’re working with? Might make it possible to give more specific advice.

https://discussions.unity.com/t/519162 page-5

If you scroll down to the bottom of that page you’ll see in the second and third to last post the pattern editor.

Firstly, you can certainly calculate a ‘safe’ space for the editor by checking the AABBs of all the renderers in the scene. Not that I would recommend doing that, but it isn’t impossible.

Second, check out this API: Unity - Scripting API: SceneManagement.EditorSceneManager.NewPreviewScene

Make your gameobjects and add it to that scene. You can create a camera for the scene, and then render it with Unity - Scripting API: Handles.DrawCamera into an EditorWindow.

PreviewScene looks like it has some potential. I’ll look into it. Thanks!

if you look into the preview scene, you might want to look at my post here:
https://discussions.unity.com/t/715108/2
where I have ripped out the source of previewgui

~The reason for this is, because the object is instantiated when you add it to the preview scene, you lose reference to it. the above code solves that~

The PreviewScene method is not the same as the OnPreviewGUI method. Using a PreviewScene does not cause you to lose the reference to gameobjects you add to it.

1 Like

ah okay, my bad

Is doing it with Handles.DrawCamera the only way? I would like the user to make use of some of the functionality that is built into the normal Scene View, such as changing the camera view and dragging the scene camera around. It seems like I would need to re-engineer such functionality doing things this way. Am I wrong?

And also, how would I go about creating a camera for this preview scene?

Yep. It’s not overly difficult though.

You create a camera same way you’d create a camera through code for any other purpose. Create a new GameObject and add a Camera component.

Okay, thank you!

Sorry, I must ask for more help, as it seems you are the only one with knowledge of this stuff (if you can point me to instructional material I will be glad to figure all this out on my own).

In any case, I have created a Preview Scene, added a camera to it (I used EditorSceneManager.MoveGameObjectToScene to make sure it is in the preview scene), and am using Handles.DrawCamera, but it seems to be drawing the camera of whatever scene I have open rather than the one I created for the Preview Scene. Also, I cannot get the camera render to cover the entire editor window. I also tried using Handles.SetCamera first.

Handles.DrawCamera(new Rect(0, 0, position.width, position.height), sceneCamera);

Where position is the EditorWindow.position rect. I am using 0, 0 after looking at the SceneView class on GitHub. sceneCamera is 100% a reference to the camera created procedurally and moved to the PreviewScene.

I am not sure what I am doing wrong.

Can you post the entirety of the EditorWindow code as it stands, as well as a screenshot of what you’re seeing? It doesn’t make any sense for it to be drawing a different camera than you pass it.

Sure.

The Preview Scene, Editor Window, and game objects are all created via a button press in the inspector of my pattern scriptable object, through a call to this static method:

OpenEditingWindow

static LoadingPatternEditor OpenEditingWindow()
{
    var scene = EditorSceneManager.NewPreviewScene();
    scene.name = "DLK_Loading_Pattern_Editor";
    workingEditor = EditorWindow.GetWindow<LoadingPatternEditor>();
    workingEditor.position = new Rect(Screen.width / 2 + 300, 400, 600, 300);
    var root = new GameObject("DLK_Loading_Pattern_Editor_Root");
    root.transform.position = new Vector3(.5f, .5f, .5f);
    EditorSceneManager.MoveGameObjectToScene(root, scene);
    var camGO = new GameObject("Camera");
    Camera cam = camGO.AddComponent<Camera>();
    camGO.transform.position = new Vector3(.5f, .5f, .5f);
    EditorSceneManager.MoveGameObjectToScene(camGO, scene);
           
    workingEditor.OnEditorLoaded(scene, cam, root);
    //workingEditor.PreviousSceneSetup = currentScenes;
    return workingEditor;
}

The scene, camera, and root game object (which just serves as a parent for game objects used as visual cues for the pattern in the scene) are all passed to the Editor Window via the OnEditorLoaded call.

The OnGUI method of the EditorWindow looks like this:
OnGUI

private void OnGUI()
{
    if (!editorScene.IsValid() || !editorScene.isLoaded)
    {
        OnEditorUnLoaded();
        return;
    }

    isInTopDownOrtho = sceneCamera.orthographic && sceneCamera.transform.rotation == downView;

    if (patternRepositoryCurrentlyBeingEdited == null)
        AccountForNewRepository();

    patternRepositoryCurrentlyBeingEdited.Update();

    //GUI.Box(rect, GUIContent.none);
    GUISkin skin = GUI.skin;
    GUI.skin = style;

    DrawGUI();
    if (currentPattern != null)
        currentPattern.DrawEditor();

    SceneView.RepaintAll();
    GUI.skin = skin;

    patternRepositoryCurrentlyBeingEdited.ApplyModifiedProperties();
}

The DrawGUI method is what contains the actual camera rendering.
DrawGUI

void DrawGUI()
{
    GetStyles();

    Handles.SetCamera(sceneCamera);
    Handles.DrawCamera(new Rect(0, 0, position.width, position.height), sceneCamera);
    Handles.BeginGUI();
    EditorGUILayout.BeginVertical("BackgroundWindow");

    EditorGUILayout.BeginHorizontal(horizontalStyle);
    LabelField("Show Full Menu");
    showMenuProp.boolValue = EditorGUILayout.Toggle(showMenuProp.boolValue, toggleStyle, toggleWidth, toggleHeight);
    EditorGUILayout.EndHorizontal();

    if (showMenuProp.boolValue)
        DrawFullMenu();
    else
        DrawHiddenMenu();
}

There is a lot more code. I can post it all if you don’t think it would be helpful, but I am hopeful that whatever I am doing wrong is apparent in the code posted above. Posting the entire code would provide a lot to sift through.

Thanks for the help!