127 lines
4 KiB
OpenSCAD
127 lines
4 KiB
OpenSCAD
/* [Main settings] */
|
|
// path to the tab icon
|
|
icon = "icons/classes/Guardian.svg";
|
|
|
|
// number of tabs
|
|
tabs = 4;
|
|
// index of the tab, 0 for first tab. must be smaller than number of tabs
|
|
index = 0;
|
|
|
|
// generate a card for each tab index for testing overlap
|
|
test_tabs = false;
|
|
|
|
/* [Dimensions] */
|
|
|
|
// horizontal size of the card
|
|
horizontal = 87.0;
|
|
// vertical size of the card (not including the tab)
|
|
vertical = 61.0;
|
|
|
|
// width of the tab's top (excluding the slope)
|
|
tab_width = 16.0;
|
|
|
|
// height of the tab
|
|
tab_height = 10.0;
|
|
|
|
// angle of the slope. lower angle means steeper slope, i.e. 0 makes square tabs
|
|
tab_angle = 45; // [0:89]
|
|
|
|
// height of the icon (will be resized). Must be smaller than tab_height
|
|
target_icon_height = 9.0;
|
|
// width of the icon. If set to zero, will keep aspect, but may cause it to be off center if it isn't square
|
|
target_icon_width = 0.0;
|
|
|
|
base_color = "black";
|
|
icon_color = "lime";
|
|
|
|
/* [Hidden] */
|
|
$fa = 1;
|
|
$fs = 0.4;
|
|
|
|
module outer_tab(tab_height = 10, tab_width = 16, tab_angle = 45, flip = false)
|
|
{
|
|
slope_width = tab_height * tan(tab_angle);
|
|
tab = ([
|
|
[ 0, 0 ],
|
|
[ 0, tab_height ],
|
|
[ tab_width, tab_height ],
|
|
[ tab_width + slope_width, 0 ],
|
|
]);
|
|
|
|
if (flip)
|
|
{
|
|
translate([ tab_width + slope_width, 0, 0 ]) mirror([ 1, 0, 0 ]) polygon(tab);
|
|
}
|
|
else
|
|
{
|
|
polygon(tab);
|
|
}
|
|
}
|
|
|
|
module inner_tab(tab_height = 10, tab_width = 16, tab_angle = 45)
|
|
{
|
|
slope_width = tab_height * tan(tab_angle);
|
|
tab = ([
|
|
[ 0, 0 ],
|
|
[ slope_width, tab_height ],
|
|
[ tab_width + slope_width, tab_height ],
|
|
[ tab_width + 2 * slope_width, 0 ],
|
|
]);
|
|
polygon(tab);
|
|
}
|
|
|
|
module card(index = 0, thickness = 0.6, icon = "", icon_thickness = 0.4, horizontal = 87, vertical = 61, tabs = 4,
|
|
tab_height = 10, tab_width = 16, tab_angle = 45, target_icon_height = 9, target_icon_width = 9)
|
|
{
|
|
assert(0 <= index && index < tabs, str("Tab index out of range. Index: ", index, " Tabs: ", tabs));
|
|
assert(target_icon_height <= tab_height, str("Icon larger than tab!"));
|
|
|
|
is_inner = index > 0 && index < tabs - 1;
|
|
|
|
tab_spacing = (horizontal - tabs * tab_width) / (tabs - 1);
|
|
assert(tab_spacing >= 0, "Card width is too small for the number and width of tabs.");
|
|
|
|
position = index * (tab_width + tab_spacing);
|
|
slope_width = tab_height * tan(tab_angle);
|
|
indent = index == 0 ? 0 : (tab_width + tab_spacing) * index - slope_width;
|
|
|
|
color(base_color) linear_extrude(thickness)
|
|
{
|
|
square([ horizontal, vertical ]);
|
|
translate([ indent, vertical, 0 ])
|
|
{
|
|
if (is_inner)
|
|
inner_tab(tab_height, tab_width, tab_angle);
|
|
else
|
|
outer_tab(tab_height, tab_width, tab_angle, index == tabs - 1);
|
|
}
|
|
}
|
|
if (icon != "")
|
|
{
|
|
// If no icon width is given, we assume the icon is square.
|
|
icon_width = (target_icon_width == 0 ? target_icon_height : target_icon_width);
|
|
icon_x_offset = (index > 0 ? slope_width : 0) + tab_width / 2 - icon_width / 2;
|
|
icon_y_offset = tab_height / 2 - target_icon_height / 2;
|
|
translate([ indent + icon_x_offset, vertical + icon_y_offset, thickness ]) color(icon_color)
|
|
linear_extrude(icon_thickness) resize([ target_icon_width, target_icon_height, 0 ], auto = true)
|
|
offset(delta = 0.001) import(icon);
|
|
}
|
|
}
|
|
|
|
if (test_tabs)
|
|
{
|
|
for (idx = [0:tabs - 1])
|
|
{
|
|
translate([ 0, 0, idx ])
|
|
card(index = idx, icon = icon, horizontal = horizontal, vertical = vertical, tab_width = tab_width,
|
|
tabs = tabs, tab_height = tab_height, tab_angle = tab_angle, target_icon_height = target_icon_height,
|
|
target_icon_width = target_icon_width);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
card(index, icon = icon, horizontal = horizontal, vertical = vertical, tab_width = tab_width, tabs = tabs,
|
|
tab_height = tab_height, tab_angle = tab_angle, target_icon_height = target_icon_height,
|
|
target_icon_width = target_icon_width);
|
|
}
|