Average area color when merging small regions in top-surface coloring
- Show layer count recommendation for top-surface coloring - Show warning when shell layer count is lower than color pattern length
This commit is contained in:
@@ -46,6 +46,12 @@ float srgb_to_linear_component(float value)
|
||||
return x <= 0.04045f ? x / 12.92f : std::pow((x + 0.055f) / 1.055f, 2.4f);
|
||||
}
|
||||
|
||||
float linear_to_srgb_component(float value)
|
||||
{
|
||||
const float x = clamp01(value);
|
||||
return x <= 0.0031308f ? 12.92f * x : 1.055f * std::pow(x, 1.f / 2.4f) - 0.055f;
|
||||
}
|
||||
|
||||
std::array<float, 3> oklab_from_srgb(const std::array<float, 3> &rgb)
|
||||
{
|
||||
const float r = srgb_to_linear_component(rgb[0]);
|
||||
@@ -63,6 +69,27 @@ std::array<float, 3> oklab_from_srgb(const std::array<float, 3> &rgb)
|
||||
};
|
||||
}
|
||||
|
||||
std::array<float, 3> srgb_from_oklab(const std::array<float, 3> &oklab)
|
||||
{
|
||||
const float l_ = oklab[0] + 0.3963377774f * oklab[1] + 0.2158037573f * oklab[2];
|
||||
const float m_ = oklab[0] - 0.1055613458f * oklab[1] - 0.0638541728f * oklab[2];
|
||||
const float s_ = oklab[0] - 0.0894841775f * oklab[1] - 1.2914855480f * oklab[2];
|
||||
|
||||
const float l = l_ * l_ * l_;
|
||||
const float m = m_ * m_ * m_;
|
||||
const float s = s_ * s_ * s_;
|
||||
|
||||
const float r = 4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s;
|
||||
const float g = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s;
|
||||
const float b = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s;
|
||||
|
||||
return {
|
||||
linear_to_srgb_component(r),
|
||||
linear_to_srgb_component(g),
|
||||
linear_to_srgb_component(b)
|
||||
};
|
||||
}
|
||||
|
||||
std::array<float, 3> color_solver_v2_axis_weights(const std::array<float, 3> &target_oklab)
|
||||
{
|
||||
const float chroma = std::hypot(target_oklab[1], target_oklab[2]);
|
||||
@@ -605,6 +632,11 @@ std::array<float, 3> color_solver_oklab_from_srgb(const std::array<float, 3> &rg
|
||||
return oklab_from_srgb(rgb);
|
||||
}
|
||||
|
||||
std::array<float, 3> color_solver_srgb_from_oklab(const std::array<float, 3> &oklab)
|
||||
{
|
||||
return srgb_from_oklab(oklab);
|
||||
}
|
||||
|
||||
std::string color_solver_candidate_cache_key(const std::vector<std::array<float, 3>> &component_colors,
|
||||
ColorSolverMixModel mix_model,
|
||||
int total_units)
|
||||
|
||||
@@ -111,6 +111,7 @@ std::array<float, 3> mix_color_solver_ordered_stack(const std::vector<std::array
|
||||
const std::array<float, 3> &background_rgb,
|
||||
ColorSolverMixModel mix_model);
|
||||
std::array<float, 3> color_solver_oklab_from_srgb(const std::array<float, 3> &rgb);
|
||||
std::array<float, 3> color_solver_srgb_from_oklab(const std::array<float, 3> &oklab);
|
||||
|
||||
std::string color_solver_candidate_cache_key(const std::vector<std::array<float, 3>> &component_colors,
|
||||
ColorSolverMixModel mix_model,
|
||||
|
||||
@@ -1098,6 +1098,7 @@ struct TopSurfaceImageContoningCellSample {
|
||||
std::array<float, 3> rgb { { 0.f, 0.f, 0.f } };
|
||||
int solve_layers { 0 };
|
||||
int available_depth { 0 };
|
||||
int sample_count { 0 };
|
||||
};
|
||||
|
||||
struct TopSurfaceImageContoningSolvedLabel {
|
||||
@@ -1946,6 +1947,7 @@ static std::optional<TopSurfaceImageContoningCellSample> top_surface_image_conto
|
||||
out.rgb[2] = std::clamp(out.rgb[2] / float(sample_count), 0.f, 1.f);
|
||||
if (out.solve_layers <= 0 || out.available_depth <= 0)
|
||||
return std::nullopt;
|
||||
out.sample_count = sample_count;
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -1985,6 +1987,128 @@ static std::optional<TopSurfaceImageContoningSolvedLabel> top_surface_image_cont
|
||||
return out;
|
||||
}
|
||||
|
||||
static void top_surface_image_contoning_resolve_merged_grid_regions(
|
||||
std::vector<int> &grid,
|
||||
int cols,
|
||||
int rows,
|
||||
std::vector<TopSurfaceImageContoningVectorLabel> &labels,
|
||||
const std::vector<std::optional<TopSurfaceImageContoningCellSample>> &cell_samples,
|
||||
const TextureMappingContoningSolver &solver,
|
||||
int stack_layers,
|
||||
int pattern_filaments,
|
||||
bool lower_surface,
|
||||
const ThrowIfCanceled *throw_if_canceled)
|
||||
{
|
||||
if (grid.empty() || labels.empty() || cols <= 0 || rows <= 0 ||
|
||||
grid.size() != size_t(cols) * size_t(rows) ||
|
||||
cell_samples.size() != grid.size() ||
|
||||
stack_layers <= 0 || pattern_filaments <= 0 || !solver.valid())
|
||||
return;
|
||||
|
||||
std::vector<int> resolved_grid(grid.size(), -1);
|
||||
std::vector<TopSurfaceImageContoningVectorLabel> resolved_labels;
|
||||
std::map<std::pair<std::vector<unsigned int>, int>, int> label_by_stack;
|
||||
std::vector<unsigned char> visited(grid.size(), 0);
|
||||
|
||||
auto append_fallback_label = [&](int source_label) {
|
||||
if (source_label < 0 || source_label >= int(labels.size()))
|
||||
return -1;
|
||||
const int label = int(resolved_labels.size());
|
||||
resolved_labels.emplace_back(labels[size_t(source_label)]);
|
||||
return label;
|
||||
};
|
||||
|
||||
for (int row = 0; row < rows; ++row) {
|
||||
if ((row & 15) == 0)
|
||||
check_canceled(throw_if_canceled);
|
||||
for (int col = 0; col < cols; ++col) {
|
||||
const int start_idx = row * cols + col;
|
||||
const int source_label = grid[size_t(start_idx)];
|
||||
if (source_label < 0 || visited[size_t(start_idx)])
|
||||
continue;
|
||||
|
||||
std::vector<int> queue;
|
||||
std::vector<int> cells;
|
||||
queue.push_back(start_idx);
|
||||
visited[size_t(start_idx)] = 1;
|
||||
std::array<double, 3> oklab_sum { { 0., 0., 0. } };
|
||||
double sample_weight = 0.;
|
||||
int visible_layers = std::numeric_limits<int>::max();
|
||||
|
||||
for (size_t queue_idx = 0; queue_idx < queue.size(); ++queue_idx) {
|
||||
if ((queue_idx & 255) == 0)
|
||||
check_canceled(throw_if_canceled);
|
||||
const int idx = queue[queue_idx];
|
||||
cells.push_back(idx);
|
||||
if (cell_samples[size_t(idx)]) {
|
||||
const TopSurfaceImageContoningCellSample &sample = *cell_samples[size_t(idx)];
|
||||
const std::array<float, 3> sample_oklab = color_solver_oklab_from_srgb(sample.rgb);
|
||||
const double weight = double(std::max(1, sample.sample_count));
|
||||
oklab_sum[0] += double(sample_oklab[0]) * weight;
|
||||
oklab_sum[1] += double(sample_oklab[1]) * weight;
|
||||
oklab_sum[2] += double(sample_oklab[2]) * weight;
|
||||
visible_layers = std::min(visible_layers, sample.available_depth);
|
||||
sample_weight += weight;
|
||||
}
|
||||
|
||||
const int r = idx / cols;
|
||||
const int c = idx - r * cols;
|
||||
const std::array<std::pair<int, int>, 4> neighbors{
|
||||
std::pair<int, int>{ c - 1, r },
|
||||
std::pair<int, int>{ c + 1, r },
|
||||
std::pair<int, int>{ c, r - 1 },
|
||||
std::pair<int, int>{ c, r + 1 }
|
||||
};
|
||||
for (const std::pair<int, int> &neighbor : neighbors) {
|
||||
const int nc = neighbor.first;
|
||||
const int nr = neighbor.second;
|
||||
if (nc < 0 || nc >= cols || nr < 0 || nr >= rows)
|
||||
continue;
|
||||
const int nidx = nr * cols + nc;
|
||||
if (visited[size_t(nidx)] || grid[size_t(nidx)] != source_label)
|
||||
continue;
|
||||
visited[size_t(nidx)] = 1;
|
||||
queue.push_back(nidx);
|
||||
}
|
||||
}
|
||||
|
||||
int resolved_label = -1;
|
||||
if (sample_weight > 0. && visible_layers > 0 && visible_layers != std::numeric_limits<int>::max()) {
|
||||
const std::array<float, 3> average_oklab {
|
||||
float(oklab_sum[0] / sample_weight),
|
||||
float(oklab_sum[1] / sample_weight),
|
||||
float(oklab_sum[2] / sample_weight)
|
||||
};
|
||||
const std::array<float, 3> average_rgb = color_solver_srgb_from_oklab(average_oklab);
|
||||
const int solve_layers = std::min({ visible_layers, stack_layers, pattern_filaments });
|
||||
if (solve_layers > 0) {
|
||||
std::optional<TopSurfaceImageContoningSolvedLabel> solved =
|
||||
top_surface_image_contoning_solve_label(average_rgb,
|
||||
solve_layers,
|
||||
visible_layers,
|
||||
solver,
|
||||
lower_surface,
|
||||
resolved_labels,
|
||||
label_by_stack);
|
||||
if (solved)
|
||||
resolved_label = solved->label;
|
||||
}
|
||||
}
|
||||
if (resolved_label < 0)
|
||||
resolved_label = append_fallback_label(source_label);
|
||||
if (resolved_label < 0)
|
||||
continue;
|
||||
for (int idx : cells)
|
||||
resolved_grid[size_t(idx)] = resolved_label;
|
||||
}
|
||||
}
|
||||
|
||||
if (!resolved_labels.empty()) {
|
||||
grid = std::move(resolved_grid);
|
||||
labels = std::move(resolved_labels);
|
||||
}
|
||||
}
|
||||
|
||||
static std::optional<TopSurfaceImageContoningSourceContext> top_surface_image_contoning_source_context(
|
||||
const TopSurfaceImageRegionPlan &plan,
|
||||
const Layer &source_layer,
|
||||
@@ -2226,6 +2350,18 @@ static std::vector<TopSurfaceImageContoningVectorRegion> top_surface_image_conto
|
||||
plan.contoning_min_feature_mm,
|
||||
plan.contoning_external_width_mm,
|
||||
throw_if_canceled);
|
||||
if (plan.contoning_td_adjustment_enabled) {
|
||||
top_surface_image_contoning_resolve_merged_grid_regions(grid,
|
||||
cols,
|
||||
rows,
|
||||
labels,
|
||||
cell_samples,
|
||||
solver,
|
||||
source->stack_layers,
|
||||
source->pattern_filaments,
|
||||
source_surface == TopSurfaceImageSourceSurface::Bottom,
|
||||
throw_if_canceled);
|
||||
}
|
||||
check_canceled(throw_if_canceled);
|
||||
|
||||
return top_surface_image_contoning_component_regions_from_grid(grid,
|
||||
@@ -2422,6 +2558,18 @@ static std::shared_ptr<const TopSurfaceImageContoningStackPlan> top_surface_imag
|
||||
plan.contoning_min_feature_mm,
|
||||
plan.contoning_external_width_mm,
|
||||
throw_if_canceled);
|
||||
if (plan.contoning_td_adjustment_enabled) {
|
||||
top_surface_image_contoning_resolve_merged_grid_regions(grid,
|
||||
cols,
|
||||
rows,
|
||||
out->labels,
|
||||
cell_samples,
|
||||
solver,
|
||||
source_context->stack_layers,
|
||||
source_context->pattern_filaments,
|
||||
source_surface == TopSurfaceImageSourceSurface::Bottom,
|
||||
throw_if_canceled);
|
||||
}
|
||||
for (size_t idx = 0; idx < out->cells.size(); ++idx)
|
||||
out->cells[idx].label = grid[idx];
|
||||
return out;
|
||||
|
||||
@@ -1508,14 +1508,16 @@ std::string TextureMappingManager::serialize_entries()
|
||||
TextureMappingZone::DefaultTopSurfaceContoningAngleThresholdDeg),
|
||||
TextureMappingZone::MinTopSurfaceContoningAngleThresholdDeg,
|
||||
TextureMappingZone::MaxTopSurfaceContoningAngleThresholdDeg);
|
||||
texture["top_surface_contoning_stack_layers"] =
|
||||
clamp_int(zone.top_surface_contoning_stack_layers,
|
||||
TextureMappingZone::MinTopSurfaceContoningStackLayers,
|
||||
TextureMappingZone::MaxTopSurfaceContoningStackLayers);
|
||||
texture["top_surface_contoning_pattern_filaments"] =
|
||||
const int top_surface_contoning_pattern_filaments =
|
||||
clamp_int(zone.top_surface_contoning_pattern_filaments,
|
||||
TextureMappingZone::MinTopSurfaceContoningPatternFilaments,
|
||||
TextureMappingZone::MaxTopSurfaceContoningPatternFilaments);
|
||||
texture["top_surface_contoning_stack_layers"] =
|
||||
std::max(top_surface_contoning_pattern_filaments,
|
||||
clamp_int(zone.top_surface_contoning_stack_layers,
|
||||
TextureMappingZone::MinTopSurfaceContoningStackLayers,
|
||||
TextureMappingZone::MaxTopSurfaceContoningStackLayers));
|
||||
texture["top_surface_contoning_pattern_filaments"] = top_surface_contoning_pattern_filaments;
|
||||
texture["top_surface_contoning_min_feature_mm"] =
|
||||
std::clamp(finite_or(zone.top_surface_contoning_min_feature_mm,
|
||||
TextureMappingZone::DefaultTopSurfaceContoningMinFeatureMm),
|
||||
@@ -1788,6 +1790,9 @@ void TextureMappingManager::load_entries(const std::string &serialized,
|
||||
TextureMappingZone::DefaultTopSurfaceContoningPatternFilaments),
|
||||
TextureMappingZone::MinTopSurfaceContoningPatternFilaments,
|
||||
TextureMappingZone::MaxTopSurfaceContoningPatternFilaments);
|
||||
zone.top_surface_contoning_stack_layers =
|
||||
std::max(zone.top_surface_contoning_stack_layers,
|
||||
zone.top_surface_contoning_pattern_filaments);
|
||||
zone.top_surface_contoning_min_feature_mm =
|
||||
std::clamp(finite_or(texture.value("top_surface_contoning_min_feature_mm",
|
||||
TextureMappingZone::DefaultTopSurfaceContoningMinFeatureMm),
|
||||
|
||||
@@ -712,6 +712,113 @@ static bool model_uses_texture_mapping_zone_id(const Model &model, const ConfigO
|
||||
return false;
|
||||
}
|
||||
|
||||
struct TextureMappingZoneShellUsageSummary {
|
||||
int object_count { 0 };
|
||||
int min_top_shell_layers { 0 };
|
||||
int min_bottom_shell_layers { 0 };
|
||||
};
|
||||
|
||||
static int texture_mapping_config_int_or(const ConfigOptionResolver &config, const char *key, int fallback)
|
||||
{
|
||||
const ConfigOptionInt *opt = dynamic_cast<const ConfigOptionInt *>(config.option(key));
|
||||
return opt != nullptr ? opt->getInt() : fallback;
|
||||
}
|
||||
|
||||
static bool texture_mapping_effective_config_uses_zone_id(const ConfigOptionResolver &config,
|
||||
const ConfigOptionResolver *fallback_config,
|
||||
const ConfigOptionResolver *secondary_fallback_config,
|
||||
unsigned int zone_id)
|
||||
{
|
||||
const int target = int(zone_id);
|
||||
const std::array<const ConfigOptionResolver *, 3> configs { &config, fallback_config, secondary_fallback_config };
|
||||
for (const char *key : texture_mapping_filament_config_keys()) {
|
||||
for (const ConfigOptionResolver *resolver : configs) {
|
||||
if (resolver == nullptr)
|
||||
continue;
|
||||
const ConfigOptionInt *opt = dynamic_cast<const ConfigOptionInt *>(resolver->option(key));
|
||||
if (opt == nullptr)
|
||||
continue;
|
||||
if (opt->getInt() == target)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static TextureMappingZoneShellUsageSummary texture_mapping_zone_shell_usage_summary(
|
||||
const Model &model,
|
||||
const DynamicPrintConfig &print_config,
|
||||
unsigned int zone_id)
|
||||
{
|
||||
TextureMappingZoneShellUsageSummary out;
|
||||
if (zone_id == 0)
|
||||
return out;
|
||||
|
||||
const int global_top_shell_layers = texture_mapping_config_int_or(print_config, "top_shell_layers", 0);
|
||||
const int global_bottom_shell_layers = texture_mapping_config_int_or(print_config, "bottom_shell_layers", 0);
|
||||
int min_top_shell_layers = std::numeric_limits<int>::max();
|
||||
int min_bottom_shell_layers = std::numeric_limits<int>::max();
|
||||
|
||||
for (const ModelObject *object : model.objects) {
|
||||
if (object == nullptr)
|
||||
continue;
|
||||
|
||||
const ConfigOptionResolver &object_config = object->config.get();
|
||||
const int object_top_shell_layers =
|
||||
texture_mapping_config_int_or(object_config, "top_shell_layers", global_top_shell_layers);
|
||||
const int object_bottom_shell_layers =
|
||||
texture_mapping_config_int_or(object_config, "bottom_shell_layers", global_bottom_shell_layers);
|
||||
int object_min_top_shell_layers = object_top_shell_layers;
|
||||
int object_min_bottom_shell_layers = object_bottom_shell_layers;
|
||||
bool object_uses_zone = false;
|
||||
|
||||
auto note_usage = [&](int top_shell_layers, int bottom_shell_layers) {
|
||||
object_uses_zone = true;
|
||||
object_min_top_shell_layers = std::min(object_min_top_shell_layers, top_shell_layers);
|
||||
object_min_bottom_shell_layers = std::min(object_min_bottom_shell_layers, bottom_shell_layers);
|
||||
};
|
||||
|
||||
if (texture_mapping_effective_config_uses_zone_id(object_config, &print_config, nullptr, zone_id))
|
||||
note_usage(object_top_shell_layers, object_bottom_shell_layers);
|
||||
|
||||
for (const auto &layer_range : object->layer_config_ranges) {
|
||||
const ConfigOptionResolver &layer_config = layer_range.second.get();
|
||||
if (!texture_mapping_effective_config_uses_zone_id(layer_config, &object_config, &print_config, zone_id))
|
||||
continue;
|
||||
note_usage(texture_mapping_config_int_or(layer_config, "top_shell_layers", object_top_shell_layers),
|
||||
texture_mapping_config_int_or(layer_config, "bottom_shell_layers", object_bottom_shell_layers));
|
||||
}
|
||||
|
||||
for (const ModelVolume *volume : object->volumes) {
|
||||
if (volume == nullptr)
|
||||
continue;
|
||||
const ConfigOptionResolver &volume_config = volume->config.get();
|
||||
const int volume_top_shell_layers =
|
||||
texture_mapping_config_int_or(volume_config, "top_shell_layers", object_top_shell_layers);
|
||||
const int volume_bottom_shell_layers =
|
||||
texture_mapping_config_int_or(volume_config, "bottom_shell_layers", object_bottom_shell_layers);
|
||||
if (texture_mapping_effective_config_uses_zone_id(volume_config, &object_config, &print_config, zone_id))
|
||||
note_usage(volume_top_shell_layers, volume_bottom_shell_layers);
|
||||
const std::vector<bool> &used_states = volume->mmu_segmentation_facets.get_data().used_states;
|
||||
if (size_t(zone_id) < used_states.size() && used_states[zone_id])
|
||||
note_usage(volume_top_shell_layers, volume_bottom_shell_layers);
|
||||
}
|
||||
|
||||
if (!object_uses_zone)
|
||||
continue;
|
||||
++out.object_count;
|
||||
min_top_shell_layers = std::min(min_top_shell_layers, object_min_top_shell_layers);
|
||||
min_bottom_shell_layers = std::min(min_bottom_shell_layers, object_min_bottom_shell_layers);
|
||||
}
|
||||
|
||||
if (out.object_count > 0) {
|
||||
out.min_top_shell_layers = min_top_shell_layers == std::numeric_limits<int>::max() ? 0 : min_top_shell_layers;
|
||||
out.min_bottom_shell_layers = min_bottom_shell_layers == std::numeric_limits<int>::max() ? 0 : min_bottom_shell_layers;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static std::set<unsigned int> texture_mapping_zone_ids_from_import_config(const DynamicPrintConfig &config)
|
||||
{
|
||||
const ConfigOptionString *defs = config.option<ConfigOptionString>("texture_mapping_definitions");
|
||||
@@ -1987,6 +2094,7 @@ public:
|
||||
int top_surface_contoning_polygonize_resolution,
|
||||
bool top_surface_contoning_surface_anchored_stacks_enabled,
|
||||
bool top_surface_contoning_td_adjustment_enabled,
|
||||
const TextureMappingZoneShellUsageSummary &top_surface_contoning_shell_usage,
|
||||
const TextureMappingManager &texture_mapping_zones,
|
||||
const TextureMappingGlobalSettings &global_settings,
|
||||
const TextureMappingPrimeTowerImage &prime_tower_image,
|
||||
@@ -2002,6 +2110,7 @@ public:
|
||||
(void) reduce_outer_surface_texture;
|
||||
m_modulation_mode_manually_changed = modulation_mode_manually_changed;
|
||||
m_strength_offsets_expanded = initial_strength_offsets_expanded;
|
||||
m_top_surface_contoning_shell_usage = top_surface_contoning_shell_usage;
|
||||
const int gap = FromDIP(8);
|
||||
auto *root = new wxBoxSizer(wxVERTICAL);
|
||||
auto *tab_row = new wxBoxSizer(wxHORIZONTAL);
|
||||
@@ -2562,6 +2671,15 @@ public:
|
||||
contoning_angle_row->Add(m_top_surface_contoning_angle_threshold_spin, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, gap / 2);
|
||||
contoning_angle_row->Add(new wxStaticText(m_top_surface_contoning_panel, wxID_ANY, _L("deg")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
top_surface_contoning_root->Add(contoning_angle_row, 0, wxEXPAND | wxBOTTOM, gap);
|
||||
const int clamped_contoning_pattern_filaments =
|
||||
std::clamp(top_surface_contoning_pattern_filaments,
|
||||
TextureMappingZone::MinTopSurfaceContoningPatternFilaments,
|
||||
TextureMappingZone::MaxTopSurfaceContoningPatternFilaments);
|
||||
const int clamped_contoning_stack_layers =
|
||||
std::max(clamped_contoning_pattern_filaments,
|
||||
std::clamp(top_surface_contoning_stack_layers,
|
||||
TextureMappingZone::MinTopSurfaceContoningStackLayers,
|
||||
TextureMappingZone::MaxTopSurfaceContoningStackLayers));
|
||||
auto *contoning_layers_row = new wxBoxSizer(wxHORIZONTAL);
|
||||
contoning_layers_row->Add(new wxStaticText(m_top_surface_contoning_panel, wxID_ANY, _L("Max infill layer depth")),
|
||||
0,
|
||||
@@ -2576,9 +2694,7 @@ public:
|
||||
wxSP_ARROW_KEYS | wxALIGN_RIGHT,
|
||||
TextureMappingZone::MinTopSurfaceContoningStackLayers,
|
||||
TextureMappingZone::MaxTopSurfaceContoningStackLayers,
|
||||
std::clamp(top_surface_contoning_stack_layers,
|
||||
TextureMappingZone::MinTopSurfaceContoningStackLayers,
|
||||
TextureMappingZone::MaxTopSurfaceContoningStackLayers));
|
||||
clamped_contoning_stack_layers);
|
||||
contoning_layers_row->Add(m_top_surface_contoning_stack_layers_spin, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, gap / 2);
|
||||
contoning_layers_row->Add(new wxStaticText(m_top_surface_contoning_panel, wxID_ANY, _L("layers")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
top_surface_contoning_root->Add(contoning_layers_row, 0, wxEXPAND | wxBOTTOM, gap);
|
||||
@@ -2596,16 +2712,22 @@ public:
|
||||
wxSP_ARROW_KEYS | wxALIGN_RIGHT,
|
||||
TextureMappingZone::MinTopSurfaceContoningPatternFilaments,
|
||||
TextureMappingZone::MaxTopSurfaceContoningPatternFilaments,
|
||||
std::clamp(top_surface_contoning_pattern_filaments,
|
||||
TextureMappingZone::MinTopSurfaceContoningPatternFilaments,
|
||||
TextureMappingZone::MaxTopSurfaceContoningPatternFilaments));
|
||||
clamped_contoning_pattern_filaments);
|
||||
contoning_pattern_row->Add(m_top_surface_contoning_pattern_filaments_spin, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, gap / 2);
|
||||
contoning_pattern_row->Add(new wxStaticText(m_top_surface_contoning_panel, wxID_ANY, _L("layers")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
top_surface_contoning_root->Add(contoning_pattern_row, 0, wxEXPAND);
|
||||
m_top_surface_contoning_pattern_recommendation_text =
|
||||
new wxStaticText(m_top_surface_contoning_panel, wxID_ANY, wxEmptyString);
|
||||
m_top_surface_contoning_pattern_recommendation_text->Wrap(FromDIP(520));
|
||||
new wxStaticText(m_top_surface_contoning_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
|
||||
top_surface_contoning_root->Add(m_top_surface_contoning_pattern_recommendation_text, 0, wxEXPAND | wxTOP | wxBOTTOM, gap / 2);
|
||||
m_top_surface_contoning_shell_warning_text =
|
||||
new wxStaticText(m_top_surface_contoning_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
|
||||
m_top_surface_contoning_shell_warning_text->SetForegroundColour(wxColour(180, 86, 0));
|
||||
top_surface_contoning_root->Add(m_top_surface_contoning_shell_warning_text, 0, wxEXPAND | wxBOTTOM, gap / 2);
|
||||
wrap_top_surface_contoning_message_texts(false);
|
||||
m_top_surface_contoning_panel->Bind(wxEVT_SIZE, [this](wxSizeEvent &evt) {
|
||||
evt.Skip();
|
||||
queue_top_surface_contoning_message_resize_wrap();
|
||||
});
|
||||
auto *contoning_feature_row = new wxBoxSizer(wxHORIZONTAL);
|
||||
contoning_feature_row->Add(new wxStaticText(m_top_surface_contoning_panel, wxID_ANY, _L("Minimum feature")),
|
||||
0,
|
||||
@@ -2849,17 +2971,42 @@ public:
|
||||
}
|
||||
if (m_top_surface_contoning_td_adjustment_checkbox != nullptr) {
|
||||
m_top_surface_contoning_td_adjustment_checkbox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &) {
|
||||
update_top_surface_contoning_td_recommendation(true);
|
||||
queue_top_surface_contoning_message_update(true);
|
||||
});
|
||||
}
|
||||
if (m_top_surface_contoning_color_lower_surfaces_checkbox != nullptr) {
|
||||
m_top_surface_contoning_color_lower_surfaces_checkbox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &) {
|
||||
queue_top_surface_contoning_message_update(true);
|
||||
});
|
||||
}
|
||||
if (m_top_surface_contoning_stack_layers_spin != nullptr) {
|
||||
m_top_surface_contoning_stack_layers_spin->Bind(wxEVT_SPINCTRL, [this](wxSpinEvent &) {
|
||||
enforce_top_surface_contoning_stack_depth_at_least_pattern();
|
||||
queue_top_surface_contoning_message_update(true);
|
||||
});
|
||||
m_top_surface_contoning_stack_layers_spin->Bind(wxEVT_TEXT, [this](wxCommandEvent &) {
|
||||
enforce_top_surface_contoning_stack_depth_at_least_pattern();
|
||||
queue_top_surface_contoning_message_update(true);
|
||||
});
|
||||
}
|
||||
if (m_top_surface_contoning_pattern_filaments_spin != nullptr) {
|
||||
m_top_surface_contoning_pattern_filaments_spin->Bind(wxEVT_SPINCTRL, [this](wxSpinEvent &) {
|
||||
enforce_top_surface_contoning_stack_depth_at_least_pattern();
|
||||
queue_top_surface_contoning_message_update(true);
|
||||
});
|
||||
m_top_surface_contoning_pattern_filaments_spin->Bind(wxEVT_TEXT, [this](wxCommandEvent &) {
|
||||
enforce_top_surface_contoning_stack_depth_at_least_pattern();
|
||||
queue_top_surface_contoning_message_update(true);
|
||||
});
|
||||
}
|
||||
for (wxSpinCtrlDouble *spin : m_transmission_distance_spins) {
|
||||
if (spin == nullptr)
|
||||
continue;
|
||||
spin->Bind(wxEVT_SPINCTRLDOUBLE, [this](wxSpinDoubleEvent &) {
|
||||
update_top_surface_contoning_td_recommendation(true);
|
||||
queue_top_surface_contoning_message_update(true);
|
||||
});
|
||||
spin->Bind(wxEVT_TEXT, [this](wxCommandEvent &) {
|
||||
update_top_surface_contoning_td_recommendation(false);
|
||||
queue_top_surface_contoning_message_update(true);
|
||||
});
|
||||
}
|
||||
m_top_surface_image_printing_enabled_checkbox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &) {
|
||||
@@ -3011,8 +3158,11 @@ public:
|
||||
m_options_book->AddPage(global_page, _L("Prime Tower Texture Mapping"));
|
||||
update_options_book_min_size();
|
||||
m_options_tab_choice->Bind(wxEVT_CHOICE, [this](wxCommandEvent &evt) {
|
||||
const int selection = std::clamp(evt.GetSelection(), 0, 6);
|
||||
if (m_options_book)
|
||||
m_options_book->SetSelection(std::clamp(evt.GetSelection(), 0, 6));
|
||||
m_options_book->SetSelection(selection);
|
||||
if (selection == 5)
|
||||
queue_top_surface_contoning_message_update(true);
|
||||
});
|
||||
if (m_options_book)
|
||||
m_options_book->SetSelection(std::clamp(initial_options_tab, 0, 6));
|
||||
@@ -3022,6 +3172,7 @@ public:
|
||||
SetSizerAndFit(root);
|
||||
SetMinSize(wxSize(FromDIP(420), GetBestSize().GetHeight()));
|
||||
CentreOnParent();
|
||||
CallAfter([this]() { update_top_surface_contoning_td_recommendation(true); });
|
||||
}
|
||||
|
||||
int texture_mapping_mode() const
|
||||
@@ -3183,11 +3334,12 @@ public:
|
||||
}
|
||||
int top_surface_contoning_stack_layers() const
|
||||
{
|
||||
return m_top_surface_contoning_stack_layers_spin ?
|
||||
const int stack_layers = m_top_surface_contoning_stack_layers_spin ?
|
||||
std::clamp(m_top_surface_contoning_stack_layers_spin->GetValue(),
|
||||
TextureMappingZone::MinTopSurfaceContoningStackLayers,
|
||||
TextureMappingZone::MaxTopSurfaceContoningStackLayers) :
|
||||
TextureMappingZone::DefaultTopSurfaceContoningStackLayers;
|
||||
return std::max(stack_layers, top_surface_contoning_pattern_filaments());
|
||||
}
|
||||
int top_surface_contoning_pattern_filaments() const
|
||||
{
|
||||
@@ -3665,15 +3817,248 @@ private:
|
||||
}
|
||||
|
||||
if (!has_translucent)
|
||||
return _L("TD recommendation: 1-3 layers.");
|
||||
return _L("Recommendation based on TD: 1-3 layers.");
|
||||
upper = std::max(upper, lower);
|
||||
strong = std::max(strong, upper);
|
||||
return wxString::Format(_L("TD recommendation: %d-%d layers. %d+ layers for stronger saturation."),
|
||||
return wxString::Format(_L("Recommendation based on highest TD: %d-%d layers (%d+ to show highest TD at strong saturation)."),
|
||||
lower,
|
||||
upper,
|
||||
strong);
|
||||
}
|
||||
|
||||
wxString top_surface_contoning_shell_warning_text() const
|
||||
{
|
||||
if (m_top_surface_contoning_shell_usage.object_count <= 0)
|
||||
return wxEmptyString;
|
||||
|
||||
const int pattern_layers = top_surface_contoning_pattern_filaments();
|
||||
const bool top_too_shallow = m_top_surface_contoning_shell_usage.min_top_shell_layers < pattern_layers;
|
||||
const bool bottom_too_shallow =
|
||||
top_surface_contoning_color_lower_surfaces() &&
|
||||
m_top_surface_contoning_shell_usage.min_bottom_shell_layers < pattern_layers;
|
||||
if (!top_too_shallow && !bottom_too_shallow)
|
||||
return wxEmptyString;
|
||||
|
||||
const wxString object_text = m_top_surface_contoning_shell_usage.object_count == 1 ?
|
||||
_L("1 object") :
|
||||
wxString::Format(_L("%d objects"), m_top_surface_contoning_shell_usage.object_count);
|
||||
wxString shell_text;
|
||||
if (top_too_shallow && bottom_too_shallow) {
|
||||
shell_text = wxString::Format(_L("top shell (%d) and bottom shell count (%d)"),
|
||||
m_top_surface_contoning_shell_usage.min_top_shell_layers,
|
||||
m_top_surface_contoning_shell_usage.min_bottom_shell_layers);
|
||||
} else if (top_too_shallow) {
|
||||
shell_text = wxString::Format(_L("top shell count (%d)"),
|
||||
m_top_surface_contoning_shell_usage.min_top_shell_layers);
|
||||
} else {
|
||||
shell_text = wxString::Format(_L("bottom shell count (%d)"),
|
||||
m_top_surface_contoning_shell_usage.min_bottom_shell_layers);
|
||||
}
|
||||
return wxString::Format(_L("Warning: this zone is used by %s, but the lowest %s is lower than the %d-layer color pattern."),
|
||||
object_text.c_str(),
|
||||
shell_text.c_str(),
|
||||
pattern_layers);
|
||||
}
|
||||
|
||||
void enforce_top_surface_contoning_stack_depth_at_least_pattern()
|
||||
{
|
||||
if (m_top_surface_contoning_stack_layers_spin == nullptr ||
|
||||
m_top_surface_contoning_pattern_filaments_spin == nullptr)
|
||||
return;
|
||||
const int pattern_layers = top_surface_contoning_pattern_filaments();
|
||||
if (m_top_surface_contoning_stack_layers_spin->GetValue() < pattern_layers)
|
||||
m_top_surface_contoning_stack_layers_spin->SetValue(pattern_layers);
|
||||
}
|
||||
|
||||
int top_surface_contoning_message_wrap_width()
|
||||
{
|
||||
int width = 0;
|
||||
auto consider_width = [this, &width](int candidate) {
|
||||
if (candidate <= FromDIP(120))
|
||||
return;
|
||||
width = width <= FromDIP(120) ? candidate : std::min(width, candidate);
|
||||
};
|
||||
if (m_top_surface_contoning_panel != nullptr)
|
||||
consider_width(m_top_surface_contoning_panel->GetClientSize().GetWidth());
|
||||
if (m_options_book != nullptr)
|
||||
consider_width(m_options_book->GetClientSize().GetWidth() - FromDIP(16));
|
||||
consider_width(GetClientSize().GetWidth() - FromDIP(56));
|
||||
if (width <= FromDIP(120))
|
||||
width = FromDIP(360);
|
||||
return std::clamp(width - FromDIP(16), FromDIP(120), FromDIP(380));
|
||||
}
|
||||
|
||||
int wrapped_static_text_height(wxStaticText *text, const wxSize &best_size)
|
||||
{
|
||||
if (text == nullptr || !text->IsShown())
|
||||
return 0;
|
||||
const wxString label = text->GetLabel();
|
||||
if (label.empty())
|
||||
return 0;
|
||||
int line_height = 0;
|
||||
int lines = 0;
|
||||
size_t start = 0;
|
||||
while (start <= label.length()) {
|
||||
size_t end = label.find('\n', start);
|
||||
const wxString line = end == wxString::npos ? label.Mid(start) : label.Mid(start, end - start);
|
||||
int line_width = 0;
|
||||
int measured_height = 0;
|
||||
const wxString measured_line = line.empty() ? wxString(" ") : line;
|
||||
text->GetTextExtent(measured_line, &line_width, &measured_height);
|
||||
line_height = std::max(line_height, measured_height);
|
||||
++lines;
|
||||
if (end == wxString::npos)
|
||||
break;
|
||||
start = end + 1;
|
||||
}
|
||||
return std::max(best_size.GetHeight(), lines * std::max(1, line_height) + FromDIP(6));
|
||||
}
|
||||
|
||||
int static_text_width(wxStaticText *text, const wxString &label)
|
||||
{
|
||||
if (text == nullptr || label.empty())
|
||||
return 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
text->GetTextExtent(label, &width, &height);
|
||||
return width;
|
||||
}
|
||||
|
||||
void append_wrapped_static_text_line(wxString &wrapped, const wxString &line)
|
||||
{
|
||||
if (line.empty())
|
||||
return;
|
||||
if (!wrapped.empty())
|
||||
wrapped += '\n';
|
||||
wrapped += line;
|
||||
}
|
||||
|
||||
wxString wrapped_static_text_label(wxStaticText *text, const wxString &label, int wrap_width)
|
||||
{
|
||||
if (label.empty() || text == nullptr)
|
||||
return wxEmptyString;
|
||||
wxString wrapped;
|
||||
wxString line;
|
||||
wxStringTokenizer tokens(label, " \t\r\n");
|
||||
while (tokens.HasMoreTokens()) {
|
||||
const wxString word = tokens.GetNextToken();
|
||||
const wxString candidate = line.empty() ? word : line + " " + word;
|
||||
if (line.empty() || static_text_width(text, candidate) <= wrap_width) {
|
||||
line = candidate;
|
||||
continue;
|
||||
}
|
||||
append_wrapped_static_text_line(wrapped, line);
|
||||
line = word;
|
||||
}
|
||||
append_wrapped_static_text_line(wrapped, line);
|
||||
return wrapped.empty() ? label : wrapped;
|
||||
}
|
||||
|
||||
void wrap_top_surface_contoning_message_text(wxStaticText *text, const wxString &label, int wrap_width)
|
||||
{
|
||||
if (text == nullptr)
|
||||
return;
|
||||
text->SetMinSize(wxDefaultSize);
|
||||
text->SetLabel(wrapped_static_text_label(text, label, wrap_width));
|
||||
text->InvalidateBestSize();
|
||||
const wxSize best_size = text->GetBestSize();
|
||||
const int height = wrapped_static_text_height(text, best_size);
|
||||
text->SetMinSize(wxSize(wrap_width, height));
|
||||
text->SetSize(wxSize(wrap_width, height));
|
||||
}
|
||||
|
||||
void refresh_top_surface_contoning_message_layout()
|
||||
{
|
||||
for (wxWindow *window = m_top_surface_contoning_panel; window != nullptr; window = window->GetParent()) {
|
||||
window->InvalidateBestSize();
|
||||
if (window == this)
|
||||
break;
|
||||
}
|
||||
if (m_top_surface_contoning_panel != nullptr)
|
||||
m_top_surface_contoning_panel->Layout();
|
||||
layout_current_options_page();
|
||||
update_options_book_min_size();
|
||||
if (GetSizer() != nullptr) {
|
||||
GetSizer()->Layout();
|
||||
Layout();
|
||||
}
|
||||
}
|
||||
|
||||
void wrap_top_surface_contoning_message_texts(bool refresh_layout, bool fit_dialog = false)
|
||||
{
|
||||
const int wrap_width = top_surface_contoning_message_wrap_width();
|
||||
m_top_surface_contoning_message_last_wrap_width = wrap_width;
|
||||
wrap_top_surface_contoning_message_text(m_top_surface_contoning_pattern_recommendation_text,
|
||||
m_top_surface_contoning_pattern_recommendation_label,
|
||||
wrap_width);
|
||||
wrap_top_surface_contoning_message_text(m_top_surface_contoning_shell_warning_text,
|
||||
m_top_surface_contoning_shell_warning_label,
|
||||
wrap_width);
|
||||
if (!refresh_layout || m_top_surface_contoning_message_wrap_refreshing)
|
||||
return;
|
||||
m_top_surface_contoning_message_wrap_fit_pending = m_top_surface_contoning_message_wrap_fit_pending || fit_dialog;
|
||||
m_top_surface_contoning_message_wrap_refreshing = true;
|
||||
refresh_top_surface_contoning_message_layout();
|
||||
m_top_surface_contoning_message_wrap_refreshing = false;
|
||||
if (m_top_surface_contoning_message_wrap_pending)
|
||||
return;
|
||||
m_top_surface_contoning_message_wrap_pending = true;
|
||||
CallAfter([this]() {
|
||||
m_top_surface_contoning_message_wrap_pending = false;
|
||||
const bool deferred_fit = m_top_surface_contoning_message_wrap_fit_pending;
|
||||
m_top_surface_contoning_message_wrap_fit_pending = false;
|
||||
if (m_top_surface_contoning_pattern_recommendation_text == nullptr)
|
||||
return;
|
||||
wrap_top_surface_contoning_message_texts(false);
|
||||
refresh_top_surface_contoning_message_layout();
|
||||
if (deferred_fit && GetSizer() != nullptr) {
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void wrap_top_surface_contoning_message_texts_for_resize()
|
||||
{
|
||||
const int wrap_width = top_surface_contoning_message_wrap_width();
|
||||
if (wrap_width == m_top_surface_contoning_message_last_wrap_width)
|
||||
return;
|
||||
wrap_top_surface_contoning_message_texts(false);
|
||||
if (m_top_surface_contoning_panel != nullptr)
|
||||
m_top_surface_contoning_panel->Layout();
|
||||
}
|
||||
|
||||
void queue_top_surface_contoning_message_resize_wrap()
|
||||
{
|
||||
if (m_top_surface_contoning_message_resize_wrap_pending)
|
||||
return;
|
||||
m_top_surface_contoning_message_resize_wrap_pending = true;
|
||||
CallAfter([this]() {
|
||||
m_top_surface_contoning_message_resize_wrap_pending = false;
|
||||
if (m_top_surface_contoning_panel == nullptr)
|
||||
return;
|
||||
wrap_top_surface_contoning_message_texts_for_resize();
|
||||
});
|
||||
}
|
||||
|
||||
void queue_top_surface_contoning_message_update(bool fit_dialog)
|
||||
{
|
||||
m_top_surface_contoning_message_update_fit_pending = m_top_surface_contoning_message_update_fit_pending || fit_dialog;
|
||||
if (m_top_surface_contoning_message_update_pending)
|
||||
return;
|
||||
m_top_surface_contoning_message_update_pending = true;
|
||||
CallAfter([this]() {
|
||||
m_top_surface_contoning_message_update_pending = false;
|
||||
const bool deferred_fit = m_top_surface_contoning_message_update_fit_pending;
|
||||
m_top_surface_contoning_message_update_fit_pending = false;
|
||||
if (m_top_surface_contoning_panel == nullptr)
|
||||
return;
|
||||
layout_current_options_page();
|
||||
m_top_surface_contoning_message_last_wrap_width = 0;
|
||||
update_top_surface_contoning_td_recommendation(deferred_fit);
|
||||
});
|
||||
}
|
||||
|
||||
void update_top_surface_contoning_td_recommendation(bool fit_dialog)
|
||||
{
|
||||
if (m_top_surface_contoning_pattern_recommendation_text == nullptr)
|
||||
@@ -3683,9 +4068,14 @@ private:
|
||||
m_top_surface_image_printing_enabled_checkbox->GetValue() &&
|
||||
m_top_surface_image_method_choice != nullptr &&
|
||||
m_top_surface_image_method_choice->GetSelection() == int(TextureMappingZone::TopSurfaceImageContoning);
|
||||
const wxString text = contoning ? top_surface_contoning_td_recommendation_text() : wxString();
|
||||
m_top_surface_contoning_pattern_recommendation_text->SetLabel(text);
|
||||
m_top_surface_contoning_pattern_recommendation_text->Show(!text.empty());
|
||||
enforce_top_surface_contoning_stack_depth_at_least_pattern();
|
||||
m_top_surface_contoning_pattern_recommendation_label = contoning ? top_surface_contoning_td_recommendation_text() : wxString();
|
||||
m_top_surface_contoning_pattern_recommendation_text->Show(!m_top_surface_contoning_pattern_recommendation_label.empty());
|
||||
if (m_top_surface_contoning_shell_warning_text != nullptr) {
|
||||
m_top_surface_contoning_shell_warning_label = contoning ? top_surface_contoning_shell_warning_text() : wxString();
|
||||
m_top_surface_contoning_shell_warning_text->Show(!m_top_surface_contoning_shell_warning_label.empty());
|
||||
}
|
||||
wrap_top_surface_contoning_message_texts(true, fit_dialog);
|
||||
if (!fit_dialog)
|
||||
return;
|
||||
layout_current_options_page();
|
||||
@@ -3942,6 +4332,16 @@ private:
|
||||
wxChoice *m_modulation_mode_choice {nullptr};
|
||||
std::vector<int> m_modulation_mode_choice_values;
|
||||
bool m_modulation_mode_manually_changed {false};
|
||||
TextureMappingZoneShellUsageSummary m_top_surface_contoning_shell_usage;
|
||||
bool m_top_surface_contoning_message_wrap_refreshing {false};
|
||||
bool m_top_surface_contoning_message_wrap_pending {false};
|
||||
bool m_top_surface_contoning_message_wrap_fit_pending {false};
|
||||
bool m_top_surface_contoning_message_resize_wrap_pending {false};
|
||||
bool m_top_surface_contoning_message_update_pending {false};
|
||||
bool m_top_surface_contoning_message_update_fit_pending {false};
|
||||
int m_top_surface_contoning_message_last_wrap_width {0};
|
||||
wxString m_top_surface_contoning_pattern_recommendation_label;
|
||||
wxString m_top_surface_contoning_shell_warning_label;
|
||||
wxCheckBox *m_recolor_small_perimeter_loops_checkbox {nullptr};
|
||||
wxCheckBox *m_recolor_top_visible_perimeter_sections_checkbox {nullptr};
|
||||
wxStaticText *m_top_visible_perimeter_recolor_aggressiveness_label {nullptr};
|
||||
@@ -3968,6 +4368,7 @@ private:
|
||||
wxSpinCtrl *m_top_surface_contoning_stack_layers_spin {nullptr};
|
||||
wxSpinCtrl *m_top_surface_contoning_pattern_filaments_spin {nullptr};
|
||||
wxStaticText *m_top_surface_contoning_pattern_recommendation_text {nullptr};
|
||||
wxStaticText *m_top_surface_contoning_shell_warning_text {nullptr};
|
||||
wxSpinCtrlDouble *m_top_surface_contoning_min_feature_spin {nullptr};
|
||||
wxChoice *m_top_surface_contoning_flat_surface_infill_choice {nullptr};
|
||||
wxPanel *m_top_surface_contoning_checkboxes_panel {nullptr};
|
||||
@@ -8929,6 +9330,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
physical_colors,
|
||||
apply_zone,
|
||||
bundle,
|
||||
print_cfg,
|
||||
set_config_string,
|
||||
notify_change,
|
||||
refresh_texture_mapping_preview]() {
|
||||
@@ -8954,6 +9356,8 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
updated.filament_transmission_distances_mm[idx] :
|
||||
0.f);
|
||||
}
|
||||
const TextureMappingZoneShellUsageSummary shell_usage =
|
||||
texture_mapping_zone_shell_usage_summary(wxGetApp().model(), *print_cfg, mgr_ptr->zone_id_for_index(zone_index));
|
||||
TextureMappingAdvancedOptionsDialog dlg(this,
|
||||
updated.texture_mapping_mode,
|
||||
updated.filament_color_mode,
|
||||
@@ -9012,6 +9416,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
updated.top_surface_contoning_polygonize_resolution,
|
||||
updated.top_surface_contoning_surface_anchored_stacks_enabled,
|
||||
updated.top_surface_contoning_td_adjustment_enabled,
|
||||
shell_usage,
|
||||
bundle->texture_mapping_zones,
|
||||
bundle->texture_mapping_global_settings,
|
||||
wxGetApp().model().texture_mapping_prime_tower_image,
|
||||
|
||||
Reference in New Issue
Block a user