-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathUtil.cs
649 lines (547 loc) · 24.9 KB
/
Util.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
using Dalamud.Interface;
using Dalamud.Interface.Components;
using Dalamud.Interface.Textures;
using Dalamud.Interface.Textures.TextureWraps;
using Dalamud.Interface.Utility;
using ImGuiNET;
using OtterGui.Raii;
using OtterGui.Text;
namespace OtterGui;
[InterpolatedStringHandler]
public ref struct HoverTooltipStringHandler
{
private DefaultInterpolatedStringHandler _builder;
public bool IsEnabled;
public HoverTooltipStringHandler(int literalLength, int formattedCount, out bool isEnabled)
{
IsEnabled = (literalLength > 0 || formattedCount > 0) && ImGui.IsItemHovered();
isEnabled = IsEnabled;
_builder = isEnabled ? new DefaultInterpolatedStringHandler(literalLength, formattedCount) : default;
}
public HoverTooltipStringHandler(int literalLength, int formattedCount, ImGuiHoveredFlags flags, out bool isEnabled)
{
IsEnabled = (literalLength > 0 || formattedCount > 0) && ImGui.IsItemHovered(flags);
isEnabled = IsEnabled;
_builder = isEnabled ? new DefaultInterpolatedStringHandler(literalLength, formattedCount) : default;
}
public void AppendLiteral(string s)
=> _builder.AppendLiteral(s);
public void AppendFormatted<T>(T t)
=> _builder.AppendFormatted(t);
public void AppendFormatted<T>(T t, string format) where T : IFormattable
=> _builder.AppendFormatted(t, format);
public void AppendFormatted<T>(T t, int alignment) where T : IFormattable
=> _builder.AppendFormatted(t, alignment);
public void AppendFormatted<T>(T t, int alignment, string format) where T : IFormattable
=> _builder.AppendFormatted(t, alignment, format);
internal string GetFormattedText()
=> _builder.ToStringAndClear();
}
public static partial class ImGuiUtil
{
// Exception safe clipboard.
public static string GetClipboardText()
{
try
{
return ImGui.GetClipboardText();
}
catch
{
return string.Empty;
}
}
/// <summary> InputInt for ulong. </summary>
public static bool InputUlong(string label, ref ulong value, string format = "%llu",
ImGuiInputTextFlags flags = ImGuiInputTextFlags.None)
{
var v = value;
if (!ImUtf8.InputScalar(label, ref v, format, flags: flags) || v == value)
return false;
value = v;
return true;
}
// Print unformatted text wrapped.
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void TextWrapped(string text)
{
ImGui.PushTextWrapPos(0);
ImGui.TextUnformatted(text);
ImGui.PopTextWrapPos();
}
// Draw the same text multiple times to simulate a shadowed text.
public static void TextShadowed(string text, uint foregroundColor, uint shadowColor, byte shadowWidth = 1)
{
var x = ImGui.GetCursorPosX();
var y = ImGui.GetCursorPosY();
for (var i = -shadowWidth; i <= shadowWidth; i++)
{
for (var j = -shadowWidth; j <= shadowWidth; j++)
{
if (i == 0 && j == 0)
continue;
ImGui.SetCursorPosX(x + i);
ImGui.SetCursorPosY(y + j);
TextColored(shadowColor, text);
}
}
ImGui.SetCursorPosX(x);
ImGui.SetCursorPosY(y);
TextColored(foregroundColor, text);
}
// Draw the same text multiple times to simulate a shadowed text.
public static void TextShadowed(ImDrawListPtr drawList, Vector2 position, string text, uint foregroundColor, uint shadowColor,
byte shadowWidth = 1)
{
for (var i = -shadowWidth; i <= shadowWidth; i++)
{
for (var j = -shadowWidth; j <= shadowWidth; j++)
{
if (i == 0 && j == 0)
continue;
drawList.AddText(position + new Vector2(i, j), shadowColor, text);
}
}
drawList.AddText(position, foregroundColor, text);
}
/// <summary> Draw a group of texts with colors without additional spacing between them in the same line. </summary>
public static void DrawColoredText(params (string, uint)[] data)
{
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero);
foreach (var (text, color) in data)
{
if (color == 0)
ImGui.TextUnformatted(text);
else
TextColored(color, text);
ImGui.SameLine();
}
ImGui.NewLine();
}
// Draw a single piece of text in the given color.
/// <seealso cref="ImUtf8.Text(ReadOnlySpan{byte}, uint)"/>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void TextColored(uint color, string text)
{
using var _ = ImRaii.PushColor(ImGuiCol.Text, color);
ImGui.TextUnformatted(text);
}
public static void BulletTextColored(uint color, string text)
{
using var g = ImRaii.Group();
ImGui.Bullet();
ImGui.SameLine();
TextColored(color, text);
}
// Create a selectable that copies a text to clipboard when clicked.
// Also adds a tooltip on hover.
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void CopyOnClickSelectable(string text, string copiedText, string tooltip)
{
if (ImGui.Selectable(text))
{
try
{
ImGui.SetClipboardText(copiedText);
}
catch
{
// ignored
}
}
HoverTooltip(tooltip);
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void CopyOnClickSelectable(string text)
=> CopyOnClickSelectable(text, text, "Click to copy to clipboard.");
// Draw a single FontAwesomeIcon.
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void PrintIcon(FontAwesomeIcon icon)
{
using var font = ImRaii.PushFont(UiBuilder.IconFont);
ImGui.TextUnformatted(icon.ToIconString());
}
// Draw a help marker, followed by a label.
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void LabeledHelpMarker(string label, string tooltip)
{
ImGuiComponents.HelpMarker(tooltip);
ImGui.SameLine();
ImGui.TextUnformatted(label);
HoverTooltip(tooltip);
}
// Draw a help marker on a selectable, typically for combo box items.
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void SelectableHelpMarker(string tooltip)
{
var hovered = ImGui.IsItemHovered();
ImGui.SameLine();
using (var _ = ImRaii.PushFont(UiBuilder.IconFont))
{
using var color = ImRaii.PushColor(ImGuiCol.Text, ImGui.GetColorU32(ImGuiCol.TextDisabled));
RightAlign(FontAwesomeIcon.InfoCircle.ToIconString(), ImGui.GetStyle().ItemSpacing.X);
}
if (hovered)
{
using var tt = ImRaii.Tooltip();
ImGui.TextUnformatted(tooltip);
}
}
// Drag between min and max with the given speed and format.
// Has width of width.
// Returns true if the item was edited but is not active anymore.
public static bool DragFloat(string label, ref float value, float width, float speed, float min, float max, string format)
{
ImGui.SetNextItemWidth(width);
if (ImGui.DragFloat(label, ref value, speed, min, max, format))
value = Math.Clamp(value, min, max);
return ImGui.IsItemDeactivatedAfterEdit();
}
// Drag between min and max with the given speed and format.
// Has width of width.
// Returns true if the item was edited but is not active anymore.
public static bool DragInt(string label, ref int value, float width, float speed, int min, int max, string format)
{
ImGui.SetNextItemWidth(width);
if (ImGui.DragInt(label, ref value, speed, min, max, format))
value = Math.Clamp(value, min, max);
return ImGui.IsItemDeactivatedAfterEdit();
}
// Create a centered, modal help popup with the given content for the given label.
// It has a centered 'Understood' button to close the window.
public static void HelpPopup(string label, Vector2 size, Action content)
{
ImGui.SetNextWindowPos(ImGui.GetMainViewport().GetCenter(), ImGuiCond.Always, new Vector2(0.5f));
ImGui.SetNextWindowSize(size);
using var pop = ImRaii.Popup(label, ImGuiWindowFlags.Modal | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove);
if (pop)
{
content();
const string buttonText = "Understood";
var buttonSize = Math.Max(size.X / 5, ImGui.CalcTextSize(buttonText).X + 2 * ImGui.GetStyle().FramePadding.X);
var buttonCenter = (size.X - buttonSize) / 2 - ImGui.GetStyle().WindowPadding.X;
ImGui.SetCursorPos(new Vector2(buttonCenter, size.Y - ImGui.GetFrameHeight() * 1.75f));
if (ImGui.Button(buttonText, new Vector2(buttonSize, 0)))
ImGui.CloseCurrentPopup();
}
}
// Draw a selectable combo box for a generic enumerable.
// Uses the supplied toString function if any, otherwise ToString.
// Can specify enum values to skip at start or end and gives all those enum values as options.
public static bool GenericEnumCombo<T>(string label, float width, T current, out T newValue,
Func<T, string>? toString = null, int skip = 0, int skipEnd = 0) where T : struct, Enum
=> GenericEnumCombo(label, width, current, out newValue, Enum.GetValues<T>().Skip(skip).SkipLast(skipEnd), toString);
// Draw a selectable combo box for a generic enumerable.
// Uses the supplied toString function if any, otherwise ToString.
// Can specify the options to supply.
public static bool GenericEnumCombo<T>(string label, float width, T current, out T newValue,
IEnumerable<T> options, Func<T, string>? toString = null) where T : struct, Enum
{
ImGui.SetNextItemWidth(width);
using var combo = ImRaii.Combo(label, toString?.Invoke(current) ?? current.ToString());
if (combo)
foreach (var data in options)
{
var name = toString?.Invoke(data) ?? data.ToString();
if (name.Length == 0 || !ImGui.Selectable(name, data.Equals(current)) || data.Equals(current))
continue;
newValue = data;
return true;
}
newValue = current;
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static bool DrawDisabledButton(string label, Vector2 size, string description, bool disabled, bool icon = false)
{
using var dis = ImRaii.PushStyle(ImGuiStyleVar.Alpha, 0.5f, disabled);
using var font = ImRaii.PushFont(UiBuilder.IconFont, icon);
var ret = ImGui.Button(label, size);
font.Pop();
dis.Pop();
HoverTooltip(description);
return ret && !disabled;
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static bool DrawTextButton(string text, Vector2 size, uint buttonColor)
{
using var color = ImRaii.PushColor(ImGuiCol.Button, buttonColor)
.Push(ImGuiCol.ButtonActive, buttonColor)
.Push(ImGuiCol.ButtonHovered, buttonColor);
return ImGui.Button(text, size);
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static bool DrawTextButton(string text, Vector2 size, uint buttonColor, uint textColor)
{
using var color = ImRaii.PushColor(ImGuiCol.Button, buttonColor)
.Push(ImGuiCol.ButtonActive, buttonColor)
.Push(ImGuiCol.ButtonHovered, buttonColor)
.Push(ImGuiCol.Text, textColor);
return ImGui.Button(text, size);
}
/// <seealso cref="ImUtf8.HoverTooltip(ImGuiHoveredFlags, ReadOnlySpan{byte})"/>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void HoverTooltip(string tooltip, ImGuiHoveredFlags flags = ImGuiHoveredFlags.None)
{
if (tooltip.Length > 0 && ImGui.IsItemHovered(flags))
{
using var tt = ImRaii.Tooltip();
ImGui.TextUnformatted(tooltip);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void HoverTooltip(HoverTooltipStringHandler tooltip)
{
if (tooltip.IsEnabled)
{
using var tt = ImRaii.Tooltip();
ImGui.TextUnformatted(tooltip.GetFormattedText());
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void HoverTooltip(ImGuiHoveredFlags flags, [InterpolatedStringHandlerArgument("flags")] HoverTooltipStringHandler tooltip)
{
if (tooltip.IsEnabled)
{
using var tt = ImRaii.Tooltip();
ImGui.TextUnformatted(tooltip.GetFormattedText());
}
}
public static bool Checkbox(string label, string description, bool current, Action<bool> setter,
ImGuiHoveredFlags flags = ImGuiHoveredFlags.None)
{
var tmp = current;
var result = ImGui.Checkbox(label, ref tmp);
HoverTooltip(description, flags);
if (!result || tmp == current)
return false;
setter(tmp);
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void DrawTableColumn(string text)
{
ImGui.TableNextColumn();
ImGui.TextUnformatted(text);
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void DrawFrameColumn(string text)
{
ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(text);
}
public static bool DrawEditButtonText(int id, string current, out string newText, ref bool edit, Vector2 buttonSize, float inputWidth,
uint maxLength = 256)
{
newText = current;
var tmpEdit = edit;
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing / 2);
using var _ = ImRaii.PushId(id);
if (DrawDisabledButton(FontAwesomeIcon.Edit.ToIconString(), buttonSize, "Rename", edit, true))
edit = true;
ImGui.SameLine();
style.Pop();
if (!edit)
{
DrawTextButton(current, Vector2.Zero, ImGui.GetColorU32(ImGuiCol.FrameBg));
return false;
}
ImGui.SetNextItemWidth(inputWidth);
if (edit != tmpEdit)
{
ImGui.SetKeyboardFocusHere();
ImGui.SetItemDefaultFocus();
}
if (ImGui.InputText("##rename", ref newText, maxLength, ImGuiInputTextFlags.EnterReturnsTrue))
return true;
if (edit == tmpEdit && !ImGui.IsItemActive())
edit = false;
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void HoverIcon(IDalamudTextureWrap icon, Vector2 iconSize)
=> HoverIcon(icon.ImGuiHandle, icon.Size, iconSize);
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void HoverIcon(ISharedImmediateTexture icon, Vector2 iconSize)
{
if (icon.TryGetWrap(out var wrap, out _))
HoverIcon(wrap.ImGuiHandle, wrap.Size, iconSize);
else
ImGui.Dummy(iconSize);
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void HoverIcon(nint ptr, Vector2 contentSize, Vector2 iconSize)
{
ImGui.Image(ptr, iconSize);
HoverIconTooltip(ptr, iconSize, contentSize);
}
public static void HoverIconTooltip(IDalamudTextureWrap icon, Vector2 iconSize)
=> HoverIconTooltip(icon, iconSize, string.Empty);
public static void HoverIconTooltip(IDalamudTextureWrap icon, Vector2 iconSize, string text)
{
var size = new Vector2(icon.Width, icon.Height);
if (iconSize.X > size.X || iconSize.Y > size.Y || !ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
return;
using var enable = ImRaii.Enabled();
ImGui.BeginTooltip();
ImGui.Image(icon.ImGuiHandle, size);
if (text.Length > 0)
ImGui.TextUnformatted(text);
ImGui.EndTooltip();
}
public static void HoverIconTooltip(nint icon, Vector2 iconSize, Vector2 size)
{
if (iconSize.X > size.X || iconSize.Y > size.Y || !ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
return;
using var enable = ImRaii.Enabled();
ImGui.BeginTooltip();
ImGui.Image(icon, size);
ImGui.EndTooltip();
}
/// <seealso cref="ImUtf8.TextRightAligned(ReadOnlySpan{byte}, float)"/>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void RightAlign(string text, float offset = 0)
{
offset = ImGui.GetContentRegionAvail().X - offset - ImGui.CalcTextSize(text).X;
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + offset);
ImGui.TextUnformatted(text);
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void RightJustify(string text, uint color)
{
ImGui.SetCursorPosX(ImGui.GetCursorPosX() - ImGui.CalcTextSize(text).X);
TextColored(color, text);
}
/// <seealso cref="ImUtf8.TextCentered(ReadOnlySpan{byte})"/>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void Center(string text)
{
var offset = (ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize(text).X) / 2;
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + offset);
ImGui.TextUnformatted(text);
}
public static bool OpenNameField(string popupName, ref string newName)
{
using var popup = ImRaii.Popup(popupName);
if (!popup)
return false;
if (ImGui.IsKeyPressed(ImGuiKey.Escape))
ImGui.CloseCurrentPopup();
ImGui.SetNextItemWidth(300 * ImGuiHelpers.GlobalScale);
if (ImGui.IsWindowAppearing())
ImGui.SetKeyboardFocusHere();
var enterPressed = ImGui.InputTextWithHint("##newName", "Enter New Name...", ref newName, 512, ImGuiInputTextFlags.EnterReturnsTrue);
if (!enterPressed)
return false;
ImGui.CloseCurrentPopup();
return true;
}
/// <summary>
/// A dummy that is only applied conditionally.
/// </summary>
public static void Dummy(float width, float height, bool condition = true)
{
if (!condition)
return;
ImGui.Dummy(new Vector2(width, height));
}
public static void Dummy(Vector2 size, bool condition = true)
{
if (!condition)
return;
ImGui.Dummy(size);
}
/// <summary>
/// Input an ushort.
/// </summary>
public static unsafe bool InputUInt16(string label, ref ushort v, ImGuiInputTextFlags flags)
{
fixed (ushort* v2 = &v)
{
return ImGui.InputScalar(label, ImGuiDataType.U16, (nint)v2, nint.Zero, nint.Zero, "%hu", flags);
}
}
/// <inheritdoc cref="ColorIntensity(Vector4)"/>
public static float ColorIntensity(uint color)
=> ColorIntensity(ColorHelpers.RgbaUintToVector4(color));
/// <inheritdoc cref="ColorIntensity(Vector4)"/>
public static float ColorIntensity(Vector3 color)
=> ColorIntensity(new Vector4(color, 0));
/// <summary> Computes the intensity of an RGB color without taking into consideration alpha values. </summary>
public static float ColorIntensity(Vector4 color)
=> 2 * color.X * color.X + 7 * color.Y * color.Y + color.Z * color.Z;
/// <summary> Obtain the better choice of black and white regarding contrast for a color. </summary>
public static uint ContrastColorBw(uint color)
=> ColorIntensity(color) >= 4 ? 0xFF000000 : 0xFFFFFFFF;
/// <summary> Obtain the better choice of black and white regarding contrast for a color. </summary>
public static Vector3 ContrastColorBw(Vector3 color)
=> ColorIntensity(color) >= 4 ? Vector3.Zero : Vector3.One;
/// <summary> Obtain the better choice of black and white regarding contrast for a color. </summary>
public static Vector4 ContrastColorBw(Vector4 color)
=> ColorIntensity(color) >= 4 ? new Vector4(0, 0, 0, color.W) : new Vector4(1, 1, 1, color.W);
/// <seealso cref="Text.EndObjects.DragDropTarget.CheckPayload(ReadOnlySpan{byte}, ImGuiDragDropFlags)"/>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static unsafe bool IsDropping(string name)
=> ImGui.AcceptDragDropPayload(name).NativePtr != null;
/// <summary> Make a single-button color picker with a contrasted letter centered on it. </summary>
public static bool ColorPicker(string label, string tooltip, Vector3 input, Action<Vector3> setter, string letter = "")
{
var ret = false;
if (ImGui.ColorEdit3(label, ref input,
ImGuiColorEditFlags.NoInputs
| ImGuiColorEditFlags.DisplayRGB
| ImGuiColorEditFlags.InputRGB
| ImGuiColorEditFlags.NoTooltip
| ImGuiColorEditFlags.HDR))
{
setter(input);
ret = true;
}
if (letter.Length > 0 && ImGui.IsItemVisible())
{
var textSize = ImGui.CalcTextSize(letter);
var center = ImGui.GetItemRectMin() + (ImGui.GetItemRectSize() - textSize) / 2;
var textColor = ContrastColorBw(new Vector4(input, 0.7f));
ImGui.GetWindowDrawList().AddText(center, ImGui.ColorConvertFloat4ToU32(textColor), letter);
}
HoverTooltip(tooltip);
return ret;
}
public static bool GuidInput(string label, string hint, string tooltip, ref Guid? guid, ref string text, float width = 0)
{
if (width != 0)
ImGui.SetNextItemWidth(width);
bool ret;
using (ImRaii.PushFont(UiBuilder.MonoFont))
{
ret = ImGui.InputTextWithHint(label, hint, ref text, 64);
}
HoverTooltip(tooltip);
if (ret)
guid = Guid.TryParse(text, out var g) ? g : null;
return ret;
}
/// <summary> Halves the alpha of the given color. </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint HalfTransparent(uint baseColor)
=> (baseColor & 0x00FFFFFFu) | ((baseColor & 0xFE000000u) >> 1);
/// <summary> Gets the current text color, but with halved alpha. </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint HalfTransparentText()
=> HalfTransparent(ImGui.GetColorU32(ImGuiCol.Text));
/// <summary>
/// Blends the given colors in equal proportions.
/// <paramref name="overlayColor"/> can only be fully saturated black, red, green, blue, cyan, magenta, yellow or white.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint HalfBlend(uint baseColor, uint overlayColor)
=> (baseColor & 0xFF000000u) | ((baseColor & 0x00FEFEFEu) >> 1) | (overlayColor & 0x00808080u);
/// <summary> Gets the current text color, blended in equal proportions with the given fully saturated color. </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint HalfBlendText(uint overlayColor)
=> HalfBlend(ImGui.GetColorU32(ImGuiCol.Text), overlayColor);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint ColorConvertFloat3ToU32(Vector3 color)
=> ImGui.ColorConvertFloat4ToU32(new Vector4(color, 1.0f));
}