public static void DrawVariableThicknessRectangle(ImDrawListPtr drawList, Vector2 minCorner, Vector2 maxCorner, float thicknessTop, float thicknessBottom, float thicknessLeft, float thicknessRight, uint color) { var X1 = minCorner.X + thicknessLeft; var X2 = maxCorner.X - thicknessRight; var Y1 = minCorner.Y + thicknessTop; var Y2 = maxCorner.Y - thicknessBottom; if (thicknessLeft > 0) { drawList.AddRectFilled(minCorner, new Vector2(X1, maxCorner.Y), color); // Left column } if (thicknessRight > 0) { drawList.AddRectFilled(new Vector2(X2, minCorner.Y), maxCorner, color); // Right column } if (thicknessTop > 0) { drawList.AddRectFilled(new Vector2(X1, minCorner.Y), new Vector2(X2, Y1), color); // Remainder top } if (thicknessBottom > 0) { drawList.AddRectFilled(new Vector2(X1, Y2), new Vector2(X2, maxCorner.Y), color); // Remainder bottom } }
public static bool ToggleButton(string strId, ref bool v) { Vector2 p = ImGuiNET.ImGui.GetCursorScreenPos(); ImDrawListPtr drawList = ImGuiNET.ImGui.GetWindowDrawList(); bool isClicked = false; float height = ImGuiNET.ImGui.GetFrameHeight(); float width = height * 1.55f; float radius = height * 0.50f; if (ImGuiNET.ImGui.InvisibleButton(strId, new Vector2(width, height))) { isClicked = true; v = !v; } uint colBg; uint colNub; if (ImGuiNET.ImGui.IsItemHovered()) { colBg = v ? ImGuiNET.ImGui.GetColorU32(ImGuiCol.ButtonHovered) : ImGuiNET.ImGui.GetColorU32(ImGuiCol.ButtonActive, 0.5f); colNub = v ? ImGuiNET.ImGui.GetColorU32(ImGuiCol.ScrollbarGrabActive) : ImGuiNET.ImGui.GetColorU32(ImGuiCol.ScrollbarGrabActive); } else { colBg = v ? ImGuiNET.ImGui.GetColorU32(ImGuiCol.ButtonHovered, 0.8f) : ImGuiNET.ImGui.GetColorU32(ImGuiCol.ButtonHovered, 0.5f); colNub = v ? ImGuiNET.ImGui.GetColorU32(ImGuiCol.ScrollbarGrabHovered) : ImGuiNET.ImGui.GetColorU32(ImGuiCol.ScrollbarGrabHovered); } drawList.AddRectFilled(p, new Vector2(p.X + width, p.Y + height), colBg, height * 0.5f); drawList.AddCircleFilled(new Vector2(v ? (p.X + width - radius) : (p.X + radius), p.Y + radius), radius - 1.5f, colNub); return(isClicked); }
public void Render() { ImGui.BeginChild("Log", Vector2.Zero, false); ReadOnlySpan <LogEvent> logEvents = _logEventRecorder.LogEvents; ImDrawListPtr drawList = ImGui.GetWindowDrawList(); foreach (LogEvent logEvent in logEvents) { Vector4 color = logEvent.LogLevel switch { LogLevel.Information => Vector4.One, LogLevel.Warning => new Vector4(1, 1, 0, 1), LogLevel.Error => new Vector4(1, 0, 0, 1), _ => ThrowHelper.Unreachable <Vector4>() }; Vector2 topLeft = ImGui.GetCursorScreenPos(); Vector2 textSize = ImGui.CalcTextSize(logEvent.Message); ImGui.TextColored(color, logEvent.Message); if (ImGui.IsItemHovered()) { ImGui.BeginTooltip(); ImGui.Text("Copy to clipboard"); ImGui.EndTooltip(); drawList.AddRectFilled( a: topLeft, b: topLeft + textSize, ImGui.GetColorU32(ImGuiCol.FrameBgHovered) ); } if (ImGui.IsItemClicked()) { ImGui.SetClipboardText(logEvent.Message); } } if (logEvents.Length > _prevEventCount) { ImGui.SetScrollHereY(); } _prevEventCount = logEvents.Length; ImGui.EndChild(); } }
//adapted from code somewhere from imgui internal public static bool ToggleButton(string str_id, bool isToggled, string?tooltip, bool isEnabled = true) { const uint TOGGLE_OFF_HOVER_COL = 0xff888888; const uint TOGGLE_ON_HOVER_COL = 0xff008800; const uint TOGGLE_OFF_NOHOVER_COL = 0xff686868; const uint TOGGLE_ON_NOHOVER_COL = 0xff005500; Vector2 p = ImGui.GetCursorScreenPos(); ImDrawListPtr draw_list = ImGui.GetWindowDrawList(); float height = ImGui.GetFrameHeight() - 2; float width = height * 1.55f; float radius = height * 0.50f; ImGui.InvisibleButton(str_id, new Vector2(width, height)); bool changed = isEnabled && ImGui.IsItemClicked(); if (changed) { _lastActiveID = ImGui.GetID(str_id); _LastActiveIdTimer = DateTime.UtcNow; } if (tooltip != null && ImGui.IsItemHovered()) { ImGui.BeginTooltip(); ImGui.Text(tooltip); ImGui.EndTooltip(); } float t = isToggled ? 1.0f : 0.0f; float ANIM_SPEED = 0.08f; if (_lastActiveID == ImGui.GetID(str_id)) { float t_anim = ImSaturate((float)(DateTime.UtcNow - _LastActiveIdTimer).TotalSeconds / ANIM_SPEED); t = isToggled ? (t_anim) : (1.0f - t_anim); if (t == 0f || t == 1.0f) { _lastActiveID = 0; } } uint col_bg, col_btn; if (isEnabled) { if (ImGui.IsItemHovered()) { col_bg = isToggled ? TOGGLE_ON_HOVER_COL : TOGGLE_OFF_HOVER_COL; } else { col_bg = isToggled ? TOGGLE_ON_NOHOVER_COL : TOGGLE_OFF_NOHOVER_COL; } col_btn = 0xffffffff; } else { col_btn = 0xff909090; col_bg = 0xff454545; } draw_list.AddRectFilled(p, new Vector2(p.X + width, p.Y + height), col_bg, height * 0.5f); draw_list.AddCircleFilled(new Vector2(p.X + radius + t * (width - radius * 2.0f), p.Y + radius), radius - 1.5f, col_btn); return(changed); }
private void OnLayout() { ImGui.SetNextWindowPos(Vector2.zero); ImGui.SetNextWindowSize(new Vector2(Screen.width, Screen.height)); ImGui.SetNextWindowContentSize(Vector2.one * 20000f); ImGui.SetNextWindowFocus(); if (ImGui.Begin("Choreographer", ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoBringToFrontOnFocus | ImGuiWindowFlags.NoScrollbar)) { ScrollPosition.x = ImGui.GetScrollX(); ScrollPosition.y = ImGui.GetScrollY(); if (ImGui.IsMouseDragging(ImGuiMouseButton.Right)) { ScrollPosition -= ImGui.GetMouseDragDelta(ImGuiMouseButton.Right) / ImGui.GetIO().FontGlobalScale; ImGui.ResetMouseDragDelta(ImGuiMouseButton.Right); ImGui.SetScrollX(ScrollPosition.x); ImGui.SetScrollY(ScrollPosition.y); ScrollPosition.x = ImGui.GetScrollX(); ScrollPosition.y = ImGui.GetScrollY(); } ImDrawListPtr bgDrawList = ImGui.GetBackgroundDrawList(), fgDrawList = ImGui.GetForegroundDrawList(); bgDrawList.AddRectFilled(Vector2.zero, new Vector2(2000f, 2000f), ColorBackground); for (var i = 1; i < 19; ++i) { bgDrawList.AddLine(new Vector2(0f, i * 100f), new Vector2(2000f, i * 100f), ColorGridLineHorizontal, 1f); bgDrawList.AddLine(new Vector2(i * 100f, 0f), new Vector2(i * 100f, 2000f), ColorGridLineVertical, 1f); } var imGuiStyle = ImGui.GetStyle(); foreach (var node in Nodes) { node.Style.Push(); ImGui.SetNextWindowPos(Scale(node.Pos - ScrollPosition), ImGuiCond.Always, _half); ImGui.SetNextWindowSize(Scale(node.Size), ImGuiCond.Always); if (ImGui.Begin(node.Name, ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoScrollbar)) { var drawList = ImGui.IsWindowFocused() | ImGui.IsWindowHovered() ? ImGui.GetForegroundDrawList() : ImGui.GetBackgroundDrawList(); CustomEvent.Trigger(gameObject, "OnNode", drawList, node); ImGui.Columns(2, "Column", false); ImGui.SetColumnWidth(0, Scale(node.LeftSize.x)); ImGui.SetColumnOffset(1, Scale(node.LeftSize.x)); ImGui.SetColumnWidth(1, Scale(node.RightSize.x)); for (var i = 0; i < node.RowHeights.Length; ++i) { if (i < node.Inputs.Length) { ImGui.PushID(node.Inputs[i].Id); if (ImGui.Selectable(node.Inputs[i].Name, false, ReadOnly ? ImGuiSelectableFlags.Disabled : ImGuiSelectableFlags.None, Scale(new Vector2(node.LeftSize.x, node.RowHeights[i])))) { CustomEvent.Trigger(gameObject, "OnInput", drawList, node.Inputs[i].Id); } CustomEvent.Trigger(gameObject, "OnConnection", drawList, new Vector2(ImGui.GetItemRectMin().x, (ImGui.GetItemRectMin().y + ImGui.GetItemRectMax().y) / 2f), -1, node.Inputs[i].Id, ReadOnly); ImGui.PopID(); } ImGui.NextColumn(); if (i < node.Outputs.Length) { ImGui.PushID(node.Outputs[i].Id); ImGui.PushStyleVar(ImGuiStyleVar.SelectableTextAlign, new Vector2(1.0f, 0f)); ImGui.Unindent(imGuiStyle.ItemSpacing.x); if (ImGui.Selectable(node.Outputs[i].Name, false, ReadOnly ? ImGuiSelectableFlags.Disabled : ImGuiSelectableFlags.None, Scale(new Vector2(node.RightSize.x, node.RowHeights[i])))) { CustomEvent.Trigger(gameObject, "OnOutput", drawList, node.Outputs[i].Id); } CustomEvent.Trigger(gameObject, "OnConnection", drawList, new Vector2(ImGui.GetItemRectMax().x, (ImGui.GetItemRectMin().y + ImGui.GetItemRectMax().y) / 2f), 1, node.Outputs[i].Id, ReadOnly); ImGui.Indent(imGuiStyle.ItemSpacing.x); ImGui.PopStyleVar(); ImGui.PopID(); } ImGui.NextColumn(); } ImGui.Columns(); } ImGui.End(); node.Style.Pop(); // TODO: Don't draw connections if neither node is visible? Edge Case: If the viewport is in-between the two nodes, the line should be visible. foreach (var connection in node.Connections) { var parentNode = _nodes[connection.Parent]; switch (connection.Type) { case Connection.ConnectionType.Inherited: DrawCurvedLine(fgDrawList, new Vector2(parentNode.Pos.x + parentNode.Size.x / 2f, parentNode.Pos.y - parentNode.Size.y / 2f), node.Pos - node.Size / 2f); break; case Connection.ConnectionType.Recursive: DrawCurvedLine(fgDrawList, new Vector2(parentNode.Pos.x + parentNode.Size.x / 2f, parentNode.Pos.y + parentNode.Size.y / 2f), node.Pos + new Vector2(-node.Size.x / 2f, node.Size.y / 2f)); break; } } } } ImGui.End(); if (ImGui.BeginMainMenuBar()) { ImGui.Checkbox("Read Only", ref ReadOnly); if (ImGui.GetIO().KeyCtrl) { ImGui.GetIO().FontGlobalScale = Mathf.Max(0.1f, Mathf.Min(2f, ImGui.GetIO().FontGlobalScale + ImGui.GetIO().MouseWheel * 0.1f)); } ImGui.SliderFloat("Zoom", ref ImGui.GetIO().FontGlobalScale, 0.1f, 2f, "%.2f"); ImGui.EndMainMenuBar(); } CustomEvent.Trigger(gameObject, "OnLayout"); }
/// <summary> /// Draw a preview graph texture on the preview pane /// </summary> /// <param name="plot">The graph being drawn</param> /// <param name="xPadding">horizontal padding</param> /// <param name="captionHeight">height of the caption</param> /// <param name="captionBackgroundcolor">contrast background colour of the caption</param> /// <param name="canHover">output flag states if we can safely draw a mouseover tooltip</param> /// <param name="mainWidgetSize">Size of the maingraph widget, used for projecting the zoom envelope</param> /// <returns>The graph was clicked</returns> private bool DrawPreviewGraph(PlottedGraph plot, float xPadding, float captionHeight, uint captionBackgroundcolor, out bool canHover, Vector2 mainWidgetSize) { ImDrawListPtr imdp = ImGui.GetWindowDrawList(); //draw on and clipped to this window bool clicked = false; canHover = false; if (plot == null) { return(clicked); } int graphNodeCount = plot.GraphNodeCount(); if (graphNodeCount == 0) { return(clicked); } plot.GetLatestTexture(out Texture previewTexture); if (previewTexture == null) { return(clicked); } bool isSelected = plot.TID == selectedGraphTID; canHover = true; //copy in the actual rendered graph ImGui.SetCursorPosY(ImGui.GetCursorPosY()); Vector2 subGraphPosition = ImGui.GetCursorScreenPos() + new Vector2(xPadding, 0); IntPtr CPUframeBufferTextureId = _ImGuiController !.GetOrCreateImGuiBinding(_gd !.ResourceFactory, previewTexture, $"PreviewPlot{plot.TID}"); imdp.AddImage(user_texture_id: CPUframeBufferTextureId, p_min: subGraphPosition, p_max: new Vector2(subGraphPosition.X + EachGraphWidth, subGraphPosition.Y + EachGraphHeight), uv_min: new Vector2(0, 1), uv_max: new Vector2(1, 0)); float borderThickness = Themes.GetThemeSize(Themes.eThemeSize.PreviewSelectedBorder); float halfBorderThickness = (float)Math.Floor(borderThickness / 2f); if (isSelected) { DrawPreviewZoomEnvelope(plot, subGraphPosition); //Draw the thicker selected graph border if (borderThickness > 0) { imdp.AddRect( p_min: new Vector2(subGraphPosition.X + halfBorderThickness, subGraphPosition.Y + halfBorderThickness), p_max: new Vector2((subGraphPosition.X + EachGraphWidth - halfBorderThickness), subGraphPosition.Y + EachGraphHeight - halfBorderThickness), col: GetGraphBorderColour(plot), 0, ImDrawFlags.None, borderThickness); } } //write the caption string Caption = $"TID:{plot.TID} {graphNodeCount} nodes {(isSelected ? "[Selected]" : "")}"; ImGui.SetCursorPosX(ImGui.GetCursorPosX()); Vector2 captionBGStart = subGraphPosition + new Vector2(borderThickness, borderThickness); Vector2 captionBGEnd = new Vector2((captionBGStart.X + EachGraphWidth - borderThickness * 2), captionBGStart.Y + captionHeight); imdp.AddRectFilled(p_min: captionBGStart, p_max: captionBGEnd, col: captionBackgroundcolor); ImGui.PushStyleColor(ImGuiCol.Text, Themes.GetThemeColourUINT(Themes.eThemeColour.PreviewText)); ImGui.SetCursorPosX(ImGui.GetCursorPosX() + CONSTANTS.UI.PREVIEW_PANE_X_PADDING + borderThickness + 1); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + borderThickness); ImGui.Text(Caption); ImGui.PopStyleColor(); ImGui.SetCursorPosX(ImGui.GetCursorPosX() + EachGraphWidth - 48); //live thread activity plot if (ActiveTrace is not null && !ActiveTrace.WasLoadedFromSave) { ImGui.SetCursorPosY(ImGui.GetCursorPosY() - captionHeight); float maxVal; float[]? invalues = null; if (plot.InternalProtoGraph.TraceReader != null) { plot.InternalProtoGraph.TraceReader.RecentMessageRates(out invalues); } if (invalues == null || invalues.Length == 0) { invalues = new List <float>() { 0, 0, 0, 0, 0 }.ToArray(); maxVal = 100; } else { maxVal = invalues.Max(); } ImGui.PushStyleColor(ImGuiCol.FrameBg, captionBackgroundcolor); ImGui.PlotLines("", ref invalues[0], invalues.Length, 0, "", 0, maxVal, new Vector2(40, captionHeight)); if (ImGui.IsItemHovered()) { canHover = false; //The PlotLines widget doesn't allow disabling the mouseover, so have to prevent our mousover to avoid a merged tooltip } ImGui.PopStyleColor(); } //invisible button to detect graph click ImGui.SetCursorPos(new Vector2(1, ImGui.GetCursorPosY() - (float)(captionHeight))); if (ImGui.InvisibleButton("PrevGraphBtn" + plot.TID, new Vector2(EachGraphWidth, EachGraphHeight - 2)) || ImGui.IsItemActive()) { clicked = true; if (isSelected) { Vector2 clickPos = ImGui.GetMousePos(); Vector2 clickOffset = clickPos - subGraphPosition; clickOffset.Y = EachGraphHeight - clickOffset.Y; plot.MoveCameraToPreviewClick(clickOffset, new Vector2(EachGraphWidth, EachGraphHeight), mainGraphWidgetSize: mainWidgetSize, PreviewProjection); } } return(clicked); }