mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-16 21:42:43 +00:00
Port colored OBJ import pipeline from BambuStudio
This commit is contained in:
@@ -491,7 +491,8 @@ public:
|
||||
std::function<void(wxColour)> on_add_filament,
|
||||
std::function<void()> on_decompose_color,
|
||||
std::function<bool()> can_add_filament,
|
||||
std::function<void(bool)> on_close)
|
||||
std::function<void(bool)> on_close,
|
||||
std::vector<int> display_numbers)
|
||||
: PopupWindow(parent, wxBORDER_NONE | wxPU_CONTAINS_CONTROLS)
|
||||
, m_entries(entries)
|
||||
, m_colors_rgba(colors_rgba)
|
||||
@@ -503,6 +504,7 @@ public:
|
||||
, m_on_decompose_color(std::move(on_decompose_color))
|
||||
, m_can_add_filament(std::move(can_add_filament))
|
||||
, m_on_close(std::move(on_close))
|
||||
, m_display_numbers(std::move(display_numbers))
|
||||
{
|
||||
wxColour pop_bg = dark_or(*wxWHITE, wxColour(0x2D, 0x2D, 0x31));
|
||||
SetBackgroundColour(pop_bg);
|
||||
@@ -550,9 +552,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// Section order matches compute_display_numbers() so the visible IDs
|
||||
// ascend monotonically (ExistingPhysical -> NewPhysical -> ExistingMixed
|
||||
// -> NewMixed) instead of jumping (e.g. 1,2 -> 7 -> 3,4,5,6 -> 8,9,10).
|
||||
add_section(_L("Project Physical Filaments"), TextureFilamentKind::ExistingPhysical);
|
||||
add_section(_L("Project Mixed Filaments"), TextureFilamentKind::ExistingMixed);
|
||||
add_section(_L("New Physical Filaments"), TextureFilamentKind::NewPhysical);
|
||||
add_section(_L("Project Mixed Filaments"), TextureFilamentKind::ExistingMixed);
|
||||
add_section(_L("New Mixed Filaments"), TextureFilamentKind::NewMixed);
|
||||
|
||||
auto* decompose_label = new wxStaticText(this, wxID_ANY, _L("Decompose Color"));
|
||||
@@ -682,7 +687,7 @@ private:
|
||||
: wxColour(128, 128, 128);
|
||||
|
||||
wxString name_str = (idx < m_names.size()) ? filament_name_to_wx_string(m_names[idx])
|
||||
: wxString::Format("Filament %d", (int)(idx + 1));
|
||||
: wxString::Format("Filament %d", display_number((int)idx));
|
||||
row->SetToolTip(name_str);
|
||||
|
||||
row->Bind(wxEVT_PAINT, [this, idx, sq, sq_r, sq_x, gap1, fil_clr, name_str, row_bg, hover_bg, name_fg](wxPaintEvent& e) {
|
||||
@@ -711,7 +716,7 @@ private:
|
||||
nf.SetPointSize(9);
|
||||
dc.SetFont(nf);
|
||||
dc.SetTextForeground(paint_clr.GetLuminance() < 0.6 ? *wxWHITE : texture_import_gray9000());
|
||||
wxString ns = wxString::Format("%d", (int)(idx + 1));
|
||||
wxString ns = wxString::Format("%d", display_number((int)idx));
|
||||
wxSize tsz = dc.GetTextExtent(ns);
|
||||
dc.DrawText(ns, sq_x + (sq - tsz.x) / 2, sq_y + (sq - tsz.y) / 2);
|
||||
}
|
||||
@@ -767,7 +772,7 @@ private:
|
||||
row->SetBackgroundColour(row_bg);
|
||||
row->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
row->SetCursor(wxCursor(wxCURSOR_HAND));
|
||||
row->SetToolTip(entry.name.empty() ? wxString::Format("Filament %d", idx + 1) : filament_name_to_wx_string(entry.name));
|
||||
row->SetToolTip(entry.name.empty() ? wxString::Format("Filament %d", display_number(idx)) : filament_name_to_wx_string(entry.name));
|
||||
|
||||
row->Bind(wxEVT_PAINT, [this, entry, idx, row_bg, hover_bg, name_fg, plus_fg](wxPaintEvent& e) {
|
||||
auto* p = static_cast<wxPanel*>(e.GetEventObject());
|
||||
@@ -810,7 +815,7 @@ private:
|
||||
dc.DrawRoundedRectangle(x, y, sw, sw, sw_r);
|
||||
draw_filament_swatch_border(dc, comp_clr, x, y, sw, sw, sw_r);
|
||||
|
||||
wxString num = wxString::Format("%u", comp_id);
|
||||
wxString num = wxString::Format("%d", display_number(comp_dialog_idx));
|
||||
wxSize nsz = dc.GetTextExtent(num);
|
||||
dc.SetTextForeground(comp_clr.GetLuminance() < 0.6 ? *wxWHITE : texture_import_gray9000());
|
||||
dc.DrawText(num, x + (sw - nsz.x) / 2, y + (sw - nsz.y) / 2);
|
||||
@@ -858,9 +863,19 @@ private:
|
||||
std::function<void()> m_on_decompose_color;
|
||||
std::function<bool()> m_can_add_filament;
|
||||
std::function<void(bool)> m_on_close;
|
||||
// 1-based display number per dialog_index, mirroring the post-apply
|
||||
// sidebar ordering (ExistingPhysical, NewPhysical, ExistingMixed, NewMixed).
|
||||
std::vector<int> m_display_numbers;
|
||||
int m_hover_idx = -1;
|
||||
bool m_closing_from_action = false;
|
||||
bool m_destroy_scheduled = false;
|
||||
|
||||
// Returns the display number for a dialog_index, falling back to idx + 1
|
||||
// when no mapping is available (e.g. index out of range).
|
||||
int display_number(int idx) const {
|
||||
return (idx >= 0 && idx < (int)m_display_numbers.size() && m_display_numbers[idx] > 0)
|
||||
? m_display_numbers[idx] : idx + 1;
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================
|
||||
@@ -1735,8 +1750,11 @@ TextureImportDialog::TextureImportDialog(
|
||||
|
||||
m_preview_canvas->set_mesh_data(m_textured_mesh.vertices, m_textured_mesh.indices);
|
||||
|
||||
// Prepare texture rendering data for the Original tab
|
||||
if (!m_textured_mesh.textures.empty()) {
|
||||
// Pre-computed face colors (OBJ vertex colors / MTL face colors):
|
||||
// use them directly as the Original preview, skip texture decode.
|
||||
if (!m_textured_mesh.precomputed_face_colors.empty()) {
|
||||
m_preview_canvas->set_original_face_colors(m_textured_mesh.precomputed_face_colors);
|
||||
} else if (!m_textured_mesh.textures.empty()) {
|
||||
std::vector<std::vector<unsigned char>> tex_pixels_rgb;
|
||||
std::vector<int> tex_widths, tex_heights;
|
||||
tex_pixels_rgb.reserve(m_textured_mesh.textures.size());
|
||||
@@ -2444,7 +2462,13 @@ void TextureImportDialog::start_computation(bool auto_color, bool initial)
|
||||
auto worker_settings = settings;
|
||||
bool mesh_repair_decision_required = false;
|
||||
worker_settings.mesh_repair_decision_required = &mesh_repair_decision_required;
|
||||
bool ok = Slic3r::texture_to_painting(mesh_copy, result, worker_settings, progress_cb, cancel_cb);
|
||||
bool ok;
|
||||
if (!mesh_copy.precomputed_face_colors.empty()) {
|
||||
ok = Slic3r::face_colors_to_painting(
|
||||
mesh_copy, result, worker_settings, progress_cb, cancel_cb);
|
||||
} else {
|
||||
ok = Slic3r::texture_to_painting(mesh_copy, result, worker_settings, progress_cb, cancel_cb);
|
||||
}
|
||||
|
||||
if (m_cancel_flag.load()) {
|
||||
wxQueueEvent(handler, new wxCommandEvent(EVT_TEXTURE_COMPUTE_ERROR));
|
||||
@@ -3075,6 +3099,54 @@ void TextureImportDialog::compact_used_virtual_filaments()
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> TextureImportDialog::compute_display_numbers() const
|
||||
{
|
||||
// Assigns each entry a 1-based display number in the order the sidebar will
|
||||
// show after apply: ExistingPhysical, NewPhysical, ExistingMixed, NewMixed.
|
||||
// This keeps the dialog's visible IDs in sync with the post-apply sidebar,
|
||||
// instead of the raw dialog_index (which interleaves physicals and mixeds
|
||||
// by processing order and causes e.g. CMYW to show 4,5,6,8 instead of 3,4,5,6).
|
||||
// MUST mirror ordering in apply_textured_mesh_import_result (Plater.cpp:9896):
|
||||
// - ExistingPhysical keeps its project_config_index
|
||||
// - NewPhysical is inserted at existing_physical_count + new_order
|
||||
// - ExistingMixed shifts to project_config_index + new_physical_count
|
||||
// - NewMixed is appended after all existing mixeds
|
||||
std::vector<int> result(m_filament_entries.size(), 0);
|
||||
int next = 1;
|
||||
|
||||
auto assign_group = [&](TextureFilamentKind kind, bool by_project_config_index) {
|
||||
if (by_project_config_index) {
|
||||
std::vector<const TextureFilamentEntry*> group;
|
||||
for (const auto& e : m_filament_entries)
|
||||
if (e.kind == kind)
|
||||
group.push_back(&e);
|
||||
std::sort(group.begin(), group.end(),
|
||||
[](const TextureFilamentEntry* a, const TextureFilamentEntry* b) {
|
||||
return a->project_config_index < b->project_config_index;
|
||||
});
|
||||
for (const auto* e : group) {
|
||||
if (e->dialog_index >= 0 && e->dialog_index < (int)result.size())
|
||||
result[e->dialog_index] = next;
|
||||
++next;
|
||||
}
|
||||
} else {
|
||||
for (const auto& e : m_filament_entries) {
|
||||
if (e.kind != kind)
|
||||
continue;
|
||||
if (e.dialog_index >= 0 && e.dialog_index < (int)result.size())
|
||||
result[e.dialog_index] = next;
|
||||
++next;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
assign_group(TextureFilamentKind::ExistingPhysical, true);
|
||||
assign_group(TextureFilamentKind::NewPhysical, false);
|
||||
assign_group(TextureFilamentKind::ExistingMixed, true);
|
||||
assign_group(TextureFilamentKind::NewMixed, false);
|
||||
return result;
|
||||
}
|
||||
|
||||
void TextureImportDialog::dismiss_filament_popup()
|
||||
{
|
||||
if (!m_filament_popup) {
|
||||
@@ -3429,7 +3501,13 @@ void TextureImportDialog::show_filament_popup(size_t row_index)
|
||||
dismiss_filament_popup();
|
||||
}
|
||||
|
||||
auto on_select = [this, row_index](int idx) {
|
||||
const auto display_numbers = compute_display_numbers();
|
||||
auto display_number = [display_numbers](int idx) -> int {
|
||||
return (idx >= 0 && idx < (int)display_numbers.size() && display_numbers[idx] > 0)
|
||||
? display_numbers[idx] : idx + 1;
|
||||
};
|
||||
|
||||
auto on_select = [this, row_index, display_number](int idx) {
|
||||
if (row_index >= m_mapping_rows.size()) return;
|
||||
m_mapping_rows[row_index].target_filament_idx = idx;
|
||||
if (row_index < m_current_matches.size())
|
||||
@@ -3437,7 +3515,7 @@ void TextureImportDialog::show_filament_popup(size_t row_index)
|
||||
if (m_mapping_rows[row_index].target_panel) {
|
||||
wxString label = (idx >= 0 && idx < (int)m_filament_names.size())
|
||||
? filament_name_to_wx_string(m_filament_names[idx])
|
||||
: wxString::Format("Filament %d", idx + 1);
|
||||
: wxString::Format("Filament %d", display_number(idx));
|
||||
m_mapping_rows[row_index].target_panel->SetToolTip(label);
|
||||
m_mapping_rows[row_index].target_panel->Refresh();
|
||||
}
|
||||
@@ -3490,7 +3568,8 @@ void TextureImportDialog::show_filament_popup(size_t row_index)
|
||||
m_existing_filament_count, tp->GetSize().x, tp, on_select, on_add_filament,
|
||||
on_decompose_color,
|
||||
[this]() { return can_add_virtual_filament(); },
|
||||
on_close);
|
||||
on_close,
|
||||
display_numbers);
|
||||
|
||||
wxPoint pos = tp->ClientToScreen(wxPoint(0, tp->GetSize().y));
|
||||
wxRect display_rect;
|
||||
@@ -3673,10 +3752,16 @@ void TextureImportDialog::rebuild_mapping_rows()
|
||||
return wxColour(128, 128, 128);
|
||||
};
|
||||
|
||||
auto get_filament_label = [this](int idx) -> wxString {
|
||||
const auto display_numbers = compute_display_numbers();
|
||||
auto display_number = [display_numbers](int idx) -> int {
|
||||
return (idx >= 0 && idx < (int)display_numbers.size() && display_numbers[idx] > 0)
|
||||
? display_numbers[idx] : idx + 1;
|
||||
};
|
||||
|
||||
auto get_filament_label = [this, display_number](int idx) -> wxString {
|
||||
if (idx >= 0 && idx < (int)m_filament_names.size())
|
||||
return filament_name_to_wx_string(m_filament_names[idx]);
|
||||
return wxString::Format("Filament %d", idx + 1);
|
||||
return wxString::Format("Filament %d", display_number(idx));
|
||||
};
|
||||
|
||||
const wxColour dash_clr = dark_or(wxColour(179, 179, 179), wxColour(100, 100, 106));
|
||||
@@ -3804,7 +3889,7 @@ void TextureImportDialog::rebuild_mapping_rows()
|
||||
row.target_panel->SetCursor(wxCursor(wxCURSOR_HAND));
|
||||
|
||||
row.target_panel->Bind(wxEVT_PAINT, [this, ci, get_target_wxcolor, get_filament_label,
|
||||
card_bg, card_bd, name_fg, chev_clr](wxPaintEvent& e) {
|
||||
display_number, card_bg, card_bd, name_fg, chev_clr](wxPaintEvent& e) {
|
||||
auto* p = static_cast<wxPanel*>(e.GetEventObject());
|
||||
wxAutoBufferedPaintDC dc(p);
|
||||
wxSize sz = p->GetClientSize();
|
||||
@@ -3856,7 +3941,7 @@ void TextureImportDialog::rebuild_mapping_rows()
|
||||
dc.DrawRoundedRectangle(x, sw_y, sw, sw, sw_r);
|
||||
draw_filament_swatch_border(dc, comp_clr, x, sw_y, sw, sw, sw_r);
|
||||
|
||||
wxString num_str = wxString::Format("%u", comp_id);
|
||||
wxString num_str = wxString::Format("%d", display_number(comp_idx));
|
||||
wxSize nsz = dc.GetTextExtent(num_str);
|
||||
dc.SetTextForeground(comp_clr.GetLuminance() < 0.6 ? *wxWHITE : texture_import_gray9000());
|
||||
dc.DrawText(num_str, x + (sw - nsz.x) / 2, sw_y + (sw - nsz.y) / 2);
|
||||
@@ -3897,7 +3982,7 @@ void TextureImportDialog::rebuild_mapping_rows()
|
||||
num_font.SetPointSize(10);
|
||||
dc.SetFont(num_font);
|
||||
dc.SetTextForeground(fil_clr.GetLuminance() < 0.6 ? *wxWHITE : texture_import_gray9000());
|
||||
wxString num_str = wxString::Format("%d", fil_idx + 1);
|
||||
wxString num_str = wxString::Format("%d", display_number(fil_idx));
|
||||
wxSize nsz = dc.GetTextExtent(num_str);
|
||||
dc.DrawText(num_str, sq_x + (sq - nsz.x) / 2, sq_y + (sq - nsz.y) / 2);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user