Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions 3d/flap.scad
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use<flap_characters.scad>;
use<splitflap.scad>;

character_list = get_character_list();

color_list = [
["p", [122, 40, 203] / 255], // #7a28cb
["r", [230, 57, 70] / 255], // "#e63946
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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]) {
Expand Down
52 changes: 51 additions & 1 deletion 3d/flap_fonts.scad
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@ use<fonts/Epilogue/Epilogue-VariableFont_wght.ttf>;
// 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

// ---------------------------
Expand All @@ -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:
Expand All @@ -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",
Expand Down Expand Up @@ -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]];
Loading