tweak the fit of the parts

This commit is contained in:
Nick Estes
2026-08-04 12:27:31 -07:00
parent 45a77885f9
commit 69d9b956e6
41 changed files with 5378 additions and 324 deletions
+63 -4
View File
@@ -2,16 +2,23 @@
module FeatherCaseWizard
class PackageBuilder
attr_reader :config, :root, :toolchain, :model_source, :renderer_source
attr_reader :config, :root, :toolchain, :model_source, :renderer_source,
:multicolor_renderer_source, :multicolor_packager_source, :logo_source
def initialize(config, root: CASES_ROOT, toolchain: Toolchain.new,
model_source: MODEL_SOURCE, renderer_source: RENDERER_SOURCE,
multicolor_renderer_source: MULTICOLOR_RENDERER_SOURCE,
multicolor_packager_source: MULTICOLOR_PACKAGER_SOURCE,
logo_source: LOGO_SOURCE,
reporter: nil)
@config = config
@root = Pathname(root)
@toolchain = toolchain
@model_source = Pathname(model_source)
@renderer_source = Pathname(renderer_source)
@multicolor_renderer_source = Pathname(multicolor_renderer_source)
@multicolor_packager_source = Pathname(multicolor_packager_source)
@logo_source = Pathname(logo_source)
@reporter = reporter || ->(_message) {}
end
@@ -37,13 +44,22 @@ module FeatherCaseWizard
def verify_sources!
raise ToolError, "Missing model source: #{model_source}" unless model_source.file?
raise ToolError, "Missing preview renderer: #{renderer_source}" unless renderer_source.file?
raise ToolError, "Missing multicolor renderer: #{multicolor_renderer_source}" unless
multicolor_renderer_source.file?
raise ToolError, "Missing multicolor packager: #{multicolor_packager_source}" unless
multicolor_packager_source.file?
raise ToolError, "Missing lid logo: #{logo_source}" unless logo_source.file?
end
def prepare_package(stage, previous)
source_dir = stage.join("source")
FileUtils.mkdir_p(source_dir)
tools_dir = stage.join("tools")
FileUtils.mkdir_p([source_dir, source_dir.join("assets"), tools_dir])
FileUtils.cp(model_source, source_dir.join("feather_case.scad"))
FileUtils.cp(renderer_source, source_dir.join("render_stl_previews.py"))
FileUtils.cp(multicolor_renderer_source, source_dir.join("render_multicolor_lid.py"))
FileUtils.cp(multicolor_packager_source, tools_dir.join("package_multimaterial_3mf.py"))
FileUtils.cp(logo_source, source_dir.join("assets/NME-fixed.svg"))
FileUtils.cp(ROOT.join("templates/standalone_build.rb"), stage.join("build.rb"))
copy_history(previous, stage)
@@ -91,9 +107,26 @@ module FeatherCaseWizard
report("Exporting #{part}.#{format}")
export_model(stage, directory.join("#{part}.#{format}"), part)
end
package_multicolor_lid(stage, directory) if format == "3mf" && config.lid_artwork?
end
end
def package_multicolor_lid(stage, directory)
report("Packaging lid_multicolor.3mf")
command = [
toolchain.python,
stage.join("tools/package_multimaterial_3mf.py").to_s,
directory.join("lid_base.3mf").to_s,
directory.join("lid_accent.3mf").to_s,
directory.join("lid_multicolor.3mf").to_s,
"--title", "#{config.name} Lid"
]
toolchain.run!(*command)
output = directory.join("lid_multicolor.3mf")
raise ToolError, "Multicolor packager did not create #{output}" unless
output.file? && output.size.positive?
end
def generate_previews(stage)
previews = stage.join("previews")
scratch = stage.join(".preview-meshes")
@@ -111,9 +144,22 @@ module FeatherCaseWizard
export_model(stage, mesh, part) unless mesh.file?
render(stage, mesh, previews, part, ["iso"])
end
render_multicolor_lid(stage, scratch, previews) if config.lid_artwork?
FileUtils.rm_rf(scratch)
end
def render_multicolor_lid(stage, scratch, previews)
report("Rendering multicolor lid preview")
command = [
toolchain.blender, "--background", "-noaudio", "--python",
stage.join("source/render_multicolor_lid.py").to_s, "--",
scratch.join("lid_base.stl").to_s,
scratch.join("lid_accent.stl").to_s,
previews.to_s, "lid_multicolor", config.parameters["lid_art_orientation"]
]
toolchain.run!(*command, env: {"DISPLAY" => nil, "WAYLAND_DISPLAY" => nil})
end
def export_model(stage, output, part, overrides = {})
model = stage.join("source/feather_case.scad")
parameters = config.model_parameters.merge(overrides).merge("part" => part)
@@ -139,6 +185,18 @@ module FeatherCaseWizard
def write_summary(stage)
dims = config.dimensions
parts = config.printable_parts.map { |part| "`#{part}`" }.join(", ")
artwork = if config.lid_artwork?
<<~ARTWORK.chomp
For a two-color lid, open `exports/3mf/lid_multicolor.3mf` as one
multipart object. Assign “Lid base — Filament 1” and “Accent inlays —
Filament 2” to the desired filaments. `lid.3mf` is the complete
single-color fallback; `lid_base.3mf` and `lid_accent.3mf` are also
provided separately.
ARTWORK
else
""
end
text = <<~MARKDOWN
# #{config.name}
@@ -154,8 +212,8 @@ module FeatherCaseWizard
- Custom cutouts: #{config.cutouts.length}
Run `ruby build.rb` in this directory to regenerate exports and previews.
OpenSCAD and Blender must be installed. Set `OPENSCAD` or `BLENDER` to
override their executable paths.
OpenSCAD, Blender, and Python 3 must be installed. Set `OPENSCAD`,
`BLENDER`, or `PYTHON` to override their executable paths.
To open the saved Customizer values manually:
@@ -165,6 +223,7 @@ module FeatherCaseWizard
The 3MF files contain portable geometry only. Choose printer, filament,
plate, and slicing settings in Bambu Studio.
#{artwork}
MARKDOWN
File.write(stage.join("README.md"), text)
end