public FontFile.FontSize GetFontSize(float pixelsPreUnit) { var actualSize = MathUtils.Round(pixelsPreUnit * size); if (lastFontSize == null || lastFontSize.size != actualSize) { lastFontSize = fontFile.GetFontForSize(actualSize); } return(lastFontSize); }
private float GetCharacterPosition(int id, FontFile.FontSize fontSize, float max) { if (id == 0) { return(0); } if (id == text.Length) { return(max); } SDL_ttf.TTF_SizeUNICODE(fontSize.handle, text.Substring(0, id), out var w, out _); return(gui.PixelsToUnits(w)); }
private unsafe int FindCaretIndex(string text, float position, FontFile.FontSize fontSize, float maxWidth) { if (string.IsNullOrEmpty(text) || position <= 0f) { return(0); } var cachedText = gui.textCache.GetCached((fontSize, text, uint.MaxValue)); var maxW = gui.PixelsToUnits(cachedText.texRect.w); var scale = 1f; if (maxW > maxWidth) { scale = maxWidth / maxW; maxW = maxWidth; } int min = 0, max = text.Length; var minW = 0f; if (position >= maxW) { return(max); } var handle = fontSize.handle; fixed(char *arr = text) { while (max > min + 1) { var ratio = (maxW - position) / (maxW - minW); var mid = MathUtils.Clamp(MathUtils.Round(min * ratio + max * (1f - ratio)), min + 1, max - 1); var prev = arr[mid]; arr[mid] = '\0'; TTF_SizeUNICODE(handle, arr, out var w, out _); arr[mid] = prev; var midW = gui.PixelsToUnits(w) * scale; if (midW > position) { max = mid; maxW = midW; } else { min = mid; minW = midW; } } } return(maxW - position > position - minW ? min : max); }
private void GetTextParameters(string textToBuild, Rect textRect, FontFile.FontSize fontSize, RectAlignment alignment, out TextCache cachedText, out float scale, out float textWidth, out Rect realTextRect) { realTextRect = textRect; scale = 1f; textWidth = 0f; if (!string.IsNullOrEmpty(textToBuild)) { cachedText = gui.textCache.GetCached((fontSize, textToBuild, uint.MaxValue)); textWidth = gui.PixelsToUnits(cachedText.texRect.w); if (textWidth > realTextRect.Width) { scale = realTextRect.Width / textWidth; } else { realTextRect = ImGui.AlignRect(textRect, alignment, textWidth, textRect.Height); } } else { realTextRect = ImGui.AlignRect(textRect, alignment, 0f, textRect.Height); cachedText = null; } }
public bool BuildTextInput(string text, out string newText, string placeholder, FontFile.FontSize fontSize, bool delayed, Icon icon, Padding padding, RectAlignment alignment, SchemeColor color) { newText = text; Rect textRect, realTextRect; using (gui.EnterGroup(padding, RectAllocator.LeftRow)) { var lineSize = gui.PixelsToUnits(fontSize.lineSize); if (icon != Icon.None) { gui.BuildIcon(icon, lineSize, color + 3); } textRect = gui.RemainingRow(0.3f).AllocateRect(0, lineSize, RectAlignment.MiddleFullRow); } var boundingRect = gui.lastRect; var focused = rect == boundingRect; if (focused && this.text == null) { this.text = text ?? ""; SetCaret(0, this.text.Length); } switch (gui.action) { case ImGuiAction.MouseDown: if (gui.actionParameter != SDL.SDL_BUTTON_LEFT) { break; } if (gui.ConsumeMouseDown(boundingRect)) { SetFocus(boundingRect, text ?? ""); GetTextParameters(this.text, textRect, fontSize, alignment, out _, out _, out _, out realTextRect); SetCaret(FindCaretIndex(text, gui.mousePosition.X - realTextRect.X, fontSize, textRect.Width)); } break; case ImGuiAction.MouseMove: if (focused && gui.actionParameter == SDL.SDL_BUTTON_LEFT) { GetTextParameters(this.text, textRect, fontSize, alignment, out _, out _, out _, out realTextRect); SetCaret(caret, FindCaretIndex(this.text, gui.mousePosition.X - realTextRect.X, fontSize, textRect.Width)); } gui.ConsumeMouseOver(boundingRect, RenderingUtils.cursorCaret, false); break; case ImGuiAction.Build: var textColor = color + 2; string textToBuild; if (focused) { textToBuild = this.text; } else if (string.IsNullOrEmpty(text)) { textToBuild = placeholder; textColor = color + 3; } else { textToBuild = text; } GetTextParameters(textToBuild, textRect, fontSize, alignment, out var cachedText, out var scale, out var textWidth, out realTextRect); if (cachedText != null) { gui.DrawRenderable(realTextRect, cachedText, textColor); } if (focused) { if (selectionAnchor != caret) { var left = GetCharacterPosition(Math.Min(selectionAnchor, caret), fontSize, textWidth) * scale; var right = GetCharacterPosition(Math.Max(selectionAnchor, caret), fontSize, textWidth) * scale; gui.DrawRectangle(new Rect(left + realTextRect.X, realTextRect.Y, right - left, realTextRect.Height), SchemeColor.TextSelection); } else { if (nextCaretTimer <= Ui.time) { nextCaretTimer = Ui.time + 500; caretVisible = !caretVisible; } gui.SetNextRebuild(nextCaretTimer); if (caretVisible) { var caretPosition = GetCharacterPosition(caret, fontSize, textWidth) * scale; gui.DrawRectangle(new Rect(caretPosition + realTextRect.X - 0.05f, realTextRect.Y, 0.1f, realTextRect.Height), color + 2); } } } gui.DrawRectangle(boundingRect, color); break; } if (boundingRect == prevRect) { var changed = text != prevText; if (changed) { newText = prevText; } prevRect = default; prevText = null; return(changed); } if (focused && !delayed && this.text != text) { newText = this.text; return(true); } return(false); }