mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-07-25 04:44:30 +08:00
#152manual seam placement tool, inspired from @dartrax pull request
Currently it only use the center of sphere, using the nearest z for each layer.
This commit is contained in:
parent
8438de487b
commit
a1acd5b167
75
resources/icons/add_seam.svg
Normal file
75
resources/icons/add_seam.svg
Normal file
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.0"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 16 16"
|
||||
enable-background="new 0 0 16 16"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="add_seam.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
|
||||
id="metadata12"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs10"><linearGradient
|
||||
id="linearGradient4549-6-6"
|
||||
inkscape:collect="always"><stop
|
||||
id="stop4568"
|
||||
offset="0"
|
||||
style="stop-color:#ed6b21;stop-opacity:1;" /><stop
|
||||
id="stop4570"
|
||||
offset="1"
|
||||
style="stop-color:#808080;stop-opacity:1" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4549-6-6"
|
||||
id="linearGradient4551"
|
||||
x1="0.95844549"
|
||||
y1="2.2075603"
|
||||
x2="15.084078"
|
||||
y2="2.2075603"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-1,0,0,1,16.042524,0)" /></defs><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1001"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
inkscape:zoom="22.627417"
|
||||
inkscape:cx="14.547048"
|
||||
inkscape:cy="-0.37641358"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#ed6b21;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 14.584078,1.5485052 V 14.453204 H 8.883029 v -1.370019"
|
||||
id="path4526"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
style="fill:#000000;fill-opacity:0;stroke:#808080;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 1.4805051,1.5636706 V 14.468368 h 5.701048 v -1.370019"
|
||||
id="path4526-6"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
style="fill:none;stroke:url(#linearGradient4551);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 14.584116,3.3604663 14.562019,1.5636706 1.4584455,1.5485056 v 1.8119611"
|
||||
id="path4543"
|
||||
inkscape:connector-curvature="0" /></svg>
|
After Width: | Height: | Size: 2.9 KiB |
@ -3120,7 +3120,7 @@ void GCode::split_at_seam_pos(ExtrusionLoop &loop, std::unique_ptr<EdgeGrid::Gri
|
||||
Point last_pos = this->last_pos();
|
||||
if (m_config.spiral_vase) {
|
||||
loop.split_at(last_pos, false);
|
||||
} else if (seam_position == spNearest || seam_position == spAligned || seam_position == spRear || seam_position == spHidden) {
|
||||
} else if (seam_position == spNearest || seam_position == spAligned || seam_position == spRear || seam_position == spHidden || seam_position == spCustom) {
|
||||
Polygon polygon = loop.polygon();
|
||||
const coordf_t nozzle_dmr = EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, loop.paths.front().width);
|
||||
const coord_t nozzle_r = coord_t(scale_(0.5 * nozzle_dmr) + 0.5);
|
||||
@ -3128,6 +3128,33 @@ void GCode::split_at_seam_pos(ExtrusionLoop &loop, std::unique_ptr<EdgeGrid::Gri
|
||||
// Retrieve the last start position for this object.
|
||||
float last_pos_weight = 1.f;
|
||||
|
||||
if (seam_position == spCustom) {
|
||||
// Seam is aligned to be nearest to the position of a "lambda-seam"-named modifier in this or any preceding layer
|
||||
last_pos = m_layer->object()->bounding_box().center();
|
||||
// Look for all lambda-seam-modifiers below current z, choose the highest one
|
||||
ModelVolume *v_lambda_seam = nullptr;
|
||||
Vec3d lambda_pos;
|
||||
for (ModelVolume *v : m_layer->object()->model_object()->volumes)
|
||||
if (v->is_seam_position()) {
|
||||
Vec3d test_lambda_pos = m_layer->object()->model_object()->instances.front()->transform_vector(v->get_offset());
|
||||
//use this one if the first or nearer (in z)
|
||||
if (v_lambda_seam == nullptr || std::abs(m_layer->print_z - test_lambda_pos.z()) < std::abs(m_layer->print_z - lambda_pos.z())) {
|
||||
v_lambda_seam = v;
|
||||
lambda_pos = m_layer->object()->model_object()->instances.front()->transform_vector(v_lambda_seam->get_offset());
|
||||
}
|
||||
}
|
||||
|
||||
if (v_lambda_seam != nullptr) {
|
||||
lambda_pos = m_layer->object()->model_object()->instances.front()->transform_vector(v_lambda_seam->get_offset(), true);
|
||||
// Found, get the center point and apply rotation and scaling of Model instance. Continues to spAligned if not found or Weight set to Zero.
|
||||
last_pos = Point::new_scale(lambda_pos.x(), lambda_pos.y());
|
||||
// Weight is set by user and stored in the radius of the sphere
|
||||
double weight_temp = (m_layer->object()->model_object()->instances.front()->transform_bounding_box(v_lambda_seam->mesh().bounding_box(), true).size().x() / 2.0);
|
||||
last_pos_weight = std::max(0.0, std::round(100 * (weight_temp - 0.5)));
|
||||
if (last_pos_weight <= 0.0)
|
||||
seam_position = spHidden;
|
||||
}
|
||||
}
|
||||
if (seam_position == spAligned) {
|
||||
// Seam is aligned to the seam at the preceding layer.
|
||||
if (m_layer != NULL && m_seam_position.count(m_layer->object()) > 0) {
|
||||
@ -3202,7 +3229,9 @@ void GCode::split_at_seam_pos(ExtrusionLoop &loop, std::unique_ptr<EdgeGrid::Gri
|
||||
std::min(lengths[i] - lengths[last_pos_proj_idx], lengths.back() - lengths[i] + lengths[last_pos_proj_idx]);
|
||||
penalty -= last_pos_weight * bspline_kernel(dist_to_last_pos_proj / dist_max);
|
||||
}
|
||||
penalties[i] = std::max(0.f, penalty);
|
||||
// Allow negative penalties to overcome penalty for overhangs when in Custom mode
|
||||
penalties[i] = (seam_position == spCustom) ? penalty : std::max(0.f, penalty);
|
||||
|
||||
}
|
||||
|
||||
// Penalty for overhangs.
|
||||
@ -3232,7 +3261,7 @@ void GCode::split_at_seam_pos(ExtrusionLoop &loop, std::unique_ptr<EdgeGrid::Gri
|
||||
size_t idx_min = std::min_element(penalties.begin(), penalties.end()) - penalties.begin();
|
||||
|
||||
// if (seam_position == spAligned)
|
||||
// For all (aligned, nearest, rear) seams:
|
||||
// For all (aligned, nearest, rear, hidden, custom) seams:
|
||||
{
|
||||
// Very likely the weight of idx_min is very close to the weight of last_pos_proj_idx.
|
||||
// In that case use last_pos_proj_idx instead.
|
||||
|
@ -1622,6 +1622,8 @@ ModelVolumeType ModelVolume::type_from_string(const std::string &s)
|
||||
return ModelVolumeType::SUPPORT_ENFORCER;
|
||||
if (s == "SupportBlocker")
|
||||
return ModelVolumeType::SUPPORT_BLOCKER;
|
||||
if (s == "SeamPosition")
|
||||
return ModelVolumeType::SEAM_POSITION;
|
||||
assert(s == "0");
|
||||
// Default value if invalud type string received.
|
||||
return ModelVolumeType::MODEL_PART;
|
||||
@ -1634,6 +1636,7 @@ std::string ModelVolume::type_to_string(const ModelVolumeType t)
|
||||
case ModelVolumeType::PARAMETER_MODIFIER: return "ParameterModifier";
|
||||
case ModelVolumeType::SUPPORT_ENFORCER: return "SupportEnforcer";
|
||||
case ModelVolumeType::SUPPORT_BLOCKER: return "SupportBlocker";
|
||||
case ModelVolumeType::SEAM_POSITION: return "SeamPosition";
|
||||
default:
|
||||
assert(false);
|
||||
return "ModelPart";
|
||||
|
@ -389,6 +389,7 @@ enum class ModelVolumeType : int {
|
||||
PARAMETER_MODIFIER,
|
||||
SUPPORT_ENFORCER,
|
||||
SUPPORT_BLOCKER,
|
||||
SEAM_POSITION,
|
||||
};
|
||||
|
||||
// An object STL, or a modifier volume, over which a different set of parameters shall be applied.
|
||||
@ -429,7 +430,8 @@ public:
|
||||
bool is_modifier() const { return m_type == ModelVolumeType::PARAMETER_MODIFIER; }
|
||||
bool is_support_enforcer() const { return m_type == ModelVolumeType::SUPPORT_ENFORCER; }
|
||||
bool is_support_blocker() const { return m_type == ModelVolumeType::SUPPORT_BLOCKER; }
|
||||
bool is_support_modifier() const { return m_type == ModelVolumeType::SUPPORT_BLOCKER || m_type == ModelVolumeType::SUPPORT_ENFORCER; }
|
||||
bool is_support_modifier() const { return m_type == ModelVolumeType::SUPPORT_BLOCKER || m_type == ModelVolumeType::SUPPORT_ENFORCER; }
|
||||
bool is_seam_position() const { return m_type == ModelVolumeType::SEAM_POSITION; }
|
||||
t_model_material_id material_id() const { return m_material_id; }
|
||||
void set_material_id(t_model_material_id material_id);
|
||||
ModelMaterial* material() const;
|
||||
|
@ -397,7 +397,7 @@ double Print::max_allowed_layer_height() const
|
||||
// Add or remove support modifier ModelVolumes from model_object_dst to match the ModelVolumes of model_object_new
|
||||
// in the exact order and with the same IDs.
|
||||
// It is expected, that the model_object_dst already contains the non-support volumes of model_object_new in the correct order.
|
||||
void Print::model_volume_list_update_supports(ModelObject &model_object_dst, const ModelObject &model_object_new)
|
||||
void Print::model_volume_list_update_supports_seams(ModelObject &model_object_dst, const ModelObject &model_object_new)
|
||||
{
|
||||
typedef std::pair<const ModelVolume*, bool> ModelVolumeWithStatus;
|
||||
std::vector<ModelVolumeWithStatus> old_volumes;
|
||||
@ -420,7 +420,7 @@ void Print::model_volume_list_update_supports(ModelObject &model_object_dst, con
|
||||
// For support modifiers, the type may have been switched from blocker to enforcer and vice versa.
|
||||
assert((model_volume_dst->is_support_modifier() && model_volume_src->is_support_modifier()) || model_volume_dst->type() == model_volume_src->type());
|
||||
model_object_dst.volumes.emplace_back(model_volume_dst);
|
||||
if (model_volume_dst->is_support_modifier()) {
|
||||
if (model_volume_dst->is_support_modifier() || model_volume_dst->is_seam_position()) {
|
||||
// For support modifiers, the type may have been switched from blocker to enforcer and vice versa.
|
||||
model_volume_dst->set_type(model_volume_src->type());
|
||||
model_volume_dst->set_transformation(model_volume_src->get_transformation());
|
||||
@ -428,7 +428,7 @@ void Print::model_volume_list_update_supports(ModelObject &model_object_dst, con
|
||||
assert(model_volume_dst->get_matrix().isApprox(model_volume_src->get_matrix()));
|
||||
} else {
|
||||
// The volume was not found in the old list. Create a new copy.
|
||||
assert(model_volume_src->is_support_modifier());
|
||||
assert(model_volume_src->is_support_modifier() || model_volume_dst->is_seam_position());
|
||||
model_object_dst.volumes.emplace_back(new ModelVolume(*model_volume_src));
|
||||
model_object_dst.volumes.back()->set_model_object(&model_object_dst);
|
||||
}
|
||||
@ -895,7 +895,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
bool modifiers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::PARAMETER_MODIFIER);
|
||||
bool support_blockers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_BLOCKER);
|
||||
bool support_enforcers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_ENFORCER);
|
||||
if (model_parts_differ || modifiers_differ ||
|
||||
bool seam_position_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SEAM_POSITION);
|
||||
if (model_parts_differ || modifiers_differ ||
|
||||
model_object.origin_translation != model_object_new.origin_translation ||
|
||||
model_object.layer_height_profile != model_object_new.layer_height_profile ||
|
||||
! layer_height_ranges_equal(model_object.layer_config_ranges, model_object_new.layer_config_ranges, model_object_new.layer_height_profile.empty())) {
|
||||
@ -916,7 +917,15 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
for (auto it = range.first; it != range.second; ++ it)
|
||||
update_apply_status(it->print_object->invalidate_step(posSupportMaterial));
|
||||
// Copy just the support volumes.
|
||||
model_volume_list_update_supports(model_object, model_object_new);
|
||||
model_volume_list_update_supports_seams(model_object, model_object_new);
|
||||
}else if (seam_position_differ) {
|
||||
// First stop background processing before shuffling or deleting the ModelVolumes in the ModelObject's list.
|
||||
this->call_cancel_callback();
|
||||
update_apply_status(false);
|
||||
// Invalidate just the gcode step.
|
||||
invalidate_step(psGCodeExport);
|
||||
// Copy just the seam volumes.
|
||||
model_volume_list_update_supports_seams(model_object, model_object_new);
|
||||
}
|
||||
if (! model_parts_differ && ! modifiers_differ) {
|
||||
// Synchronize Object's config.
|
||||
@ -1051,11 +1060,9 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
for (PrintRegion *region : m_regions)
|
||||
region->m_refcnt = 0;
|
||||
for (PrintObject *print_object : m_objects) {
|
||||
int idx_region = 0;
|
||||
for (const auto &volumes : print_object->region_volumes) {
|
||||
if (! volumes.empty())
|
||||
++ m_regions[idx_region]->m_refcnt;
|
||||
++ idx_region;
|
||||
for (int idx_region = 0; idx_region < print_object->region_volumes.size(); ++idx_region) {
|
||||
if (!print_object->region_volumes[idx_region].empty())
|
||||
++ m_regions[idx_region]->m_refcnt;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -488,7 +488,7 @@ private:
|
||||
void _make_wipe_tower();
|
||||
|
||||
// Declared here to have access to Model / ModelObject / ModelInstance
|
||||
static void model_volume_list_update_supports(ModelObject &model_object_dst, const ModelObject &model_object_src);
|
||||
static void model_volume_list_update_supports_seams(ModelObject &model_object_dst, const ModelObject &model_object_src);
|
||||
|
||||
PrintConfig m_config;
|
||||
PrintObjectConfig m_default_object_config;
|
||||
|
@ -2551,18 +2551,25 @@ void PrintConfigDef::init_fff_params()
|
||||
def = this->add("seam_position", coEnum);
|
||||
def->label = L("Seam position");
|
||||
def->category = OptionCategory::perimeter;
|
||||
def->tooltip = L("Position of perimeters starting points.");
|
||||
def->tooltip = L("Position of perimeters starting points."
|
||||
"\n --- When using Custom ---"
|
||||
"\nYou have to create one or more seam sphere in the context menu of the object."
|
||||
" Note that the custom setting is automatically added to the object when creating a seam object,"
|
||||
" so you shouldn't have to set it in the global config."
|
||||
" The center of the seam sphere is used to position the seam. If you set multiple spheres, the nearest in z is chosen for a given layer.");
|
||||
def->enum_keys_map = &ConfigOptionEnum<SeamPosition>::get_enum_values();
|
||||
def->enum_values.push_back("random");
|
||||
def->enum_values.push_back("near");
|
||||
def->enum_values.push_back("aligned");
|
||||
def->enum_values.push_back("rear");
|
||||
def->enum_values.push_back("hidden");
|
||||
def->enum_values.push_back("custom");
|
||||
def->enum_labels.push_back(L("Random"));
|
||||
def->enum_labels.push_back(L("Nearest"));
|
||||
def->enum_labels.push_back(L("Aligned"));
|
||||
def->enum_labels.push_back(L("Rear"));
|
||||
def->enum_labels.push_back(L("Corners"));
|
||||
def->enum_labels.push_back(L("Custom"));
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionEnum<SeamPosition>(spHidden));
|
||||
|
||||
|
@ -67,7 +67,7 @@ enum SupportMaterialPattern {
|
||||
};
|
||||
|
||||
enum SeamPosition {
|
||||
spRandom, spNearest, spAligned, spRear, spHidden
|
||||
spRandom, spNearest, spAligned, spRear, spHidden, spCustom
|
||||
};
|
||||
|
||||
enum SLAMaterial {
|
||||
@ -207,6 +207,7 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<SeamPosition>::ge
|
||||
keys_map["aligned"] = spAligned;
|
||||
keys_map["rear"] = spRear;
|
||||
keys_map["hidden"] = spHidden;
|
||||
keys_map["custom"] = spCustom;
|
||||
}
|
||||
return keys_map;
|
||||
}
|
||||
|
@ -288,8 +288,8 @@ void GLVolume::set_color_from_model_volume(const ModelVolume *model_volume)
|
||||
{
|
||||
if (model_volume->is_modifier()) {
|
||||
color[0] = 0.2f;
|
||||
color[1] = 1.0f;
|
||||
color[2] = 0.2f;
|
||||
color[1] = 0.2f;
|
||||
color[2] = 1.0f;
|
||||
}
|
||||
else if (model_volume->is_support_blocker()) {
|
||||
color[0] = 1.0f;
|
||||
@ -298,6 +298,11 @@ void GLVolume::set_color_from_model_volume(const ModelVolume *model_volume)
|
||||
}
|
||||
else if (model_volume->is_support_enforcer()) {
|
||||
color[0] = 0.2f;
|
||||
color[1] = 1.0f;
|
||||
color[2] = 0.2f;
|
||||
}
|
||||
else if (model_volume->is_seam_position()) {
|
||||
color[0] = 0.9f;
|
||||
color[1] = 0.2f;
|
||||
color[2] = 1.0f;
|
||||
}
|
||||
|
@ -51,7 +51,8 @@ static std::vector<std::pair<std::string, std::string>> ADD_VOLUME_MENU_ITEMS =
|
||||
{L("Add part"), "add_part" }, // ~ModelVolumeType::MODEL_PART
|
||||
{L("Add modifier"), "add_modifier"}, // ~ModelVolumeType::PARAMETER_MODIFIER
|
||||
{L("Add support enforcer"), "support_enforcer"}, // ~ModelVolumeType::SUPPORT_ENFORCER
|
||||
{L("Add support blocker"), "support_blocker"} // ~ModelVolumeType::SUPPORT_BLOCKER
|
||||
{L("Add support blocker"), "support_blocker"}, // ~ModelVolumeType::SUPPORT_BLOCKER
|
||||
{L("Add seam position"), "add_seam"} // ~ModelVolumeType::SEAM_POSITION
|
||||
};
|
||||
|
||||
static PrinterTechnology printer_technology()
|
||||
@ -577,13 +578,15 @@ void ObjectList::init_icons()
|
||||
m_bmp_solidmesh = ScalableBitmap(this, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::MODEL_PART) ].second);
|
||||
m_bmp_modifiermesh = ScalableBitmap(this, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::PARAMETER_MODIFIER)].second);
|
||||
m_bmp_support_enforcer = ScalableBitmap(this, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SUPPORT_ENFORCER) ].second);
|
||||
m_bmp_support_blocker = ScalableBitmap(this, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SUPPORT_BLOCKER) ].second);
|
||||
m_bmp_support_blocker = ScalableBitmap(this, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SUPPORT_BLOCKER) ].second);
|
||||
m_bmp_seam_position = ScalableBitmap(this, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SEAM_POSITION) ].second);
|
||||
|
||||
m_bmp_vector.reserve(4); // bitmaps for different types of parts
|
||||
m_bmp_vector.push_back(&m_bmp_solidmesh.bmp());
|
||||
m_bmp_vector.push_back(&m_bmp_modifiermesh.bmp());
|
||||
m_bmp_vector.push_back(&m_bmp_support_enforcer.bmp());
|
||||
m_bmp_vector.push_back(&m_bmp_support_blocker.bmp());
|
||||
m_bmp_vector.push_back(&m_bmp_solidmesh.bmp());
|
||||
m_bmp_vector.push_back(&m_bmp_modifiermesh.bmp());
|
||||
m_bmp_vector.push_back(&m_bmp_support_enforcer.bmp());
|
||||
m_bmp_vector.push_back(&m_bmp_support_blocker.bmp());
|
||||
m_bmp_vector.push_back(&m_bmp_seam_position.bmp());
|
||||
|
||||
|
||||
// Set volumes default bitmaps for the model
|
||||
@ -605,7 +608,8 @@ void ObjectList::msw_rescale_icons()
|
||||
for (ScalableBitmap* bitmap : { &m_bmp_solidmesh, // Add part
|
||||
&m_bmp_modifiermesh, // Add modifier
|
||||
&m_bmp_support_enforcer, // Add support enforcer
|
||||
&m_bmp_support_blocker }) // Add support blocker
|
||||
&m_bmp_support_blocker, // Add support blocker
|
||||
&m_bmp_seam_position }) // Add seam position
|
||||
{
|
||||
bitmap->msw_rescale();
|
||||
m_bmp_vector.push_back(& bitmap->bmp());
|
||||
@ -1442,12 +1446,15 @@ wxMenu* ObjectList::append_submenu_add_generic(wxMenu* menu, const ModelVolumeTy
|
||||
sub_menu->AppendSeparator();
|
||||
}
|
||||
|
||||
for (auto& item : { L("Box"), L("Cylinder"), L("Sphere"), L("Slab") })
|
||||
std::vector<std::string> items = { "Box", "Cylinder", "Sphere", "Slab" };
|
||||
if(type == ModelVolumeType::SEAM_POSITION) items = { "Sphere" };
|
||||
|
||||
for (std::string& item : items)
|
||||
{
|
||||
if (type == ModelVolumeType::INVALID && strncmp(item, "Slab", 4) == 0)
|
||||
if (type == ModelVolumeType::INVALID && item == "Slab")
|
||||
continue;
|
||||
append_menu_item(sub_menu, wxID_ANY, _(item), "",
|
||||
[this, type, item](wxCommandEvent&) { load_generic_subobject(item, type); }, "", menu);
|
||||
append_menu_item(sub_menu, wxID_ANY, _(L(item)), "",
|
||||
[this, type, item](wxCommandEvent&) { load_generic_subobject(L(item), type); }, "", menu);
|
||||
}
|
||||
|
||||
return sub_menu;
|
||||
@ -1481,6 +1488,10 @@ void ObjectList::append_menu_items_add_volume(wxMenu* menu)
|
||||
[this](wxCommandEvent&) { load_generic_subobject(L("Box"), ModelVolumeType::SUPPORT_BLOCKER); },
|
||||
ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SUPPORT_BLOCKER)].second, nullptr,
|
||||
[this]() { return is_instance_or_object_selected(); }, parent);
|
||||
append_menu_item(menu, wxID_ANY, _(ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SEAM_POSITION)].first), "",
|
||||
[this](wxCommandEvent&) { load_generic_subobject(L("Sphere"), ModelVolumeType::SEAM_POSITION); },
|
||||
ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SEAM_POSITION)].second, nullptr,
|
||||
[this]() { return is_instance_or_object_selected(); }, parent);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1488,10 +1499,16 @@ void ObjectList::append_menu_items_add_volume(wxMenu* menu)
|
||||
for (size_t type = (mode == comExpert || wxGetApp().app_config->get("objects_always_expert") == "1" ? 0 : 1) ; type < ADD_VOLUME_MENU_ITEMS.size(); type++)
|
||||
{
|
||||
auto& item = ADD_VOLUME_MENU_ITEMS[type];
|
||||
|
||||
wxMenu* sub_menu = append_submenu_add_generic(menu, ModelVolumeType(type));
|
||||
append_submenu(menu, sub_menu, wxID_ANY, _(item.first), "", item.second,
|
||||
[this]() { return is_instance_or_object_selected(); }, parent);
|
||||
if (type == int(ModelVolumeType::SEAM_POSITION)) {
|
||||
append_menu_item(menu, wxID_ANY, _(item.first), "",
|
||||
[this](wxCommandEvent&) { load_generic_subobject(L("Sphere"), ModelVolumeType::SEAM_POSITION); },
|
||||
item.second, nullptr,
|
||||
[this]() { return is_instance_or_object_selected(); }, parent);
|
||||
} else {
|
||||
wxMenu* sub_menu = append_submenu_add_generic(menu, ModelVolumeType(type));
|
||||
append_submenu(menu, sub_menu, wxID_ANY, _(item.first), "", item.second,
|
||||
[this]() { return is_instance_or_object_selected(); }, parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1969,7 +1986,7 @@ static TriangleMesh create_mesh(const std::string& type_name, const BoundingBoxf
|
||||
else if (type_name == "Cylinder")
|
||||
// Centered around 0, sitting on the print bed.
|
||||
// The cylinder has the same volume as the box above.
|
||||
mesh = make_cylinder(0.564 * side, side);
|
||||
mesh = make_cylinder(0.564 * side, bb.size().z()>0 ? bb.size().z() : side);
|
||||
else if (type_name == "Sphere")
|
||||
// Centered around 0, half the sphere below the print bed, half above.
|
||||
// The sphere has the same volume as the box above.
|
||||
@ -2011,6 +2028,9 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
|
||||
// Bounding box of the selected instance in world coordinate system including the translation, without modifiers.
|
||||
BoundingBoxf3 instance_bb = model_object.instance_bounding_box(instance_idx);
|
||||
|
||||
if(type == ModelVolumeType::SEAM_POSITION)
|
||||
model_object.config.set_key_value("seam_position", new ConfigOptionEnum<SeamPosition>(spCustom));
|
||||
|
||||
TriangleMesh mesh = create_mesh(type_name, instance_bb);
|
||||
|
||||
// Mesh will be centered when loading.
|
||||
@ -2033,7 +2053,11 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
|
||||
new_volume->set_offset(v->get_instance_transformation().get_matrix(true).inverse() * offset);
|
||||
}
|
||||
|
||||
const wxString name = _(L("Generic")) + "-" + _(type_name);
|
||||
std::string base_name = "Generic";
|
||||
if (type == ModelVolumeType::SEAM_POSITION) base_name = "Seam";
|
||||
if (type == ModelVolumeType::SUPPORT_ENFORCER) base_name = "Support";
|
||||
if (type == ModelVolumeType::SUPPORT_BLOCKER) base_name = "Blocker";
|
||||
const wxString name = _(L(base_name)) + "-" + _(type_name);
|
||||
new_volume->name = into_u8(name);
|
||||
// set a default extruder value, since user can't add it manually
|
||||
new_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
|
||||
@ -2049,6 +2073,8 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
|
||||
//#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
|
||||
selection_changed();
|
||||
//#endif //no __WXOSX__ //__WXMSW__
|
||||
if (type == ModelVolumeType::SEAM_POSITION)
|
||||
this->update_after_undo_redo();
|
||||
}
|
||||
|
||||
void ObjectList::load_shape_object(const std::string& type_name)
|
||||
|
@ -127,6 +127,7 @@ private:
|
||||
ScalableBitmap m_bmp_solidmesh;
|
||||
ScalableBitmap m_bmp_support_enforcer;
|
||||
ScalableBitmap m_bmp_support_blocker;
|
||||
ScalableBitmap m_bmp_seam_position;
|
||||
ScalableBitmap m_bmp_manifold_warning;
|
||||
ScalableBitmap m_bmp_cog;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user