91 lines
3.0 KiB
Ruby
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')}"
|