public ImFontConfig() { Face = null; FontData = null; FontDataSize = 0; FontDataOwnedByAtlas = true; FontNo = 0; SizePixels = 0.0f; OversampleH = 3; OversampleV = 1; PixelSnapH = false; GlyphExtraSpacing = new ImVec2(0.0f, 0.0f); GlyphRanges = null; MergeMode = false; MergeGlyphCenterV = false; DstFont = null; //memset(Name, 0, sizeof(Name)); Name = null; }
public void Add(ImVec2 rhs) { if (Min.x > rhs.x) { Min.x = rhs.x; } if (Min.y > rhs.y) { Min.y = rhs.y; } if (Max.x < rhs.x) { Max.x = rhs.x; } if (Max.y < rhs.y) { Max.y = rhs.y; } }
internal float[] KeysDownDurationPrev = new float[512]; // Previous duration the key has been down internal ImGuiIO() { DisplaySize = new ImVec2(-1.0f, -1.0f); DeltaTime = 1.0f / 60.0f; IniSavingRate = 5.0f; IniFilename = "imgui.ini"; LogFilename = "imgui_log.txt"; //TODO: We can't access instance here because it will get in a ctor loop, Fonts = ImGui.Instance.ImDefaultFontAtlas; Fonts = ImGui.ImDefaultFontAtlas; FontGlobalScale = 1.0f; DisplayFramebufferScale = new ImVec2(1.0f, 1.0f); MousePos = new ImVec2(-1, -1); MousePosPrev = new ImVec2(-1, -1); MouseDoubleClickTime = 0.30f; MouseDoubleClickMaxDist = 6.0f; MouseDragThreshold = 6.0f; for (int i = 0; i < MouseDownDuration.Length; i++) { MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; } for (int i = 0; i < KeysDownDuration.Length; i++) { KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f; } for (int i = 0; i < (int)ImGuiKey.ImGuiKey_COUNT; i++) { KeyMap[i] = -1; } KeyRepeatDelay = 0.500f; KeyRepeatRate = 0.070f; //TODO: UserData = null; // User functions RenderDrawListsFn = null; GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl; }
public ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) { if (!on_edge && Contains(p)) { return(p); } if (p.x > Max.x) { p.x = Max.x; } else if (p.x < Min.x) { p.x = Min.x; } if (p.y > Max.y) { p.y = Max.y; } else if (p.y < Min.y) { p.y = Min.y; } return(p); }
void RenderCustomTexData(MaxRectsBinPack spc, int pass, ImVector <ImFontPackingRect> rects) { // A work of art lies ahead! (. = white layer, X = black layer, others are blank) // The white texels on the top left are the ones we'll use everywhere in ImGui to render filled shapes. const int TEX_DATA_W = 90; const int TEX_DATA_H = 27; const string texture_data = "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX" + "..- -X.....X- X.X - X.X -X.....X - X.....X" + "--- -XXX.XXX- X...X - X...X -X....X - X....X" + "X - X.X - X.....X - X.....X -X...X - X...X" + "XX - X.X -X.......X- X.......X -X..X.X - X.X..X" + "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X" + "X..X - X.X - X.X - X.X -XX X.X - X.X XX" + "X...X - X.X - X.X - XX X.X XX - X.X - X.X " + "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X " + "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X " + "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X " + "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X " + "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X " + "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X " + "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X " + "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X " + "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX " + "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------" + "X.X X..X - -X.......X- X.......X - XX XX - " + "XX X..X - - X.....X - X.....X - X.X X.X - " + " X..X - X...X - X...X - X..X X..X - " + " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - " + "------------ - X - X -X.....................X- " + " ----------------------------------- X...XXXXXXXXXXXXX...X - " + " - X..X X..X - " + " - X.X X.X - " + " - XX XX - "; //ImVector < stbrp_rect > &rects = *(ImVector<stbrp_rect>*)p_rects; if (pass == 0) { // Request rectangles var custom = new ImFontPackingRect(); custom.w = TEX_DATA_W * 2 + 1; custom.h = TEX_DATA_H + 1; rects.push_back(custom); custom.pack(spc); } else if (pass == 1) { // Render/copy pixels //the first rect in rects will always be custom font data var r = rects[0]; for (int y = 0, n = 0; y < TEX_DATA_H; y++) { for (int x = 0; x < TEX_DATA_W; x++, n++) { int offset0 = (r.x + x) + (r.y + y) * TexWidth; int offset1 = offset0 + 1 + TEX_DATA_W; TexPixelsAlpha8[offset0] = (byte)(texture_data[n] == '.' ? 0xFF : 0x00); TexPixelsAlpha8[offset1] = (byte)(texture_data[n] == 'X' ? 0xFF : 0x00); } } ImVec2 tex_uv_scale = new ImVec2(1.0f / TexWidth, 1.0f / TexHeight); TexUvWhitePixel = new ImVec2((r.x + 0.5f) * tex_uv_scale.x, (r.y + 0.5f) * tex_uv_scale.y); //TODO: Finish render custom text //// Setup mouse cursors var cursor_datas = new ImVec2[, ] { // Pos ........ Size ......... Offset ...... { new ImVec2(0, 3), new ImVec2(12, 19), new ImVec2(0, 0) }, // ImGuiMouseCursor_Arrow { new ImVec2(13, 0), new ImVec2(7, 16), new ImVec2(4, 8) }, // ImGuiMouseCursor_TextInput { new ImVec2(31, 0), new ImVec2(23, 23), new ImVec2(11, 11) }, // ImGuiMouseCursor_Move { new ImVec2(21, 0), new ImVec2(9, 23), new ImVec2(5, 11) }, // ImGuiMouseCursor_ResizeNS { new ImVec2(55, 18), new ImVec2(23, 9), new ImVec2(11, 5) }, // ImGuiMouseCursor_ResizeEW { new ImVec2(73, 0), new ImVec2(17, 17), new ImVec2(9, 9) }, // ImGuiMouseCursor_ResizeNESW { new ImVec2(55, 0), new ImVec2(17, 17), new ImVec2(9, 9) }, // ImGuiMouseCursor_ResizeNWSE }; for (int type = 0; type < 7; type++) { ImGuiMouseCursorData cursor_data = ImGui.Instance.State.MouseCursorData[type]; ImVec2 pos = cursor_datas[type, 0] + new ImVec2((float)r.x, (float)r.y); ImVec2 size = cursor_datas[type, 1]; cursor_data.Type = (ImGuiMouseCursor)type; cursor_data.Size = size; cursor_data.HotOffset = cursor_datas[type, 2]; cursor_data.TexUvMin[0] = (pos) * tex_uv_scale; cursor_data.TexUvMax[0] = (pos + size) * tex_uv_scale; pos.x += TEX_DATA_W + 1; cursor_data.TexUvMin[1] = (pos) * tex_uv_scale; cursor_data.TexUvMax[1] = (pos + size) * tex_uv_scale; } } }
//public ImRect[] PackFont(MaxRectsBinPack packer, Texture2D texture, Texture2D[] textures, int width, int height, int maxSize) //{ // if (width > maxSize && height > maxSize) return null; // if (width > maxSize || height > maxSize) { int temp = width; width = height; height = temp; } // MaxRectsBinPack bp = new MaxRectsBinPack(width, height); // ImRect[] rects = new ImRect[textures.Length]; // for (int i = 0; i < textures.Length; i++) // { // Texture2D tex = textures[i]; // ImRect rect = bp.Insert(tex.width, tex.height, MaxRectsBinPack.FreeRectChoiceHeuristic.RectBestAreaFit); // if (rect.width == 0 || rect.height == 0) // { // return PackTextures(texture, textures, width * (width <= height ? 2 : 1), height * (height < width ? 2 : 1), maxSize); // } // rects[i] = rect; // } // texture.Resize(width, height); // texture.SetPixels(new ImColor[width * height]); // for (int i = 0; i < textures.Length; i++) // { // Texture2D tex = textures[i]; // ImRect rect = rects[i]; // ImColor[] colors = tex.GetPixels(); // if (rect.width != tex.width) // { // ImColor[] newColors = tex.GetPixels(); // for (int x = 0; x < rect.width; x++) // { // for (int y = 0; y < rect.height; y++) // { // int prevIndex = ((int)rect.height - (y + 1)) + x * (int)tex.width; // newColors[x + y * (int)rect.width] = colors[prevIndex]; // } // } // colors = newColors; // } // texture.SetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height, colors); // rect.x /= width; // rect.y /= height; // rect.width /= width; // rect.height /= height; // rects[i] = rect; // } // return rects; //} internal bool Build() { System.Diagnostics.Debug.Assert(ConfigData.Size > 0); TexID = null; TexWidth = TexHeight = 0; TexUvWhitePixel = new ImVec2(0, 0); ClearTexData(); int total_glyph_count = 0; int total_glyph_range_count = 0; for (int input_i = 0; input_i < ConfigData.Size; input_i++) { ImFontConfig cfg = ConfigData[input_i]; System.Diagnostics.Debug.Assert(cfg.DstFont != null && (!cfg.DstFont.IsLoaded() || cfg.DstFont.ContainerAtlas == this)); System.Diagnostics.Debug.Assert(cfg.FontData != null); // Count glyphs if (cfg.GlyphRanges == null) { cfg.GlyphRanges = GetGlyphRangesDefault(); } for (int in_range = 0; cfg.GlyphRanges[in_range] > 0 && cfg.GlyphRanges[in_range + 1] > 0; in_range += 2) { total_glyph_count += (cfg.GlyphRanges[in_range + 1] - cfg.GlyphRanges[in_range]) + 1; total_glyph_range_count++; } } // Start packing. We need a known width for the skyline algorithm. Using a cheap heuristic here to decide of width. User can override TexDesiredWidth if they wish. // After packing is done, width shouldn't matter much, but some API/GPU have texture size limitations and increasing width can decrease height. TexWidth = (TexDesiredWidth > 0) ? TexDesiredWidth : (total_glyph_count > 4000) ? 4096 : (total_glyph_count > 2000) ? 2048 : (total_glyph_count > 1000) ? 1024 : 512; TexHeight = 0; int max_tex_height = 1024 * 32; var spc = new MaxRectsBinPack(TexWidth, max_tex_height, false); ImVector <ImFontPackingRect> rects = new ImVector <ImFontPackingRect>(); RenderCustomTexData(spc, 0, rects); // First font pass: pack all glyphs (no rendering at this point, we are working with rectangles in an infinitely tall texture at this point) for (int input_i = 0; input_i < ConfigData.Size; input_i++) { ImFontConfig cfg = ConfigData[input_i]; cfg.Face.SetPixelSizes((uint)(cfg.SizePixels * cfg.OversampleH), (uint)(cfg.SizePixels * cfg.OversampleV)); for (int in_range = 0; cfg.GlyphRanges[in_range] > 0 && cfg.GlyphRanges[in_range + 1] > 0; in_range += 2) { var glyphs = new List <ImRect>((cfg.GlyphRanges[in_range + 1] - cfg.GlyphRanges[in_range]) + 1); var packedGlyphs = new List <ImRect>((cfg.GlyphRanges[in_range + 1] - cfg.GlyphRanges[in_range]) + 1); for (var range = cfg.GlyphRanges[in_range]; range <= cfg.GlyphRanges[in_range + 1]; range++) { char c = (char)range; uint glyphIndex = cfg.Face.GetCharIndex(c); cfg.Face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); //added padding to keep from bleeding glyphs.Add(new ImRect(0, 0, (int)cfg.Face.Glyph.Metrics.Width + 2, (int)cfg.Face.Glyph.Metrics.Height + 2)); spc.Insert((int)cfg.Face.Glyph.Metrics.Width + 2, (int)cfg.Face.Glyph.Metrics.Height + 2, MaxRectsBinPack.FreeRectChoiceHeuristic.RectBestAreaFit); } spc.Insert(glyphs, packedGlyphs, MaxRectsBinPack.FreeRectChoiceHeuristic.RectBestAreaFit); System.Diagnostics.Debug.Assert(glyphs.Count == packedGlyphs.Count); for (var i = 0; i < glyphs.Count; i++) { var c = (cfg.GlyphRanges[in_range] + i); var g = glyphs[i]; var pg = packedGlyphs[i]; var was_packed = pg.width > 0 && pg.height > 0; var r = new ImFontPackingRect() { id = c, x = (int)pg.x + 1, y = (int)pg.y + 1, w = (int)pg.width, h = (int)pg.height, was_packed = was_packed }; if (was_packed) { TexHeight = ImGui.Max(TexHeight, r.y + r.h); } rects.push_back(r); } } } // Create texture TexHeight = ImGui.UpperPowerOfTwo(TexHeight); TexPixelsAlpha8 = new byte[TexWidth * TexHeight]; for (int input_i = 0; input_i < ConfigData.Size; input_i++) { ImFontConfig cfg = ConfigData[input_i]; ImFont dst_font = cfg.DstFont; int unscaled_ascent = cfg.Face.Ascender, unscaled_descent = cfg.Face.Descender; float font_scale = cfg.SizePixels / (unscaled_ascent - unscaled_descent); //taken from stbtt_ScaleForPixelHeight var max_height = cfg.Face.Height * font_scale; float ascent = unscaled_ascent * font_scale; float descent = unscaled_descent * font_scale; if (!cfg.MergeMode) { dst_font.ContainerAtlas = this; dst_font.ConfigData = cfg; dst_font.ConfigDataCount = 0; dst_font.FontSize = cfg.SizePixels; dst_font.Ascent = ascent; dst_font.Descent = descent; dst_font.Glyphs.resize(0); } dst_font.ConfigDataCount++; float off_y = (cfg.MergeMode && cfg.MergeGlyphCenterV) ? (ascent - dst_font.Ascent) * 0.5f : 0.0f; //render for (var i = 0; i < rects.Size; i++) { var rect = rects[i]; //if (rect.id > 0 /*&& rect.was_packed*/) { var codepoint = (ushort)rect.id; if (cfg.MergeMode && dst_font.HasGlyph((char)codepoint)) { continue; } uint glyphIndex = cfg.Face.GetCharIndex(codepoint); cfg.Face.LoadGlyph(glyphIndex, LoadFlags.Render, LoadTarget.Normal); cfg.Face.Glyph.RenderGlyph(RenderMode.Normal); var bmp = cfg.Face.Glyph.Bitmap; for (var x = 0; x < bmp.Width; x++) { for (var y = 0; y < bmp.Rows; y++) { TexPixelsAlpha8[(rect.x + x) + ((rect.y + y) * TexWidth)] = bmp.BufferData[x + y * bmp.Pitch]; } } } } cfg.Face.SetPixelSizes((uint)cfg.SizePixels, (uint)cfg.SizePixels); //need to calculate origin/baseline var top = 0f; var bot = 0f; for (var i = 0; i < rects.Size; i++) { var rect = rects[i]; //if (rect.id > 0 /*&& rect.was_packed*/) { var codepoint = (ushort)rect.id; if (cfg.MergeMode && dst_font.HasGlyph((char)codepoint)) { continue; } uint glyphIndex = cfg.Face.GetCharIndex(codepoint); cfg.Face.LoadGlyph(glyphIndex, LoadFlags.ComputeMetrics, LoadTarget.Normal); var glyphTop = (float)cfg.Face.Glyph.Metrics.HorizontalBearingY; var glyphBot = (float)(cfg.Face.Glyph.Metrics.Height - cfg.Face.Glyph.Metrics.HorizontalBearingY); if (glyphTop > top) { top = glyphTop; } if (glyphBot > bot) { bot = glyphBot; } } } //dst_font.FallbackGlyph = null; // Always clear fallback so FindGlyph can return NULL. It will be set again in BuildLookupTable() for (var i = 0; i < rects.Size; i++) { var rect = rects[i]; //if (rect.id > 0 /*&& rect.was_packed*/) { var codepoint = (ushort)rect.id; if (cfg.MergeMode && dst_font.HasGlyph((char)codepoint)) { continue; } uint glyphIndex = cfg.Face.GetCharIndex(codepoint); cfg.Face.LoadGlyph(glyphIndex, LoadFlags.ComputeMetrics, LoadTarget.Normal); dst_font.Glyphs.resize(dst_font.Glyphs.Size + 1); var glyph = dst_font.Glyphs[dst_font.Glyphs.Size - 1]; glyph.Codepoint = codepoint; glyph.X0 = (int)cfg.Face.Glyph.Metrics.HorizontalBearingX + (float)cfg.Face.Glyph.BitmapLeft; glyph.X1 = (int)cfg.Face.Glyph.Metrics.Width + glyph.X0; glyph.Y0 = top - (float)cfg.Face.Glyph.Metrics.HorizontalBearingY; glyph.Y1 = glyph.Y0 + (float)cfg.Face.Glyph.Metrics.Height; glyph.U0 = rect.x / (float)TexWidth; glyph.V0 = rect.y / (float)TexHeight; glyph.U1 = (rect.x + rect.w) / (float)TexWidth; glyph.V1 = (rect.y + rect.h) / (float)TexHeight; glyph.XAdvance = ((int)cfg.Face.Glyph.Metrics.HorizontalAdvance + cfg.GlyphExtraSpacing.x); // Bake spacing into XAdvance if (cfg.PixelSnapH) { glyph.XAdvance = (int)(glyph.XAdvance + 0.5f); } dst_font.Glyphs[dst_font.Glyphs.Size - 1] = glyph; } } cfg.DstFont.BuildLookupTable(); } // Cleanup temporaries //ImGui::MemFree(buf_packedchars); //ImGui::MemFree(buf_ranges); //ImGui::MemFree(tmp_array); // Render into our custom data block RenderCustomTexData(spc, 1, rects); return(true); }
} // Bottom-right public bool Contains(ImVec2 p) { return(p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y); }
public ImRect(ImVec2 min, ImVec2 max) { Min = min; Max = max; }
public void Reduce(ImVec2 amount) { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; }
public void Expand(ImVec2 amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
/// <summary> /// Returns a boolean indicating whether the given Vector3 is equal to this Vector3 instance. /// </summary> /// <param name="other">The Vector3 to compare this instance to.</param> /// <returns>True if the other Vector3 is equal to this instance; False otherwise.</returns> public bool Equals(ImVec2 other) { return(x == other.x && y == other.y); }
internal char[] TempBuffer = new char[1024 * 3 + 1]; // temporary text buffer internal ImGuiState() { IO = new ImGuiIO(); Style = new ImGuiStyle(); Windows = new ImVector <ImGuiWindow>(); WindowsSortBuffer = new ImVector <ImGuiWindow>(); CurrentWindowStack = new ImVector <ImGuiWindow>(); Settings = new ImVector <ImGuiIniData>(); ColorModifiers = new ImVector <ImGuiColMod>(); StyleModifiers = new ImVector <ImGuiStyleMod>(); FontStack = new ImVector <ImFont>(); OpenedPopupStack = new ImVector <ImGuiPopupRef>(); CurrentPopupStack = new ImVector <ImGuiPopupRef>(); RenderDrawData = new ImDrawData(); for (var i = 0; i < RenderDrawLists.Length; i++) { RenderDrawLists[i] = new ImVector <ImDrawList>(); } OverlayDrawList = new ImDrawList(); ColorEditModeStorage = new ImGuiStorage(); for (var i = 0; i < MouseCursorData.Length; i++) { MouseCursorData[i] = new ImGuiMouseCursorData(); } InputTextState = new ImGuiTextEditState(); Initialized = false; Font = null; FontSize = FontBaseSize = 0.0f; FontTexUvWhitePixel = new ImVec2(0.0f, 0.0f); Time = 0.0f; FrameCount = 0; FrameCountEnded = FrameCountRendered = -1; CurrentWindow = null; FocusedWindow = null; HoveredWindow = null; HoveredRootWindow = null; HoveredId = 0; HoveredIdAllowOverlap = false; HoveredIdPreviousFrame = 0; ActiveId = 0; ActiveIdPreviousFrame = 0; ActiveIdIsAlive = false; ActiveIdIsJustActivated = false; ActiveIdAllowOverlap = false; ActiveIdWindow = null; MovedWindow = null; SettingsDirtyTimer = 0.0f; SetNextWindowPosVal = new ImVec2(0.0f, 0.0f); SetNextWindowSizeVal = new ImVec2(0.0f, 0.0f); SetNextWindowCollapsedVal = false; SetNextWindowPosCond = 0; SetNextWindowSizeCond = 0; SetNextWindowContentSizeCond = 0; SetNextWindowCollapsedCond = 0; SetNextWindowFocus = false; SetNextTreeNodeOpenedVal = false; SetNextTreeNodeOpenedCond = 0; ScalarAsInputTextId = 0; ActiveClickDeltaToCenter = new ImVec2(0.0f, 0.0f); DragCurrentValue = 0.0f; DragLastMouseDelta = new ImVec2(0.0f, 0.0f); DragSpeedDefaultRatio = 0.01f; DragSpeedScaleSlow = 0.01f; DragSpeedScaleFast = 10.0f; ScrollbarClickDeltaToGrabCenter = new ImVec2(0.0f, 0.0f); //memset(Tooltip, 0, sizeof(Tooltip)); PrivateClipboard = null; OsImePosRequest = OsImePosSet = new ImVec2(-1.0f, -1.0f); ModalWindowDarkeningRatio = 0.0f; OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging MouseCursor = ImGuiMouseCursor.ImGuiMouseCursor_Arrow; //memset(MouseCursorData, 0, sizeof(MouseCursorData)); LogEnabled = false; //LogFile = null; //TODO: LogClipboard = null; LogStartDepth = 0; LogAutoExpandMaxDepth = 2; //memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); FramerateSecPerFrameIdx = 0; FramerateSecPerFrameAccum = 0.0f; CaptureMouseNextFrame = CaptureKeyboardNextFrame = -1; //memset(TempBuffer, 0, sizeof(TempBuffer)); }