/// <summary> /// Opens the event edit window for the specified event. /// </summary> /// <param name="eventIdx">Event index to open the edit window for.</param> private void StartEventEdit(int eventIdx) { AnimationEvent animEvent = events[eventIdx].animEvent; Vector2I position = new Vector2I(); position.x = guiEvents.GetOffset(animEvent.Time); position.y = EVENTS_HEIGHT / 2; Rect2I eventBounds = GUIUtility.CalculateBounds(eventsPanel, window.GUI); Vector2I windowPos = position + new Vector2I(eventBounds.x, eventBounds.y); SceneObject so = window.SelectedSO; Component[] components = so.GetComponents(); string[] componentNames = new string[components.Length]; for (int i = 0; i < components.Length; i++) { componentNames[i] = components[i].GetType().Name; } EventEditWindow editWindow = DropDownWindow.Open <EventEditWindow>(window, windowPos); editWindow.Initialize(animEvent, componentNames, () => { UpdateEventsGUI(); OnEventModified?.Invoke(); }); }
/// <summary> /// Updates the displayed texture with specified color information. /// </summary> /// <param name="start">Initial color on the top of the slider.</param> /// <param name="step">Final color to the bottom of the slider.</param> /// <param name="isHSV">Determines are the provided colors in RGB or HSV space.</param> public void UpdateTexture(Color start, Color step, bool isHSV) { Color[] colors = new Color[width * height]; FillArea(width, height, colors, start, new Color(0, 0, 0, 0), step); if (isHSV) { for (int i = 0; i < colors.Length; i++) { colors[i] = Color.HSV2RGB(colors[i]); } } texture.SetPixels(colors); guiTexture.SetTexture(spriteTexture); Rect2I sliderBounds = guiTexture.Bounds; sliderBounds.x -= SLIDER_X_OFFSET; sliderBounds.width += SLIDER_X_OFFSET; sliderBounds.y -= SLIDER_Y_OFFSET; sliderBounds.height += SLIDER_Y_OFFSET * 2; guiSlider.Bounds = sliderBounds; }
/// <summary> /// Moves the handle to a specific location on the color box and selects that color. /// </summary> /// <param name="value">Coordinates relative to the color box.</param> public void SetValue(Vector2 value) { Vector2 pos = value; pos.y = 1.0f - pos.y; if (oldValue == value) { return; } Rect2I handleBounds = guiSliderHandle.Bounds; Rect2I boxBounds = guiTexture.Bounds; handleBounds.x = boxBounds.x + MathEx.RoundToInt(pos.x * boxBounds.width) - handleBounds.width / 2; handleBounds.y = boxBounds.y + MathEx.RoundToInt(pos.y * boxBounds.height) - handleBounds.height / 2; guiSliderHandle.Bounds = handleBounds; oldValue = value; if (OnValueChanged != null) { OnValueChanged(value); } }
/// <summary> /// Updates drop areas used for dragging and dropping components on the inspector. /// </summary> private void UpdateDropAreas() { if (activeSO == null) { return; } Rect2I contentBounds = inspectorLayout.Bounds; dropAreas = new Rect2I[inspectorComponents.Count + 1]; int yOffset = GetTitleBounds().height; for (int i = 0; i < inspectorComponents.Count; i++) { dropAreas[i] = new Rect2I(0, yOffset, contentBounds.width, COMPONENT_SPACING); yOffset += inspectorComponents[i].title.Bounds.height + COMPONENT_SPACING; if (!inspectorComponents[i].folded) { yOffset += inspectorComponents[i].panel.Bounds.height; } } dropAreas[dropAreas.Length - 1] = new Rect2I(0, yOffset, contentBounds.width, contentBounds.height - yOffset); }
/// <summary> /// Triggered when the user double clicks the left mouse button. /// </summary> /// <param name="ev">Information about the mouse event.</param> private void OnPointerDoubleClicked(PointerEvent ev) { if (ev.IsUsed) { return; } Vector2I panelPos = ScreenToKeyEditorPos(ev.ScreenPos); Rect2I guiGradientBounds = guiGradientTexture.Bounds; if (guiGradientBounds.Contains(panelPos)) { Vector2I canvasPos = panelPos - new Vector2I(guiGradientBounds.x, guiGradientBounds.y); float time = canvasPos.x / (float)Math.Max(guiGradientBounds.width - 1, 1); if (time >= 0.0f && time <= 1.0f) { List <ColorGradientKey> keys = new List <ColorGradientKey>(gradient.GetKeys()); keys.Add(new ColorGradientKey(Color.Black, time)); keys.Sort((lhs, rhs) => lhs.time.CompareTo(rhs.time)); gradient = new ColorGradient(keys.ToArray()); UpdateTexture(); editor.Rebuild(keys); UpdateKeyLines(); } } else { editor.OnPointerDoubleClicked(panelPos, ev.Button); } }
/// <summary> /// Updates a selection outline drag operation by expanding the outline to the new location. Elements in the outline /// are selected. /// </summary> /// <param name="scenePos">Coordinates of the pointer relative to the scene.</param> /// <returns>True if the selection outline drag is valid and was updated, false otherwise.</returns> private bool UpdateDragSelection(Vector2I scenePos) { if (!isDraggingSelection) { return(false); } if (dragSelection == null) { dragSelection = new GUITexture(null, true, EditorStylesInternal.SelectionArea); selectionPanel.AddElement(dragSelection); } dragSelectionEnd = scenePos; Rect2I selectionArea = new Rect2I(); Vector2I min = new Vector2I(Math.Min(dragSelectionStart.x, dragSelectionEnd.x), Math.Min(dragSelectionStart.y, dragSelectionEnd.y)); Vector2I max = new Vector2I(Math.Max(dragSelectionStart.x, dragSelectionEnd.x), Math.Max(dragSelectionStart.y, dragSelectionEnd.y)); selectionArea.x = min.x; selectionArea.y = min.y; selectionArea.width = Math.Max(max.x - min.x, 1); selectionArea.height = Math.Max(max.y - min.y, 1); dragSelection.Bounds = selectionArea; return(true); }
/// <summary> /// Attempts to find an event under the provided coordinates. /// </summary> /// <param name="pixelCoords">Coordinates relative to the layout the GUI element is on.</param> /// <param name="eventIdx">Index of the event that was clicked on. Index references the events array as provided /// to <see cref="SetEvents"/>. Only valid if method returns true.</param> /// <returns>True if an event was found under the coordinates, false otherwise.</returns> public bool FindEvent(Vector2I pixelCoords, out int eventIdx) { Rect2I bounds = canvas.Bounds; if (pixelCoords.x < (bounds.x + PADDING) || pixelCoords.x >= (bounds.x + bounds.width - PADDING) || pixelCoords.y < bounds.y || pixelCoords.y >= (bounds.y + bounds.height)) { eventIdx = -1; return(false); } Vector2I relativeCoords = pixelCoords - new Vector2I(bounds.x, bounds.y); for (int i = 0; i < events.Length; i++) { AnimationEvent evnt = events[i]; int xPos = (int)(((evnt.Time - rangeOffset) / GetRange()) * drawableWidth) + PADDING; if (relativeCoords.x >= (xPos - EVENT_HALF_WIDTH) && relativeCoords.x <= (xPos + EVENT_HALF_WIDTH)) { eventIdx = i; return(true); } } eventIdx = -1; return(false); }
/// <summary> /// Converts screen coordinates in coordinates relative to the panel containing the key editor control. /// </summary> /// <param name="screenPos">Coordinates in screen space.</param> /// <returns>Coordinates relative to the key editor control.</returns> private Vector2I ScreenToKeyEditorPos(Vector2I screenPos) { Vector2I windowPos = ScreenToWindowPos(screenPos); Rect2I elementBounds = GUIUtility.CalculateBounds(editorPanel, GUI); return(windowPos - new Vector2I(elementBounds.x, elementBounds.y)); }
/// <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 is required because ScenePicking uses it renderTexture = new RenderTexture2D(PixelFormat.R8G8B8A8, width, height, 1, false, true); renderTexture.Priority = 1; if (camera == null) { SceneObject sceneCameraSO = new SceneObject("SceneCamera", true); camera = sceneCameraSO.AddComponent <Camera>(); camera.Target = renderTexture; camera.ViewportRect = 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.NearClipPlane = 0.05f; camera.FarClipPlane = 2500.0f; camera.ClearColor = ClearColor; camera.Layers = UInt64.MaxValue & ~SceneAxesHandle.LAYER; // Don't draw scene axes in this camera cameraController = sceneCameraSO.AddComponent <SceneCamera>(); 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.Target = renderTexture; renderTextureGUI.RenderTexture = renderTexture; } Rect2I rtBounds = new Rect2I(0, 0, width, height); renderTextureGUI.Bounds = rtBounds; focusCatcher.Bounds = GUILayoutUtility.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; if (profilerCamera != null) { profilerCamera.Target = renderTexture; } }
/// <summary> /// Returns the time at the specified pixel value along the timeline. /// </summary> /// <param name="pixel">Coordinate relative to this GUI element, in pixels.</param> /// <returns>Time along the curve at the specified coordinates.</returns> public float GetTime(int pixel) { Rect2I bounds = canvas.Bounds; int relativeCoords = pixel - (bounds.x + PADDING); float lengthPerPixel = GetRange() / drawableWidth; return(rangeOffset + relativeCoords * lengthPerPixel); }
/// <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((uint)width, (uint)height, PixelFormat.RGBA8, TextureUsage.Render | TextureUsage.CPUReadable); Texture depthTex = Texture.Create2D((uint)width, (uint)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> /// Converts coordinates in window space (relative to the parent window origin) into coordinates in curve space. /// </summary> /// <param name="windowPos">Coordinates relative to parent editor window, in pixels.</param> /// <param name="curveCoord">Curve coordinates within the range as specified by <see cref="Range"/>. Only /// valid when function returns true.</param> /// <returns>True if the coordinates are within the curve area, false otherwise.</returns> public bool WindowToCurveSpace(Vector2I windowPos, out Vector2 curveCoord) { Rect2I elementBounds = GUIUtility.CalculateBounds(gui, window.GUI); Vector2I pointerPos = windowPos - new Vector2I(elementBounds.x, elementBounds.y); Rect2I drawingBounds = drawingPanel.Bounds; Vector2I drawingPos = pointerPos - new Vector2I(drawingBounds.x, drawingBounds.y); return(guiCurveDrawing.PixelToCurveSpace(drawingPos, out curveCoord)); }
/// <summary> /// Triggered when the user clicks on the create button on the title bar. Creates a brand new object with default /// values in the place of the current array. /// </summary> private void OnCreateButtonClicked() { if (createContextMenu == null) { return; } Rect2I bounds = GUIUtility.CalculateBounds(guiCreateBtn, guiInternalTitleLayout); Vector2I position = new Vector2I(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2); createContextMenu.Open(position, guiInternalTitleLayout); }
private void OnCameraOptionsClicked() { Vector2I openPosition; Rect2I buttonBounds = GUIUtility.CalculateBounds(cameraOptionsButton, GUI); openPosition.x = buttonBounds.x + buttonBounds.width / 2; openPosition.y = buttonBounds.y + buttonBounds.height / 2; SceneCameraOptionsDropdown cameraOptionsDropdown = DropDownWindow.Open <SceneCameraOptionsDropdown>(GUI, openPosition); cameraOptionsDropdown.Initialize(this); }
/// <summary> /// Draws a quad with a the provided texture displayed. /// </summary> /// <param name="texture">Texture to draw.</param> /// <param name="area">Position and size of the texture to draw. Position is relative to the canvas origin /// (top-left). If size is zero, the default texture size will be used.</param> /// <param name="color">Color to tint the drawn texture with.</param> /// <param name="scaleMode">Scale mode to use when sizing the texture. Only relevant if the provided quad size /// doesn't match the texture size.</param> /// <param name="depth">Depth at which to draw the element. Elements with higher depth will be drawn before others. /// Additionally elements of the same type (triangle or line) will be drawn in order they are /// submitted if they share the same depth.</param> public void DrawTexture(SpriteTexture texture, Rect2I area, Color color, GUITextureScaleMode scaleMode = GUITextureScaleMode.StretchToFit, byte depth = 128) { IntPtr texturePtr = IntPtr.Zero; if (texture != null) { texturePtr = texture.GetCachedPtr(); } Internal_DrawTexture(mCachedPtr, texturePtr, ref area, scaleMode, ref color, depth); }
/// <summary> /// Clips current rectangle so that it does not overlap the provided rectangle. After clipping no area of this /// rectangle will intersect the clip area. /// </summary> /// <param name="clipRect">Rectangle to clip against.</param> public void Clip(Rect2I clipRect) { int newLeft = Math.Max(x, clipRect.x); int newTop = Math.Max(y, clipRect.y); int newRight = Math.Min(x + width, clipRect.x + clipRect.width); int newBottom = Math.Min(y + height, clipRect.y + clipRect.height); x = Math.Min(newLeft, newRight); y = Math.Min(newTop, newBottom); width = Math.Max(0, newRight - newLeft); height = Math.Max(0, newBottom - newTop); }
/// <summary> /// Changes the size of the list view. /// </summary> /// <param name="width">Width in pixels.</param> /// <param name="height">Height in pixels.</param> public void SetSize(int width, int height) { if (width != this.width || height != this.height) { this.width = width; this.height = height; Rect2I bounds = scrollArea.Bounds; bounds.width = width; bounds.height = height; scrollArea.Bounds = bounds; } }
/// <summary> /// Attempts to find all resource tile elements overlapping the specified bounds. /// </summary> /// <param name="scrollBounds">Bounds to check for overlap, specified relative to the scroll area the content area /// is part of.</param> /// <returns>A list of found entries.</returns> public LibraryGUIEntry[] FindElementsOverlapping(Rect2I scrollBounds) { List <LibraryGUIEntry> elements = new List <LibraryGUIEntry>(); foreach (var element in entries) { if (element.Bounds.Overlaps(scrollBounds)) { elements.Add(element); } } return(elements.ToArray()); }
/// <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(); }
/// <summary> /// Converts screen coordinates into coordinates relative to the scene view render texture. /// </summary> /// <param name="screenPos">Coordinates relative to the screen.</param> /// <param name="scenePos">Output coordinates relative to the scene view texture.</param> /// <returns>True if the coordinates are within the scene view texture, false otherwise.</returns> private bool ScreenToScenePos(Vector2I screenPos, out Vector2I scenePos) { scenePos = screenPos; Vector2I windowPos = ScreenToWindowPos(screenPos); Rect2I bounds = GUILayoutUtility.CalculateBounds(renderTextureGUI, GUI); if (bounds.Contains(windowPos)) { scenePos.x = windowPos.x - bounds.x; scenePos.y = windowPos.y - bounds.y; return true; } return false; }
/// <summary> /// Handles input over the color box, moving the handle as needed. /// </summary> /// <param name="windowPos">Position of the pointer relative to the color picker window.</param> public void UpdateInput(Vector2I windowPos) { if (Input.IsPointerButtonHeld(PointerButton.Left)) { Rect2I bounds = guiTexture.Bounds; if (bounds.Contains(windowPos)) { Vector2 newValue = Vector2.Zero; newValue.x = (windowPos.x - bounds.x) / (float)bounds.width; newValue.y = 1.0f - (windowPos.y - bounds.y) / (float)bounds.height; SetValue(newValue); } } }
/// <summary> /// Returns true if the rectangle overlaps the provided rectangle. Also returns true if the rectangles are // contained within each other completely (no intersecting edges). /// </summary> /// <param name="other">Other rectangle to compare with.</param> /// <returns>True if the rectangles overlap.</returns> public bool Overlaps(Rect2I other) { int otherRight = other.x + other.width; int myRight = x + width; int otherBottom = other.y + other.height; int myBottom = y + height; if (x < otherRight && myRight > other.x && y < otherBottom && myBottom > other.y) { return(true); } return(false); }
/// <inheritdoc/> public override bool Equals(object other) { if (!(other is Rect2I)) { return(false); } Rect2I rect = (Rect2I)other; if (x.Equals(rect.x) && y.Equals(rect.y) && width.Equals(rect.width) && height.Equals(rect.height)) { return(true); } return(false); }
/// <summary> /// Triggered when the user clicks on the create button on the title bar. Creates a brand new object with default /// values in the place of the current array. /// </summary> private void OnCreateButtonClicked() { if (createContextMenu == null) { if (instantiableTypes.Length > 0) { property.SetValue(Activator.CreateInstance(instantiableTypes[0])); } } else { Rect2I bounds = GUIUtility.CalculateBounds(guiCreateBtn, guiInternalTitleLayout); Vector2I position = new Vector2I(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2); createContextMenu.Open(position, guiInternalTitleLayout); } }
/// <summary> /// Uses the assigned FPS, range and physical size to calculate the frame that is under the provided coordinates. /// </summary> /// <param name="pixelCoords">Coordinate relative to the layout the GUI element is on.</param> /// <returns>Frame that was clicked on, or -1 if the coordinates are outside of valid bounds. </returns> public int GetFrame(Vector2I pixelCoords) { Rect2I bounds = canvas.Bounds; if (pixelCoords.x < (bounds.x + PADDING) || pixelCoords.x >= (bounds.x + bounds.width - PADDING) || pixelCoords.y < bounds.y || pixelCoords.y >= (bounds.y + bounds.height)) { return(-1); } Vector2I relativeCoords = pixelCoords - new Vector2I(bounds.x + PADDING, bounds.y); float lengthPerPixel = GetRange() / drawableWidth; float time = rangeOffset + relativeCoords.x * lengthPerPixel; return(MathEx.RoundToInt(time * fps)); }
/// <summary> /// Creates or rebuilds the main render texture. Should be called at least once before using the /// game window. 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) { height = height - HeaderHeight; int rtWidth = MathEx.Max(20, width); int rtHeight = MathEx.Max(20, height); if (selectedAspectRatio != 0) // 0 is free aspect { AspectRatio aspectRatio = aspectRatios[selectedAspectRatio - 1]; int visibleAreaHeight = rtHeight; float aspectInv = aspectRatio.height / (float)aspectRatio.width; rtHeight = MathEx.RoundToInt(rtWidth * aspectInv); if (rtHeight > visibleAreaHeight) { rtHeight = visibleAreaHeight; float aspect = aspectRatio.width / (float)aspectRatio.height; rtWidth = MathEx.RoundToInt(rtHeight * aspect); } } RenderTexture renderTexture = new RenderTexture(PixelFormat.RGBA8, rtWidth, rtHeight) { Priority = 1 }; EditorApplication.MainRenderTarget = renderTexture; renderTextureGUI.RenderTexture = renderTexture; int offsetX = (width - rtWidth) / 2; int offsetY = (height - rtHeight) / 2; Rect2I rtBounds = new Rect2I(offsetX, offsetY, rtWidth, rtHeight); renderTextureGUI.Bounds = rtBounds; Rect2I bgBounds = new Rect2I(0, 0, width, height); renderTextureBg.Bounds = bgBounds; NotifyNeedsRedraw(); }
/// <summary> /// Handles input. Should be called by the owning window whenever a pointer is double-clicked. /// </summary> /// <param name="panelPos">Position of the pointer relative to the panel parent to this element.</param> /// <param name="button">Pointer button involved in the event.</param> internal void OnPointerDoubleClicked(Vector2I panelPos, PointerButton button) { Rect2I canvasBounds = canvas.Bounds; if (!canvasBounds.Contains(panelPos)) { return; } Vector2I canvasPos = panelPos - new Vector2I(canvasBounds.x, canvasBounds.y); int keyIdx; if (FindKey(canvasPos, out keyIdx)) { ColorPicker.Show(keys[keyIdx].color, false, (b, color) => { if (b) { ColorGradientKey key = keys[keyIdx]; key.color = color; keys[keyIdx] = key; OnGradientModified?.Invoke(new ColorGradient(keys.ToArray())); Rebuild(); } }); } else { float time = PixelToTime(canvasPos.x); if (time >= 0.0f && time <= 1.0f) { keys.Add(new ColorGradientKey(Color.Black, time)); keys.Sort((lhs, rhs) => lhs.time.CompareTo(rhs.time)); OnGradientModified?.Invoke(new ColorGradient(keys.ToArray())); } Rebuild(); } }
/// <summary> /// Shows a preview of the specified camera with the specified bounds. /// </summary> /// <param name="camera">The camera to preview</param> /// <param name="bounds">The bounds of the preview</param> public void ShowPreview(Camera camera, Rect2I bounds) { previewPanel.Bounds = bounds; cameraNameLabel.SetContent(camera.SceneObject?.Name); renderTextureGUI.SetWidth(bounds.width); renderTextureGUI.SetHeight(bounds.height); var cameraRenderTexture = (RenderTexture)camera.Viewport.Target; if (cameraRenderTexture != null) { var renderTexture = new RenderTexture(cameraRenderTexture.ColorSurface); renderTextureGUI.RenderTexture = renderTexture; } else { // TODO: We cannot preview cameras that don't have a render target because we need preview support for // setting a temporary render target for preview purposes } }
/// <summary> /// Opens the edit window for the currently selected keyframe. /// </summary> private void EditSelectedKeyframe() { if (disableCurveEdit) { ShowReadOnlyMessage(); return; } if (selectedKeyframes.Count == 0) { return; } EdAnimationCurve curve = curveInfos[selectedKeyframes[0].curveIdx].curve; KeyFrame[] keyFrames = curve.KeyFrames; int keyIndex = selectedKeyframes[0].keyIndices[0]; KeyFrame keyFrame = keyFrames[keyIndex]; Vector2I position = guiCurveDrawing.CurveToPixelSpace(new Vector2(keyFrame.time, keyFrame.value)); Rect2I drawingBounds = GUIUtility.CalculateBounds(drawingPanel, window.GUI); position.x = MathEx.Clamp(position.x, 0, drawingBounds.width); position.y = MathEx.Clamp(position.y, 0, drawingBounds.height); Vector2I windowPos = position + new Vector2I(drawingBounds.x, drawingBounds.y); KeyframeEditWindow editWindow = DropDownWindow.Open <KeyframeEditWindow>(window, windowPos); editWindow.Initialize(keyFrame, x => { curve.UpdateKeyframe(keyIndex, x.time, x.value); curve.Apply(); // TODO UNDOREDO guiCurveDrawing.Rebuild(); OnCurveModified?.Invoke(); }); }
/// <summary> /// Handles input. Should be called by the owning window whenever a pointer is pressed. /// </summary> /// <param name="panelPos">Position of the pointer relative to the panel parent to this element.</param> /// <param name="button">Pointer button involved in the event.</param> internal void OnPointerPressed(Vector2I panelPos, PointerButton button) { Rect2I canvasBounds = canvas.Bounds; Vector2I canvasPos = panelPos - new Vector2I(canvasBounds.x, canvasBounds.y); if (button == PointerButton.Left) { int keyIdx; if (FindKey(canvasPos, out keyIdx)) { selectedIdx = keyIdx; isMousePressedOverKey = true; dragStart = canvasPos; } else { selectedIdx = -1; } Rebuild(); } }