diff --git a/src/case.scad b/src/case.scad index 730bffe..29aa6e4 100644 --- a/src/case.scad +++ b/src/case.scad @@ -9,10 +9,17 @@ MarginCameraCut = 1; MarginButtonsCut = 2.0; MarginPortsCut = 7.0; -// radial margin +// radial margin. how much the buttons are allowed to drift within the button mold. MarginButtonsSeat = 1.0; // x margin (how extra thick the buttons could be) MarginButtonsSeatX = 0.2; + +// width of the cut *surrounding* the buttons +ButtonsTabGap = 2.5; +ButtonsTabInset = 0.4; +ButtonsTabBumpWidth = 1.0; +ButtonsTabBumpLength = 3.0; + // how far into the xy plane to extend the part of the case which covers the front of the phone. // the top of the phone contains stuff we don't want to cover (camera); the bottom has more margin FrontOverhangX = 2; @@ -137,7 +144,7 @@ module _FrontKeep(tol=tol) { }; } -/// complete case except for cutouts +/// complete case except for cutouts, button style module _CaseExceptFeatures(ButtonStyle, tol=tol) { body = 0; @@ -163,38 +170,119 @@ module _CaseExceptFeatures(ButtonStyle, tol=tol) }; } +// create a cutout next to the buttons, +// and also make the outer model thinner. +module _ApplyButtonTabCuts() { + case = 0; + buttons = 1; + difference() { + children(case); + union() { + // full cut through plastic to help the button covers flex + difference() { + minkowski() { + // cylinderX(r=ButtonsTabGap, h=2*Thickness, center=true); + cube([2*Thickness, ButtonsTabGap, tol], center=true); + children(buttons); + }; + minkowski() { + // cylinderX(r=tol, h=2*Thickness, center=true); + cube([2*Thickness, tol, 2*tol], center=true); + children(buttons); + }; + }; + // make the walls around the buttons extra thin + translate([Thickness-ButtonsTabInset, 0, 0]) children(buttons); + }; + }; +} + +/// given a subset of the buttons geometry, +/// shift and extrude that to give it depth. +module _RaiseButtons() { + translate([Thickness-ButtonsTabInset, 0, 0]) + minkowski() { + translate([0, -tol/2, -tol/2]) cube([ButtonsTabBumpWidth, tol, tol], center=false); + difference() { + children(0); + translate([tol, 0, 0]) children(0); + // translate([ButtonsTabBumpWidth, 0, 0]) children(0); + }; + }; +}; + +module _ApplyButtonTabBumps() { + case = 0; + buttons = 1; + union() { + children(case); + _RaiseButtons() + difference() { + children(buttons); + // subtract the inside portions of the buttons + intersection() { + minkowski() { + translate([0, ButtonsTabBumpLength, 0]) cube([2*tol, ButtonsTabBumpLength+tol, 2*tol], center=true); + children(buttons); + }; + minkowski() { + translate([0, -ButtonsTabBumpLength, 0]) cube([2*tol, ButtonsTabBumpLength+tol, 2*tol], center=true); + children(buttons); + }; + }; + }; + }; +}; + +module _ApplyButtonStyle(ButtonStyle) { + case = 0; + buttons = 1; + if (ButtonStyle == "tab") { + _ApplyButtonTabBumps() { + _ApplyButtonTabCuts() { + children(case); + children(buttons); + }; + children(buttons); + }; + }; +} + module _Case(ButtonStyle) { body = 0; buttons = 1; ports = 2; camera = 3; - difference() { - _CaseExceptFeatures(ButtonStyle=ButtonStyle) { - children(body); - children(buttons); - }; - union() { - // then the cutouts - _PeripheralCutouts(ButtonStyle=ButtonStyle) { + _ApplyButtonStyle(ButtonStyle=ButtonStyle) { + difference() { + _CaseExceptFeatures(ButtonStyle=ButtonStyle) { children(body); children(buttons); - children(ports); - children(camera); }; - // subtract the buttons (we want to give them a buffer even if ButtonStyle=extrude) - minkowski() { - cylinderX(r=MarginButtonsSeat, h=MarginButtonsSeatX, center=true); - children(buttons); - }; - } - } + union() { + // then the cutouts + _PeripheralCutouts(ButtonStyle=ButtonStyle) { + children(body); + children(buttons); + children(ports); + children(camera); + }; + // subtract the buttons (we want to give them a buffer even if ButtonStyle=extrude) + minkowski() { + cylinderX(r=MarginButtonsSeat, h=MarginButtonsSeatX, center=true); + children(buttons); + }; + } + }; + children(buttons); + }; } /// create a case for the provided phone. /// /// ``` -/// Case(ButtonStyle="extrude"|"cut") { +/// Case(ButtonStyle="extrude"|"cut"|"tab") { /// PhoneBody(); /// PhoneButtons(); /// PhonePorts(); @@ -203,7 +291,7 @@ module _Case(ButtonStyle) /// ``` /// /// replace "Phone" above with the specific model, e.g. `PP` like `PPBody()` -module Case(ButtonStyle="extrude", RenderPhone=false, OrientForPrint=true) { +module Case(ButtonStyle="tab", RenderPhone=false, OrientForPrint=true) { body = 0; buttons = 1; ports = 2; diff --git a/src/cases/pp.scad b/src/cases/pp.scad index 6eb6d6d..db8cfb6 100644 --- a/src/cases/pp.scad +++ b/src/cases/pp.scad @@ -1,7 +1,8 @@ +include <../lib/defaults.scad> use <../case.scad> use <../pp/exports.scad> -Case(RenderPhone=false, OrientForPrint=true) { +Case(ButtonStyle="tab", RenderPhone=false, OrientForPrint=!$preview) { PPBody(); PPButtons(); PPPorts(); diff --git a/src/lib/primitives.scad b/src/lib/primitives.scad index 0104209..5dcac76 100644 --- a/src/lib/primitives.scad +++ b/src/lib/primitives.scad @@ -7,57 +7,57 @@ module empty() {} /// cylinder() but with the axis on the x axis instead of the z axis. /// and where `center=false` behaves like for `cube(center=false)`, /// i.e. circle center is not at (0, 0) but (r, r) -module cylinderX(d=undef, r=undef, h=undef, center=false) { +module cylinderX(d=undef, r=undef, h=undef, center=false, $fs=$fs) { _translateIf(!center, [0, _toRad(r=r, d=d), _toRad(r=r, d=d)]) { - rotate(a=[0,90,0]) cylinder(d=d, r=r, h=h, center=center); + rotate(a=[0,90,0]) cylinder(d=d, r=r, h=h, center=center, $fs=$fs); } } /// cylinder() but with the axis on the y axis instead of the z axis /// and where `center=false` behaves like for `cube(center=false)`, /// i.e. circle center is not at (0, 0) but (r, r) -module cylinderY(d=undef, r=undef, h=undef, center=false) { +module cylinderY(d=undef, r=undef, h=undef, center=false, $fs=$fs) { _translateIf(!center, [_toRad(r=r, d=d), 0, _toRad(r=r, d=d)]) { - rotate(a=[-90,0,0]) cylinder(d=d, r=r, h=h, center=center); + rotate(a=[-90,0,0]) cylinder(d=d, r=r, h=h, center=center, $fs=$fs); } } /// cylinder() where `center=false` behaves like for `cube(center=false)`, /// i.e. circle center is not at (0, 0) but (r, r) -module cylinderZ(d=undef, r=undef, h=undef, center=false) { +module cylinderZ(d=undef, r=undef, h=undef, center=false, $fs=$fs) { _translateIf(!center, [_toRad(r=r, d=d), _toRad(r=r, d=d), 0]) { - cylinder(d=d, r=r, h=h, center=center); + cylinder(d=d, r=r, h=h, center=center, $fs=$fs); } } // a 2d-cylinder normal to the x axis, and elongated over the y/z axis. -module pillX(dimX, dimY, dimZ, center=false) { +module pillX(dimX, dimY, dimZ, center=false, $fs=$fs) { diam = min(dimY, dimZ); hull() { - cylinderX(d=diam, h=dimX, center=center); - translate([0, dimY-diam, dimZ-diam]) cylinderX(d=diam, h=dimX, center=center); + cylinderX(d=diam, h=dimX, center=center, $fs=$fs); + translate([0, dimY-diam, dimZ-diam]) cylinderX(d=diam, h=dimX, center=center, $fs=$fs); }; } // a 2d-cylinder normal to the y axis, and elongated over the x/z axis. -module pillY(dimX, dimY, dimZ, center=false) { +module pillY(dimX, dimY, dimZ, center=false, $fs=$fs) { diam = min(dimX, dimZ); hull() { - cylinderY(d=diam, h=dimY, center=center); - translate([dimX-diam, 0, dimZ-diam]) cylinderY(d=diam, h=dimY, center=center); + cylinderY(d=diam, h=dimY, center=center, $fs=$fs); + translate([dimX-diam, 0, dimZ-diam]) cylinderY(d=diam, h=dimY, center=center, $fs=$fs); }; } // a 2d-cylinder normal to the z axis, and elongated over the x/y axis. -module pillZ(dimX, dimY, dimZ, center=false) { +module pillZ(dimX, dimY, dimZ, center=false, $fs=$fs) { diam = min(dimX, dimY); hull() { - cylinderZ(d=diam, h=dimZ, center=center); - translate([dimX-diam, dimY-diam, 0]) cylinderZ(d=diam, h=dimZ, center=center); + cylinderZ(d=diam, h=dimZ, center=center, $fs=$fs); + translate([dimX-diam, dimY-diam, 0]) cylinderZ(d=diam, h=dimZ, center=center, $fs=$fs); }; } -module sphere_(r, align=undef, alignX=undef, alignY=undef, alignZ=undef) { +module sphere_(r, align=undef, alignX=undef, alignY=undef, alignZ=undef, $fs=$fs) { alignX_ = _default(alignX, align); alignY_ = _default(alignY, align); alignZ_ = _default(alignZ, align); @@ -66,7 +66,7 @@ module sphere_(r, align=undef, alignX=undef, alignY=undef, alignZ=undef) { sY = _selectScale(alignY); sZ = _selectScale(alignZ); - translate([r * sX, r * sY, r * sZ]) sphere(r=r); + translate([r * sX, r * sY, r * sZ]) sphere(r=r, $fs=$fs); } function _default(primary, secondary) = (primary != undef) ? primary : secondary;