Bugfixes
- Allow pasting hex codes in color picker on macos - Prevent texture mapping zone panel resetting to top - Fix solid rectangle showing in projection panel while text is being rendered - Allow textures to be restored from crash backups
This commit is contained in:
@@ -1950,6 +1950,7 @@ static void append_triangle_material_data(std::vector<uint8_t> &uv_valid,
|
||||
|
||||
void _generate_current_object_list(std::vector<Component> &sub_objects, Id object_id, IdToCurrentObjectMap& current_objects);
|
||||
bool _generate_volumes_new(ModelObject& object, const std::vector<Component> &sub_objects, const ObjectMetadata::VolumeMetadataList& volumes, ConfigSubstitutionContext& config_substitutions);
|
||||
bool _try_extract_imported_obj_texture_from_archive(mz_zip_archive &archive, const std::string &image_file, std::vector<uint8_t> &image_payload);
|
||||
void _restore_imported_obj_textures_from_archive(mz_zip_archive &archive);
|
||||
void _restore_prime_tower_texture_from_archive(mz_zip_archive &archive, const DynamicPrintConfig &config, Model &model);
|
||||
//bool _generate_volumes(ModelObject& object, const Geometry& geometry, const ObjectMetadata::VolumeMetadataList& volumes, ConfigSubstitutionContext& config_substitutions);
|
||||
@@ -5931,6 +5932,53 @@ static void append_triangle_material_data(std::vector<uint8_t> &uv_valid,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Importer::_try_extract_imported_obj_texture_from_archive(mz_zip_archive &archive, const std::string &image_file, std::vector<uint8_t> &image_payload)
|
||||
{
|
||||
image_payload.clear();
|
||||
if (try_extract_file_from_archive(archive, image_file, image_payload))
|
||||
return true;
|
||||
|
||||
if (!m_load_restore)
|
||||
return false;
|
||||
|
||||
for (const std::string &sub_model_path : m_sub_model_paths) {
|
||||
std::string path = sub_model_path;
|
||||
std::replace(path.begin(), path.end(), '\\', '/');
|
||||
while (!path.empty() && path.front() == '/')
|
||||
path.erase(path.begin());
|
||||
if (path.empty())
|
||||
continue;
|
||||
|
||||
const boost::filesystem::path object_archive_path = boost::filesystem::path(m_backup_path) / path;
|
||||
if (!boost::filesystem::exists(object_archive_path))
|
||||
continue;
|
||||
|
||||
mz_zip_archive object_archive;
|
||||
mz_zip_zero_struct(&object_archive);
|
||||
if (!open_zip_reader(&object_archive, object_archive_path.string()))
|
||||
continue;
|
||||
|
||||
const bool found = try_extract_file_from_archive(object_archive, image_file, image_payload);
|
||||
close_zip_reader(&object_archive);
|
||||
if (found)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_origin_file.empty() && boost::filesystem::exists(m_origin_file)) {
|
||||
mz_zip_archive origin_archive;
|
||||
mz_zip_zero_struct(&origin_archive);
|
||||
if (open_zip_reader(&origin_archive, m_origin_file)) {
|
||||
const bool found = try_extract_file_from_archive(origin_archive, image_file, image_payload);
|
||||
close_zip_reader(&origin_archive);
|
||||
if (found)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
image_payload.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
void _BBS_3MF_Importer::_restore_imported_obj_textures_from_archive(mz_zip_archive &archive)
|
||||
{
|
||||
if (m_model == nullptr)
|
||||
@@ -5946,7 +5994,7 @@ static void append_triangle_material_data(std::vector<uint8_t> &uv_valid,
|
||||
continue;
|
||||
|
||||
std::vector<uint8_t> image_payload;
|
||||
if (!try_extract_file_from_archive(archive, source.image_file, image_payload)) {
|
||||
if (!_try_extract_imported_obj_texture_from_archive(archive, source.image_file, image_payload)) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "3MF texture2d payload missing for image='" << source.image_file << "'";
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ struct TextureMappingZone
|
||||
static constexpr bool DefaultSeamHiding = false;
|
||||
static constexpr bool DefaultNonlinearOffsetAdjustment = false;
|
||||
static constexpr int DefaultModulationMode = int(ModulationLineWidth);
|
||||
static constexpr bool DefaultRecolorSmallPerimeterLoops = true;
|
||||
static constexpr bool DefaultRecolorSmallPerimeterLoops = false;
|
||||
static constexpr bool DefaultRecolorTopVisiblePerimeterSections = false;
|
||||
static constexpr int DefaultTopVisiblePerimeterRecolorAggressiveness = int(TopVisibleRecolorAggressive);
|
||||
static constexpr bool DefaultCompactOffsetMode = true;
|
||||
|
||||
@@ -13498,19 +13498,6 @@ void GLGizmoImageProjection::on_render_input_window(float x, float y, float bott
|
||||
ensure_text_projection_image();
|
||||
update_default_projection_mode();
|
||||
|
||||
if (m_show_overlay && ensure_overlay_texture()) {
|
||||
const OverlayRect rect = overlay_rect();
|
||||
if (rect.width > 0.f && rect.height > 0.f) {
|
||||
ImGui::GetBackgroundDrawList()->AddImage((void *)(intptr_t)m_overlay_texture.get_id(),
|
||||
ImVec2(rect.left, rect.top),
|
||||
ImVec2(rect.left + rect.width, rect.top + rect.height),
|
||||
ImVec2(0.f, 0.f),
|
||||
ImVec2(1.f, 1.f),
|
||||
ImGui::GetColorU32(
|
||||
ImVec4(1.f, 1.f, 1.f, 0.72f * std::clamp(m_projection_opacity, 0.f, 1.f))));
|
||||
}
|
||||
}
|
||||
|
||||
const float approx_height = m_imgui->scaled(12.0f);
|
||||
y = std::min(y, bottom_limit - approx_height);
|
||||
GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always);
|
||||
@@ -13649,6 +13636,19 @@ void GLGizmoImageProjection::on_render_input_window(float x, float y, float bott
|
||||
|
||||
GizmoImguiEnd();
|
||||
ImGuiWrapper::pop_toolbar_style();
|
||||
|
||||
if (m_show_overlay && ensure_overlay_texture()) {
|
||||
const OverlayRect rect = overlay_rect();
|
||||
if (rect.width > 0.f && rect.height > 0.f) {
|
||||
ImGui::GetBackgroundDrawList()->AddImage((void *)(intptr_t)m_overlay_texture.get_id(),
|
||||
ImVec2(rect.left, rect.top),
|
||||
ImVec2(rect.left + rect.width, rect.top + rect.height),
|
||||
ImVec2(0.f, 0.f),
|
||||
ImVec2(1.f, 1.f),
|
||||
ImGui::GetColorU32(
|
||||
ImVec4(1.f, 1.f, 1.f, 0.72f * std::clamp(m_projection_opacity, 0.f, 1.f))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GLGizmoImageProjection::project_image_to_selected_object()
|
||||
|
||||
@@ -300,6 +300,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
|
||||
{
|
||||
#ifdef __WXOSX__
|
||||
set_miniaturizable(GetHandle());
|
||||
mac_install_text_paste_shortcut();
|
||||
#endif
|
||||
|
||||
#ifdef __WXGTK__
|
||||
@@ -2899,6 +2900,9 @@ void MainFrame::init_menubar_as_editor()
|
||||
// BBS Paste
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Paste") + sep + ctrl_t + "V",
|
||||
_L("Paste clipboard"), [this, handle_key_event](wxCommandEvent&) {
|
||||
if (mac_paste_to_text_control()) {
|
||||
return;
|
||||
}
|
||||
wxKeyEvent e;
|
||||
e.SetEventType(wxEVT_KEY_DOWN);
|
||||
e.SetControlDown(true);
|
||||
@@ -2907,7 +2911,7 @@ void MainFrame::init_menubar_as_editor()
|
||||
return;
|
||||
}
|
||||
m_plater->paste_from_clipboard(); },
|
||||
"", nullptr, [this](){return m_plater->can_paste_from_clipboard(); }, this);
|
||||
"", nullptr, [this](){return mac_can_paste_to_text_control() || m_plater->can_paste_from_clipboard(); }, this);
|
||||
#if 0
|
||||
// BBS Delete selected
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Delete selected") + "\t" + _L("Backspace"),
|
||||
@@ -4346,4 +4350,3 @@ void SettingsDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
|
||||
} // GUI
|
||||
} // Slic3r
|
||||
|
||||
|
||||
@@ -719,6 +719,21 @@ static wxSize from_dip_for_parent(wxWindow *parent, const wxSize &size)
|
||||
return wxWindow::FromDIP(size, parent);
|
||||
}
|
||||
|
||||
class TextureMappingScrolledWindow : public wxScrolledWindow
|
||||
{
|
||||
public:
|
||||
TextureMappingScrolledWindow(wxWindow *parent,
|
||||
wxWindowID id = wxID_ANY,
|
||||
const wxPoint &pos = wxDefaultPosition,
|
||||
const wxSize &size = wxDefaultSize,
|
||||
long style = wxVSCROLL)
|
||||
: wxScrolledWindow(parent, id, pos, size, style)
|
||||
{
|
||||
}
|
||||
|
||||
bool ShouldScrollToChildOnFocus(wxWindow *child) override { return false; }
|
||||
};
|
||||
|
||||
class TextureMappingPatternPreview : public wxPanel
|
||||
{
|
||||
public:
|
||||
@@ -1353,7 +1368,7 @@ public:
|
||||
m_recolor_top_visible_perimeter_sections_checkbox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &) { update_modulation_mode_options_visibility(false); });
|
||||
auto *top_visible_recolor_row = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_top_visible_perimeter_recolor_aggressiveness_label =
|
||||
new wxStaticText(print_settings_page, wxID_ANY, _L("Top-visible recolor sensitivity:"));
|
||||
new wxStaticText(print_settings_page, wxID_ANY, _L("Top layer line recolor sensitivity:"));
|
||||
top_visible_recolor_row->Add(m_top_visible_perimeter_recolor_aggressiveness_label, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, gap);
|
||||
wxArrayString top_visible_recolor_choices;
|
||||
top_visible_recolor_choices.Add(_L("Conservative"));
|
||||
@@ -4090,7 +4105,7 @@ Sidebar::Sidebar(Plater *parent)
|
||||
spliter_texture_2->SetLineColour("#CECECE");
|
||||
scrolled_sizer->Add(spliter_texture_2, 0, wxEXPAND);
|
||||
|
||||
p->m_panel_texture_mapping_content = new wxScrolledWindow(p->scrolled, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
p->m_panel_texture_mapping_content = new TextureMappingScrolledWindow(p->scrolled, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
p->m_panel_texture_mapping_content->SetScrollRate(0, 5);
|
||||
p->m_panel_texture_mapping_content->ShowScrollbars(wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT);
|
||||
p->m_panel_texture_mapping_content->SetBackgroundColour(wxGetApp().dark_mode() ? wxColour(45, 45, 49) : wxColour(255, 255, 255));
|
||||
@@ -5659,6 +5674,19 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
wxWindowUpdateLocker no_updates_sidebar(this);
|
||||
wxWindowUpdateLocker no_updates_panel(p->m_panel_texture_mapping_content);
|
||||
|
||||
int texture_mapping_scroll_x = 0;
|
||||
int texture_mapping_scroll_y = 0;
|
||||
p->m_panel_texture_mapping_content->GetViewStart(&texture_mapping_scroll_x, &texture_mapping_scroll_y);
|
||||
|
||||
auto scroll_texture_mapping_content_to = [this](int scroll_x, int scroll_y) {
|
||||
if (p->m_panel_texture_mapping_content != nullptr)
|
||||
p->m_panel_texture_mapping_content->Scroll(scroll_x, scroll_y);
|
||||
};
|
||||
|
||||
auto restore_texture_mapping_scroll = [scroll_texture_mapping_content_to, texture_mapping_scroll_x, texture_mapping_scroll_y]() {
|
||||
scroll_texture_mapping_content_to(texture_mapping_scroll_x, texture_mapping_scroll_y);
|
||||
};
|
||||
|
||||
PresetBundle *bundle = wxGetApp().preset_bundle;
|
||||
if (bundle == nullptr)
|
||||
return;
|
||||
@@ -5735,9 +5763,12 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
return;
|
||||
content_sizer->Clear(true);
|
||||
content_sizer->AddSpacer(FromDIP(SidebarProps::ContentMargin()));
|
||||
auto update_texture_mapping_area_height = [this]() {
|
||||
auto update_texture_mapping_area_height = [this, scroll_texture_mapping_content_to]() {
|
||||
if (p->m_panel_texture_mapping_content == nullptr || p->m_panel_texture_mapping_content->GetSizer() == nullptr)
|
||||
return;
|
||||
int scroll_x = 0;
|
||||
int scroll_y = 0;
|
||||
p->m_panel_texture_mapping_content->GetViewStart(&scroll_x, &scroll_y);
|
||||
const int max_height = FromDIP(260);
|
||||
p->m_panel_texture_mapping_content->SetMaxSize(wxSize(-1, max_height));
|
||||
p->m_panel_texture_mapping_content->Layout();
|
||||
@@ -5746,6 +5777,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
if (min_size.y > max_height)
|
||||
min_size.y = max_height;
|
||||
p->m_panel_texture_mapping_content->SetMinSize(wxSize(-1, std::max(FromDIP(1), min_size.y)));
|
||||
scroll_texture_mapping_content_to(scroll_x, scroll_y);
|
||||
};
|
||||
|
||||
if (p->m_btn_add_texture_map != nullptr)
|
||||
@@ -5839,6 +5871,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
update_texture_mapping_area_height();
|
||||
m_scrolled_sizer->Layout();
|
||||
Layout();
|
||||
restore_texture_mapping_scroll();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6395,6 +6428,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
update_texture_mapping_area_height();
|
||||
m_scrolled_sizer->Layout();
|
||||
Layout();
|
||||
restore_texture_mapping_scroll();
|
||||
}
|
||||
|
||||
std::vector<unsigned int> Sidebar::get_ui_ordered_filament_ids() const
|
||||
|
||||
@@ -9,6 +9,9 @@ namespace GUI {
|
||||
#if __APPLE__
|
||||
extern bool mac_dark_mode();
|
||||
extern double mac_max_scaling_factor();
|
||||
extern bool mac_can_paste_to_text_control();
|
||||
extern bool mac_paste_to_text_control();
|
||||
extern void mac_install_text_paste_shortcut();
|
||||
extern void set_miniaturizable(void * window);
|
||||
void WKWebView_evaluateJavaScript(void * web, wxString const & script, void (*callback)(wxString const &));
|
||||
void WKWebView_setTransparentBackground(void * web);
|
||||
|
||||
@@ -41,6 +41,77 @@ double mac_max_scaling_factor()
|
||||
}
|
||||
return scaling;
|
||||
}
|
||||
|
||||
static id mac_text_paste_target()
|
||||
{
|
||||
id target = [NSApp targetForAction:@selector(paste:) to:nil from:nil];
|
||||
if (target != nil && [target isKindOfClass:[NSText class]])
|
||||
return target;
|
||||
return nil;
|
||||
}
|
||||
|
||||
static NSString *mac_color_panel_hex_string()
|
||||
{
|
||||
NSWindow *window = [NSApp keyWindow];
|
||||
if (![window isKindOfClass:[NSColorPanel class]])
|
||||
return nil;
|
||||
|
||||
NSString *string = [[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString];
|
||||
string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
if (![string hasPrefix:@"#"])
|
||||
return nil;
|
||||
|
||||
NSString *value = [string substringFromIndex:1];
|
||||
if ([value length] != 6)
|
||||
return nil;
|
||||
|
||||
NSCharacterSet *non_hex = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdefABCDEF"] invertedSet];
|
||||
if ([value rangeOfCharacterFromSet:non_hex].location != NSNotFound)
|
||||
return nil;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
bool mac_can_paste_to_text_control()
|
||||
{
|
||||
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
|
||||
if ([pasteboard stringForType:NSPasteboardTypeString] == nil)
|
||||
return false;
|
||||
return mac_text_paste_target() != nil;
|
||||
}
|
||||
|
||||
bool mac_paste_to_text_control()
|
||||
{
|
||||
id target = mac_text_paste_target();
|
||||
if (target == nil)
|
||||
return false;
|
||||
|
||||
NSString *color_panel_hex = mac_color_panel_hex_string();
|
||||
if (color_panel_hex != nil && [target respondsToSelector:@selector(insertText:)]) {
|
||||
[target insertText:color_panel_hex];
|
||||
return true;
|
||||
}
|
||||
|
||||
return [NSApp sendAction:@selector(paste:) to:nil from:nil] == YES;
|
||||
}
|
||||
|
||||
void mac_install_text_paste_shortcut()
|
||||
{
|
||||
static id monitor = nil;
|
||||
if (monitor != nil)
|
||||
return;
|
||||
|
||||
monitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown handler:^NSEvent *(NSEvent *event) {
|
||||
NSEventModifierFlags flags = [event modifierFlags];
|
||||
if ((flags & NSEventModifierFlagCommand) != 0 &&
|
||||
(flags & (NSEventModifierFlagShift | NSEventModifierFlagControl | NSEventModifierFlagOption)) == 0) {
|
||||
NSString *characters = [event charactersIgnoringModifiers];
|
||||
if ([characters length] == 1 && [[characters lowercaseString] isEqualToString:@"v"] && mac_paste_to_text_control())
|
||||
return nil;
|
||||
}
|
||||
return event;
|
||||
}];
|
||||
}
|
||||
|
||||
void set_miniaturizable(void * window)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user