// --- Parameters --- columns = 4; // Numpad Width rows = 6; // Numpad Height switch_spacing = 19.05; switch_outer_width = 14.2; switch_total_height = 14.2; margin = 5.0; plate_w = (columns - 1) * switch_spacing + switch_outer_width + (margin * 2); plate_h = (rows - 1) * switch_spacing + switch_total_height + (margin * 2); // --- Plate --- plate_thickness = 1.5; plate_slack = 0.15; recess_depth = 2.5; // --- Case Dimensions --- case_angle = 5; wall_thickness = 4.0; front_height = 18.0; clearance = 0.25; floor_thickness = 4.0; rim_extra_height = 3.0; pillar_dia = 3; case_w = plate_w + (wall_thickness * 2) + (clearance * 2) - 2; case_h = (plate_h * cos(case_angle)) + (wall_thickness * 2) + (clearance * 2) - 2 * cos(case_angle); back_height = front_height + (tan(case_angle) * case_h); // --- USB-C and Controller Holder --- usb_w = 12.0; usb_h = 6.5; usb_x_offset = (case_w / 2) - (usb_w / 2); usb_z_pos = floor_thickness; holder_x = 20.0; holder_y = 30.0; holder_height = 5.0; holder_wall = 2.0; // --- Clips --- clip_width = 10.0; clip_depth = 1.5; clip_height = 1.5; module controller_holder() { x_pos = (case_w / 2) - (holder_x / 2) - holder_wall; y_inner_wall = case_h - wall_thickness; y_pos = y_inner_wall - holder_y - holder_wall; translate([x_pos, y_pos, floor_thickness]) { difference() { cube([holder_x + (holder_wall * 2), holder_y + holder_wall, holder_height]); translate([holder_wall, holder_wall, -0.1]) cube([holder_x, holder_y + 0.1, holder_height + 0.2]); } } } module usb_cutout() { translate([usb_x_offset, case_h - wall_thickness - 1, usb_z_pos]) cube([usb_w, wall_thickness + 2, usb_h]); } module angled_clip() { color("red") rotate([case_angle, 0, 0]) cube([clip_width, clip_depth, clip_height]); } module support_pillars() { col_gaps = [1, 3]; row_gaps = [1, 3, 5]; plate_start_x = (case_w - plate_w)/2 - 2; plate_start_y = (case_h - (plate_h * cos(case_angle)))/2 - 2 * cos(case_angle); intersection() { union() { for (c = col_gaps) { for (r = row_gaps) { x_pos = plate_start_x + margin + (c * switch_spacing); y_pos_flat = margin + (r * switch_spacing); y_pos = plate_start_y + (y_pos_flat * cos(case_angle)); translate([x_pos, y_pos, 0]) cylinder(d = pillar_dia, h = back_height + 10, $fn = 32); } } } translate([0, plate_start_y, front_height - recess_depth]) rotate([case_angle, 0, 0]) translate([-50, 0, -500]) cube([case_w + 100, plate_h, 500]); } } module case_full_geometry() { clip_z_offset = plate_thickness + plate_slack; recess_w = plate_w + (plate_slack * 2); recess_h = plate_h + (plate_slack * 2); union() { difference() { // Shell polyhedron( points=[ [0,0,0], [case_w,0,0], [case_w,case_h,0], [0,case_h,0], [0,0,front_height + rim_extra_height], [case_w,0,front_height + rim_extra_height], [0,case_h,back_height + rim_extra_height], [case_w,case_h,back_height + rim_extra_height] ], faces=[[0,1,2,3], [4,5,1,0], [7,6,3,2], [5,7,2,1], [6,4,0,3], [4,6,7,5]] ); // Internal Tub translate([wall_thickness, wall_thickness, floor_thickness]) cube([case_w - (wall_thickness * 2), case_h - (wall_thickness * 2), back_height + 20]); // Plate Recess translate([(case_w - recess_w)/2, (case_h - (recess_h * cos(case_angle)))/2, front_height - recess_depth]) rotate([case_angle, 0, 0]) cube([recess_w, recess_h, 20]); } support_pillars(); // Clips (Reduced number for smaller case) for (i = [0:2]) { z_front = (front_height - recess_depth) + clip_z_offset; translate([wall_thickness + (case_w - wall_thickness*2)/4 * (i+1) - clip_width/2, wall_thickness - clip_depth, z_front]) angled_clip(); y_back_wall = case_h - wall_thickness; z_back_shelf = (front_height - recess_depth) + (tan(case_angle) * (y_back_wall - wall_thickness)); z_back_clip = z_back_shelf + clip_z_offset; translate([wall_thickness + (case_w - wall_thickness*2)/4 * (i+1) - clip_width/2, y_back_wall - clip_depth * 0.5, z_back_clip]) angled_clip(); } } } // --- Final Render (Single Part) --- difference() { case_full_geometry(); usb_cutout(); } controller_holder();