/// <summary> /// Used to check whether the cursor is moused over the element and whether its being /// obstructed by another element. /// </summary> protected override void InputDepth() { State &= ~HudElementStates.IsMouseInBounds; if (HudMain.InputMode != HudInputMode.NoInput && (HudSpace?.IsFacingCamera ?? false)) { Vector3 cursorPos = HudSpace.CursorPos; Vector2 halfSize = Vector2.Max(cachedSize, new Vector2(minMouseBounds)) * .5f; BoundingBox2 box = new BoundingBox2(cachedPosition - halfSize, cachedPosition + halfSize); bool mouseInBounds; if (maskingBox == null) { mouseInBounds = box.Contains(new Vector2(cursorPos.X, cursorPos.Y)) == ContainmentType.Contains; } else { mouseInBounds = box.Intersect(maskingBox.Value).Contains(new Vector2(cursorPos.X, cursorPos.Y)) == ContainmentType.Contains; } if (mouseInBounds) { State |= HudElementStates.IsMouseInBounds; HudMain.Cursor.TryCaptureHudSpace(cursorPos.Z, HudSpace.GetHudSpaceFunc); } } }
protected override void Draw() { if (ShowCaret) { bool isCharVisible = text.Count == 0 || text[0].Count == 0; CaretIndex = ClampIndex(CaretIndex); // If line visible if ((text.Count > 0 && text[0].Count > 0) && (CaretIndex.X >= text.VisibleLineRange.X && CaretIndex.X <= text.VisibleLineRange.Y)) { // Damned special cases Vector2I index = Vector2I.Max(CaretIndex, Vector2I.Zero); // Calculate visibilty on line IRichChar ch = text[index]; Vector2 size = ch.Size, pos = ch.Offset + text.TextOffset; BoundingBox2 textBounds = BoundingBox2.CreateFromHalfExtent(Vector2.Zero, .5f * text.Size), charBounds = BoundingBox2.CreateFromHalfExtent(pos, .5f * Vector2.Max(size, new Vector2(8f))); if (textBounds.Contains(charBounds) != ContainmentType.Disjoint) { isCharVisible = true; } } if (blink & isCharVisible) { UpdateOffset(); base.Draw(); } if (blinkTimer.ElapsedMilliseconds > 500) { blink = !blink; blinkTimer.Restart(); } } }
/// <summary> /// Update selection and highlight based on user input /// </summary> protected virtual void UpdateSelectionInput(Vector2 cursorPos) { HighlightIndex = MathHelper.Clamp(HighlightIndex, 0, Entries.Count - 1); // If using arrow keys to scroll, adjust the scrollbox's start/end indices if (KeyboardScroll) { // If using arrow keys to scroll, then the focus should follow the highlight FocusIndex = HighlightIndex; } else // Otherwise, focus index should follow the selection { FocusIndex = SelectionIndex; } // Keyboard input if (HasFocus) { if (SharedBinds.UpArrow.IsNewPressed || SharedBinds.UpArrow.IsPressedAndHeld) { HighlightIndex--; KeyboardScroll = true; lastCursorPos = cursorPos; } else if (SharedBinds.DownArrow.IsNewPressed || SharedBinds.DownArrow.IsPressedAndHeld) { HighlightIndex++; KeyboardScroll = true; lastCursorPos = cursorPos; } } else { KeyboardScroll = false; lastCursorPos = new Vector2(float.MinValue); } bool listMousedOver = false; // Mouse input if (IsMousedOver) { // If the user moves the cursor after using arrow keys for selection then moves the // mouse, disable arrow selection if ((cursorPos - lastCursorPos).LengthSquared() > 4f) { KeyboardScroll = false; } if (!KeyboardScroll) { Vector2 cursorOffset = cursorPos - ListPos; BoundingBox2 listBounds = new BoundingBox2(-ListSize * .5f, ListSize * .5f); // If the list is moused over, then calculate highlight index based on cursor position. if (listBounds.Contains(cursorOffset) == ContainmentType.Contains) { int newIndex = ListRange.X; for (int i = ListRange.X; i <= ListRange.Y; i++) { if (Entries[i].Enabled) { TElement element = Entries[i].Element; Vector2 halfSize = element.Size * .5f, offset = element.Offset; BoundingBox2 bb = new BoundingBox2(offset - halfSize, offset + halfSize); if (bb.Contains(cursorOffset) == ContainmentType.Contains) { break; } } newIndex++; } if (newIndex >= 0 && newIndex < Entries.Count) { HighlightIndex = newIndex; listMousedOver = true; } } } } if ((listMousedOver && SharedBinds.LeftButton.IsNewPressed) || (HasFocus && SharedBinds.Space.IsNewPressed)) { SelectionIndex = HighlightIndex; SelectionChanged?.Invoke(this, EventArgs.Empty); KeyboardScroll = false; } HighlightIndex = MathHelper.Clamp(HighlightIndex, 0, Entries.Count - 1); }
/// <summary> /// Draws the text board in world space on the XY plane of the matrix, facing in the +Z /// direction. /// </summary> public void Draw(BoundingBox2 box, BoundingBox2 mask, MatrixD[] matrix) { ContainmentType containment; mask.Contains(ref box, out containment); if (containment != ContainmentType.Disjoint) { if (offsetsAreStale) { UpdateOffsets(); } else if (lineRangeIsStale || (endLine == -1 && lines.Count > 0)) { UpdateLineRange(); } if (AutoResize) { _textOffset = Vector2.Zero; } if (updateEvent && (eventTimer.ElapsedTicks / TimeSpan.TicksPerMillisecond) > 500) { TextChanged?.Invoke(); eventTimer.Restart(); updateEvent = false; } BoundingBox2 textMask = box.Intersect(mask); Vector2 offset = box.Center + _textOffset * Scale; IReadOnlyList <Line> lineList = lines.PooledLines; CroppedBox bb = default(CroppedBox); bb.mask = textMask; // Draw glyphs for (int ln = startLine; ln <= endLine && ln < lines.Count; ln++) { Line line = lineList[ln]; for (int ch = 0; ch < line.Count; ch++) { GlyphLocData locData = line.LocData[ch]; Vector2 halfSize = locData.bbSize * Scale * .5f, pos = offset + locData.bbOffset * Scale; bb.bounds = new BoundingBox2(pos - halfSize, pos + halfSize); bb.mask.Value.Contains(ref bb.bounds, out containment); if (containment == ContainmentType.Contains) { line.GlyphBoards[ch].Draw(ref bb, ref matrix[0]); } else if (containment != ContainmentType.Disjoint) { line.GlyphBoards[ch].DrawCroppedTex(ref bb, ref matrix[0]); } } } QuadBoard underlineBoard = QuadBoard.Default; // Draw underlines for (int n = 0; n < underlines.Count; n++) { Vector2 halfSize = underlines[n].size * Scale * .5f, pos = offset + underlines[n].offset * Scale; bb.bounds = new BoundingBox2(pos - halfSize, pos + halfSize); bb.mask.Value.Contains(ref bb.bounds, out containment); underlineBoard.bbColor = underlines[n].color; if (containment == ContainmentType.Contains) { underlineBoard.Draw(ref bb, ref matrix[0]); } else if (containment != ContainmentType.Disjoint) { underlineBoard.DrawCropped(ref bb, ref matrix[0]); } } } }