/// <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> /// 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="scaleMode">Scale mode to use when sizing the texture. Only relevant if the provided quad size /// doesn't match the texture size.</param> public void DrawTexture(SpriteTexture texture, Rect2I area, GUITextureScaleMode scaleMode = GUITextureScaleMode.StretchToFit) { IntPtr texturePtr = IntPtr.Zero; if (texture != null) { texturePtr = texture.GetCachedPtr(); } Color color = Color.White; Internal_DrawTexture(mCachedPtr, texturePtr, ref area, scaleMode, ref color); }
/// <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> /// 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 RenderTexture2D(PixelFormat.R8G8B8A8, width, height); renderTexture.Priority = 1; SceneObject cameraSO = new SceneObject("SceneAxesCamera", true); camera = cameraSO.AddComponent<Camera>(); camera.Target = renderTexture; camera.ViewportRect = 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.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.HDR = false; 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; }
/// <summary> /// Clips the cursor to the specified area. Enabled until <see cref="ClipDisable"/> is called. /// </summary> /// <param name="area">Area in screen space to clip the cursor to.</param> public static void ClipToRect(Rect2I area) { Internal_ClipToRect(ref area); }
/// <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); } } RenderTexture2D renderTexture = new RenderTexture2D(PixelFormat.R8G8B8A8, 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; }
/// <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; }
private static extern void Internal_CalculateBounds(IntPtr element, IntPtr relativeTo, out Rect2I output);
private static extern void Internal_GetVisualBounds(IntPtr nativeInstance, out Rect2I 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 + inspectorComponents[i].panel.Bounds.height + COMPONENT_SPACING; } dropAreas[dropAreas.Length - 1] = new Rect2I(0, yOffset, contentBounds.width, contentBounds.height - yOffset); }
/// <summary> /// Calculates bounds of the selection area used for selection overlay drag operation, depending on drag starting /// point coordinates and current drag coordinates. /// </summary> /// <returns>Bounds of the selection area, relative to the content scroll area.</returns> private Rect2I CalculateSelectionArea() { Rect2I selectionArea = new Rect2I(); if (dragSelectionStart.x < dragSelectionEnd.x) { selectionArea.x = dragSelectionStart.x; selectionArea.width = dragSelectionEnd.x - dragSelectionStart.x; } else { selectionArea.x = dragSelectionEnd.x; selectionArea.width = dragSelectionStart.x - dragSelectionEnd.x; } if (dragSelectionStart.y < dragSelectionEnd.y) { selectionArea.y = dragSelectionStart.y; selectionArea.height = dragSelectionEnd.y - dragSelectionStart.y; } else { selectionArea.y = dragSelectionEnd.y; selectionArea.height = dragSelectionStart.y - dragSelectionEnd.y; } Rect2I maxBounds = contentScrollArea.Layout.Bounds; maxBounds.x = 0; maxBounds.y = 0; selectionArea.Clip(maxBounds); return selectionArea; }
private static extern void Internal_DrawTexture(IntPtr nativeInstance, IntPtr texture, ref Rect2I area, GUITextureScaleMode scaleMode, ref Color color, byte depth);
/// <summary> /// Selects all elements overlapping the specified bounds. /// </summary> /// <param name="scrollBounds">Bounds relative to the content scroll area.</param> private void SelectInArea(Rect2I scrollBounds) { LibraryGUIEntry[] foundElements = content.FindElementsOverlapping(scrollBounds); if (foundElements.Length > 0) { selectionAnchorStart = foundElements[0].index; selectionAnchorEnd = foundElements[foundElements.Length - 1].index; } else { selectionAnchorStart = -1; selectionAnchorEnd = -1; } List<string> elementPaths = new List<string>(); foreach (var elem in foundElements) elementPaths.Add(elem.path); SetSelection(elementPaths); }
private static extern void Internal_ClipToRect(ref Rect2I value);
/// <summary> /// Constructs a new resource tile entry. /// </summary> /// <param name="owner">Content area this entry is part of.</param> /// <param name="parent">Parent layout to add this entry's GUI elements to.</param> /// <param name="path">Path to the project library entry to display data for.</param> /// <param name="index">Sequential index of the entry in the conent area.</param> /// <param name="width">Width of the GUI entry.</param> /// <param name="height">Maximum allowed height for the label.</param>" /// <param name="type">Type of the entry, which controls its style and/or behaviour.</param> public LibraryGUIEntry(LibraryGUIContent owner, GUILayout parent, string path, int index, int width, int height, LibraryGUIEntryType type) { GUILayout entryLayout; if (owner.GridLayout) entryLayout = parent.AddLayoutY(); else entryLayout = parent.AddLayoutX(); SpriteTexture iconTexture = GetIcon(path, owner.TileSize); icon = new GUITexture(iconTexture, GUIImageScaleMode.ScaleToFit, true, GUIOption.FixedHeight(owner.TileSize), GUIOption.FixedWidth(owner.TileSize)); label = null; string name = PathEx.GetTail(path); if (owner.GridLayout) { int labelHeight = height - owner.TileSize; label = new GUILabel(name, EditorStyles.MultiLineLabelCentered, GUIOption.FixedWidth(width), GUIOption.FixedHeight(labelHeight)); switch (type) { case LibraryGUIEntryType.Single: break; case LibraryGUIEntryType.MultiFirst: groupUnderlay = new GUITexture(null, LibraryEntryFirstBg); break; case LibraryGUIEntryType.MultiElement: groupUnderlay = new GUITexture(null, LibraryEntryBg); break; case LibraryGUIEntryType.MultiLast: groupUnderlay = new GUITexture(null, LibraryEntryLastBg); break; } } else { label = new GUILabel(name, GUIOption.FixedWidth(width - owner.TileSize), GUIOption.FixedHeight(height)); switch (type) { case LibraryGUIEntryType.Single: break; case LibraryGUIEntryType.MultiFirst: groupUnderlay = new GUITexture(null, LibraryEntryVertFirstBg); break; case LibraryGUIEntryType.MultiElement: groupUnderlay = new GUITexture(null, LibraryEntryVertBg); break; case LibraryGUIEntryType.MultiLast: groupUnderlay = new GUITexture(null, LibraryEntryVertLastBg); break; } } entryLayout.AddElement(icon); entryLayout.AddElement(label); if (groupUnderlay != null) owner.DeepUnderlay.AddElement(groupUnderlay); this.owner = owner; this.index = index; this.path = path; this.bounds = new Rect2I(); this.underlay = null; this.type = type; this.width = width; this.height = height; }
/// <summary> /// Positions the GUI elements. Must be called after construction, but only after all content area entries have /// been constructed so that entry's final bounds are known. /// </summary> public void Initialize() { Rect2I iconBounds = icon.Bounds; bounds = iconBounds; Rect2I labelBounds = label.Bounds; if (owner.GridLayout) { bounds.x = labelBounds.x; bounds.y -= VERT_PADDING; bounds.width = labelBounds.width; bounds.height = (labelBounds.y + labelBounds.height + VERT_PADDING) - bounds.y; } else { bounds.y -= VERT_PADDING; bounds.width = width; bounds.height += VERT_PADDING; } string hoistedPath = path; GUIButton overlayBtn = new GUIButton("", EditorStyles.Blank); overlayBtn.Bounds = bounds; overlayBtn.OnClick += () => OnEntryClicked(hoistedPath); overlayBtn.OnDoubleClick += () => OnEntryDoubleClicked(hoistedPath); overlayBtn.SetContextMenu(owner.Window.ContextMenu); owner.Overlay.AddElement(overlayBtn); if (groupUnderlay != null) { if (owner.GridLayout) { int offsetToNext = BG_HORZ_PADDING + owner.HorzElementSpacing; if (type == LibraryGUIEntryType.MultiLast) offsetToNext = BG_HORZ_PADDING * 2; Rect2I bgBounds = new Rect2I(bounds.x - BG_HORZ_PADDING, bounds.y, bounds.width + offsetToNext, bounds.height); groupUnderlay.Bounds = bgBounds; } else { int offsetToNext = BG_VERT_PADDING + LibraryGUIContent.LIST_ENTRY_SPACING; if (type == LibraryGUIEntryType.MultiLast) offsetToNext = BG_VERT_PADDING * 2; Rect2I bgBounds = new Rect2I(bounds.x, bounds.y - BG_VERT_PADDING, bounds.width, bounds.height + offsetToNext); groupUnderlay.Bounds = bgBounds; } } }
/// <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(); }
private void OnEditorUpdate() { if (currentType == InspectorType.SceneObject) { Component[] allComponents = activeSO.GetComponents(); bool requiresRebuild = allComponents.Length != inspectorComponents.Count; if (!requiresRebuild) { for (int i = 0; i < inspectorComponents.Count; i++) { if (inspectorComponents[i].instanceId != allComponents[i].InstanceId) { requiresRebuild = true; break; } } } if (requiresRebuild) { SceneObject so = activeSO; Clear(); SetObjectToInspect(so); } else { RefreshSceneObjectFields(false); InspectableState componentModifyState = InspectableState.NotModified; for (int i = 0; i < inspectorComponents.Count; i++) componentModifyState |= inspectorComponents[i].inspector.Refresh(); if (componentModifyState.HasFlag(InspectableState.ModifyInProgress)) EditorApplication.SetSceneDirty(); modifyState |= componentModifyState; } } else if (currentType == InspectorType.Resource) { inspectorResource.inspector.Refresh(); } // Detect drag and drop bool isValidDrag = false; if (activeSO != null) { if ((DragDrop.DragInProgress || DragDrop.DropInProgress) && DragDrop.Type == DragDropType.Resource) { Vector2I windowPos = ScreenToWindowPos(Input.PointerPosition); Vector2I scrollPos = windowPos; Rect2I contentBounds = inspectorLayout.Bounds; scrollPos.x -= contentBounds.x; scrollPos.y -= contentBounds.y; bool isInBounds = false; Rect2I dropArea = new Rect2I(); foreach (var bounds in dropAreas) { if (bounds.Contains(scrollPos)) { isInBounds = true; dropArea = bounds; break; } } Type draggedComponentType = null; if (isInBounds) { ResourceDragDropData dragData = DragDrop.Data as ResourceDragDropData; if (dragData != null) { foreach (var resPath in dragData.Paths) { ResourceMeta meta = ProjectLibrary.GetMeta(resPath); if (meta != null) { if (meta.ResType == ResourceType.ScriptCode) { ScriptCode scriptFile = ProjectLibrary.Load<ScriptCode>(resPath); if (scriptFile != null) { Type[] scriptTypes = scriptFile.Types; foreach (var type in scriptTypes) { if (type.IsSubclassOf(typeof (Component))) { draggedComponentType = type; isValidDrag = true; break; } } if (draggedComponentType != null) break; } } } } } } if (isValidDrag) { scrollAreaHighlight.Bounds = dropArea; if (DragDrop.DropInProgress) { activeSO.AddComponent(draggedComponentType); modifyState = InspectableState.Modified; EditorApplication.SetSceneDirty(); } } } } if (scrollAreaHighlight != null) scrollAreaHighlight.Active = isValidDrag; }
/// <summary> /// Refreshes the contents of the content area. Must be called at least once after construction. /// </summary> /// <param name="viewType">Determines how to display the resource tiles.</param> /// <param name="entriesToDisplay">Project library entries to display.</param> /// <param name="bounds">Bounds within which to lay out the content entries.</param> public void Refresh(ProjectViewType viewType, LibraryEntry[] entriesToDisplay, Rect2I bounds) { if (mainPanel != null) mainPanel.Destroy(); entries.Clear(); entryLookup.Clear(); mainPanel = parent.Layout.AddPanel(); GUIPanel contentPanel = mainPanel.AddPanel(1); overlay = mainPanel.AddPanel(0); underlay = mainPanel.AddPanel(2); deepUnderlay = mainPanel.AddPanel(3); renameOverlay = mainPanel.AddPanel(-1); main = contentPanel.AddLayoutY(); List<ResourceToDisplay> resourcesToDisplay = new List<ResourceToDisplay>(); foreach (var entry in entriesToDisplay) { if (entry.Type == LibraryEntryType.Directory) resourcesToDisplay.Add(new ResourceToDisplay(entry.Path, LibraryGUIEntryType.Single)); else { FileEntry fileEntry = (FileEntry)entry; ResourceMeta[] metas = fileEntry.ResourceMetas; if (metas.Length > 0) { if (metas.Length == 1) resourcesToDisplay.Add(new ResourceToDisplay(entry.Path, LibraryGUIEntryType.Single)); else { resourcesToDisplay.Add(new ResourceToDisplay(entry.Path, LibraryGUIEntryType.MultiFirst)); for (int i = 1; i < metas.Length - 1; i++) { string path = Path.Combine(entry.Path, metas[i].SubresourceName); resourcesToDisplay.Add(new ResourceToDisplay(path, LibraryGUIEntryType.MultiElement)); } string lastPath = Path.Combine(entry.Path, metas[metas.Length - 1].SubresourceName); resourcesToDisplay.Add(new ResourceToDisplay(lastPath, LibraryGUIEntryType.MultiLast)); } } } } if (viewType == ProjectViewType.List16) { tileSize = 16; gridLayout = false; elementsPerRow = 1; horzElementSpacing = 0; int elemWidth = bounds.width; int elemHeight = tileSize; main.AddSpace(TOP_MARGIN); for (int i = 0; i < resourcesToDisplay.Count; i++) { ResourceToDisplay entry = resourcesToDisplay[i]; LibraryGUIEntry guiEntry = new LibraryGUIEntry(this, main, entry.path, i, elemWidth, elemHeight, entry.type); entries.Add(guiEntry); entryLookup[guiEntry.path] = guiEntry; if (i != resourcesToDisplay.Count - 1) main.AddSpace(LIST_ENTRY_SPACING); } main.AddFlexibleSpace(); } else { int elemWidth = 0; int elemHeight = 0; int vertElemSpacing = 0; switch (viewType) { case ProjectViewType.Grid64: tileSize = 64; elemWidth = tileSize; elemHeight = tileSize + 36; horzElementSpacing = 10; vertElemSpacing = 12; break; case ProjectViewType.Grid48: tileSize = 48; elemWidth = tileSize; elemHeight = tileSize + 36; horzElementSpacing = 8; vertElemSpacing = 10; break; case ProjectViewType.Grid32: tileSize = 32; elemWidth = tileSize + 16; elemHeight = tileSize + 48; horzElementSpacing = 6; vertElemSpacing = 10; break; } gridLayout = true; int availableWidth = bounds.width; elementsPerRow = MathEx.FloorToInt((availableWidth - horzElementSpacing) / (float)(elemWidth + horzElementSpacing)); elementsPerRow = Math.Max(elementsPerRow, 1); int numRows = MathEx.CeilToInt(resourcesToDisplay.Count / (float)elementsPerRow); int neededHeight = numRows * elemHeight + TOP_MARGIN; if (numRows > 0) neededHeight += (numRows - 1)* vertElemSpacing; bool requiresScrollbar = neededHeight > bounds.height; if (requiresScrollbar) { availableWidth -= parent.ScrollBarWidth; elementsPerRow = MathEx.FloorToInt((availableWidth - horzElementSpacing) / (float)(elemWidth + horzElementSpacing)); elementsPerRow = Math.Max(elementsPerRow, 1); } int extraRowSpace = availableWidth - (elementsPerRow * (elemWidth + horzElementSpacing) + horzElementSpacing); main.AddSpace(TOP_MARGIN); GUILayoutX rowLayout = main.AddLayoutX(); rowLayout.AddSpace(horzElementSpacing); int elemsInRow = 0; for (int i = 0; i < resourcesToDisplay.Count; i++) { if (elemsInRow == elementsPerRow && elemsInRow > 0) { main.AddSpace(vertElemSpacing); rowLayout.AddSpace(extraRowSpace); rowLayout = main.AddLayoutX(); rowLayout.AddSpace(horzElementSpacing); elemsInRow = 0; } ResourceToDisplay entry = resourcesToDisplay[i]; LibraryGUIEntry guiEntry = new LibraryGUIEntry(this, rowLayout, entry.path, i, elemWidth, elemHeight, entry.type); entries.Add(guiEntry); entryLookup[guiEntry.path] = guiEntry; rowLayout.AddSpace(horzElementSpacing); elemsInRow++; } int extraElements = elementsPerRow - elemsInRow; rowLayout.AddSpace((elemWidth + horzElementSpacing) * extraElements + extraRowSpace); main.AddFlexibleSpace(); } for (int i = 0; i < entries.Count; i++) { LibraryGUIEntry guiEntry = entries[i]; guiEntry.Initialize(); } }
private static extern void Internal_getPixelArea(IntPtr thisPtr, out Rect2I __output);
private static extern void Internal_SetBounds(IntPtr nativeInstance, ref Rect2I value);
private static extern void Internal_GetContentBounds(IntPtr nativeInstance, out Rect2I value);
/// <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; }
private void OnEditorUpdate() { if (HasFocus) { if (!Input.IsPointerButtonHeld(PointerButton.Right)) { if (VirtualInput.IsButtonDown(EditorApplication.DuplicateKey)) DuplicateSelection(); else if (VirtualInput.IsButtonDown(EditorApplication.DeleteKey)) DeleteSelection(); else if (VirtualInput.IsButtonDown(toggleProfilerOverlayKey)) EditorSettings.SetBool(ProfilerOverlayActiveKey, !EditorSettings.GetBool(ProfilerOverlayActiveKey)); 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(); UpdateProfilerOverlay(); editorSettingsHash = EditorSettings.Hash; } // Update scene view handles and selection sceneGizmos.Draw(); sceneGrid.Draw(); bool handleActive = sceneHandles.IsActive() || sceneAxesGUI.IsActive(); Vector2I scenePos; bool inBounds = ScreenToScenePos(Input.PointerPosition, out scenePos); bool dragResult = false; if (Input.IsPointerButtonUp(PointerButton.Left)) { dragResult = EndDragSelection(); if (sceneHandles.IsActive()) sceneHandles.ClearSelection(); if (sceneAxesGUI.IsActive()) sceneAxesGUI.ClearSelection(); } else if (Input.IsPointerButtonDown(PointerButton.Left)) { mouseDownPosition = scenePos; } 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.ViewportToWorldRay(scenePos); draggedSO.Position = worldRay * DefaultPlacementDepth - draggedSOOffset; } } } return; } else { if (dragActive) { dragActive = false; if (draggedSO != null) { draggedSO.Destroy(); draggedSO = null; } } } if (HasContentFocus || IsPointerHovering) { cameraController.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 cameraController.EnableInput(false); SceneHandles.BeginInput(); sceneHandles.UpdateInput(scenePos, Input.PointerDelta); sceneHandles.Draw(); sceneAxesGUI.UpdateInput(scenePos); sceneAxesGUI.Draw(); SceneHandles.EndInput(); sceneSelection.Draw(); UpdateGridMode(); if (VirtualInput.IsButtonDown(frameKey)) cameraController.FrameSelected(); }
/// <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 Texture2D colorTex = new Texture2D(width, height, PixelFormat.R8G8B8A8, TextureUsage.Render | TextureUsage.CPUReadable); Texture2D depthTex = new Texture2D(width, height, PixelFormat.D32_S8X24, TextureUsage.DepthStencil | TextureUsage.CPUReadable); renderTexture = new RenderTexture2D(colorTex, depthTex); 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 = 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; if (profilerCamera != null) profilerCamera.Target = renderTexture; }
private static extern void Internal_SetBounds(IntPtr nativeInstance, ref Rect2I bounds);