mirror of
https://github.com/rsheldiii/KeyV2.git
synced 2026-01-15 06:47:54 -05:00
Compare commits
10 Commits
github-des
...
custom-ste
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd68c281c3 | ||
|
|
24e280fe3c | ||
|
|
69175f08e4 | ||
|
|
f4f595c651 | ||
|
|
fa49ee0c70 | ||
|
|
9e3f5f4bcd | ||
|
|
c7602e2ce9 | ||
|
|
f98c0d4a4f | ||
|
|
18892c02b0 | ||
|
|
9cb3e12b9b |
@@ -60,7 +60,7 @@ You can chain as many modifier functions as you like!
|
||||
|
||||
## Modifier functions
|
||||
|
||||
There is a bevy of supporting functions to customize your keycaps. You can add a brim to more easily print the stem with `brimmed_stem_support`, make 2x2 keycaps with `2u() 2uh()`, add legends, rotate stems, and more. All these functions manipulate the settings available to you in [`settings.scad`](https://github.com/rsheldiii/KeyV2/blob/master/src/settings.scad), though [some of them](https://github.com/rsheldiii/KeyV2/blob/master/src/key_transformations.scad#L128) are quite complex.
|
||||
There is a bevy of supporting functions to customize your keycaps. You can add a brim to more easily print the stem with `brimmed_stem_support`, make 2x2 keycaps with `2u() 2uh()`, add legends, rotate stems, and more. All these functions manipulate the settings available to you in [`settings.scad`](https://github.com/rsheldiii/KeyV2/blob/master/src/settings.scad), though [some of them](https://github.com/rsheldiii/KeyV2/blob/851ececdb297c77bfbcd0a7cb4cdbc5e21970396/src/key_transformations.scad#L128) are quite complex.
|
||||
|
||||
These modifier functions can be found in [`key_profiles/`](https://github.com/rsheldiii/KeyV2/blob/master/src/key_profiles) for different keycap profiles, [`key_types.scad`](https://github.com/rsheldiii/KeyV2/blob/master/src/key_types.scad) for predefined settings for common keys (spacebar, left shift, etc), [`key_sizes.scad`](https://github.com/rsheldiii/KeyV2/blob/master/src/key_sizes.scad) for common unit sizes, and [`key_transformations.scad`](https://github.com/rsheldiii/KeyV2/blob/master/src/key_transformations.scad) for everything else. I encourage you to do some sleuthing but for a list of (most) helper functions with explanations, [Check out the wiki!](https://github.com/rsheldiii/KeyV2/wiki/KeyV2-Helper-Documentation)
|
||||
|
||||
|
||||
769
customizer.scad
769
customizer.scad
File diff suppressed because it is too large
Load Diff
84
keys.scad
84
keys.scad
@@ -5,88 +5,14 @@
|
||||
// without having to rely on this file. Unfortunately that means setting tons of
|
||||
// special variables, but that's a limitation of SCAD we have to work around
|
||||
|
||||
|
||||
echo($fa);
|
||||
echo("WHERES THE BEEF");
|
||||
|
||||
|
||||
include <./includes.scad>
|
||||
dsa_row(3) {
|
||||
union() {
|
||||
$key_shape_type="sculpted_square";
|
||||
$dish_type="disabled";
|
||||
$skin_extrude_shape = true;
|
||||
key();
|
||||
}
|
||||
}
|
||||
|
||||
/* $inverted_dish = true; */
|
||||
/* $rounded_key = true; */
|
||||
|
||||
/* $linear_extrude_shape=true; */
|
||||
/* $rounded_key=true; */
|
||||
/* $outset_legends = true; */
|
||||
/* $inverted_dish =true; */
|
||||
/* $dish_type = "pyramid"; */
|
||||
/* legend("q") key(); */
|
||||
/* $outset_legends = true; */
|
||||
dcs_row(3) {
|
||||
/* iso_enter() */
|
||||
union() {
|
||||
union() {
|
||||
/* $minkowski_radius = 10; */
|
||||
/* $minkowski_radius = 0.12; */
|
||||
|
||||
/* $key_shape_type = "iso_enter"; */
|
||||
$key_shape_type="sculpted_square";
|
||||
/* $dish_type ="disable"; */
|
||||
/* $inverted_dish = true; */
|
||||
/* $stem_type = "disable"; */
|
||||
/* $dish_type="3d_surface"; */
|
||||
/* $support_type = "disable"; */
|
||||
/* $stabilizer_type = "disable"; */
|
||||
/* rounded_shape(); */
|
||||
/* minkowski() { */
|
||||
|
||||
/* rounded_key(); */
|
||||
/* translate([0,0,-200]) cube(10); */
|
||||
|
||||
|
||||
/* difference(){ */
|
||||
/* key(); */
|
||||
/* cube(100); */
|
||||
/* } */
|
||||
|
||||
/* minkowski_shape(); */
|
||||
/* } */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* translate_u(1,0) {
|
||||
oem_row(3) {
|
||||
cherry() legend("q")
|
||||
union() {
|
||||
key();
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
/* difference() {
|
||||
translate([0,0,-.1]) cube(1.1);
|
||||
translate([0.5,0.5,-0.5]) polar_3d_surface(step=0.1);
|
||||
} */
|
||||
|
||||
|
||||
// Written in 2015 by Torsten Paul <Torsten.Paul@gmx.de>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all
|
||||
// copyright and related and neighboring rights to this software to the
|
||||
// public domain worldwide. This software is distributed without any
|
||||
// warranty.
|
||||
//
|
||||
// For details of the CC0 Public Domain Dedication see
|
||||
// <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
// example key
|
||||
/* $stem_throw = 1; */
|
||||
$stem_type = "custom";
|
||||
$outset_legends = true;
|
||||
dcs_row(5) front_legend("j") key();
|
||||
|
||||
// example row
|
||||
/* for (x = [0:1:4]) {
|
||||
|
||||
@@ -5,6 +5,7 @@ include <dishes/old_spherical.scad>
|
||||
include <dishes/sideways_cylindrical.scad>
|
||||
include <dishes/spherical.scad>
|
||||
include <dishes/flat.scad>
|
||||
include <dishes/3d_surface.scad>
|
||||
|
||||
//geodesic looks much better, but runs very slow for anything above a 2u
|
||||
geodesic=false;
|
||||
@@ -19,9 +20,10 @@ module dish(width, height, depth, inverted) {
|
||||
}
|
||||
else if ($dish_type == "sideways cylindrical"){
|
||||
sideways_cylindrical_dish(width, height, depth, inverted);
|
||||
}
|
||||
else if ($dish_type == "old spherical") {
|
||||
} else if ($dish_type == "old spherical") {
|
||||
old_spherical_dish(width, height, depth, inverted);
|
||||
} else if ($dish_type == "3d_surface") {
|
||||
3d_surface_dish(width, height, depth, inverted);
|
||||
} else if ($dish_type == "flat") {
|
||||
flat_dish(width, height, depth, inverted);
|
||||
} else if ($dish_type == "disable") {
|
||||
|
||||
14
src/dishes/3d_surface.scad
Normal file
14
src/dishes/3d_surface.scad
Normal file
@@ -0,0 +1,14 @@
|
||||
include <../libraries/3d_surface.scad>
|
||||
|
||||
module 3d_surface_dish(width, height, depth, inverted) {
|
||||
echo(inverted ? "inverted" : "not inverted");
|
||||
// scale_factor is dead reckoning
|
||||
// it doesn't have to be dead reckoning for anything but sculpted sides
|
||||
// we know the angle of the sides from the width difference, height difference,
|
||||
// skew and tilt of the top. it's a pain to calculate though
|
||||
scale_factor = 1.1;
|
||||
// the edges on this behave differently than with the previous dish implementations
|
||||
scale([width*scale_factor/$3d_surface_size/2,height*scale_factor/$3d_surface_size/2,depth]) rotate([inverted ? 0:180,0,90]) polar_3d_surface(bottom=-10);
|
||||
/* %scale([width*scale_factor/$3d_surface_size/2,height*scale_factor/$3d_surface_size/2,depth]) rotate([180,0,0]) polar_3d_surface(bottom=-10); */
|
||||
|
||||
}
|
||||
@@ -40,3 +40,22 @@ function vertical_inclination_due_to_top_tilt() = sin($top_tilt) * (top_total_ke
|
||||
// of the keycap a flat plane. 1 = front, -1 = back
|
||||
// I derived this through a bunch of trig reductions I don't really understand.
|
||||
function extra_keytop_length_for_flat_sides() = ($width_difference * vertical_inclination_due_to_top_tilt()) / ($total_depth);
|
||||
|
||||
// 3d surface functions (still in beta)
|
||||
|
||||
// monotonically increasing function that distributes the points of the surface mesh
|
||||
// only for polar_3d_surface right now
|
||||
// if it's linear it's a grid. sin(dim) * size concentrates detail around the edges
|
||||
function surface_distribution_function(dim, size) = sin(dim) * size;
|
||||
|
||||
// the function that actually determines what the surface is.
|
||||
// feel free to override, the last one wins
|
||||
|
||||
// debug
|
||||
function surface_function(x,y) = 1;
|
||||
// cylindrical
|
||||
function surface_function(x,y) = (sin(acos(x/$3d_surface_size)));
|
||||
// spherical
|
||||
function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size));
|
||||
// (statically) random!
|
||||
/* function surface_function(x,y) = sin(rands(0,90,1,x+y)[0]); */
|
||||
|
||||
473
src/key.scad
473
src/key.scad
@@ -5,8 +5,7 @@ include <stems.scad>
|
||||
include <stem_supports.scad>
|
||||
include <dishes.scad>
|
||||
include <supports.scad>
|
||||
include <features.scad>
|
||||
include <hulls.scad>
|
||||
include <key_features.scad>
|
||||
|
||||
include <libraries/geodesic_sphere.scad>
|
||||
|
||||
@@ -16,10 +15,10 @@ use <libraries/scad-utils/lists.scad>
|
||||
use <libraries/scad-utils/shapes.scad>
|
||||
use <libraries/skin.scad>
|
||||
|
||||
|
||||
/* [Hidden] */
|
||||
SMALLEST_POSSIBLE = 1/128;
|
||||
// basically disable $fs - though it might be useful for these CGAL problems
|
||||
$fs = .01;
|
||||
$fs = .1;
|
||||
$unit = 19.05;
|
||||
|
||||
// key shape including dish. used as the ouside and inside shape in hollow_key(). allows for itself to be shrunk in depth and width / height
|
||||
@@ -29,100 +28,157 @@ module shape(thickness_difference, depth_difference=0){
|
||||
}
|
||||
}
|
||||
|
||||
// shape of the key but with soft, rounded edges. no longer includes dish
|
||||
// randomly doesnt work sometimes
|
||||
// the dish doesn't _quite_ reach as far as it should
|
||||
module rounded_shape() {
|
||||
dished(-$minkowski_radius, $inverted_dish) {
|
||||
color($primary_color) minkowski(){
|
||||
// half minkowski in the z direction
|
||||
color($primary_color) shape_hull($minkowski_radius * 2, $minkowski_radius/2, $inverted_dish ? 2 : 0);
|
||||
/* cube($minkowski_radius); */
|
||||
sphere(r=$minkowski_radius, $fn=$minkowski_facets);
|
||||
}
|
||||
}
|
||||
/* %envelope(); */
|
||||
}
|
||||
|
||||
// this function is more correct, but takes _forever_
|
||||
// the main difference is minkowski happens after dishing, meaning the dish is
|
||||
// also minkowski'd
|
||||
module rounded_shape() {
|
||||
/* module rounded_shape() {
|
||||
color($primary_color) minkowski(){
|
||||
// half minkowski in the z direction
|
||||
shape($minkowski_radius * 2, $minkowski_radius/2);
|
||||
minkowski_object();
|
||||
}
|
||||
}
|
||||
|
||||
// minkowski places this object at every vertex of the other object then mashes
|
||||
// it all together
|
||||
module minkowski_object() {
|
||||
// alternative minkowski shape that needs the bottom of the keycap to be trimmed
|
||||
/* sphere(1); */
|
||||
|
||||
difference(){
|
||||
sphere(r=$minkowski_radius, $fa=360/$minkowski_facets);
|
||||
translate([0,0,-$minkowski_radius]){
|
||||
cube($minkowski_radius * 2, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module envelope(depth_difference=0) {
|
||||
s = 1.5;
|
||||
hull(){
|
||||
cube([total_key_width() * s, total_key_height() * s, 0.01], center = true);
|
||||
top_placement(SMALLEST_POSSIBLE + depth_difference){
|
||||
cube([top_total_key_width() * s, top_total_key_height() * s, 0.01], center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for when you want to take the dish out of things
|
||||
// used for adding the dish to the key shape and making sure stems don't stick out the top
|
||||
// creates a bounding box 1.5 times larger in width and height than the keycap.
|
||||
module dished(depth_difference = 0, inverted = false) {
|
||||
intersection() {
|
||||
children();
|
||||
difference(){
|
||||
union() {
|
||||
// envelope is needed to "fill in" the rest of the keycap
|
||||
envelope(depth_difference);
|
||||
if (inverted) top_placement(depth_difference) _dish(inverted);
|
||||
sphere(r=$minkowski_radius, $fn=20);
|
||||
translate([0,0,-$minkowski_radius]){
|
||||
cube($minkowski_radius * 2, center=true);
|
||||
}
|
||||
if (!inverted) top_placement(depth_difference) _dish(inverted);
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
|
||||
// basic key shape, no dish, no inside
|
||||
// which is only used for dishing to cut the dish off correctly
|
||||
// $height_difference used for keytop thickness
|
||||
// extra_slices is a hack to make inverted dishes still work
|
||||
module shape_hull(thickness_difference, depth_difference, extra_slices = 0){
|
||||
render() {
|
||||
if ($skin_extrude_shape) {
|
||||
skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices);
|
||||
} else if ($linear_extrude_shape) {
|
||||
linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices);
|
||||
} else {
|
||||
hull_shape_hull(thickness_difference, depth_difference, extra_slices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// just to DRY up the code
|
||||
module _dish(inverted=$inverted_dish) {
|
||||
color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, inverted);
|
||||
// use skin() instead of successive hulls. much more correct, and looks faster
|
||||
// too, in most cases. successive hull relies on overlapping faces which are
|
||||
// not good. But, skin works on vertex sets instead of shapes, which makes it
|
||||
// a lot more difficult to use
|
||||
module skin_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0 ) {
|
||||
skin([
|
||||
for (index = [0:$height_slices + extra_slices])
|
||||
let(
|
||||
progress = (index / $height_slices),
|
||||
skew_this_slice = $top_skew * progress,
|
||||
x_skew_this_slice = $top_skew_x * progress,
|
||||
depth_this_slice = ($total_depth - depth_difference) * progress,
|
||||
tilt_this_slice = -$top_tilt / $key_height * progress,
|
||||
y_tilt_this_slice = $double_sculpted ? (-$top_tilt_y / $key_length * progress) : 0
|
||||
)
|
||||
skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice)
|
||||
]);
|
||||
}
|
||||
|
||||
// puts its children at the center of the dishing on the key, including dish height
|
||||
// more user-friendly than top_placement
|
||||
module top_of_key(){
|
||||
// if there is a dish, we need to account for how much it digs into the top
|
||||
dish_depth = ($dish_type == "disable") ? 0 : $dish_depth;
|
||||
// if the dish is inverted, we need to account for that too. in this case we do half, otherwise the children would be floating on top of the dish
|
||||
corrected_dish_depth = ($inverted_dish) ? -dish_depth / 2 : dish_depth;
|
||||
function skin_shape_slice(progress, thickness_difference, skew_this_slice, x_skew_this_slice, depth_this_slice, tilt_this_slice, y_tilt_this_slice) =
|
||||
transform(
|
||||
translation([x_skew_this_slice,skew_this_slice,depth_this_slice]),
|
||||
transform(
|
||||
rotation([tilt_this_slice,y_tilt_this_slice,0]),
|
||||
skin_key_shape([
|
||||
total_key_width(0),
|
||||
total_key_height(0),
|
||||
],
|
||||
[$width_difference, $height_difference],
|
||||
progress,
|
||||
thickness_difference
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
top_placement(corrected_dish_depth) {
|
||||
// corollary is hull_shape_hull
|
||||
// extra_slices unused, only to match argument signatures
|
||||
module linear_extrude_shape_hull(thickness_difference, depth_difference, extra_slices = 0){
|
||||
height = $total_depth - depth_difference;
|
||||
width_scale = top_total_key_width() / total_key_width();
|
||||
height_scale = top_total_key_height() / total_key_height();
|
||||
|
||||
translate([0,$linear_extrude_height_adjustment,0]){
|
||||
linear_extrude(height = height, scale = [width_scale, height_scale]) {
|
||||
translate([0,-$linear_extrude_height_adjustment,0]){
|
||||
key_shape(
|
||||
[total_key_width(thickness_difference), total_key_height(thickness_difference)],
|
||||
[$width_difference, $height_difference]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module hull_shape_hull(thickness_difference, depth_difference, extra_slices = 0) {
|
||||
for (index = [0:$height_slices - 1 + extra_slices]) {
|
||||
hull() {
|
||||
shape_slice(index / $height_slices, thickness_difference, depth_difference);
|
||||
shape_slice((index + 1) / $height_slices, thickness_difference, depth_difference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module shape_slice(progress, thickness_difference, depth_difference) {
|
||||
skew_this_slice = $top_skew * progress;
|
||||
x_skew_this_slice = $top_skew_x * progress;
|
||||
|
||||
depth_this_slice = ($total_depth - depth_difference) * progress;
|
||||
|
||||
tilt_this_slice = -$top_tilt / $key_height * progress;
|
||||
y_tilt_this_slice = $double_sculpted ? (-$top_tilt_y / $key_length * progress) : 0;
|
||||
|
||||
translate([x_skew_this_slice, skew_this_slice, depth_this_slice]) {
|
||||
rotate([tilt_this_slice,y_tilt_this_slice,0]){
|
||||
linear_extrude(height = SMALLEST_POSSIBLE){
|
||||
key_shape(
|
||||
[
|
||||
total_key_width(thickness_difference),
|
||||
total_key_height(thickness_difference)
|
||||
],
|
||||
[$width_difference, $height_difference],
|
||||
progress
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for when you want something to only exist inside the keycap.
|
||||
// used for the support structure
|
||||
module inside() {
|
||||
intersection() {
|
||||
shape($wall_thickness, $keytop_thickness);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
// puts its children at each keystem position provided
|
||||
module keystem_positions(positions) {
|
||||
for (connector_pos = positions) {
|
||||
translate(connector_pos) {
|
||||
rotate([0, 0, $stem_rotation]){
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module support_for(positions, stem_type) {
|
||||
keystem_positions(positions) {
|
||||
color($tertiary_color) supports($support_type, stem_type, $stem_throw, $total_depth - $stem_throw);
|
||||
}
|
||||
}
|
||||
|
||||
module stems_for(positions, stem_type) {
|
||||
keystem_positions(positions) {
|
||||
color($tertiary_color) stem(stem_type, $total_depth, $stem_slop);
|
||||
if ($stem_support_type != "disable") {
|
||||
color($quaternary_color) stem_support($stem_support_type, stem_type, $stem_support_height, $stem_slop);
|
||||
}
|
||||
// for when you want something to only exist outside the keycap
|
||||
module outside() {
|
||||
difference() {
|
||||
children();
|
||||
shape($wall_thickness, $keytop_thickness);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +196,7 @@ module top_placement(depth_difference=0) {
|
||||
}
|
||||
}
|
||||
|
||||
module front_of_key() {
|
||||
module front_placement() {
|
||||
// all this math is to take top skew and tilt into account
|
||||
// we need to find the new effective height and depth of the top, front lip
|
||||
// of the keycap to find the angle so we can rotate things correctly into place
|
||||
@@ -159,99 +215,216 @@ module front_of_key() {
|
||||
}
|
||||
}
|
||||
|
||||
module outer_shape() {
|
||||
if ($rounded_key) {
|
||||
rounded_shape();
|
||||
} else {
|
||||
shape(0, 0);
|
||||
}
|
||||
// just to DRY up the code
|
||||
module _dish() {
|
||||
color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, $inverted_dish);
|
||||
}
|
||||
|
||||
module inner_shape(extra_wall_thickness = 0, extra_keytop_thickness = 0) {
|
||||
translate([0,0,-SMALLEST_POSSIBLE]) {
|
||||
if ($flat_keytop_bottom) {
|
||||
/* $key_shape_type="square"; */
|
||||
$height_slices = 1;
|
||||
color($primary_color) shape_hull($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness, 0);
|
||||
} else {
|
||||
shape($wall_thickness + extra_wall_thickness, $keytop_thickness + extra_keytop_thickness);
|
||||
module envelope(depth_difference=0) {
|
||||
s = 1.5;
|
||||
hull(){
|
||||
cube([total_key_width() * s, total_key_height() * s, 0.01], center = true);
|
||||
top_placement(SMALLEST_POSSIBLE + depth_difference){
|
||||
cube([top_total_key_width() * s, top_total_key_height() * s, 0.01], center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// additive objects at the top of the key
|
||||
module additive_features(inset) {
|
||||
top_of_key() {
|
||||
if($key_bump) keybump($key_bump_depth, $key_bump_edge);
|
||||
if(!inset && $children > 0) color($secondary_color) children();
|
||||
// I think this is unused
|
||||
module dished_for_show() {
|
||||
difference(){
|
||||
union() {
|
||||
envelope();
|
||||
if ($inverted_dish) top_placement(0) _dish();
|
||||
}
|
||||
if (!$inverted_dish) top_placement(0) _dish();
|
||||
}
|
||||
if($outset_legends) legends(0);
|
||||
// render the clearance check if it's enabled, but don't have it intersect with anything
|
||||
if ($clearance_check) %clearance_check();
|
||||
}
|
||||
|
||||
// subtractive objects at the top of the key
|
||||
module subtractive_features(inset) {
|
||||
top_of_key() {
|
||||
if (inset && $children > 0) color($secondary_color) children();
|
||||
|
||||
// for when you want to take the dish out of things
|
||||
// used for adding the dish to the key shape and making sure stems don't stick out the top
|
||||
// creates a bounding box 1.5 times larger in width and height than the keycap.
|
||||
module dished(depth_difference = 0, inverted = false) {
|
||||
intersection() {
|
||||
children();
|
||||
difference(){
|
||||
union() {
|
||||
envelope(depth_difference);
|
||||
if (inverted) top_placement(depth_difference) _dish();
|
||||
}
|
||||
if (!inverted) top_placement(depth_difference) _dish();
|
||||
}
|
||||
}
|
||||
if(!$outset_legends) legends($inset_legend_depth);
|
||||
// subtract the clearance check if it's enabled, letting the user see the
|
||||
// parts of the keycap that will hit the cherry switch
|
||||
if ($clearance_check) %clearance_check();
|
||||
}
|
||||
|
||||
module inside_features() {
|
||||
translate([0, 0, $stem_inset]) {
|
||||
// both stem and support are optional
|
||||
if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type);
|
||||
if ($stem_type != "disable") stems_for($stem_positions, $stem_type);
|
||||
if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type);
|
||||
// always render stem support even if there isn't a stem.
|
||||
// rendering flat support w/no stem is much more common than a hollow keycap
|
||||
// so if you want a hollow keycap you'll have to turn support off entirely
|
||||
support_for($stem_positions, $stem_type);
|
||||
// puts it's children at the center of the dishing on the key, including dish height
|
||||
// more user-friendly than top_placement
|
||||
module top_of_key(){
|
||||
// if there is a dish, we need to account for how much it digs into the top
|
||||
dish_depth = ($dish_type == "disable") ? 0 : $dish_depth;
|
||||
// if the dish is inverted, we need to account for that too. in this case we do half, otherwise the children would be floating on top of the dish
|
||||
corrected_dish_depth = ($inverted_dish) ? -dish_depth / 2 : dish_depth;
|
||||
|
||||
top_placement(corrected_dish_depth) {
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
module keytext(text, position, font_size, depth) {
|
||||
woffset = (top_total_key_width()/3.5) * position[0];
|
||||
hoffset = (top_total_key_height()/3.5) * -position[1];
|
||||
translate([woffset, hoffset, -depth]){
|
||||
color($tertiary_color) linear_extrude(height=$dish_depth){
|
||||
text(text=text, font=$font, size=font_size, halign="center", valign="center");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module keystem_positions(positions) {
|
||||
for (connector_pos = positions) {
|
||||
translate(connector_pos) {
|
||||
rotate([0, 0, $stem_rotation]){
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module support_for(positions, stem_type) {
|
||||
keystem_positions(positions) {
|
||||
color($tertiary_color) supports($support_type, stem_type, $stem_throw, $total_depth - $stem_throw);
|
||||
}
|
||||
}
|
||||
|
||||
module stems_for(positions, stem_type) {
|
||||
keystem_positions(positions) {
|
||||
color($tertiary_color) stem(stem_type, $total_depth, $stem_slop, $stem_throw);
|
||||
if ($stem_support_type != "disable") {
|
||||
color($quaternary_color) stem_support($stem_support_type, stem_type, $stem_support_height, $stem_slop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// a fake cherry keyswitch, abstracted out to maybe replace with a better one later
|
||||
module cherry_keyswitch() {
|
||||
union() {
|
||||
hull() {
|
||||
cube([15.6, 15.6, 0.01], center=true);
|
||||
translate([0,1,5 - 0.01]) cube([10.5,9.5, 0.01], center=true);
|
||||
}
|
||||
hull() {
|
||||
cube([15.6, 15.6, 0.01], center=true);
|
||||
translate([0,0,-5.5]) cube([13.5,13.5,0.01], center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//approximate (fully depressed) cherry key to check clearances
|
||||
module clearance_check() {
|
||||
if($stem_type == "cherry" || $stem_type == "cherry_rounded"){
|
||||
color($warning_color){
|
||||
translate([0,0,3.6 + $stem_inset - 5]) {
|
||||
cherry_keyswitch();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module legends(depth=0) {
|
||||
if (len($front_legends) > 0) {
|
||||
front_placement() {
|
||||
if (len($front_legends) > 0) {
|
||||
for (i=[0:len($front_legends)-1]) {
|
||||
rotate([90,0,0]) keytext($front_legends[i][0], $front_legends[i][1], $front_legends[i][2], depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (len($legends) > 0) {
|
||||
top_of_key() {
|
||||
// outset legend
|
||||
if (len($legends) > 0) {
|
||||
for (i=[0:len($legends)-1]) {
|
||||
keytext($legends[i][0], $legends[i][1], $legends[i][2], depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// legends / artisan support
|
||||
module artisan(depth) {
|
||||
top_of_key() {
|
||||
// artisan objects / outset shape legends
|
||||
color($secondary_color) children();
|
||||
}
|
||||
}
|
||||
|
||||
// key with hollowed inside but no stem
|
||||
module hollow_key() {
|
||||
difference(){
|
||||
if ($rounded_key) {
|
||||
rounded_shape();
|
||||
} else {
|
||||
shape(0, 0);
|
||||
}
|
||||
// translation purely for aesthetic purposes, to get rid of that awful lattice
|
||||
translate([0,0,-SMALLEST_POSSIBLE]) {
|
||||
shape($wall_thickness, $keytop_thickness);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The final, penultimate key generation function.
|
||||
// takes all the bits and glues them together. requires configuration with special variables.
|
||||
module key(inset=false) {
|
||||
difference(){
|
||||
union() {
|
||||
outer_shape();
|
||||
additive_features(inset);
|
||||
}
|
||||
|
||||
difference() {
|
||||
inner_shape();
|
||||
inside_features();
|
||||
}
|
||||
|
||||
subtractive_features(inset);
|
||||
}
|
||||
}
|
||||
|
||||
module rounded_key(inset=false) {
|
||||
module key(inset = false) {
|
||||
difference() {
|
||||
minkowski() {
|
||||
difference() {
|
||||
outer_shape();
|
||||
inner_shape();
|
||||
}
|
||||
|
||||
minkowski_object();
|
||||
union(){
|
||||
// the shape of the key, inside and out
|
||||
hollow_key();
|
||||
if($key_bump) top_of_key() keybump($key_bump_depth, $key_bump_edge);
|
||||
// additive objects at the top of the key
|
||||
// outside() makes them stay out of the inside. it's a bad name
|
||||
if(!inset && $children > 0) outside() artisan(0) children();
|
||||
if($outset_legends) legends(0);
|
||||
// render the clearance check if it's enabled, but don't have it intersect with anything
|
||||
if ($clearance_check) %clearance_check();
|
||||
}
|
||||
|
||||
subtractive_features(inset);
|
||||
// subtractive objects at the top of the key
|
||||
// no outside() - I can't think of a use for it. will save render time
|
||||
if (inset && $children > 0) artisan($inset_legend_depth) children();
|
||||
if(!$outset_legends) legends($inset_legend_depth);
|
||||
// subtract the clearance check if it's enabled, letting the user see the
|
||||
// parts of the keycap that will hit the cherry switch
|
||||
if ($clearance_check) %clearance_check();
|
||||
}
|
||||
|
||||
/* additive_features(inset); */
|
||||
// both stem and support are optional
|
||||
if ($stem_type != "disable" || ($stabilizers != [] && $stabilizer_type != "disable")) {
|
||||
dished($keytop_thickness, $inverted_dish) {
|
||||
translate([0, 0, $stem_inset]) {
|
||||
if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type);
|
||||
|
||||
/* intersection() {
|
||||
inner_shape($wall_thickness, $keytop_thickness);
|
||||
inside_features();
|
||||
} */
|
||||
if ($stem_type != "disable") stems_for($stem_positions, $stem_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($support_type != "disable"){
|
||||
inside() {
|
||||
translate([0, 0, $stem_inset]) {
|
||||
if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type);
|
||||
|
||||
// always render stem support even if there isn't a stem.
|
||||
// rendering flat support w/no stem is much more common than a hollow keycap
|
||||
// so if you want a hollow keycap you'll have to turn support off entirely
|
||||
support_for($stem_positions, $stem_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// actual full key with space carved out and keystem/stabilizer connectors
|
||||
|
||||
@@ -9,6 +9,7 @@ include <key_profiles/sa.scad>
|
||||
include <key_profiles/g20.scad>
|
||||
include <key_profiles/hipro.scad>
|
||||
include <key_profiles/grid.scad>
|
||||
include <key_profiles/cherry.scad>
|
||||
|
||||
// man, wouldn't it be so cool if functions were first order
|
||||
module key_profile(key_profile_type, row, column=0) {
|
||||
@@ -26,6 +27,8 @@ module key_profile(key_profile_type, row, column=0) {
|
||||
hipro_row(row, column) children();
|
||||
} else if (key_profile_type == "grid") {
|
||||
grid_row(row, column) children();
|
||||
} else if (key_profile_type == "cherry") {
|
||||
cherry_row(row, column) children();
|
||||
} else if (key_profile_type == "disable") {
|
||||
children();
|
||||
} else {
|
||||
|
||||
48
src/key_profiles/cherry.scad
Normal file
48
src/key_profiles/cherry.scad
Normal file
@@ -0,0 +1,48 @@
|
||||
// based off GMK keycap set
|
||||
|
||||
module cherry_row(row=3, column=0) {
|
||||
$bottom_key_width = 18.16;
|
||||
$bottom_key_height = 18.16;
|
||||
$width_difference = $bottom_key_width - 11.85;
|
||||
$height_difference = $bottom_key_height - 14.64;
|
||||
$dish_type = "cylindrical";
|
||||
$dish_depth = 0.65;
|
||||
$dish_skew_x = 0;
|
||||
$dish_skew_y = 0;
|
||||
$top_skew = 2;
|
||||
|
||||
$top_tilt_y = side_tilt(column);
|
||||
extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0;
|
||||
|
||||
// NOTE: cherry keycaps have this stem inset, but I'm reticent to turn it on
|
||||
// since it'll be surprising to folks. the height has been adjusted accordingly
|
||||
// $stem_inset = 0.6;
|
||||
extra_stem_inset_height = max(0.6 - $stem_inset, 0);
|
||||
|
||||
// <= is a hack so you can do these in a for loop. function row = 0
|
||||
if (row <= 1) {
|
||||
$total_depth = 9.8 - extra_stem_inset_height + extra_height;
|
||||
$top_tilt = 0;
|
||||
|
||||
children();
|
||||
} else if (row == 2) {
|
||||
$total_depth = 7.45 - extra_stem_inset_height + extra_height;
|
||||
$top_tilt = 2.5;
|
||||
|
||||
children();
|
||||
} else if (row == 3) {
|
||||
$total_depth = 6.55 - extra_stem_inset_height + extra_height;
|
||||
$top_tilt = 5;
|
||||
children();
|
||||
} else if (row == 3) {
|
||||
$total_depth = 6.7 + 0.65 - extra_stem_inset_height + extra_height;
|
||||
$top_tilt = 11.5;
|
||||
children();
|
||||
} else if (row >= 4) {
|
||||
$total_depth = 6.7 + 0.65 - extra_stem_inset_height + extra_height;
|
||||
$top_tilt = 11.5;
|
||||
children();
|
||||
} else {
|
||||
children();
|
||||
}
|
||||
}
|
||||
79
src/libraries/3d_surface.scad
Normal file
79
src/libraries/3d_surface.scad
Normal file
@@ -0,0 +1,79 @@
|
||||
// thanks Paul https://github.com/openscad/list-comprehension-demos/
|
||||
|
||||
include <../functions.scad>
|
||||
|
||||
module 3d_surface(size=$3d_surface_size, step=$3d_surface_step, bottom=-SMALLEST_POSSIBLE){
|
||||
function p(x, y) = [ x, y, max(0,surface_function(x, y)) ];
|
||||
function p0(x, y) = [ x, y, bottom ];
|
||||
function rev(b, v) = b ? v : [ v[3], v[2], v[1], v[0] ];
|
||||
function face(x, y) = [ p(x, y + step), p(x + step, y + step), p(x + step, y), p(x + step, y), p(x, y), p(x, y + step) ];
|
||||
function fan(a, i) =
|
||||
a == 0 ? [ [ 0, 0, bottom ], [ i, -size, bottom ], [ i + step, -size, bottom ] ]
|
||||
: a == 1 ? [ [ 0, 0, bottom ], [ i + step, size, bottom ], [ i, size, bottom ] ]
|
||||
: a == 2 ? [ [ 0, 0, bottom ], [ -size, i + step, bottom ], [ -size, i, bottom ] ]
|
||||
: [ [ 0, 0, bottom ], [ size, i, bottom ], [ size, i + step, bottom ] ];
|
||||
function sidex(x, y) = [ p0(x, y), p(x, y), p(x + step, y), p0(x + step, y) ];
|
||||
function sidey(x, y) = [ p0(x, y), p(x, y), p(x, y + step), p0(x, y + step) ];
|
||||
|
||||
points = flatten(concat(
|
||||
// top surface
|
||||
[ for (x = [ -size : step : size - step ], y = [ -size : step : size - step ]) face(x, y) ],
|
||||
// bottom surface as triangle fan
|
||||
[ for (a = [ 0 : 3 ], i = [ -size : step : size - step ]) fan(a, i) ],
|
||||
// sides
|
||||
[ for (x = [ -size : step : size - step ], y = [ -size, size ]) rev(y < 0, sidex(x, y)) ],
|
||||
[ for (y = [ -size : step : size - step ], x = [ -size, size ]) rev(x > 0, sidey(x, y)) ]
|
||||
));
|
||||
|
||||
tcount = 2 * pow(2 * size / step, 2) + 8 * size / step;
|
||||
scount = 8 * size / step;
|
||||
|
||||
tfaces = [ for (a = [ 0 : 3 : 3 * (tcount - 1) ] ) [ a, a + 1, a + 2 ] ];
|
||||
sfaces = [ for (a = [ 3 * tcount : 4 : 3 * tcount + 4 * scount ] ) [ a, a + 1, a + 2, a + 3 ] ];
|
||||
faces = concat(tfaces, sfaces);
|
||||
|
||||
polyhedron(points, faces, convexity = 8);
|
||||
}
|
||||
|
||||
module polar_3d_surface(size=$3d_surface_size, step=$3d_surface_step, bottom=-SMALLEST_POSSIBLE){
|
||||
function to_polar(q, size) = q * (90 / size);
|
||||
|
||||
function p(x, y) = [
|
||||
surface_distribution_function(to_polar(x, size), size),
|
||||
surface_distribution_function(to_polar(y, size), size),
|
||||
max(0,surface_function(surface_distribution_function(to_polar(x, size), size), surface_distribution_function(to_polar(y, size), size)))
|
||||
];
|
||||
function p0(x, y) = [ x, y, bottom ];
|
||||
function rev(b, v) = b ? v : [ v[3], v[2], v[1], v[0] ];
|
||||
function face(x, y) = [ p(x, y + step), p(x + step, y + step), p(x + step, y), p(x + step, y), p(x, y), p(x, y + step) ];
|
||||
function fan(a, i) =
|
||||
a == 0 ? [ [ 0, 0, bottom ], [ i, -size, bottom ], [ i + step, -size, bottom ] ]
|
||||
: a == 1 ? [ [ 0, 0, bottom ], [ i + step, size, bottom ], [ i, size, bottom ] ]
|
||||
: a == 2 ? [ [ 0, 0, bottom ], [ -size, i + step, bottom ], [ -size, i, bottom ] ]
|
||||
: [ [ 0, 0, bottom ], [ size, i, bottom ], [ size, i + step, bottom ] ];
|
||||
function sidex(x, y) = [ p0(x, y), p(x, y), p(x + step, y), p0(x + step, y) ];
|
||||
function sidey(x, y) = [ p0(x, y), p(x, y), p(x, y + step), p0(x, y + step) ];
|
||||
|
||||
points = flatten(concat(
|
||||
// top surface
|
||||
[ for (x = [ -size : step : size - step ], y = [ -size : step : size - step ]) face(x, y) ],
|
||||
// bottom surface as triangle fan
|
||||
[ for (a = [ 0 : 3 ], i = [ -size : step : size - step ]) fan(a, i) ],
|
||||
// sides
|
||||
[ for (x = [ -size : step : size - step ], y = [ -size, size ]) rev(y < 0, sidex(x, y)) ],
|
||||
[ for (y = [ -size : step : size - step ], x = [ -size, size ]) rev(x > 0, sidey(x, y)) ]
|
||||
));
|
||||
|
||||
tcount = 2 * pow(2 * size / step, 2) + 8 * size / step;
|
||||
scount = 8 * size / step;
|
||||
|
||||
tfaces = [ for (a = [ 0 : 3 : 3 * (tcount - 1) ] ) [ a, a + 1, a + 2 ] ];
|
||||
sfaces = [ for (a = [ 3 * tcount : 4 : 3 * tcount + 4 * scount ] ) [ a, a + 1, a + 2, a + 3 ] ];
|
||||
faces = concat(tfaces, sfaces);
|
||||
|
||||
polyhedron(points, faces, convexity = 8);
|
||||
}
|
||||
|
||||
// defaults, overridden in functions.scad
|
||||
function surface_distribution_function(dim, size) = sin(dim) * size;
|
||||
function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size));
|
||||
@@ -17,17 +17,19 @@ function rectangle_profile(size=[1,1],fn=32) = [
|
||||
];
|
||||
|
||||
function rounded_rectangle_profile(size=[1,1],r=1,fn=32) = [
|
||||
for (index = [0:fn-1])
|
||||
let(a = index/fn*360)
|
||||
r * [cos(a), sin(a)]
|
||||
+ sign_x(index, fn) * [size[0]/2-r,0]
|
||||
+ sign_y(index, fn) * [0,size[1]/2-r]
|
||||
let(max_fn = max(fn,8))
|
||||
for (index = [0:max_fn-1])
|
||||
let(a = index/max_fn*360)
|
||||
r * [cos(a), sin(a)]
|
||||
+ sign_x(index, max_fn) * [size[0]/2-r,0]
|
||||
+ sign_y(index, max_fn) * [0,size[1]/2-r]
|
||||
];
|
||||
|
||||
function double_rounded_rectangle_profile(size=[1,1], r=1, fn=32) = [
|
||||
for (index = [0:fn-1])
|
||||
let(a = index/fn*360)
|
||||
r * [cos(a), sin(a)]
|
||||
+ sign_x(index, fn) * [size[0]/2-r,0]
|
||||
+ sign_y(index, fn) * [0,size[1]/2-r]
|
||||
let(max_fn = max(fn,8))
|
||||
for (index = [0:max_fn-1])
|
||||
let(a = index/max_fn*360)
|
||||
r * [cos(a), sin(a)]
|
||||
+ sign_x(index, max_fn) * [size[0]/2-r,0]
|
||||
+ sign_y(index, max_fn) * [0,size[1]/2-r]
|
||||
];
|
||||
|
||||
@@ -37,7 +37,7 @@ $outset_legends = false;
|
||||
// Height in units of key. should remain 1 for most uses
|
||||
$key_height = 1.0;
|
||||
// Keytop thickness, aka how many millimeters between the inside and outside of the top surface of the key
|
||||
$keytop_thickness = 2;
|
||||
$keytop_thickness = 1;
|
||||
// Wall thickness, aka the thickness of the sides of the keycap. note this is the total thickness, aka 3 = 1.5mm walls
|
||||
$wall_thickness = 3;
|
||||
// Radius of corners of keycap
|
||||
@@ -184,15 +184,12 @@ $tertiary_color = [1, .6941, .2];
|
||||
$quaternary_color = [.4078, .3569, .749];
|
||||
$warning_color = [1,0,0, 0.15];
|
||||
|
||||
// 3d surface variables
|
||||
// see functions.scad for the surface function
|
||||
$3d_surface_size = 10;
|
||||
$3d_surface_step = 1;
|
||||
// normally the bottom of the keytop looks like the top - curved, at least
|
||||
// underneath the support structure. This ensures there's a minimum thickness for the
|
||||
// underside of the keycap, but it's a fair bit of geometry
|
||||
$flat_keytop_bottom = true;
|
||||
|
||||
// how many facets circles will have when used in these features
|
||||
$minkowski_facets = 30;
|
||||
$shape_facets = 30;
|
||||
$shape_facets =30;
|
||||
|
||||
// 3d surface settings
|
||||
// unused for now
|
||||
$3d_surface_size = 100;
|
||||
// resolution in each axis. 10 = 10 divisions per x/y = 100 points total
|
||||
$3d_surface_step = 10;
|
||||
|
||||
@@ -9,4 +9,4 @@ module rounded_square_shape(size, delta, progress, center = true) {
|
||||
// for skin
|
||||
|
||||
function skin_rounded_square(size, delta, progress, thickness_difference) =
|
||||
rounded_rectangle_profile(size - (delta * progress) - [thickness_difference, thickness_difference]*2, fn=$shape_facets, r=$corner_radius);
|
||||
rounded_rectangle_profile(size - (delta * progress), fn=$shape_facets, r=$corner_radius);
|
||||
|
||||
@@ -67,7 +67,7 @@ function skin_sculpted_square_shape(size, delta, progress, thickness_difference)
|
||||
width - extra_width_this_slice - thickness_difference,
|
||||
height - extra_height_this_slice - thickness_difference
|
||||
]
|
||||
) double_rounded_rectangle_profile(square_size - [extra_corner_radius_this_slice, extra_corner_radius_this_slice]/4, fn=36, r=extra_corner_radius_this_slice/1.5 + $more_side_sculpting_factor * progress);
|
||||
) double_rounded_rectangle_profile(square_size - [extra_corner_radius_this_slice, extra_corner_radius_this_slice]/4, fn=$shape_facets, r=extra_corner_radius_this_slice/1.5 + $more_side_sculpting_factor * progress);
|
||||
|
||||
/* offset(r = extra_corner_radius_this_slice) {
|
||||
offset(r = -extra_corner_radius_this_slice) {
|
||||
|
||||
@@ -4,22 +4,25 @@ include <stems/box_cherry.scad>
|
||||
include <stems/alps.scad>
|
||||
include <stems/filled.scad>
|
||||
include <stems/cherry_stabilizer.scad>
|
||||
include <stems/custom.scad>
|
||||
|
||||
|
||||
//whole stem, alps or cherry, trimmed to fit
|
||||
module stem(stem_type, depth, slop){
|
||||
module stem(stem_type, depth, slop, throw){
|
||||
if (stem_type == "alps") {
|
||||
alps_stem(depth, slop);
|
||||
alps_stem(depth, slop, throw);
|
||||
} else if (stem_type == "cherry" || stem_type == "costar_stabilizer") {
|
||||
cherry_stem(depth, slop);
|
||||
cherry_stem(depth, slop, throw);
|
||||
} else if (stem_type == "rounded_cherry") {
|
||||
rounded_cherry_stem(depth, slop);
|
||||
rounded_cherry_stem(depth, slop, throw);
|
||||
} else if (stem_type == "box_cherry") {
|
||||
box_cherry_stem(depth, slop);
|
||||
box_cherry_stem(depth, slop, throw);
|
||||
} else if (stem_type == "filled") {
|
||||
filled_stem();
|
||||
} else if (stem_type == "cherry_stabilizer") {
|
||||
cherry_stabilizer_stem(depth, slop);
|
||||
cherry_stabilizer_stem(depth, slop, throw);
|
||||
} else if (stem_type == "custom") {
|
||||
custom_stem(depth, slop, throw);
|
||||
} else if (stem_type == "disable") {
|
||||
children();
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module alps_stem(depth, has_brim, slop){
|
||||
module alps_stem(depth, slop, throw){
|
||||
linear_extrude(height=depth) {
|
||||
square($alps_stem, center = true);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
include <../functions.scad>
|
||||
include <cherry.scad>
|
||||
|
||||
module box_cherry_stem(depth, slop) {
|
||||
module box_cherry_stem(depth, slop, throw) {
|
||||
difference(){
|
||||
// outside shape
|
||||
linear_extrude(height = depth) {
|
||||
|
||||
@@ -23,7 +23,7 @@ module inside_cherry_cross(slop) {
|
||||
}
|
||||
}
|
||||
|
||||
module cherry_stem(depth, slop) {
|
||||
module cherry_stem(depth, slop, throw) {
|
||||
difference(){
|
||||
// outside shape
|
||||
linear_extrude(height = depth) {
|
||||
|
||||
@@ -15,7 +15,7 @@ module inside_cherry_stabilizer_cross(slop) {
|
||||
}
|
||||
}
|
||||
|
||||
module cherry_stabilizer_stem(depth, slop) {
|
||||
module cherry_stabilizer_stem(depth, slop, throw) {
|
||||
difference(){
|
||||
// outside shape
|
||||
linear_extrude(height = depth) {
|
||||
|
||||
12
src/stems/custom.scad
Normal file
12
src/stems/custom.scad
Normal file
@@ -0,0 +1,12 @@
|
||||
thickness = .84;
|
||||
inner_stem_size = [6,4];
|
||||
outer_stem_size = inner_stem_size + [thickness, thickness];
|
||||
|
||||
module custom_stem(depth, slop, throw){
|
||||
linear_extrude(height=depth) {
|
||||
difference() {
|
||||
square(outer_stem_size + [slop,slop], center = true);
|
||||
square(inner_stem_size + [slop,slop], center = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
module filled_stem() {
|
||||
module filled_stem(_depth, _slop, _throw) {
|
||||
// I broke the crap out of this stem type due to the changes I made around how stems are differenced
|
||||
// now that we just take the dish out of stems in order to support stuff like
|
||||
// bare stem keycaps (and buckling spring eventually) we can't just make a
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
include <../functions.scad>
|
||||
include <cherry.scad>
|
||||
|
||||
module rounded_cherry_stem(depth, slop) {
|
||||
module rounded_cherry_stem(depth, slop, throw) {
|
||||
difference(){
|
||||
cylinder(d=$rounded_cherry_stem_d, h=depth);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user