diff --git a/3d/flap.scad b/3d/flap.scad index 56fd9407..b1cbb8f7 100644 --- a/3d/flap.scad +++ b/3d/flap.scad @@ -22,6 +22,7 @@ use; use; character_list = get_character_list(); + color_list = [ ["p", [122, 40, 203] / 255], // #7a28cb ["r", [230, 57, 70] / 255], // "#e63946 @@ -30,6 +31,20 @@ color_list = [ ["w", [255, 255, 255] / 255], // "#ffffff ]; +// https://emojipedia.org/noto-emoji +// Needs to not overlap with color_list +emoji_list = [ + ["a", "\u2600"], // sun + ["b", "\u2601"], // cloud + ["c", "\U01F327"], // rain + ["d", "\u2744"], // snow + ["e", "\U01F32C"], // wind + ["f", "\u26C5"], // partly cloudy + ["h", "\U01F603"], // smiley with big eyes + ["i", "\u2639"], // frowning face + ["j", "\U01F525"], // fire + ["k", "\U01F90D"], // heart +]; // Facet number variable refers to a special variable "$fn" that is used to control the number of facets to generate an arc. // Higher than 100 is not recommended according to the docs as it demands a lot resources @@ -109,6 +124,8 @@ module _draw_letter(letter, flap_gap) { thickness_offset = is_undef(overrides[5]) ? (is_undef(get_font_setting("thickness_offset")) ? 0 : get_font_setting("thickness_offset")) : overrides[5]; color_index = search([letter], color_list); + emoji_index = search([letter], emoji_list); + if (len(color_index) > 0 && is_num(color_index[0])) { color_height = get_font_setting("color_height"); color_height_with_default = is_undef(color_height) ? height : color_height; @@ -117,6 +134,25 @@ module _draw_letter(letter, flap_gap) { translate([0, color_offset_y_with_default]) { square([flap_width - flap_notch_depth * 2 - 4, (flap_height * 2 + flap_gap) * color_height_with_default], center=true); } + } else if (len(emoji_index) > 0 && is_num(emoji_index[0])) { + // Re-calc for the emoji font + overrides = get_emoji_letter_overrides(emoji_list[emoji_index[0]][1]); + height = is_undef(overrides[3]) ? get_emoji_font_setting("height") : overrides[3]; + width = is_undef(overrides[4]) ? get_emoji_font_setting("width") : overrides[4]; + offset_x = is_undef(overrides[1]) ? get_emoji_font_setting("offset_x") : get_emoji_font_setting("offset_x") + overrides[1]; + offset_y = is_undef(overrides[2]) ? get_emoji_font_setting("offset_y") : get_emoji_font_setting("offset_y") + overrides[2]; + thickness_offset = is_undef(overrides[5]) ? (is_undef(get_emoji_font_setting("thickness_offset")) ? 0 : get_emoji_font_setting("thickness_offset")) : overrides[5]; + + translate([0, -flap_height * height, 0]) { + // valign compensation + scale([width, 1, 1]) { + translate([offset_x, offset_y]) { + offset(delta=thickness_offset) { + text(text=emoji_list[emoji_index[0]][1], size=flap_height * height * 2, font=get_emoji_font_setting("font"), halign="center", $fn=letter_facet_number); + } + } + } + } } else { translate([0, -flap_height * height, 0]) { // valign compensation scale([width, 1, 1]) { diff --git a/3d/flap_fonts.scad b/3d/flap_fonts.scad index 91d97e92..4f989eac 100644 --- a/3d/flap_fonts.scad +++ b/3d/flap_fonts.scad @@ -23,12 +23,16 @@ use; // fonts/PoiretOne/PoiretOne-Regular.ttf // fonts/Voltaire/Voltaire-Regular.otf // fonts/PTSansNarrow/PTSansNarrow-Regular.ttf +// fonts/Instruction/Instruction.otf +// fonts/NotoEmoji/NotoEmoji-Bold.ttf // ----------------------- // Configurable parameters // ----------------------- -font_preset = "Epilogue"; // See available presets below +font_preset = "Epilogue"; // See available presets below +font_emoji_preset = "NotoEmoji";// Font preset to use for emojis. Defaults to "NotoEmoji" which is a good emoji font. + letter_gap_comp = true; // Shifts letter positions to compensate for gap between flaps // --------------------------- @@ -48,6 +52,8 @@ letter_gap_comp = true; // Shifts letter positions to compensate for gap // Horizontal offset, in mm, of letters within flaps. A value of 0 uses default font centering. // 'offset_y' // Vertical offset, in mm, of letters within flaps. A value of 0 uses default font centering. +// 'thickness_offset' +// Vertical offset, in mm, of the thickness of the flap. A value of 0 uses default font thickness. // 'overrides' // Array of position/size overrides for specific letters. Each entry is a set of overrides for a single letter, // specified as an array with the following entries: @@ -57,6 +63,11 @@ letter_gap_comp = true; // Shifts letter positions to compensate for gap // - Height override, as a value relative to flap height (e.g. 0.7). Replaces letter_height for this letter. Can be undef to omit. // - Width override, as a value relative to default font width (e.g. 0.7). Replaces letter_width for this letter. Can be undef to omit. // - Thickness offset override. +// 'color_height' +// Height of the color bar relative to flap height. Defaults to 'height'. +// 'color_offset_y' +// Vertical offset of the color bar relative to flap height. Defaults to 'offset_y'. + _font_settings = [ "Roboto", [ "font", "RobotoCondensed", @@ -168,14 +179,53 @@ _font_settings = [ // "color_height", 0.455, // "color_offset_y", 1.4, ], + + "Instruction", [ + "font", "Instruction", + "height", .8, + "width", .9, + "offset_x", 4, + "offset_y", -.7, + "overrides", [ + // letter, x, y, height, width, thickness + ["-", undef, -7, undef, undef, undef], + [",", 14, 8, undef, undef, undef], + [".", 14, undef, undef, undef, undef], + ["!", 14, undef, undef, undef, undef], + ["'", 14, undef, undef, undef, undef], + [":", 14, 16, undef, undef, undef], + ], + ], + + "NotoEmoji", [ + "font", "NotoEmoji:style=Bold", + "height", .43, + "width", .85, + "offset_x", -.8, + "offset_y", 2, + "overrides", [ + // letter, x, y, height, width, thickness + ["\U01F525", undef, undef, .55, undef, undef], // Fire + ["\U01F90D", undef, undef, undef, .75, undef], // Heart + ["\u2601", undef, undef, undef, .75, undef], // Cloudy + ["\U01F327", undef, 5, undef, .8, undef], // Rain + ["\u2744", undef, -1, .55, .75, undef], // Snow + ["\U01F32C", undef, -2, undef, .72, undef], // Wind + ["\u26C5", undef, undef, undef, .73, undef], // Partly Cloudy + ], + ], ]; // Private functions function _get_entry_in_dict_array(arr, key) = search([key], arr) != [[]] ? arr[search([key], arr)[0] + 1] : undef; function _get_font_settings() = _get_entry_in_dict_array(_font_settings, font_preset); +function _get_emoji_font_settings() = _get_entry_in_dict_array(_font_settings, font_emoji_preset); // Public functions function use_letter_gap_compensation() = letter_gap_comp; function get_font_setting(key) = _get_entry_in_dict_array(_get_font_settings(), key); function get_letter_overrides(letter) = get_font_setting("overrides")[search([letter], get_font_setting("overrides"))[0]]; +function get_emoji_font_setting(key) = _get_entry_in_dict_array(_get_emoji_font_settings(), key); +function get_emoji_letter_overrides(letter) = + get_emoji_font_setting("overrides")[search([letter], get_emoji_font_setting("overrides"))[0]];