mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2026-03-12 22:36:03 -06:00
Add template metalanguage support for infill rotation template (#9996)
* Add some new non-overlapping functions for rotation surfaces/infills I can't post the entire package of changes yet, but this is just the beginning. These features do not affect the latest changes to the pattern rotation system. They are merely adding new functionality. * Added relative rotation of the infill according to the template. * Update PrintConfig.cpp * Update PrintConfig.cpp * Update PrintConfig.cpp * Add height limitation * Both sparse and solid. +one-time instructions * implementation v3 need for clean code in future * + Multiply Instructions * Add solid layers into sparse infill * Update Layer.hpp * Update PrintObject.cpp * Update Tab.cpp * Remove some bugs and increase quality * rename apply_model_direction to align_infill_direction_to_model * Change the data type of top_surface_direction and bottom_surface_direction to float so that they are consistent with other infill direction parameters. * remove top_surface_direction and bottom surface_direction options * clean code --------- Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
parent
3d16c7f4c8
commit
1ef427f661
9 changed files with 230 additions and 14 deletions
|
|
@ -655,6 +655,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
|||
params.lattice_angle_1 = region_config.lattice_angle_1;
|
||||
params.lattice_angle_2 = region_config.lattice_angle_2;
|
||||
params.infill_overhang_angle = region_config.infill_overhang_angle;
|
||||
params.angle = 0.;
|
||||
if (params.pattern == ipLockedZag) {
|
||||
params.infill_lock_depth = scale_(region_config.infill_lock_depth);
|
||||
params.skin_infill_depth = scale_(region_config.skin_infill_depth);
|
||||
|
|
@ -703,10 +704,15 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
|||
}
|
||||
}
|
||||
params.bridge_angle = float(surface.bridge_angle);
|
||||
|
||||
if (region_config.align_infill_direction_to_model) {
|
||||
auto m = layer.object()->trafo().matrix();
|
||||
params.angle += atan2((float) m(1, 0), (float) m(0, 0));
|
||||
}
|
||||
if (params.extrusion_role == erInternalInfill) {
|
||||
params.angle = float(Geometry::deg2rad(region_config.infill_direction.value));
|
||||
params.angle += float(Geometry::deg2rad(region_config.infill_direction.value));
|
||||
} else {
|
||||
params.angle = float(Geometry::deg2rad(region_config.solid_infill_direction.value));
|
||||
params.angle += float(Geometry::deg2rad(region_config.solid_infill_direction.value));
|
||||
}
|
||||
|
||||
// Calculate the actual flow we'll be using for this infill.
|
||||
|
|
@ -720,9 +726,9 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
|||
if (!params.bridge) {
|
||||
if (params.extrusion_role == erInternalInfill)
|
||||
params.sparse_infill_speed = region_config.sparse_infill_speed;
|
||||
else if (params.extrusion_role == erTopSolidInfill)
|
||||
else if (params.extrusion_role == erTopSolidInfill) {
|
||||
params.top_surface_speed = region_config.top_surface_speed;
|
||||
else if (params.extrusion_role == erSolidInfill)
|
||||
} else if (params.extrusion_role == erSolidInfill)
|
||||
params.solid_infill_speed = region_config.internal_solid_infill_speed;
|
||||
}
|
||||
// Calculate flow spacing for infill pattern generation.
|
||||
|
|
@ -992,7 +998,6 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||
f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree;
|
||||
f->print_config = &this->object()->print()->config();
|
||||
f->print_object_config = &this->object()->config();
|
||||
f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree;
|
||||
if (surface_fill.params.pattern == ipConcentricInternal) {
|
||||
FillConcentricInternal *fill_concentric = dynamic_cast<FillConcentricInternal *>(f.get());
|
||||
assert(fill_concentric != nullptr);
|
||||
|
|
@ -1045,14 +1050,186 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||
params.using_internal_flow = using_internal_flow;
|
||||
params.no_extrusion_overlap = surface_fill.params.overlap;
|
||||
auto ®ion_config = layerm->region().config();
|
||||
params.config = ®ion_config;
|
||||
params.pattern = surface_fill.params.pattern;
|
||||
|
||||
ConfigOptionFloats rotate_angles;
|
||||
rotate_angles.deserialize( surface_fill.params.extrusion_role == erInternalInfill ? region_config.sparse_infill_rotate_template.value : region_config.solid_infill_rotate_template.value);
|
||||
auto rotate_angle_idx = f->layer_id % rotate_angles.size();
|
||||
f->rotate_angle = Geometry::deg2rad(rotate_angles.values[rotate_angle_idx]);
|
||||
const std::string search_string = "/NnZz$LlUuQq~^|#";
|
||||
std::string v(params.extrusion_role == erInternalInfill ? region_config.sparse_infill_rotate_template.value :
|
||||
region_config.solid_infill_rotate_template.value);
|
||||
if (regex_search(v, std::regex("[+\\-%*@\'\"cmSODMR" + search_string + "]"))) { // template metalanguage of rotating infill
|
||||
std::regex del("[\\s,]+");
|
||||
std::sregex_token_iterator it(v.begin(), v.end(), del, -1);
|
||||
std::vector<std::string> tk;
|
||||
std::sregex_token_iterator end;
|
||||
while (it != end) {
|
||||
tk.push_back(*it++);
|
||||
}
|
||||
int t = 0;
|
||||
int repeats = 0;
|
||||
double angle = 0;
|
||||
double angle_add = 0;
|
||||
double angle_steps = 1;
|
||||
double angle_start = 0;
|
||||
double limit_fill_z = this->object()->get_layer(0)->bottom_z();
|
||||
double start_fill_z = limit_fill_z;
|
||||
bool _noop = false;
|
||||
auto solid = std::string::npos; // -1 - sparse, 0 - native (D), 1 - internal solid (S), 2 - concentric (O), 3 - monotonic (M), 4 - rectilinear (R)
|
||||
auto fill_form = std::string::npos;
|
||||
bool _absolute = false;
|
||||
bool _negative = false;
|
||||
std::vector<bool> stop(tk.size(), false);
|
||||
|
||||
for (int i = 0; i <= this->id(); i++) {
|
||||
double fill_z = this->object()->get_layer(i)->bottom_z();
|
||||
|
||||
if (limit_fill_z < this->object()->get_layer(i)->slice_z) {
|
||||
if (repeats) { // if repeats >0 then restore parameters for new iteration
|
||||
limit_fill_z += limit_fill_z - start_fill_z;
|
||||
start_fill_z = fill_z;
|
||||
repeats--;
|
||||
} else {
|
||||
start_fill_z = fill_z;
|
||||
limit_fill_z = this->object()->get_layer(i)->print_z;
|
||||
solid = std::string::npos;
|
||||
fill_form = std::string::npos;
|
||||
do {
|
||||
if (!stop[t]) {
|
||||
_noop = false;
|
||||
_absolute = false;
|
||||
_negative = false;
|
||||
angle_start += angle_add;
|
||||
angle_add = 0;
|
||||
angle_steps = 1;
|
||||
repeats = 1;
|
||||
if (tk[t].find('!') != std::string::npos) // this is an one-time instruction
|
||||
stop[t] = true;
|
||||
|
||||
char* cs = &tk[t][0];
|
||||
|
||||
if ((cs[0] >= '0' && cs[0] <= '9') && !(cs[0] == '+' || cs[0] == '-')) // absolute/relative
|
||||
_absolute = true;
|
||||
|
||||
angle_add = strtod(cs, &cs); // read angle parameter
|
||||
|
||||
if (cs[0] == '%') { // percentage of angles
|
||||
angle_add *= 3.6;
|
||||
cs = &cs[1];
|
||||
}
|
||||
|
||||
int tit = tk[t].find('*');
|
||||
if (tit != std::string::npos) // overall angle_cycles
|
||||
repeats = strtol(&tk[t][tit + 1], &cs, 0);
|
||||
|
||||
if (repeats) { // run if overall cycles greater than 0
|
||||
solid = std::string("DSOMR").find(cs[0]); // solid infill
|
||||
if (solid != std::string::npos)
|
||||
cs = &cs[1];
|
||||
|
||||
if (cs[0] == 'B') {
|
||||
angle_steps = this->object()->print()->default_region_config().bottom_shell_layers.value;
|
||||
} else if (cs[0] == 'T') {
|
||||
angle_steps = this->object()->print()->default_region_config().top_shell_layers.value;
|
||||
} else {
|
||||
fill_form = search_string.find(cs[0]);
|
||||
if (fill_form != std::string::npos)
|
||||
cs = &cs[1];
|
||||
|
||||
_negative = (cs[0] == '-'); // negative parameter
|
||||
angle_steps = abs(strtod(cs, &cs));
|
||||
|
||||
if (angle_steps && cs[0] != '\0' && cs[0] != '!') {
|
||||
if (cs[0] == '%') // value in the percents of fill_z
|
||||
limit_fill_z = angle_steps * this->object()->height() * 1e-8;
|
||||
else if (cs[0] == '#') // value in the feet
|
||||
limit_fill_z = angle_steps * this->object()->config().layer_height;
|
||||
else if (cs[0] == '\'') // value in the feet
|
||||
limit_fill_z = angle_steps * 12 * 25.4;
|
||||
else if (cs[0] == '\"') // value in the inches
|
||||
limit_fill_z = angle_steps * 25.4;
|
||||
else if (cs[0] == 'c') // value in centimeters
|
||||
limit_fill_z = angle_steps * 10.;
|
||||
else if (cs[0] == 'm')
|
||||
if (cs[1] == 'm') { // value in the millimeters
|
||||
limit_fill_z = angle_steps * 1.;
|
||||
} else // value in the meters
|
||||
limit_fill_z = angle_steps * 1000.;
|
||||
limit_fill_z += fill_z;
|
||||
angle_steps = 0; // limit_fill_z has already count
|
||||
}
|
||||
}
|
||||
if (angle_steps) { // if limit_fill_z does not setting by lenght method. Get count the layer id above model height
|
||||
if (fill_form == std::string::npos && !_absolute)
|
||||
angle_add *= (int) angle_steps;
|
||||
int idx = i + std::max(angle_steps - 1, 0.);
|
||||
int sdx = std::max(0, idx - (int) this->object()->layers().size());
|
||||
idx = std::min(idx, (int) this->object()->layers().size() - 1);
|
||||
limit_fill_z = this->object()->get_layer(idx)->print_z + sdx * this->object()->config().layer_height;
|
||||
}
|
||||
repeats = std::max(--repeats, 0);
|
||||
} else
|
||||
_noop = true; // set the dumb cycle
|
||||
if (_absolute) { // is absolute
|
||||
angle_start = angle_add;
|
||||
angle_add = 0;
|
||||
}
|
||||
}
|
||||
if (++t >= tk.size())
|
||||
t = 0;
|
||||
} while (std::all_of(stop.begin(), stop.end(), [](bool v) { return v; }) ? false :
|
||||
(t ? _noop : false) || stop[t]); // if this is a dumb instruction which never reaprated twice
|
||||
}
|
||||
}
|
||||
double top_z = this->object()->get_layer(i)->print_z;
|
||||
double negvalue = (_negative ? limit_fill_z - top_z : top_z - start_fill_z) / (limit_fill_z - start_fill_z);
|
||||
|
||||
switch (fill_form) {
|
||||
case 0: break; // /-joint, linear
|
||||
case 1: negvalue -= sin(negvalue * PI * 2.) / (PI * 2.); break; // N-joint, sinus, vertical start
|
||||
case 2: negvalue -= sin(negvalue * PI * 2.) / (PI * 4.); break; // n-joint, sinus, vertical start, lazy
|
||||
case 3: negvalue += sin(negvalue * PI * 2.) / (PI * 2.); break; // Z-joint, sinus, horizontal start
|
||||
case 4: negvalue += sin(negvalue * PI * 2.) / (PI * 4.); break; // z-joint, sinus, horizontal start, lazy
|
||||
case 5: negvalue = asin(negvalue * 2. - 1.) / PI + 0.5; break; // $-joint, arcsin
|
||||
case 6: negvalue = sin(negvalue * PI / 2.); break; // L-joint, quarter of circle, horizontal start
|
||||
case 7: negvalue = 1. - cos(negvalue * PI / 2.); break; // l-joint, quarter of circle, vertical start
|
||||
case 8: negvalue = 1. - pow(1. - negvalue, 2); break; // U-joint, squared, x2
|
||||
case 9: negvalue = pow(1 - negvalue, 2); break; // u-joint, squared, x2 inverse
|
||||
case 10: negvalue = 1. - pow(1. - negvalue, 3); break; // Q-joint, cubic, x3
|
||||
case 11: negvalue = pow(1. - negvalue, 3); break; // q-joint, cubic, x3 inverse
|
||||
case 12: negvalue = (double) rand() / RAND_MAX; break; // ~-joint, random, fill the whole angle
|
||||
case 13: negvalue += (double) rand() / RAND_MAX - 0.5; break; // ^-joint, pseudorandom, disperse at middle line
|
||||
case 14: negvalue = 0.5; break; // |-joint, like #-joint but placed at middle angle
|
||||
case 15: negvalue = _negative ? 0. : 1.; break; // #-joint, vertical at the end angle
|
||||
}
|
||||
angle = angle_start + angle_add * negvalue;
|
||||
}
|
||||
if (solid != std::string::npos) {
|
||||
switch (solid) {
|
||||
case 1: params.pattern = region_config.internal_solid_infill_pattern.value; break; // selected solid pattern
|
||||
case 2: params.pattern = ipConcentric; break; // concentric pattern
|
||||
case 3: params.pattern = ipMonotonic; break; // monotonic pattern
|
||||
case 4: params.pattern = ipRectilinear; // rectilinear pattern
|
||||
} // or else use native pattern
|
||||
params.extrusion_role = erSolidInfill;
|
||||
params.density = 1.;
|
||||
surface_fill.params.pattern = params.pattern;
|
||||
|
||||
f = std::unique_ptr<Fill>(Fill::new_from_type(params.pattern)); // reinitialize surface
|
||||
f->set_bounding_box(bbox);
|
||||
f->layer_id = this->id();
|
||||
f->z = this->print_z;
|
||||
f->angle = surface_fill.params.angle;
|
||||
f->print_config = &this->object()->print()->config();
|
||||
f->print_object_config = &this->object()->config();
|
||||
params.use_arachne = surface_fill.params.pattern == ipConcentric || surface_fill.params.pattern == ipConcentricInternal;
|
||||
}
|
||||
f->rotate_angle = Geometry::deg2rad(angle);
|
||||
} else {
|
||||
rotate_angles.deserialize(v);
|
||||
auto rotate_angle_idx = f->layer_id % rotate_angles.size();
|
||||
f->rotate_angle = Geometry::deg2rad(rotate_angles.values[rotate_angle_idx]);
|
||||
}
|
||||
|
||||
params.config = ®ion_config;
|
||||
params.pattern = surface_fill.params.pattern;
|
||||
if( surface_fill.params.pattern == ipLockedZag ) {
|
||||
params.locked_zag = true;
|
||||
params.infill_lock_depth = surface_fill.params.infill_lock_depth;
|
||||
|
|
|
|||
|
|
@ -787,6 +787,7 @@ static std::vector<std::string> s_Preset_print_options {
|
|||
"extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only", "wall_direction",
|
||||
"seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density","fill_multiline", "sparse_infill_pattern", "lattice_angle_1", "lattice_angle_2", "infill_overhang_angle", "top_surface_pattern", "bottom_surface_pattern",
|
||||
"infill_direction", "solid_infill_direction", "counterbore_hole_bridging","infill_shift_step", "sparse_infill_rotate_template", "solid_infill_rotate_template", "symmetric_infill_y_axis","skeleton_infill_density", "infill_lock_depth", "skin_infill_depth", "skin_infill_density",
|
||||
"align_infill_direction_to_model",
|
||||
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern","gap_fill_target",
|
||||
"ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle", "ironing_inset",
|
||||
"support_ironing", "support_ironing_pattern", "support_ironing_flow", "support_ironing_spacing",
|
||||
|
|
|
|||
|
|
@ -2366,6 +2366,14 @@ void PrintConfigDef::init_fff_params()
|
|||
def->min = 0;
|
||||
def->max = 100;
|
||||
def->set_default_value(new ConfigOptionPercent(20));
|
||||
|
||||
def = this->add("align_infill_direction_to_model", coBool);
|
||||
def->label = L("Align infill direction to model");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Aligns infill and surface fill directions to follow the model's orientation on the build plate. When enabled, fill directions rotate with the model to maintain optimal strength characteristics.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
|
||||
// Infill multiline
|
||||
def = this->add("fill_multiline", coInt);
|
||||
|
|
|
|||
|
|
@ -983,6 +983,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionFloat, lattice_angle_1))
|
||||
((ConfigOptionFloat, lattice_angle_2))
|
||||
((ConfigOptionFloat, infill_overhang_angle))
|
||||
((ConfigOptionBool, align_infill_direction_to_model))
|
||||
((ConfigOptionEnum<FuzzySkinType>, fuzzy_skin))
|
||||
((ConfigOptionFloat, fuzzy_skin_thickness))
|
||||
((ConfigOptionFloat, fuzzy_skin_point_distance))
|
||||
|
|
|
|||
|
|
@ -1078,6 +1078,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
|| opt_key == "skeleton_infill_line_width"
|
||||
|| opt_key == "infill_direction"
|
||||
|| opt_key == "solid_infill_direction"
|
||||
|| opt_key == "align_infill_direction_to_model"
|
||||
|| opt_key == "ensure_vertical_shell_thickness"
|
||||
|| opt_key == "bridge_angle"
|
||||
|| opt_key == "internal_bridge_angle" // ORCA: Internal bridge angle override
|
||||
|
|
|
|||
|
|
@ -431,10 +431,34 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
|
|||
set_value(str, true);
|
||||
}
|
||||
} else if (m_opt.opt_key == "sparse_infill_rotate_template" || m_opt.opt_key == "solid_infill_rotate_template") {
|
||||
if (!ConfigOptionFloats::validate_string(str.utf8_string())) {
|
||||
show_error(m_parent, format_wxstr(_L("This parameter expects a comma-delimited list of numbers. E.g, \"0,90\".")));
|
||||
wxString old_value(boost::any_cast<std::string>(m_value));
|
||||
this->set_value(old_value, true); // Revert to previous value
|
||||
string ustr(str.utf8_string());
|
||||
if (!ConfigOptionFloats::validate_string(ustr)) {
|
||||
string v;
|
||||
std::smatch match;
|
||||
string ps = (m_opt.opt_key == "sparse_infill_rotate_template") ?
|
||||
u8"[SODMR]?[BT][!]?|[SODMR]?[#][\\d]+[!]?|[+\\-]?[\\d.]+[%]?[*]?[\\d]*[SODMR]?[/NnZz$LlUuQq~^|#]?[+\\-]?[\\d.]*[%#\'\"cm]?[m]?[BT]?[!*]?" :
|
||||
u8"[#][\\d]+[!]?|[+\\-]?[\\d.]+[%]?[*]?[\\d]*[/NnZz$LlUuQq~^|#]?[+\\-]?[\\d.]*[%#\'\"cm]?[m]?[!*]?";
|
||||
|
||||
//if (m_opt.opt_key == "sparse_infill_rotate_template") {
|
||||
//string ps = u8"[#][\\d]+[!]?|[+\\-]?[\\d.]+[%]?[*]?[\\d]*[SODMR]?[/NnZz$LlUuQq~^|#]?[+\\-]?[\\d.]*[%#\'\"cm]?[m]?[";
|
||||
//if (m_opt.opt_key == "sparse_infill_rotate_template") {
|
||||
// ps = u8"[BT][!]?|" + ps ;
|
||||
//}
|
||||
//ps += u8"BT]?[!*]?";
|
||||
while (std::regex_search(ustr, match, std::regex(ps))) {
|
||||
for (auto x : match) v += x.str() + ", ";
|
||||
ustr = match.suffix().str();
|
||||
}
|
||||
v = v.substr(0, v.length() - 2);
|
||||
try {
|
||||
this->set_value(from_u8(v), true);
|
||||
m_value = into_u8(v);
|
||||
} catch (...) {
|
||||
show_error(m_parent, format_wxstr(_L("This parameter expects a valid template.")));
|
||||
wxString old_value(boost::any_cast<std::string>(m_value));
|
||||
this->set_value(old_value, true); // Revert to previous value
|
||||
throw;
|
||||
}
|
||||
} else {
|
||||
// Valid string, so update m_value with the new string from the control.
|
||||
m_value = into_u8(str);
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::PART_CAT
|
|||
{ L("Strength"), {{"wall_loops", "",1},{"top_shell_layers", L("Top Solid Layers"),1},{"top_shell_thickness", L("Top Minimum Shell Thickness"),1},{"top_surface_density", L("Top Surface Density"),1},
|
||||
{"bottom_shell_layers", L("Bottom Solid Layers"),1}, {"bottom_shell_thickness", L("Bottom Minimum Shell Thickness"),1},{"bottom_surface_density", L("Bottom Surface Density"),1},
|
||||
{"sparse_infill_density", "",1},{"sparse_infill_pattern", "",1},{"lattice_angle_1", "",1},{"lattice_angle_2", "",1},{"infill_overhang_angle", "",1},{"infill_anchor", "",1},{"infill_anchor_max", "",1},{"top_surface_pattern", "",1},{"bottom_surface_pattern", "",1}, {"internal_solid_infill_pattern", "",1},
|
||||
{"align_infill_direction_to_model", "", 1},
|
||||
{"infill_combination", "",1}, {"infill_combination_max_layer_height", "",1}, {"infill_wall_overlap", "",1},{"top_bottom_infill_wall_overlap", "",1}, {"solid_infill_direction", "",1}, {"infill_direction", "",1}, {"bridge_angle", "",1}, {"internal_bridge_angle", "",1}, {"minimum_sparse_infill_area", "",1}
|
||||
}},
|
||||
{ L("Speed"), {{"outer_wall_speed", "",1},{"inner_wall_speed", "",2},{"sparse_infill_speed", "",3},{"top_surface_speed", "",4}, {"internal_solid_infill_speed", "",5},
|
||||
|
|
|
|||
|
|
@ -9902,6 +9902,7 @@ void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, i
|
|||
_obj->config.set_key_value("top_solid_infill_flow_ratio", new ConfigOptionFloat(1.0f));
|
||||
_obj->config.set_key_value("infill_direction", new ConfigOptionFloat(45));
|
||||
_obj->config.set_key_value("solid_infill_direction", new ConfigOptionFloat(135));
|
||||
_obj->config.set_key_value("align_infill_direction_to_model", new ConfigOptionBool(true));
|
||||
_obj->config.set_key_value("ironing_type", new ConfigOptionEnum<IroningType>(IroningType::NoIroning));
|
||||
_obj->config.set_key_value("internal_solid_infill_speed", new ConfigOptionFloat(internal_solid_speed));
|
||||
_obj->config.set_key_value("top_surface_speed", new ConfigOptionFloat(top_surface_speed));
|
||||
|
|
|
|||
|
|
@ -2195,6 +2195,7 @@ void TabPrint::build()
|
|||
optgroup->append_single_option_line("detect_thin_wall", "strength_settings_walls#detect-thin-wall");
|
||||
|
||||
optgroup = page->new_optgroup(L("Top/bottom shells"), L"param_shell");
|
||||
|
||||
optgroup->append_single_option_line("top_shell_layers", "strength_settings_top_bottom_shells#shells-layers");
|
||||
optgroup->append_single_option_line("top_shell_thickness", "strength_settings_top_bottom_shells#shell-thickness");
|
||||
optgroup->append_single_option_line("top_surface_density", "strength_settings_top_bottom_shells#surface-density");
|
||||
|
|
@ -2233,6 +2234,7 @@ void TabPrint::build()
|
|||
optgroup->append_single_option_line("infill_wall_overlap", "strength_settings_infill#infill-wall-overlap");
|
||||
|
||||
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
|
||||
optgroup->append_single_option_line("align_infill_direction_to_model");
|
||||
optgroup->append_single_option_line("bridge_angle", "strength_settings_advanced#bridge-infill-direction");
|
||||
optgroup->append_single_option_line("internal_bridge_angle", "strength_settings_advanced#bridge-infill-direction"); // ORCA: Internal bridge angle override
|
||||
optgroup->append_single_option_line("minimum_sparse_infill_area", "strength_settings_advanced#minimum-sparse-infill-threshold");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue