Files
copy_stand/build.rb
T
2026-08-22 11:31:10 -07:00

91 lines
3.0 KiB
Ruby

#!/usr/bin/env ruby
# frozen_string_literal: true
require "fileutils"
require "open3"
ROOT = File.expand_path(__dir__)
SCAD = File.join(ROOT, "copy_stand.scad")
OPENSCAD = ENV.fetch("OPENSCAD", "openscad")
PYTHON = ENV.fetch("PYTHON", "python3")
EXPORT_3MF = File.join(ROOT, "exports", "3mf")
EXPORT_STL = File.join(ROOT, "exports", "stl")
COMPONENT_3MF = File.join(EXPORT_3MF, "components")
COMPONENT_STL = File.join(EXPORT_STL, "components")
def run!(*command)
puts command.join(" ")
output, status = Open3.capture2e(*command)
puts output unless output.empty?
raise "Command failed: #{command.join(' ')}" unless status.success?
end
def export(part, directory, extension)
output = File.join(directory, "#{part}.#{extension}")
return output if ENV["REBUILD"] != "1" && File.size?(output)
run!(OPENSCAD, "-o", output, "-D", %(part="#{part}"), SCAD)
output
end
def export_segment(part, index, directory, extension)
output = File.join(directory, "#{part}_#{index}.#{extension}")
return output if ENV["REBUILD"] != "1" && File.size?(output)
run!(OPENSCAD, "-o", output, "-D", %(part="#{part}"),
"-D", "segment_index=#{index}", SCAD)
output
end
def package(output, title, bases, accents = [])
command = [
PYTHON, File.join(ROOT, "tools", "package_multimaterial_3mf.py"),
output, "--title", title
]
bases.each { |path| command.concat(["--base", path]) }
accents.each { |path| command.concat(["--accent", path]) }
run!(*command)
end
FileUtils.mkdir_p([EXPORT_3MF, EXPORT_STL, COMPONENT_3MF, COMPONENT_STL])
%w[base_accent socket coupon coupon_black coupon_key coupon_accent].each do |part|
export(part, EXPORT_3MF, "3mf")
end
%w[socket coupon coupon_key].each do |part|
export(part, EXPORT_STL, "stl")
end
base_segments = (0..5).map do |index|
export_segment("base_segment", index, COMPONENT_3MF, "3mf")
end
black_segments = (0..5).map do |index|
export_segment("base_black_segment", index, COMPONENT_3MF, "3mf")
end
package(File.join(EXPORT_3MF, "base.3mf"), "Copy Stand Base - Single Color",
base_segments)
package(File.join(EXPORT_3MF, "base_black.3mf"), "Copy Stand Base - Black Mesh",
black_segments)
package(File.join(EXPORT_3MF, "base_multicolor.3mf"), "Copy Stand Base",
black_segments, [File.join(EXPORT_3MF, "base_accent.3mf")])
package(File.join(EXPORT_3MF, "coupon_multicolor.3mf"),
"Copy Stand Calibration Coupon",
[File.join(EXPORT_3MF, "coupon_black.3mf"),
File.join(EXPORT_3MF, "coupon_key.3mf")],
[File.join(EXPORT_3MF, "coupon_accent.3mf")])
# A multi-solid ASCII STL fallback avoids forcing OpenSCAD/CGAL to union the
# large stepped base in one expensive operation. Slicers merge the touching
# solids at slice time.
segment_stls = (0..5).map do |index|
export_segment("base_segment", index, COMPONENT_STL, "stl")
end
File.open(File.join(EXPORT_STL, "base.stl"), "wb") do |combined|
segment_stls.each { |path| combined.write(File.binread(path)) }
end
puts "Exports written to #{File.join(ROOT, 'exports')}"