tooltip :: (mouse: Vector2, text: string) { update_text_render :: () #expand { array_reset_keeping_memory(*`codepoints); array_reset_keeping_memory(*`offsets); `rect_padded = rect; `rect_padded.x += PADDING; `rect_padded.y += PADDING; `rect_padded.width -= PADDING; `text_height = wrap_text( GetFontDefault(), to_c_string(`text), *`codepoints, *`offsets, `rect_padded, `FONT_SIZE, `SPACING, `MY_COLOR ); } BACKGROUND :: Color.{ 34, 31, 45, 242 }; OFFSET :: Vector2.{ 24.0, 33.0 }; LINES :: Color.{ 99, 90, 122, 240 }; FONT_SIZE :: 20.0; SPACING :: 4.0; PADDING :: 16.0; MY_COLOR :: WHITE; rect: Rectangle; rect.x = mouse.x + OFFSET.x; rect.y = mouse.y + OFFSET.y; rect.width = #run 14.0 * 34; rect.height = #run PADDING * 1.5; codepoints: [..]s32; offsets: [..]Vector2; rect_padded: Rectangle; text_height: float; update_text_render(); rect.height += text_height; screen_w := cast(float) GetScreenWidth(); screen_h := cast(float) GetScreenHeight(); if rect.x + rect.width > screen_w { rect.x = mouse.x - OFFSET.x - rect.width; update_text_render(); } if rect.y + rect.height > screen_h { rect.y = mouse.y - OFFSET.y - rect.height; update_text_render(); } DrawRectangleRounded(rect, 0.1, 6, BACKGROUND); DrawRectangleRoundedLinesEx(rect, 0.1, 6, 1.0, LINES); draw_text( GetFontDefault(), codepoints, offsets, FONT_SIZE, SPACING, MY_COLOR ); } tooltip_text :: (index: int, value: int) -> string { node_type: string; bv_upper: string; bv_lower: string; sa_info: string; if index == 0 { node_type = "Root Node"; } else { if value == { case NODE_EMPTY; node_type = "Empty Node"; case NODE_INTERNAL; node_type = "Internal Node"; case; node_type = "Child Node"; bv := bvs[value]; bv_upper = tprint("\nBV Upper Bound: %", bv.upper_bound); bv_lower = tprint("\nBV Lower Bound: %", bv.lower_bound); sa := aabb_bv_compute_surface_area(bv); sa_info = tprint("\nSurface Area: %", sa); } } sb: String_Builder; print_to_builder(*sb, "Type: %\n", node_type); print_to_builder(*sb, "Index: %\n", index); append(*sb, bv_upper); append(*sb, bv_lower); append(*sb, sa_info); text := builder_to_string(*sb); return text; } #scope_file /** C R E D I T Original proc `wrap_text` is from: - @Raysan (Original Author), https://github.com/raysan5 - @ahmedqarmout2 (Jai Adoption), https://github.com/ahmedqarmout2 */ wrap_text :: ( font: Font, text: *u8, codepoints: *[..]s32, offsets: *[..]Vector2, rec: Rectangle, font_size: float, spacing: float, tint: Color, word_wrap: bool = true ) -> text_height: float { length: s32 = cast(s32)TextLength(text); text_offset_y: float = 0.0; text_offset_x: float = 0.0; scale_factor: float = font_size / cast(float)font.baseSize; my_enum :: enum { MEASURE_STATE :: 0; DRAW_STATE :: 1; } state: my_enum = ifx word_wrap then .MEASURE_STATE else .DRAW_STATE; start_line: s32 = -1; // Index where to begin drawing (where a line begins) end_line: s32 = -1; // Index where to stop drawing (where a line ends) lastk: s32 = -1; // Holds last value of the character position i: s32 = 0; k: s32 = 0; while i < length { defer i += 1; defer k += 1; codepoint_byte_count: s32 = 0; codepoint: s32 = GetCodepoint(*text[i], *codepoint_byte_count); index: s32 = GetGlyphIndex(font, codepoint); if codepoint == 0x3f then codepoint_byte_count = 1; i += (codepoint_byte_count - 1); glyph_width: float = 0; if codepoint != #char "\n" { glyph_width = ifx (font.glyphs[index].advanceX == 0) then font.recs[index].width * scale_factor else font.glyphs[index].advanceX * scale_factor; if (i + 1 < length) glyph_width = glyph_width + spacing; } if (state == .MEASURE_STATE) { if codepoint == #char " " || codepoint == #char "\t" || codepoint == #char "\n" then end_line = i; if text_offset_x + glyph_width > rec.width { end_line = ifx (end_line < 1) then i else end_line; if i == end_line then end_line -= codepoint_byte_count; if (start_line + codepoint_byte_count) == end_line then end_line = (i - codepoint_byte_count); state = ifx (state == .MEASURE_STATE) then .DRAW_STATE else .MEASURE_STATE; } else if i + 1 == length { end_line = i; state = ifx (state == .MEASURE_STATE) then .DRAW_STATE else .MEASURE_STATE; } else if codepoint == #char "\n" { state = ifx (state == .MEASURE_STATE) then .DRAW_STATE else .MEASURE_STATE; } if state == .DRAW_STATE { text_offset_x = 0; i = start_line; glyph_width = 0; tmp: s32 = lastk; lastk = k - 1; k = tmp; } } else { if codepoint == #char "\n" { if !word_wrap { text_offset_y += (font.baseSize + font.baseSize / 2) * scale_factor; text_offset_x = 0; } } else { if !word_wrap && text_offset_x + glyph_width > rec.width { text_offset_y += (font.baseSize + font.baseSize / 2) * scale_factor; text_offset_x = 0; } if codepoint != #char " " && codepoint != #char "\t" { array_add(codepoints, codepoint); array_add(offsets, { rec.x + text_offset_x, rec.y + text_offset_y }); } } if word_wrap && i == end_line { text_offset_y += (font.baseSize + font.baseSize / 2) * scale_factor; text_offset_x = 0; start_line = end_line; end_line = -1; glyph_width = 0; k = lastk; state = ifx (state == .MEASURE_STATE) then .DRAW_STATE else .MEASURE_STATE; } } if text_offset_x != 0 || codepoint != #char " " then text_offset_x += glyph_width; } return text_offset_y; } draw_text :: ( font: Font, codepoints: [..]s32, offsets: [..]Vector2, font_size: float, spacing: float, tint: Color ) { assert(codepoints.count == offsets.count); for codepoints { x := offsets[it_index].x; y := offsets[it_index].y; DrawTextCodepoint( font, it, { x, y }, font_size, tint ); } }