diff --git a/divider.scad b/divider.scad index e27d44a..d7d6332 100644 --- a/divider.scad +++ b/divider.scad @@ -1,11 +1,42 @@ +/* [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; -index = 0; -icon = "icons/classes/Mystic.svg"; - -tab_offset = 14; -target_icon_height = 9; -target_icon_width = 9; module outer_tab(tab_height = 10, tab_width = 16, tab_angle = 45, flip = false) { @@ -39,46 +70,11 @@ module inner_tab(tab_height = 10, tab_width = 16, tab_angle = 45) polygon(tab); } -module card(index = 0, thickness = 0.6, icon = "", icon_thickness = 0.4, horizontal = 87, vertical = 61, - tab_height = 10, tab_width = 16, tab_angle = 45) -{ - slope_width = tab_height * tan(tab_angle); - is_inner = index > 0 && index < 3; - inner_tab_width = tab_width + 2 * slope_width; - outer_tab_width = tab_width + slope_width; - positions = [ - 0, - tab_offset, - horizontal - tab_offset - inner_tab_width, - horizontal - outer_tab_width, - ]; - - linear_extrude(thickness) - { - square([ horizontal, vertical ]); - translate([ positions[index], vertical, 0 ]) - { - if (is_inner) - inner_tab(tab_height, tab_width, tab_angle); - else - outer_tab(tab_height, tab_width, tab_angle, index == 3); - } - } - 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_offset = (index > 0 ? slope_width : 0) + tab_width / 2 - icon_width / 2; - translate([ positions[index] + icon_offset, vertical + 0.5, thickness - 0.001 ]) color("blue") - linear_extrude(icon_thickness + 0.001) resize([ target_icon_width, target_icon_height, 0 ], auto = true) - offset(delta = 0.001) import(icon); - } -} - -module card2(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) +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; @@ -89,7 +85,7 @@ module card2(index = 0, thickness = 0.6, icon = "", icon_thickness = 0.4, horizo slope_width = tab_height * tan(tab_angle); indent = index == 0 ? 0 : (tab_width + tab_spacing) * index - slope_width; - color("black") linear_extrude(thickness) + color(base_color) linear_extrude(thickness) { square([ horizontal, vertical ]); translate([ indent, vertical, 0 ]) @@ -106,16 +102,26 @@ module card2(index = 0, thickness = 0.6, icon = "", icon_thickness = 0.4, horizo 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 - 0.001 ]) color("lime") - linear_extrude(icon_thickness + 0.001) resize([ target_icon_width, target_icon_height, 0 ], auto = true) + 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); } } -card(index, icon = icon, horizontal = 61, vertical = 87); -translate([ 100, 0, 0 ]) +if (test_tabs) { - card2(index + 0, icon = icon, horizontal = 61, vertical = 87, tab_width = 16, tabs = 3, tab_angle = 30); - card2(index + 1, icon = icon, horizontal = 61, vertical = 87, tab_width = 16, tabs = 3, tab_angle = 30); - card2(index + 2, icon = icon, horizontal = 61, vertical = 87, tab_width = 16, tabs = 3, tab_angle = 30); + 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); } diff --git a/generate.zsh b/generate.zsh index 73ac11a..4f5da7a 100755 --- a/generate.zsh +++ b/generate.zsh @@ -1,29 +1,57 @@ #!/bin/zsh -zparseopts -D -E -tabs:=tabs -vertical=vertical +zparseopts -D -E -vertical=vertical + +get-icon-size() { + xmllint --xpath 'string(/*[local-name()="svg"]/@viewBox)' $1 | cut -d' ' -f3,4 +} -tabs=${tabs[2]:-4} index=0 -scad_args=( - -D "icon=\"$icon\"" - -D "index=$index" -) +scad_args=() if [[ $vertical ]]; then - scad_args+=(-D "vertical=87.0" -D "horizontal=61.0") + scad_args+=(-D "vertical=87.0" -D "horizontal=61.0" -D "tabs=3" -D "tab_angle=30" -D "tab_width=14") out_basedir=generated/vertical + tabs=3 else out_basedir=generated/horizontal + tabs=4 fi -if [[ ! -d $1 ]]; then - echo "Usage: $0 [--tabs ]" +if [[ -d $1 ]]; then + files=($1/*.svg) +else + files=($@) fi -for icon in $1/*.svg; do +for icon in $files; do target=$out_basedir/${${icon#*/}:r}.3mf mkdir -p ${target:h} + + size=( $(get-icon-size $icon) ) + if (( size[1] < size[2] )); then + scale_factor=$(( 9.0 / size[2] )) + echo "Scaling factor: $scale_factor" + width=$(( size[1] * scale_factor )) + echo "Width: $width" + scad_args+=(-D "target_icon_width=${width}" -D "target_icon_height=9") + echo "\e[1;33mIcon size: ${size[1]} x ${size[2]}; scaled to $width x 9\e[0m" + else + scale_factor=$(( 9.0 / size[1] )) + echo "Scaling factor: $scale_factor" + height=$(( size[2] * scale_factor )) + echo "Height: $height" + scad_args+=(-D "target_icon_width=9" -D "target_icon_height=${height}") + echo "\e[1;33mIcon size: ${size[1]} x ${size[2]}; scaled to 9 x $height\e[0m" + fi + echo "Generating card $icon with tab index $index" - colorscad -o $target -i divider.scad -- ${scad_args[@]} + scad_out=$(colorscad -o $target -i divider.scad -- -D "index=$index" -D "icon=\"$icon\"" ${scad_args[@]}) + if [[ $? -ne 0 ]]; then + echo "\e[1;31mError generating $target\e[0m" + echo "$scad_out" + continue + fi + (( index = (index + 1) % tabs )) done