/// <summary> /// Creates the scene camera and updates the render texture. Should be called at least once before using the /// scene view. Should be called whenever the window is resized. /// </summary> /// <param name="width">Width of the scene render target, in pixels.</param> /// <param name="height">Height of the scene render target, in pixels.</param> private void UpdateRenderTexture(int width, int height) { width = MathEx.Max(20, width); height = MathEx.Max(20, height); // Note: Depth buffer and readable flags are required because ScenePicking uses it Texture colorTex = Texture.Create2D(width, height, PixelFormat.RGBA8, TextureUsage.Render | TextureUsage.CPUReadable); Texture depthTex = Texture.Create2D(width, height, PixelFormat.D32_S8X24, TextureUsage.DepthStencil | TextureUsage.CPUReadable); renderTexture = new RenderTexture(colorTex, depthTex); renderTexture.Priority = 1; if (camera == null) { SceneObject sceneCameraSO = new SceneObject("SceneCamera", true); camera = sceneCameraSO.AddComponent <Camera>(); camera.Viewport.Target = renderTexture; camera.Viewport.Area = new Rect2(0.0f, 0.0f, 1.0f, 1.0f); sceneCameraSO.Position = new Vector3(0, 0.5f, 1); sceneCameraSO.LookAt(new Vector3(0, 0.5f, 0)); camera.Priority = 2; camera.Viewport.ClearColor = ClearColor; camera.Layers = UInt64.MaxValue & ~SceneAxesHandle.LAYER; // Don't draw scene axes in this camera cameraController = sceneCameraSO.AddComponent <SceneCamera>(); cameraController.Initialize(); renderTextureGUI = new GUIRenderTexture(renderTexture); rtPanel.AddElement(renderTextureGUI); sceneGrid = new SceneGrid(camera); sceneSelection = new SceneSelection(camera); sceneGizmos = new SceneGizmos(camera); sceneHandles = new SceneHandles(this, camera); } else { camera.Viewport.Target = renderTexture; renderTextureGUI.RenderTexture = renderTexture; } Rect2I rtBounds = new Rect2I(0, 0, width, height); renderTextureGUI.Bounds = rtBounds; focusCatcher.Bounds = GUIUtility.CalculateBounds(rtPanel, GUI); sceneAxesGUI.SetPosition(width - HandleAxesGUISize - HandleAxesGUIPaddingX, HandleAxesGUIPaddingY); // TODO - Consider only doing the resize once user stops resizing the widget in order to reduce constant // render target destroy/create cycle for every single pixel. camera.AspectRatio = width / (float)height; }
/// <summary> /// Creates a new scene axes GUI. /// </summary> /// <param name="window">Window in which the GUI is located in.</param> /// <param name="panel">Panel onto which to place the GUI element.</param> /// <param name="width">Width of the GUI element.</param> /// <param name="height">Height of the GUI element.</param> /// <param name="projType">Projection type to display on the GUI.</param> public SceneAxesGUI(SceneWindow window, GUIPanel panel, int width, int height, ProjectionType projType) { renderTexture = new RenderTexture(PixelFormat.RGBA8, width, height); renderTexture.Priority = 1; SceneObject cameraSO = new SceneObject("SceneAxesCamera", true); camera = cameraSO.AddComponent <Camera>(); camera.Viewport.Target = renderTexture; camera.Viewport.Area = new Rect2(0.0f, 0.0f, 1.0f, 1.0f); cameraSO.Position = new Vector3(0, 0, 5); cameraSO.LookAt(new Vector3(0, 0, 0)); camera.Priority = 2; camera.NearClipPlane = 0.05f; camera.FarClipPlane = 1000.0f; camera.Viewport.ClearColor = new Color(0.0f, 0.0f, 0.0f, 0.0f); camera.ProjectionType = ProjectionType.Orthographic; camera.Layers = SceneAxesHandle.LAYER; camera.AspectRatio = 1.0f; camera.OrthoHeight = 2.0f; camera.RenderSettings.EnableHDR = false; camera.RenderSettings.EnableSkybox = false; camera.Flags |= CameraFlag.OnDemand; renderTextureGUI = new GUIRenderTexture(renderTexture, true); GUILayoutY layout = panel.AddLayoutY(); GUILayoutX textureLayout = layout.AddLayoutX(); textureLayout.AddElement(renderTextureGUI); textureLayout.AddFlexibleSpace(); Rect2I bounds = new Rect2I(0, 0, width, height); sceneHandles = new SceneHandles(window, camera); renderTextureGUI.Bounds = bounds; labelGUI = new GUILabel(projType.ToString(), EditorStyles.LabelCentered); layout.AddElement(labelGUI); layout.AddFlexibleSpace(); this.panel = panel; this.bounds = bounds; NotifyNeedsRedraw(); }
private static extern void Internal_Create(SceneHandles managedInstance, IntPtr parentWindow, IntPtr camera);
private void OnEditorUpdate() { UpdateLoadingProgress(); if (HasFocus) { if (!Input.IsPointerButtonHeld(PointerButton.Right)) { if (VirtualInput.IsButtonDown(EditorApplication.DuplicateKey)) { DuplicateSelection(); } else if (VirtualInput.IsButtonDown(EditorApplication.DeleteKey)) { DeleteSelection(); } else if (VirtualInput.IsButtonDown(viewToolKey)) { EditorApplication.ActiveSceneTool = SceneViewTool.View; } else if (VirtualInput.IsButtonDown(moveToolKey)) { EditorApplication.ActiveSceneTool = SceneViewTool.Move; } else if (VirtualInput.IsButtonDown(rotateToolKey)) { EditorApplication.ActiveSceneTool = SceneViewTool.Rotate; } else if (VirtualInput.IsButtonDown(scaleToolKey)) { EditorApplication.ActiveSceneTool = SceneViewTool.Scale; } } } // Refresh GUI buttons if needed (in case someones changes the values from script) if (editorSettingsHash != EditorSettings.Hash) { UpdateButtonStates(); editorSettingsHash = EditorSettings.Hash; } // Update scene view handles and selection sceneGrid.Draw(); ProjectionType currentProjType = camera.ProjectionType; if (sceneAxesLastProjectionType != currentProjType) { sceneAxesGUI.ProjectionType = currentProjType; sceneAxesLastProjectionType = currentProjType; } bool handleActive = sceneHandles.IsActive() || sceneAxesGUI.IsActive(); Vector2I scenePos; bool inBounds = ScreenToScenePos(Input.PointerPosition, out scenePos); bool clearSelection = false; if (AllowViewportInput) { if (Input.IsPointerButtonUp(PointerButton.Left)) { clearSelection = true; } else if (Input.IsPointerButtonDown(PointerButton.Left)) { mouseDownPosition = scenePos; } } else { clearSelection = true; inBounds = false; } bool dragResult = false; if (clearSelection) { dragResult = EndDragSelection(); if (sceneHandles.IsActive()) { sceneHandles.ClearSelection(); } if (sceneAxesGUI.IsActive()) { sceneAxesGUI.ClearSelection(); } } bool draggedOver = DragDrop.DragInProgress || DragDrop.DropInProgress; draggedOver &= IsPointerHovering && inBounds && DragDrop.Type == DragDropType.Resource; if (draggedOver) { if (DragDrop.DropInProgress) { dragActive = false; if (draggedSO != null) { Selection.SceneObject = draggedSO; EditorApplication.SetSceneDirty(); } draggedSO = null; } else { if (!dragActive) { dragActive = true; ResourceDragDropData dragData = (ResourceDragDropData)DragDrop.Data; string[] draggedPaths = dragData.Paths; for (int i = 0; i < draggedPaths.Length; i++) { ResourceMeta meta = ProjectLibrary.GetMeta(draggedPaths[i]); if (meta != null) { if (meta.ResType == ResourceType.Mesh) { if (!string.IsNullOrEmpty(draggedPaths[i])) { string meshName = Path.GetFileNameWithoutExtension(draggedPaths[i]); draggedSO = UndoRedo.CreateSO(meshName, "Created a new Renderable \"" + meshName + "\""); Mesh mesh = ProjectLibrary.Load <Mesh>(draggedPaths[i]); Renderable renderable = draggedSO.AddComponent <Renderable>(); renderable.Mesh = mesh; if (mesh != null) { draggedSOOffset = mesh.Bounds.Box.Center; } else { draggedSOOffset = Vector3.Zero; } } break; } else if (meta.ResType == ResourceType.Prefab) { if (!string.IsNullOrEmpty(draggedPaths[i])) { Prefab prefab = ProjectLibrary.Load <Prefab>(draggedPaths[i]); draggedSO = UndoRedo.Instantiate(prefab, "Instantiating " + prefab.Name); if (draggedSO != null) { AABox draggedObjBounds = EditorUtility.CalculateBounds(draggedSO); draggedSOOffset = draggedObjBounds.Center; } else { draggedSOOffset = Vector3.Zero; } } break; } } } } if (draggedSO != null) { if (Input.IsButtonHeld(ButtonCode.Space)) { SnapData snapData; sceneSelection.Snap(scenePos, out snapData, new SceneObject[] { draggedSO }); Quaternion q = Quaternion.FromToRotation(Vector3.YAxis, snapData.normal); draggedSO.Position = snapData.position; draggedSO.Rotation = q; } else { Ray worldRay = camera.ScreenPointToRay(scenePos); draggedSO.Position = worldRay * DefaultPlacementDepth - draggedSOOffset; } } } return; } else { if (dragActive) { dragActive = false; if (draggedSO != null) { draggedSO.Destroy(); draggedSO = null; } } } if ((HasContentFocus || IsPointerHovering) && AllowViewportInput) { sceneCamera.EnableInput(true); if (inBounds && HasContentFocus) { if (Input.IsPointerButtonDown(PointerButton.Left)) { Rect2I sceneAxesGUIBounds = new Rect2I(Width - HandleAxesGUISize - HandleAxesGUIPaddingX, HandleAxesGUIPaddingY, HandleAxesGUISize, HandleAxesGUISize); if (sceneAxesGUIBounds.Contains(scenePos)) { sceneAxesGUI.TrySelect(scenePos); } else { sceneHandles.TrySelect(scenePos); } } else if (Input.IsPointerButtonHeld(PointerButton.Left) && !handleActive && !dragActive && draggedSO == null && scenePos != mouseDownPosition) { if (isDraggingSelection) { UpdateDragSelection(scenePos); } else { StartDragSelection(scenePos); } } else if (Input.IsPointerButtonUp(PointerButton.Left)) { if (!handleActive && !dragActive && !dragResult) { bool ctrlHeld = Input.IsButtonHeld(ButtonCode.LeftControl) || Input.IsButtonHeld(ButtonCode.RightControl); sceneSelection.PickObject(scenePos, ctrlHeld, new SceneObject[] { draggedSO }); } } } } else { sceneCamera.EnableInput(false); } if (AllowViewportInput) { SceneHandles.BeginInput(); sceneHandles.UpdateInput(scenePos, Input.PointerDelta); sceneAxesGUI.UpdateInput(scenePos); SceneHandles.EndInput(); } sceneHandles.Draw(); sceneAxesGUI.Draw(); // Must be done after handle input is processed, in order to reflect most recent transform sceneGizmos.Draw(); sceneSelection.Draw(); UpdateGridMode(); if (VirtualInput.IsButtonDown(frameKey)) { sceneCamera.FrameSelected(); } }