github desktop completely screwed me
This commit is contained in:
parent
0a07212aff
commit
15d87a8f95
81
keys.scad
81
keys.scad
|
@ -5,11 +5,88 @@
|
||||||
// without having to rely on this file. Unfortunately that means setting tons of
|
// 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
|
// special variables, but that's a limitation of SCAD we have to work around
|
||||||
|
|
||||||
|
|
||||||
|
echo($fa);
|
||||||
|
echo("WHERES THE BEEF");
|
||||||
|
|
||||||
|
|
||||||
include <./includes.scad>
|
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); */
|
||||||
|
|
||||||
|
|
||||||
// example key
|
/* difference(){ */
|
||||||
dcs_row(5) legend("⇪", size=9) key();
|
/* 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 row
|
// example row
|
||||||
/* for (x = [0:1:4]) {
|
/* for (x = [0:1:4]) {
|
||||||
|
|
391
src/key.scad
391
src/key.scad
|
@ -5,7 +5,8 @@ include <stems.scad>
|
||||||
include <stem_supports.scad>
|
include <stem_supports.scad>
|
||||||
include <dishes.scad>
|
include <dishes.scad>
|
||||||
include <supports.scad>
|
include <supports.scad>
|
||||||
include <key_features.scad>
|
include <features.scad>
|
||||||
|
include <hulls.scad>
|
||||||
|
|
||||||
include <libraries/geodesic_sphere.scad>
|
include <libraries/geodesic_sphere.scad>
|
||||||
|
|
||||||
|
@ -15,10 +16,10 @@ use <libraries/scad-utils/lists.scad>
|
||||||
use <libraries/scad-utils/shapes.scad>
|
use <libraries/scad-utils/shapes.scad>
|
||||||
use <libraries/skin.scad>
|
use <libraries/skin.scad>
|
||||||
|
|
||||||
|
|
||||||
/* [Hidden] */
|
/* [Hidden] */
|
||||||
SMALLEST_POSSIBLE = 1/128;
|
SMALLEST_POSSIBLE = 1/128;
|
||||||
$fs = .1;
|
// basically disable $fs - though it might be useful for these CGAL problems
|
||||||
|
$fs = .01;
|
||||||
$unit = 19.05;
|
$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
|
// 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
|
||||||
|
@ -28,198 +29,32 @@ 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=48);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* %envelope(); */
|
|
||||||
}
|
|
||||||
|
|
||||||
// this function is more correct, but takes _forever_
|
// this function is more correct, but takes _forever_
|
||||||
// the main difference is minkowski happens after dishing, meaning the dish is
|
// the main difference is minkowski happens after dishing, meaning the dish is
|
||||||
// also minkowski'd
|
// also minkowski'd
|
||||||
/* module rounded_shape() {
|
module rounded_shape() {
|
||||||
color($primary_color) minkowski(){
|
color($primary_color) minkowski(){
|
||||||
// half minkowski in the z direction
|
// half minkowski in the z direction
|
||||||
shape($minkowski_radius * 2, $minkowski_radius/2);
|
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(){
|
difference(){
|
||||||
sphere(r=$minkowski_radius, $fn=20);
|
sphere(r=$minkowski_radius, $fa=360/$minkowski_facets);
|
||||||
translate([0,0,-$minkowski_radius]){
|
translate([0,0,-$minkowski_radius]){
|
||||||
cube($minkowski_radius * 2, center=true);
|
cube($minkowski_radius * 2, center=true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// for when you want something to only exist outside the keycap
|
|
||||||
module outside() {
|
|
||||||
difference() {
|
|
||||||
children();
|
|
||||||
shape($wall_thickness, $keytop_thickness);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// put something at the top of the key, with no adjustments for dishing
|
|
||||||
module top_placement(depth_difference=0) {
|
|
||||||
top_tilt_by_height = -$top_tilt / $key_height;
|
|
||||||
top_tilt_y_by_length = $double_sculpted ? (-$top_tilt_y / $key_length) : 0;
|
|
||||||
|
|
||||||
minkowski_height = $rounded_key ? $minkowski_radius : 0;
|
|
||||||
|
|
||||||
translate([$top_skew_x + $dish_skew_x, $top_skew + $dish_skew_y, $total_depth - depth_difference + minkowski_height/2]){
|
|
||||||
rotate([top_tilt_by_height, top_tilt_y_by_length,0]){
|
|
||||||
children();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
total_depth_difference = sin(-$top_tilt) * (top_total_key_height()/2);
|
|
||||||
total_height_difference = $top_skew + (1 - cos(-$top_tilt)) * (top_total_key_height()/2);
|
|
||||||
|
|
||||||
angle = atan2(($total_depth - total_depth_difference), ($height_difference/2 + total_height_difference));
|
|
||||||
hypotenuse = ($total_depth -total_depth_difference) / sin(angle);
|
|
||||||
|
|
||||||
translate([0,-total_key_height()/2,0]) {
|
|
||||||
rotate([-(90-angle), 0, 0]) {
|
|
||||||
translate([0,0,hypotenuse/2]){
|
|
||||||
children();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 envelope(depth_difference=0) {
|
module envelope(depth_difference=0) {
|
||||||
s = 1.5;
|
s = 1.5;
|
||||||
hull(){
|
hull(){
|
||||||
|
@ -230,18 +65,6 @@ module envelope(depth_difference=0) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// for when you want to take the dish out of things
|
// 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
|
// 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.
|
// creates a bounding box 1.5 times larger in width and height than the keycap.
|
||||||
|
@ -250,15 +73,21 @@ module dished(depth_difference = 0, inverted = false) {
|
||||||
children();
|
children();
|
||||||
difference(){
|
difference(){
|
||||||
union() {
|
union() {
|
||||||
|
// envelope is needed to "fill in" the rest of the keycap
|
||||||
envelope(depth_difference);
|
envelope(depth_difference);
|
||||||
if (inverted) top_placement(depth_difference) _dish();
|
if (inverted) top_placement(depth_difference) _dish(inverted);
|
||||||
}
|
}
|
||||||
if (!inverted) top_placement(depth_difference) _dish();
|
if (!inverted) top_placement(depth_difference) _dish(inverted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// puts it's children at the center of the dishing on the key, including dish height
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// puts its children at the center of the dishing on the key, including dish height
|
||||||
// more user-friendly than top_placement
|
// more user-friendly than top_placement
|
||||||
module top_of_key(){
|
module top_of_key(){
|
||||||
// if there is a dish, we need to account for how much it digs into the top
|
// if there is a dish, we need to account for how much it digs into the top
|
||||||
|
@ -271,16 +100,7 @@ module top_of_key(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module keytext(text, position, font_size, depth) {
|
// puts its children at each keystem position provided
|
||||||
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) {
|
module keystem_positions(positions) {
|
||||||
for (connector_pos = positions) {
|
for (connector_pos = positions) {
|
||||||
translate(connector_pos) {
|
translate(connector_pos) {
|
||||||
|
@ -306,125 +126,132 @@ module stems_for(positions, stem_type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// a fake cherry keyswitch, abstracted out to maybe replace with a better one later
|
// put something at the top of the key, with no adjustments for dishing
|
||||||
module cherry_keyswitch() {
|
module top_placement(depth_difference=0) {
|
||||||
union() {
|
top_tilt_by_height = -$top_tilt / $key_height;
|
||||||
hull() {
|
top_tilt_y_by_length = $double_sculpted ? (-$top_tilt_y / $key_length) : 0;
|
||||||
cube([15.6, 15.6, 0.01], center=true);
|
|
||||||
translate([0,1,5 - 0.01]) cube([10.5,9.5, 0.01], center=true);
|
minkowski_height = $rounded_key ? $minkowski_radius : 0;
|
||||||
}
|
|
||||||
hull() {
|
translate([$top_skew_x + $dish_skew_x, $top_skew + $dish_skew_y, $total_depth - depth_difference + minkowski_height/2]){
|
||||||
cube([15.6, 15.6, 0.01], center=true);
|
rotate([top_tilt_by_height, top_tilt_y_by_length,0]){
|
||||||
translate([0,0,-5.5]) cube([13.5,13.5,0.01], center=true);
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//approximate (fully depressed) cherry key to check clearances
|
module front_of_key() {
|
||||||
module clearance_check() {
|
// all this math is to take top skew and tilt into account
|
||||||
if($stem_type == "cherry" || $stem_type == "cherry_rounded"){
|
// we need to find the new effective height and depth of the top, front lip
|
||||||
color($warning_color){
|
// of the keycap to find the angle so we can rotate things correctly into place
|
||||||
translate([0,0,3.6 + $stem_inset - 5]) {
|
total_depth_difference = sin(-$top_tilt) * (top_total_key_height()/2);
|
||||||
cherry_keyswitch();
|
total_height_difference = $top_skew + (1 - cos(-$top_tilt)) * (top_total_key_height()/2);
|
||||||
|
|
||||||
|
angle = atan2(($total_depth - total_depth_difference), ($height_difference/2 + total_height_difference));
|
||||||
|
hypotenuse = ($total_depth -total_depth_difference) / sin(angle);
|
||||||
|
|
||||||
|
translate([0,-total_key_height()/2,0]) {
|
||||||
|
rotate([-(90-angle), 0, 0]) {
|
||||||
|
translate([0,0,hypotenuse/2]){
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module legends(depth=0) {
|
module outer_shape() {
|
||||||
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) {
|
if ($rounded_key) {
|
||||||
rounded_shape();
|
rounded_shape();
|
||||||
} else {
|
} else {
|
||||||
shape(0, 0);
|
shape(0, 0);
|
||||||
}
|
}
|
||||||
// translation purely for aesthetic purposes, to get rid of that awful lattice
|
}
|
||||||
|
|
||||||
|
module inner_shape(extra_wall_thickness = 0, extra_keytop_thickness = 0) {
|
||||||
translate([0,0,-SMALLEST_POSSIBLE]) {
|
translate([0,0,-SMALLEST_POSSIBLE]) {
|
||||||
shape($wall_thickness, $keytop_thickness);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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(){
|
|
||||||
// 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
|
// additive objects at the top of the key
|
||||||
// outside() makes them stay out of the inside. it's a bad name
|
module additive_features(inset) {
|
||||||
if(!inset && $children > 0) outside() artisan(0) children();
|
top_of_key() {
|
||||||
|
if($key_bump) keybump($key_bump_depth, $key_bump_edge);
|
||||||
|
if(!inset && $children > 0) color($secondary_color) children();
|
||||||
|
}
|
||||||
if($outset_legends) legends(0);
|
if($outset_legends) legends(0);
|
||||||
// render the clearance check if it's enabled, but don't have it intersect with anything
|
// render the clearance check if it's enabled, but don't have it intersect with anything
|
||||||
if ($clearance_check) %clearance_check();
|
if ($clearance_check) %clearance_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
// subtractive objects at the top of the key
|
// subtractive objects at the top of the key
|
||||||
// no outside() - I can't think of a use for it. will save render time
|
module subtractive_features(inset) {
|
||||||
if (inset && $children > 0) artisan($inset_legend_depth) children();
|
top_of_key() {
|
||||||
|
if (inset && $children > 0) color($secondary_color) children();
|
||||||
|
}
|
||||||
if(!$outset_legends) legends($inset_legend_depth);
|
if(!$outset_legends) legends($inset_legend_depth);
|
||||||
// subtract the clearance check if it's enabled, letting the user see the
|
// subtract the clearance check if it's enabled, letting the user see the
|
||||||
// parts of the keycap that will hit the cherry switch
|
// parts of the keycap that will hit the cherry switch
|
||||||
if ($clearance_check) %clearance_check();
|
if ($clearance_check) %clearance_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module inside_features() {
|
||||||
|
translate([0, 0, $stem_inset]) {
|
||||||
// both stem and support are optional
|
// 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);
|
if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type);
|
||||||
|
|
||||||
if ($stem_type != "disable") stems_for($stem_positions, $stem_type);
|
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);
|
if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type);
|
||||||
|
|
||||||
// always render stem support even if there isn't a stem.
|
// 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
|
// 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
|
// so if you want a hollow keycap you'll have to turn support off entirely
|
||||||
support_for($stem_positions, $stem_type);
|
support_for($stem_positions, $stem_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
difference() {
|
||||||
|
minkowski() {
|
||||||
|
difference() {
|
||||||
|
outer_shape();
|
||||||
|
inner_shape();
|
||||||
|
}
|
||||||
|
|
||||||
|
minkowski_object();
|
||||||
|
}
|
||||||
|
|
||||||
|
subtractive_features(inset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* additive_features(inset); */
|
||||||
|
|
||||||
|
/* intersection() {
|
||||||
|
inner_shape($wall_thickness, $keytop_thickness);
|
||||||
|
inside_features();
|
||||||
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
// actual full key with space carved out and keystem/stabilizer connectors
|
// actual full key with space carved out and keystem/stabilizer connectors
|
||||||
|
|
|
@ -1,3 +1,21 @@
|
||||||
|
function sign_x(i,n) =
|
||||||
|
i < n/4 || i > n*3/4 ? 1 :
|
||||||
|
i > n/4 && i < n*3/4 ? -1 :
|
||||||
|
0;
|
||||||
|
|
||||||
|
function sign_y(i,n) =
|
||||||
|
i > 0 && i < n/2 ? 1 :
|
||||||
|
i > n/2 ? -1 :
|
||||||
|
0;
|
||||||
|
|
||||||
|
|
||||||
|
function rectangle_profile(size=[1,1],fn=32) = [
|
||||||
|
for (index = [0:fn-1])
|
||||||
|
let(a = index/fn*360)
|
||||||
|
sign_x(index, fn) * [size[0]/2,0]
|
||||||
|
+ sign_y(index, fn) * [0,size[1]/2]
|
||||||
|
];
|
||||||
|
|
||||||
function rounded_rectangle_profile(size=[1,1],r=1,fn=32) = [
|
function rounded_rectangle_profile(size=[1,1],r=1,fn=32) = [
|
||||||
for (index = [0:fn-1])
|
for (index = [0:fn-1])
|
||||||
let(a = index/fn*360)
|
let(a = index/fn*360)
|
||||||
|
@ -6,12 +24,10 @@ function rounded_rectangle_profile(size=[1,1],r=1,fn=32) = [
|
||||||
+ sign_y(index, fn) * [0,size[1]/2-r]
|
+ sign_y(index, fn) * [0,size[1]/2-r]
|
||||||
];
|
];
|
||||||
|
|
||||||
function sign_x(i,n) =
|
function double_rounded_rectangle_profile(size=[1,1], r=1, fn=32) = [
|
||||||
i < n/4 || i > n-n/4 ? 1 :
|
for (index = [0:fn-1])
|
||||||
i > n/4 && i < n-n/4 ? -1 :
|
let(a = index/fn*360)
|
||||||
0;
|
r * [cos(a), sin(a)]
|
||||||
|
+ sign_x(index, fn) * [size[0]/2-r,0]
|
||||||
function sign_y(i,n) =
|
+ sign_y(index, fn) * [0,size[1]/2-r]
|
||||||
i > 0 && i < n/2 ? 1 :
|
];
|
||||||
i > n/2 ? -1 :
|
|
||||||
0;
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ $outset_legends = false;
|
||||||
// Height in units of key. should remain 1 for most uses
|
// Height in units of key. should remain 1 for most uses
|
||||||
$key_height = 1.0;
|
$key_height = 1.0;
|
||||||
// Keytop thickness, aka how many millimeters between the inside and outside of the top surface of the key
|
// Keytop thickness, aka how many millimeters between the inside and outside of the top surface of the key
|
||||||
$keytop_thickness = 1;
|
$keytop_thickness = 2;
|
||||||
// Wall thickness, aka the thickness of the sides of the keycap. note this is the total thickness, aka 3 = 1.5mm walls
|
// 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;
|
$wall_thickness = 3;
|
||||||
// Radius of corners of keycap
|
// Radius of corners of keycap
|
||||||
|
@ -86,7 +86,7 @@ $extra_long_stem_support = false;
|
||||||
|
|
||||||
// Key shape type, determines the shape of the key. default is 'rounded square'
|
// Key shape type, determines the shape of the key. default is 'rounded square'
|
||||||
$key_shape_type = "rounded_square";
|
$key_shape_type = "rounded_square";
|
||||||
// ISO enter needs to be linear extruded NOT from the center. this tells the program how far up 'not from the center' is
|
// ISO enter needs to be linear extruded NOT from the center when not using skin. this tells the program how far up 'not from the center' is
|
||||||
$linear_extrude_height_adjustment = 0;
|
$linear_extrude_height_adjustment = 0;
|
||||||
// How many slices will be made, to approximate curves on corners. Leave at 1 if you are not curving corners
|
// How many slices will be made, to approximate curves on corners. Leave at 1 if you are not curving corners
|
||||||
// If you're doing fancy bowed keycap sides, this controls how many slices you take
|
// If you're doing fancy bowed keycap sides, this controls how many slices you take
|
||||||
|
@ -183,3 +183,16 @@ $secondary_color = [.4412, .7, .3784];
|
||||||
$tertiary_color = [1, .6941, .2];
|
$tertiary_color = [1, .6941, .2];
|
||||||
$quaternary_color = [.4078, .3569, .749];
|
$quaternary_color = [.4078, .3569, .749];
|
||||||
$warning_color = [1,0,0, 0.15];
|
$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;
|
||||||
|
|
|
@ -32,9 +32,11 @@ module key_shape(size, delta, progress = 0) {
|
||||||
|
|
||||||
function skin_key_shape(size, delta, progress = 0, thickness_difference) =
|
function skin_key_shape(size, delta, progress = 0, thickness_difference) =
|
||||||
$key_shape_type == "rounded_square" ?
|
$key_shape_type == "rounded_square" ?
|
||||||
skin_rounded_square(size, delta, progress) :
|
skin_rounded_square(size, delta, progress, thickness_difference) :
|
||||||
$key_shape_type == "sculpted_square" ?
|
$key_shape_type == "sculpted_square" ?
|
||||||
skin_sculpted_square_shape(size, delta, progress) :
|
skin_sculpted_square_shape(size, delta, progress, thickness_difference) :
|
||||||
|
$key_shape_type == "square" ?
|
||||||
|
skin_square_shape(size, delta, progress, thickness_difference) :
|
||||||
$key_shape_type == "iso_enter" ?
|
$key_shape_type == "iso_enter" ?
|
||||||
skin_iso_enter_shape(size, delta, progress, thickness_difference) :
|
skin_iso_enter_shape(size, delta, progress, thickness_difference) :
|
||||||
echo("Warning: unsupported $key_shape_type for skin shape. disable skin_extrude_shape or pick a new shape");
|
echo("Warning: unsupported $key_shape_type for skin shape. disable skin_extrude_shape or pick a new shape");
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
include <../libraries/rounded_rectangle_profile.scad>
|
include <../libraries/rounded_rectangle_profile.scad>
|
||||||
|
|
||||||
module rounded_square_shape(size, delta, progress, center = true) {
|
module rounded_square_shape(size, delta, progress, center = true) {
|
||||||
offset(r=$corner_radius){
|
offset(r=$corner_radius, $fa=360/$shape_facets){
|
||||||
square_shape([size.x - $corner_radius*2, size.y - $corner_radius*2], delta, progress);
|
square_shape([size.x - $corner_radius*2, size.y - $corner_radius*2], delta, progress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for skin
|
// for skin
|
||||||
|
|
||||||
function skin_rounded_square(size, delta, progress) =
|
function skin_rounded_square(size, delta, progress, thickness_difference) =
|
||||||
rounded_rectangle_profile(size - (delta * progress), fn=36, r=$corner_radius);
|
rounded_rectangle_profile(size - (delta * progress) - [thickness_difference, thickness_difference]*2, fn=$shape_facets, r=$corner_radius);
|
||||||
|
|
|
@ -37,7 +37,7 @@ module sculpted_square_shape(size, delta, progress) {
|
||||||
height - extra_height_this_slice
|
height - extra_height_this_slice
|
||||||
];
|
];
|
||||||
|
|
||||||
offset(r = extra_corner_radius_this_slice) {
|
offset(r = extra_corner_radius_this_slice, $fa=360/$shape_facets) {
|
||||||
offset(r = -extra_corner_radius_this_slice) {
|
offset(r = -extra_corner_radius_this_slice) {
|
||||||
side_rounded_square(square_size, r = $more_side_sculpting_factor * progress);
|
side_rounded_square(square_size, r = $more_side_sculpting_factor * progress);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ module sculpted_square_shape(size, delta, progress) {
|
||||||
|
|
||||||
// fudging the hell out of this, I don't remember what the negative-offset-positive-offset was doing in the module above
|
// fudging the hell out of this, I don't remember what the negative-offset-positive-offset was doing in the module above
|
||||||
// also no 'bowed' square shape for now
|
// also no 'bowed' square shape for now
|
||||||
function skin_sculpted_square_shape(size, delta, progress) =
|
function skin_sculpted_square_shape(size, delta, progress, thickness_difference) =
|
||||||
let(
|
let(
|
||||||
width = size[0],
|
width = size[0],
|
||||||
height = size[1],
|
height = size[1],
|
||||||
|
@ -64,10 +64,10 @@ function skin_sculpted_square_shape(size, delta, progress) =
|
||||||
extra_corner_radius_this_slice = ($corner_radius + extra_corner_size),
|
extra_corner_radius_this_slice = ($corner_radius + extra_corner_size),
|
||||||
|
|
||||||
square_size = [
|
square_size = [
|
||||||
width - extra_width_this_slice,
|
width - extra_width_this_slice - thickness_difference,
|
||||||
height - extra_height_this_slice
|
height - extra_height_this_slice - thickness_difference
|
||||||
]
|
]
|
||||||
) 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=36, 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) {
|
||||||
offset(r = -extra_corner_radius_this_slice) {
|
offset(r = -extra_corner_radius_this_slice) {
|
||||||
|
@ -85,10 +85,10 @@ module side_rounded_square(size, r) {
|
||||||
sw = iw / resolution;
|
sw = iw / resolution;
|
||||||
union() {
|
union() {
|
||||||
if (sr > 0) {
|
if (sr > 0) {
|
||||||
translate([-iw/2, 0]) scale([sr, sh]) circle(d = resolution);
|
translate([-iw/2, 0]) scale([sr, sh]) circle(d = resolution, $fa=360/$shape_facets);
|
||||||
translate([iw/2, 0]) scale([sr, sh]) circle(d = resolution);
|
translate([iw/2, 0]) scale([sr, sh]) circle(d = resolution, $fa=360/$shape_facets);
|
||||||
translate([0, -ih/2]) scale([sw, sr]) circle(d = resolution);
|
translate([0, -ih/2]) scale([sw, sr]) circle(d = resolution, $fa=360/$shape_facets);
|
||||||
translate([0, ih/2]) scale([sw, sr]) circle(d = resolution);
|
translate([0, ih/2]) scale([sw, sr]) circle(d = resolution, $fa=360/$shape_facets);
|
||||||
}
|
}
|
||||||
square([iw, ih], center=true);
|
square([iw, ih], center=true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use <../functions.scad>
|
use <../functions.scad>
|
||||||
|
include <../libraries/rounded_rectangle_profile.scad>
|
||||||
|
|
||||||
|
|
||||||
// we do this weird key_shape_type check here because rounded_square uses
|
// we do this weird key_shape_type check here because rounded_square uses
|
||||||
// square_shape, and we want flat sides to work for that too.
|
// square_shape, and we want flat sides to work for that too.
|
||||||
|
@ -28,3 +30,17 @@ module flat_sided_square_shape(size, delta, progress) {
|
||||||
[(-size.x + (delta.x - extra_keytop_length_for_flat_sides()) * progress)/2, (size.y - delta.y * progress)/2]
|
[(-size.x + (delta.x - extra_keytop_length_for_flat_sides()) * progress)/2, (size.y - delta.y * progress)/2]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function skin_square_shape(size, delta, progress, thickness_difference) =
|
||||||
|
let(
|
||||||
|
width = size[0],
|
||||||
|
height = size[1],
|
||||||
|
|
||||||
|
width_difference = delta[0] * progress,
|
||||||
|
height_difference = delta[1] * progress,
|
||||||
|
|
||||||
|
square_size = [
|
||||||
|
width - width_difference - thickness_difference,
|
||||||
|
height - height_difference - thickness_difference
|
||||||
|
]
|
||||||
|
) rectangle_profile(square_size, fn=36);
|
||||||
|
|
Loading…
Reference in New Issue