public void MoveCursorToEnd() { #if !(UNITY_ANDROID || UNITY_IOS) || UNITY_EDITOR textEditor = (TextEditor)GUIUtility.QueryStateObject(typeof(TextEditor), GUIUtility.keyboardControl); textEditor.text = text; textEditor.MoveTextEnd(); #endif }
public void OnGUI(Rect rect, AtlasRaw atlas, BinRaw bin, List <SpriteIndex> selected) { GUI.BeginClip(rect); var localRect = new Rect(0, 0, rect.width, rect.height); var texDragOffset = mOffset; var texScale = mScale; var texScaleOffset = new Vector2( localRect.width * (texScale - 1) * 0.5f, localRect.height * (texScale - 1) * 0.5f); var texOffset = texDragOffset - texScaleOffset; var texSize = localRect.size * texScale; AtlasEditorUtil.DrawGrid(localRect); AtlasEditorUtil.DrawSprite(localRect, bin.main, bin.addition, new Rect(-texOffset.x / texSize.x, (texDragOffset.y + texScaleOffset.y) / texSize.y, localRect.width / texSize.x, localRect.height / texSize.y)); int controlID = GUIUtility.GetControlID(FocusType.Passive); var eventType = Event.current.GetTypeForControl(controlID); switch (eventType) { case EventType.ScrollWheel: { if (localRect.Contains(Event.current.mousePosition)) { var scaleDelta = 15; texScale -= Event.current.delta.y / scaleDelta; texScale = Mathf.Max(texScale, 1); texScaleOffset = new Vector2(localRect.width * (texScale - 1) * 0.5f, localRect.height * (texScale - 1) * 0.5f); texDragOffset.x = Mathf.Clamp(texDragOffset.x, -texScaleOffset.x, texScaleOffset.x); texDragOffset.y = Mathf.Clamp(texDragOffset.y, -texScaleOffset.y, texScaleOffset.y); Event.current.Use(); } break; } case EventType.MouseDown: { var pos = GUIUtility.GetStateObject(typeof(List <int>), controlID) as List <int>; pos.Clear(); pos.Add((int)Event.current.mousePosition.x); pos.Add((int)Event.current.mousePosition.y); GUIUtility.hotControl = controlID; break; } case EventType.MouseDrag: { if (GUIUtility.hotControl == controlID) { var pos = GUIUtility.QueryStateObject(typeof(List <int>), controlID) as List <int>; if (pos[0] <= localRect.width && pos[1] <= localRect.height) { texDragOffset.x += Event.current.delta.x; texDragOffset.y += Event.current.delta.y; texDragOffset.x = Mathf.Clamp(texDragOffset.x, -texScaleOffset.x, texScaleOffset.x); texDragOffset.y = Mathf.Clamp(texDragOffset.y, -texScaleOffset.y, texScaleOffset.y); Event.current.Use(); } } break; } case EventType.MouseUp: { if (GUIUtility.hotControl == controlID) { var pos = GUIUtility.QueryStateObject(typeof(List <int>), controlID) as List <int>; if (pos != null && Mathf.Abs(pos[0] - (int)Event.current.mousePosition.x) <= 1 && Mathf.Abs(pos[1] - (int)Event.current.mousePosition.y) <= 1) { var rPos = new Vector2( (pos[0] - texOffset.x) / texSize.x, (pos[1] - texOffset.y) / texSize.y ); for (var i = 0; i < bin.sprites.Length; i++) { var sprite = bin.sprites[i]; var spriteRect = sprite.rect; var rRect = new Rect( spriteRect.x / bin.main.width, (bin.main.height - spriteRect.y - spriteRect.height) / bin.main.height, spriteRect.width / bin.main.width, spriteRect.height / bin.main.height ); if (rRect.Contains(rPos)) { var index = new SpriteIndex(0, sprite.bin, i); if (Event.current.button == 0) { if (!mMultiSelectEnabled || !Event.current.control) { selected.Clear(); selected.Add(index); } else { if (selected.Any(s => s.bin == index.bin && s.sprite == index.sprite)) { selected.RemoveAll(s => s.bin == index.bin && s.sprite == index.sprite); } else { selected.Add(index); } } GUI.FocusControl(""); Event.current.Use(); } break; } } } GUIUtility.hotControl = 0; } break; } } foreach (var index in selected) { if (atlas.bins[index.bin] == bin) { var sprite = bin.sprites[index.sprite]; var spriteRect = sprite.rect; var rRect = new Rect( spriteRect.x / bin.main.width, (bin.main.height - spriteRect.y - spriteRect.height) / bin.main.height, spriteRect.width / bin.main.width, spriteRect.height / bin.main.height ); var tRect = new Rect( rRect.x * texSize.x + texOffset.x, rRect.y * texSize.y + texOffset.y, rRect.width * texSize.x, rRect.height * texSize.y ); Handles.color = Color.green; Handles.DrawPolyLine(new Vector3[] { new Vector3(tRect.x, tRect.y, 0), new Vector3(tRect.xMax, tRect.y, 0), new Vector3(tRect.xMax, tRect.yMax, 0), new Vector3(tRect.x, tRect.yMax, 0), new Vector3(tRect.x, tRect.y, 0) }); Handles.color = Color.white; } } GUI.EndClip(); mOffset = texDragOffset; mScale = texScale; }
// Handy-dandy method to deal with keyboard inputs which we get as actual // events. Basically lets us deal with copy & paste, etc which GUI.TextArea // ordinarily does not support. private void FilterEditorInputs() { Event evt = Event.current; if (focusedWindow == this) { // Only attempt to grab this if our window has focus in order to make // indent/unindent menu items behave sanely. int editorId = GUIUtility.keyboardControl; try { editorState = GUIUtility.QueryStateObject(typeof(System.Object), editorId) as TextEditor; } catch (KeyNotFoundException) { // Ignoring because this seems to only mean that no such object was found. } if (editorState == null) { return; } } else { return; } if (doProcess) { // If we're waiting for a command to run, don't muck with the text! if (evt.isKey) { evt.Use(); } return; } if (evt.isKey) { if (evt.type == EventType.KeyDown) { // KeyDown gets the key press + repeating. We only care about a few // things... if (evt.functionKey) { // TODO: Make sure we don't have modifier keys pressed... // TODO: Proper edit-history support! if (evt.keyCode == KeyCode.UpArrow) { // TODO: If we're at the top of the input, move to the previous // TODO: history item. If the current item is the last history item, // TODO: update the history with changes? } else if (evt.keyCode == KeyCode.DownArrow) { // TODO: If we're at the bottom of the input, move to the previous // TODO: history item. If the current item is the last history item, // TODO: update the history with changes? } } else if (evt.keyCode == KeyCode.Return) { // TODO: Do we only want to do this only when the cursor is at the // TODO: end of the input? (Avoids unexpectedly putting newlines in // TODO: the middle of peoples' input...) if (Event.current.shift) { codeToProcess = Paste(editorState, "\n", false); } else { doProcess = true; } useContinuationPrompt = true; // In case we fail. } else if (evt.keyCode == KeyCode.Tab) { // Unity doesn't like using tab for actual editing. We're gonna // change that. So here we inject a tab, and later we'll deal with // focus issues. codeToProcess = Paste(editorState, "\t", false); } } } else if (evt.type == EventType.ValidateCommand) { switch (evt.commandName) { case "SelectAll": case "Paste": // Always allowed to muck with selection or paste stuff... evt.Use(); break; case "Copy": case "Cut": // ... but can only copy & cut when we have a selection. if (editorState.hasSelection) { evt.Use(); } break; default: // If we need to suss out other commands to support... // Debug.Log("Validate: " + evt.commandName); break; } } else if (evt.type == EventType.ExecuteCommand) { switch (evt.commandName) { // A couple TextEditor functions actually work, so use them... case "SelectAll": editorState.SelectAll(); break; case "Copy": editorState.Copy(); break; // But some don't: case "Paste": // Manually paste. Keeping Use() out of the Paste() method so we can // re-use the functionality elsewhere. codeToProcess = Paste(editorState, EditorGUIUtility.systemCopyBuffer, false); evt.Use(); break; case "Cut": // Ditto -- manual cut. codeToProcess = Cut(editorState); evt.Use(); break; } } }
public static object QueryStateObject(Type t, int controlID) { return(GUIUtility.QueryStateObject(t, controlID)); }
public static NumberedEditorState NumberedTextArea(string controlName, NumberedEditorState editorState) { // This is a WAG about Unity's box model. Seems to work though, so... yeah. float effectiveWidgetHeight = 7 * GUI.skin.label.lineHeight + GUI.skin.label.padding.top + GUI.skin.label.padding.bottom ; Rect r = EditorGUILayout.BeginVertical(); if (r.width > 0) { editorState.scrollViewWidth = r.width; editorState.scrollViewHeight = r.height; } editorState.scrollPos = GUILayout.BeginScrollView(editorState.scrollPos, false, false, CachedStyle("HorizontalScrollbar"), CachedStyle("VerticalScrollbar"), CachedStyle("TextField"), GUILayout.Height(effectiveWidgetHeight)); GUILayout.BeginHorizontal(); GUILayout.Label(editorState.lineNumberingContent, NumberedEditorStyles.LineNumbering); GUIContent txt = new GUIContent(editorState.text); GUIContent dTxt = new GUIContent(editorState.dummyText); float minW, maxW; NumberedEditorStyles.NumberedEditor.CalcMinMaxWidth(dTxt, out minW, out maxW); GUI.SetNextControlName(controlName); Rect editorRect = GUILayoutUtility.GetRect(txt, NumberedEditorStyles.NumberedEditor, GUILayout.Width(maxW)); editorRect.width = maxW; bool wasMouseDrag = Event.current.type == EventType.MouseDrag; bool wasRelevantEvent = wasMouseDrag || Event.current.type == EventType.KeyDown; editorState.text = GUI.TextField(editorRect, editorState.text, NumberedEditorStyles.NumberedEditor); if ((GUI.GetNameOfFocusedControl() == controlName) && wasRelevantEvent) { int editorId = GUIUtility.keyboardControl; TextEditor te = GUIUtility.QueryStateObject(typeof(System.Object), editorId) as TextEditor; int pos = te.pos; // TODO: How does this play with keyboard selection? We want the actual cursor pos, not necessarily the right-end. if (pos != editorState.lastPos) { Vector2 cursorPixelPos = NumberedEditorStyles.NumberedEditor.GetCursorPixelPosition(editorRect, txt, pos); cursorPixelPos.y -= 1; // 0-align... float yBuffer = NumberedEditorStyles.NumberedEditor.lineHeight * 2; float xBuffer = 40f; // TODO: Make this a little less arbitrary? if (wasMouseDrag) { yBuffer = 0; xBuffer = 0; } if (editorState.scrollViewWidth > 0) { if (cursorPixelPos.y + yBuffer > editorState.scrollPos.y + editorState.scrollViewHeight - NumberedEditorStyles.NumberedEditor.lineHeight) { editorState.scrollPos.y = cursorPixelPos.y + yBuffer + NumberedEditorStyles.NumberedEditor.lineHeight - editorState.scrollViewHeight; } if (cursorPixelPos.y - yBuffer < editorState.scrollPos.y) { editorState.scrollPos.y = cursorPixelPos.y - yBuffer; } if (cursorPixelPos.x + xBuffer > editorState.scrollPos.x + editorState.scrollViewWidth) { editorState.scrollPos.x = cursorPixelPos.x + xBuffer - editorState.scrollViewWidth; } if (cursorPixelPos.x - xBuffer < editorState.scrollPos.x) { editorState.scrollPos.x = cursorPixelPos.x - xBuffer; } } } editorState.lastPos = pos; } GUILayout.EndHorizontal(); GUILayout.EndScrollView(); EditorGUILayout.EndVertical(); return(editorState); }
private void OnNodeGUI(Node node) { var nodeRect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight); nodeRect.height += EditorGUIUtility.standardVerticalSpacing; var selected = selectedNodes != null && selectedNodes.Contains(node); if (selected) { EditorGUI.DrawRect(nodeRect, focused ? UserSetting.HierarchySelectedFocusedColor : UserSetting.HierarchySelectedColor); } var controlId = GUIUtility.GetControlID(FocusType.Keyboard); var eventType = Event.current.GetTypeForControl(controlId); var mousePos = Event.current.mousePosition; var foldout = UserDatabase.caches.GetHierarchyFoldout(node); var topRect = new Rect(nodeRect.x, nodeRect.y - 2, nodeRect.width, 4); var bottomRect = new Rect(nodeRect.x, nodeRect.yMax - 1, nodeRect.width, 4); var centerRect = new Rect(nodeRect.x, nodeRect.y + 2, nodeRect.width, nodeRect.height - 4); var fsize = EditorStyles.foldout.CalcSize(GUIContent.none); var frect = new Rect(nodeRect.x + PersistentGUI.indent, nodeRect.y, fsize.x, fsize.y); switch (eventType) { case EventType.Repaint: { if (node.childCount > 0) { EditorStyles.foldout.Draw(frect, GUIContent.none, controlId, foldout); } if (UserDatabase.highlight.node == node) { if (mHighlightProgress == 0) { UserDatabase.highlight.node = null; } else { var color = UserSetting.HierarchyHighlightColor; color.a = (float)mHighlightProgress / mHighlightDuration; PersistentGUI.DrawAAPolyLine(nodeRect, 2, color); } mHighlightProgress -= 1; } break; } case EventType.MouseDown: { if (node.childCount > 0 && frect.Contains(mousePos)) { foldout = !foldout; UserDatabase.caches.SetHierarchyFoldout(node, foldout); Event.current.Use(); } else if (nodeRect.Contains(mousePos) && (Event.current.button == 0 || Event.current.button == 1)) { var nodes = UserDatabase.selection.nodes != null ? CoreUtil.CopyArray(UserDatabase.selection.nodes) : new Node[0]; if (Event.current.control) { if (selected) { ArrayUtility.Remove(ref nodes, node); } else { ArrayUtility.Add(ref nodes, node); var list = GUIUtility.GetStateObject(typeof(List <Node>), controlId) as List <Node>; list.Add(node); } mTemps = nodes; } else if (Event.current.shift && nodes.Length > 0) { var filter = new List <Node>(); var list = new List <Node>(); foreach (var n in root) { FlattenNode(list, n); } var index = list.IndexOf(node); var nIndex = nodes.Select(n => list.IndexOf(n)).Min(); var from = Mathf.Min(nIndex, index); var to = Mathf.Max(nIndex, index); for (var i = @from; i <= to; i++) { if (!filter.Contains(list[i])) { filter.Add(list[i]); } } mTemps = filter.ToArray(); } else { if (!selected) { mTemps = new[] { node } } ; if (node.childCount > 0 && Event.current.clickCount == 2) { foldout = !foldout; UserDatabase.caches.SetHierarchyFoldout(node, foldout); } } Event.current.Use(); } break; } case EventType.MouseUp: { if (!focused || frect.Contains(mousePos)) { break; } if (UserDragDrop.dragging) { var nodes = UserDragDrop.data as Node[]; if (nodes != null && nodes.Length > 0) { if (topRect.Contains(mousePos)) { UserUtil.MoveNodes(nodes, node.parent, node.GetSiblingIndex()); UserDragDrop.StopDrag(); Cursor.SetState(Cursor.State.Default); UserDatabase.caches.SetHierarchyFoldout(node.parent, true); Event.current.Use(); } else if (bottomRect.Contains(mousePos)) { UserUtil.MoveNodes(nodes, node.parent, node.GetSiblingIndex() + 1); UserDragDrop.StopDrag(); Cursor.SetState(Cursor.State.Default); UserDatabase.caches.SetHierarchyFoldout(node.parent, true); Event.current.Use(); } else if (centerRect.Contains(mousePos)) { UserUtil.MoveNodes(nodes, node, -1); UserDragDrop.StopDrag(); Cursor.SetState(Cursor.State.Default); UserDatabase.caches.SetHierarchyFoldout(node, true); Event.current.Use(); } } } else { if (Event.current.button == 0 && nodeRect.Contains(mousePos)) { var nodes = UserDatabase.selection.nodes != null ? CoreUtil.CopyArray(UserDatabase.selection.nodes) : new Node[0]; if (Event.current.control) { if (selected) { var list = GUIUtility.QueryStateObject(typeof(List <Node>), controlId) as List <Node>; if (list != null && list.Count > 0) { if (list[0] != node) { ArrayUtility.Remove(ref nodes, node); UserUtil.SelectNodes(nodes); } list.Clear(); } } } else if (!Event.current.shift) { if (selected) { UserUtil.SelectNodes(new[] { node }); } } if (Event.current.button != 1) { Event.current.Use(); } } } break; } case EventType.MouseDrag: { if (focused && Event.current.button == 0 && !UserDragDrop.dragging) { var nodes = selectedNodes; if (nodes != null && nodes.Contains(node) && nodeRect.Contains(mousePos)) { var data = new Node[nodes.Length]; Array.Copy(nodes, data, data.Length); UserDragDrop.StartDrag(data); Cursor.SetState(Cursor.State.DragAnything); Event.current.Use(); } } break; } } EditorGUI.LabelField(new Rect(nodeRect.x + 12, nodeRect.y, nodeRect.width, nodeRect.height), new GUIContent(node.name)); if (UserDragDrop.dragging) { var indentOffset = PersistentGUI.indent + 12; if (topRect.Contains(mousePos)) { PersistentGUI.DrawAAPolyLine( new Rect(topRect.x + indentOffset, topRect.y, topRect.width - indentOffset, topRect.height), 2, UserSetting.HierarchyDragTipsColor); } else if (centerRect.Contains(mousePos)) { PersistentGUI.DrawAAPolyLine( new Rect(centerRect.x + indentOffset, centerRect.y, centerRect.width - indentOffset, centerRect.height), 2, UserSetting.HierarchyDragTipsColor); } } if (foldout && node.childCount > 0) { EditorGUI.indentLevel += 1; for (int i = 0; i < node.childCount; i++) { OnNodeGUI(node.GetChild(i)); } EditorGUI.indentLevel -= 1; } else { if (UserDragDrop.dragging) { if (bottomRect.Contains(mousePos)) { var indentOffset = PersistentGUI.indent + 12; PersistentGUI.DrawAAPolyLine( new Rect(bottomRect.x + indentOffset, bottomRect.y, bottomRect.width - indentOffset, bottomRect.height), 2, UserSetting.HierarchyDragTipsColor); } } } }