mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-25 09:50:59 +00:00
Merge branch '2.3.0' into dev_2.3.0_alves
This commit is contained in:
@@ -151,7 +151,7 @@ jobs:
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Deploy Flatpak to nightly release
|
||||
if: ${{github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.0'}}
|
||||
if: ${{github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.3'}}
|
||||
uses: WebFreak001/deploy-nightly@v3.2.0
|
||||
with:
|
||||
upload_url: https://uploads.github.com/repos/Snapmaker/OrcaSlicer/releases/169912305/assets{?name,label}
|
||||
|
||||
@@ -122,7 +122,7 @@ jobs:
|
||||
|
||||
# Thanks to RaySajuuk, it's working now
|
||||
- name: Sign app and notary
|
||||
if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || github.ref == 'refs/heads/2.2.0') && inputs.os == 'macos-14'
|
||||
if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || github.ref == 'refs/heads/2.2.3') && inputs.os == 'macos-14'
|
||||
working-directory: ${{ github.workspace }}
|
||||
env:
|
||||
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
|
||||
@@ -175,7 +175,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Create DMG without notary
|
||||
if: github.ref != 'refs/heads/main' && inputs.os == 'macos-14' && github.ref != 'refs/heads/2.2.0'
|
||||
if: github.ref != 'refs/heads/main' && inputs.os == 'macos-14' && github.ref != 'refs/heads/2.2.3'
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
mkdir -p ${{ github.workspace }}/build/universal/Snapmaker_Orca_dmg
|
||||
@@ -217,7 +217,7 @@ jobs:
|
||||
if-no-files-found: warn
|
||||
|
||||
- name: Deploy Mac release
|
||||
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.0') && inputs.os == 'macos-14'
|
||||
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.3') && inputs.os == 'macos-14'
|
||||
uses: WebFreak001/deploy-nightly@v3.2.0
|
||||
with:
|
||||
upload_url: https://uploads.github.com/repos/Snapmaker/OrcaSlicer/releases/169912305/assets{?name,label}
|
||||
@@ -228,7 +228,7 @@ jobs:
|
||||
max_releases: 1 # optional, if there are more releases than this matching the asset_name, the oldest ones are going to be deleted
|
||||
|
||||
- name: Check if profile validator DMG exists
|
||||
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.0') && inputs.os == 'macos-14'
|
||||
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.3') && inputs.os == 'macos-14'
|
||||
id: check_dmg
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
@@ -242,7 +242,7 @@ jobs:
|
||||
shell: bash
|
||||
|
||||
- name: Deploy Mac Snapmaker_Orca_profile_validator DMG release
|
||||
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.0') && inputs.os == 'macos-14' && steps.check_dmg.outputs.exists == 'true'
|
||||
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.3') && inputs.os == 'macos-14' && steps.check_dmg.outputs.exists == 'true'
|
||||
uses: WebFreak001/deploy-nightly@v3.2.0
|
||||
with:
|
||||
upload_url: https://uploads.github.com/repos/Snapmaker/OrcaSlicer/releases/169912305/assets{?name,label}
|
||||
@@ -318,7 +318,7 @@ jobs:
|
||||
path: ${{ github.workspace }}/build/src/Release/Snapmaker_Orca_profile_validator.exe
|
||||
|
||||
- name: Deploy Windows release portable
|
||||
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.0') && inputs.os == 'windows-latest'
|
||||
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.3') && inputs.os == 'windows-latest'
|
||||
uses: WebFreak001/deploy-nightly@v3.2.0
|
||||
with:
|
||||
upload_url: https://uploads.github.com/repos/Snapmaker/OrcaSlicer/releases/169912305/assets{?name,label}
|
||||
@@ -329,7 +329,7 @@ jobs:
|
||||
max_releases: 1
|
||||
|
||||
- name: Deploy Windows release installer
|
||||
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.0') && inputs.os == 'windows-latest'
|
||||
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.3') && inputs.os == 'windows-latest'
|
||||
uses: WebFreak001/deploy-nightly@v3.2.0
|
||||
with:
|
||||
upload_url: https://uploads.github.com/repos/Snapmaker/OrcaSlicer/releases/169912305/assets{?name,label}
|
||||
@@ -340,7 +340,7 @@ jobs:
|
||||
max_releases: 1
|
||||
|
||||
- name: Deploy Windows Snapmaker_Orca_profile_validator release
|
||||
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.0') && inputs.os == 'windows-latest'
|
||||
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.3') && inputs.os == 'windows-latest'
|
||||
uses: WebFreak001/deploy-nightly@v3.2.0
|
||||
with:
|
||||
upload_url: https://uploads.github.com/repos/Snapmaker/OrcaSlicer/releases/169912305/assets{?name,label}
|
||||
@@ -414,7 +414,7 @@ jobs:
|
||||
path: './build/src/Release/Snapmaker_Orca_profile_validator'
|
||||
|
||||
- name: Deploy Ubuntu release
|
||||
if: ${{ ! env.ACT && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.0') && (inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04') }}
|
||||
if: ${{ ! env.ACT && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.3') && (inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04') }}
|
||||
env:
|
||||
ubuntu-ver-str: ${{ (inputs.os == 'ubuntu-24.04' && '_Ubuntu2404') || '' }}
|
||||
uses: WebFreak001/deploy-nightly@v3.2.0
|
||||
@@ -426,7 +426,7 @@ jobs:
|
||||
asset_content_type: application/octet-stream
|
||||
max_releases: 1 # optional, if there are more releases than this matching the asset_name, the oldest ones are going to be deleted
|
||||
- name: Deploy Ubuntu release
|
||||
if: ${{ ! env.ACT && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.0') && inputs.os == 'ubuntu-24.04' }}
|
||||
if: ${{ ! env.ACT && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.3') && inputs.os == 'ubuntu-24.04' }}
|
||||
uses: rickstaa/action-create-tag@v1
|
||||
with:
|
||||
tag: "nightly-builds"
|
||||
@@ -435,7 +435,7 @@ jobs:
|
||||
message: "nightly-builds"
|
||||
|
||||
- name: Deploy Ubuntu Snapmaker_Orca_profile_validator release
|
||||
if: ${{ ! env.ACT && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.0') && (inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04') }}
|
||||
if: ${{ ! env.ACT && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/2.2.3') && (inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04') }}
|
||||
env:
|
||||
ubuntu-ver-str: ${{ (inputs.os == 'ubuntu-24.04' && '_Ubuntu2404') || '' }}
|
||||
uses: WebFreak001/deploy-nightly@v3.2.0
|
||||
|
||||
@@ -15259,7 +15259,7 @@ msgid "Point and point assembly"
|
||||
msgstr "点和点组装"
|
||||
|
||||
msgid "Please do not include the special characters #, *, ;, \\, /, :, \", <, >, or | in filenames."
|
||||
msgstr "在文件名中勿使用特殊字符"#"*""";""\\""/" ":"\""<"">"或"|"。"
|
||||
msgstr "在文件名中勿使用特殊字符#, *, ;, \\, /, :, \", <, >或|。"
|
||||
|
||||
msgid "The filename '%s' contains special characters (#, *, ;, \\, /, :, \", <, >, or |) which may cause issues.Do you wish to continue?"
|
||||
msgstr "文件名'%s'包含特殊字符(# * ; \\ / : \" < > |)可能会导致问题。是否继续?"
|
||||
|
||||
@@ -194,6 +194,7 @@
|
||||
"0"
|
||||
],
|
||||
"ramming_pressure_advance_value": "0.02",
|
||||
"default_print_profile": "0.20 Standard @Snapmaker U1 (0.4 nozzle)",
|
||||
"tool_change_temprature_wait": "0",
|
||||
"printer_notes": "",
|
||||
"machine_pause_gcode": "M600",
|
||||
|
||||
+2
-1
@@ -34,5 +34,6 @@
|
||||
"support_threshold_angle": "25",
|
||||
"support_type": "tree(auto)",
|
||||
"wipe_tower_extra_rib_length": "8",
|
||||
"wipe_tower_wall_type": "rib"
|
||||
"wipe_tower_wall_type": "rib",
|
||||
"gap_fill_target": "topbottom"
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"type": "process",
|
||||
"name": "0.14 Standard @Snapmaker U1 (0.2 nozzle)",
|
||||
"inherits": "fdm_process_U1_0.14_nozzle_0.2",
|
||||
"from": "system",
|
||||
"setting_id": "GP027",
|
||||
"instantiation": "true",
|
||||
"description": "Compared with the default profile of a 0.2 mm nozzle, it has a bigger layer height, and results in slightly visible layer lines, but shorter printing time.",
|
||||
"elefant_foot_compensation": "0.15",
|
||||
"smooth_coefficient": "150",
|
||||
"overhang_totally_speed": "50",
|
||||
"compatible_printers": [
|
||||
"Snapmaker U1 (0.2 nozzle)"
|
||||
],
|
||||
"enable_arc_fitting": "0",
|
||||
"ooze_prevention": "1",
|
||||
"precise_outer_wall": "0",
|
||||
"prime_tower_brim_width": "5",
|
||||
"prime_tower_width": "30",
|
||||
"prime_volume": "32",
|
||||
"slowdown_for_curled_perimeters": "0",
|
||||
"standby_temperature_delta": "-150",
|
||||
"support_type": "tree(auto)",
|
||||
"wipe_tower_extra_rib_length": "8",
|
||||
"wipe_tower_extra_spacing": "120%",
|
||||
"wipe_tower_wall_type": "rib"
|
||||
}
|
||||
+2
-1
@@ -34,5 +34,6 @@
|
||||
"support_threshold_angle": "30",
|
||||
"support_type": "tree(auto)",
|
||||
"wipe_tower_extra_rib_length": "8",
|
||||
"wipe_tower_wall_type": "rib"
|
||||
"wipe_tower_wall_type": "rib",
|
||||
"gap_fill_target": "topbottom"
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
{
|
||||
"type": "process",
|
||||
"name": "0.18 Standard @Snapmaker U1 (0.6 nozzle)",
|
||||
"inherits": "fdm_process_U1_0.18_nozzle_0.6",
|
||||
"from": "system",
|
||||
"setting_id": "GP028",
|
||||
"instantiation": "true",
|
||||
"description": "Compared with the default profile of a 0.6 mm nozzle, it has a smaller layer height, and results in less apparent layer lines and higher printing quality, but longer printing time.",
|
||||
"elefant_foot_compensation": "0.15",
|
||||
"smooth_coefficient": "150",
|
||||
"overhang_totally_speed": "50",
|
||||
"compatible_printers": [
|
||||
"Snapmaker U1 (0.6 nozzle)"
|
||||
],
|
||||
"filter_out_gap_fill": "1",
|
||||
"gap_fill_target": "topbottom",
|
||||
"internal_bridge_speed": "100%",
|
||||
"layer_height": "0.25",
|
||||
"prime_tower_brim_width": "5",
|
||||
"prime_tower_width": "30",
|
||||
"prime_volume": "41",
|
||||
"seam_gap": "15%",
|
||||
"wipe_tower_extra_rib_length": "8",
|
||||
"wipe_tower_extra_spacing": "120%",
|
||||
"wipe_tower_wall_type": "rib",
|
||||
"enable_arc_fitting": "0",
|
||||
"ooze_prevention": "1",
|
||||
"precise_outer_wall": "0",
|
||||
"slowdown_for_curled_perimeters": "0",
|
||||
"standby_temperature_delta": "-150",
|
||||
"support_type": "tree(auto)"
|
||||
}
|
||||
@@ -6,4 +6,4 @@
|
||||
- Feature: Added a new model entry
|
||||
|
||||
### Bugfix
|
||||
Fixed the issue where devices would automatically disconnect when connected over Lan network
|
||||
Fixed the issue where devices would automatically disconnect when connected over Lan network
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<color type="primary" scheme_preference="light">#009688</color>
|
||||
</branding>
|
||||
<releases>
|
||||
<release version="2.2.4" date="2025-12-26">
|
||||
<release version="2.2.4" date="2026-3-4">
|
||||
<description>
|
||||
<p>Version 2.2.4 release with improvements and bug fixes.</p>
|
||||
</description>
|
||||
|
||||
@@ -5,6 +5,13 @@
|
||||
#include <sstream>
|
||||
|
||||
static std::atomic<bool> isAgreeSlice(true);
|
||||
|
||||
static std::atomic<bool> g_sentry_initialized(false);
|
||||
|
||||
bool get_sentry_flags() { return g_sentry_initialized; }
|
||||
|
||||
void set_sentry_flags(bool flags) { g_sentry_initialized = flags; }
|
||||
|
||||
bool get_privacy_policy()
|
||||
{
|
||||
return isAgreeSlice;
|
||||
|
||||
@@ -63,6 +63,9 @@
|
||||
|
||||
//webview bury point
|
||||
|
||||
BURY_API bool get_sentry_flags();
|
||||
BURY_API void set_sentry_flags(bool flags);
|
||||
|
||||
BURY_API bool get_privacy_policy();
|
||||
BURY_API void set_privacy_policy(bool isAgree);
|
||||
BURY_API std::string get_timestamp_seconds();
|
||||
|
||||
@@ -2094,25 +2094,38 @@ WipeTower::ToolChangeResult WipeTower2::finish_layer()
|
||||
// brim with chamfer (gradual layer-by-layer reduction)
|
||||
int loops_num = (m_wipe_tower_brim_width + spacing/2.f) / spacing;
|
||||
|
||||
// Apply chamfer reduction if feature is enabled and brim width is configured
|
||||
if (m_wipe_tower_brim_width > 0 && m_prime_tower_brim_chamfer) {
|
||||
if (!first_layer) {
|
||||
// Apply brim logic based on chamfer setting
|
||||
if (m_wipe_tower_brim_width > 0) {
|
||||
if (first_layer) {
|
||||
// First layer: always print full brim (loops_num unchanged)
|
||||
} else if (m_prime_tower_brim_chamfer) {
|
||||
// Non-first layer + chamfer enabled: apply gradual reduction
|
||||
// Calculate distance from first layer with tool changes
|
||||
size_t current_idx = m_layer_info - m_plan.begin();
|
||||
int dist_to_1st = (int)current_idx - (int)m_first_layer_idx;
|
||||
|
||||
// Stop print chamfer if depth changes
|
||||
bool depth_changed = (m_layer_info->depth != m_plan[m_first_layer_idx].depth);
|
||||
if (depth_changed) {
|
||||
// Validate m_first_layer_idx to prevent invalid index access
|
||||
if (m_first_layer_idx == size_t(-1) || m_first_layer_idx >= m_plan.size()) {
|
||||
// Invalid first layer index, don't print brim
|
||||
loops_num = 0;
|
||||
}
|
||||
else {
|
||||
// Limit max chamfer width to configured value
|
||||
int chamfer_loops_num = (int)(m_prime_tower_brim_chamfer_max_width / spacing);
|
||||
loops_num = std::min(loops_num, chamfer_loops_num) - dist_to_1st;
|
||||
// Ensure loops_num doesn't go negative
|
||||
if (loops_num < 0) loops_num = 0;
|
||||
// Stop print chamfer if depth changes
|
||||
bool depth_changed = (m_layer_info->depth != m_plan[m_first_layer_idx].depth);
|
||||
if (depth_changed) {
|
||||
loops_num = 0;
|
||||
} else {
|
||||
// Limit max chamfer width to configured value
|
||||
int chamfer_loops_num = (int) (m_prime_tower_brim_chamfer_max_width / spacing);
|
||||
loops_num = std::min(loops_num, chamfer_loops_num) - dist_to_1st;
|
||||
// Ensure loops_num doesn't go negative
|
||||
if (loops_num < 0)
|
||||
loops_num = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Non-first layer + chamfer disabled: don't print brim (revert to original behavior)
|
||||
loops_num = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5747,7 +5747,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->tooltip = L("Enable gradual layer-by-layer reduction of the brim around the prime tower. "
|
||||
"This creates a chamfered/tapered effect, reducing material usage while "
|
||||
"maintaining first layer adhesion.");
|
||||
def->mode = comAdvanced;
|
||||
def->mode = comDevelop;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("prime_tower_brim_chamfer_max_width", coFloat);
|
||||
@@ -5756,7 +5756,7 @@ void PrintConfigDef::init_fff_params()
|
||||
"The brim will reduce within this distance. Larger values create a more "
|
||||
"gradual taper but take more layers to complete.");
|
||||
def->sidetext = "mm"; // milimeters, don't need translation
|
||||
def->mode = comAdvanced;
|
||||
def->mode = comDevelop;
|
||||
def->min = 0.;
|
||||
def->set_default_value(new ConfigOptionFloat(4.0));
|
||||
|
||||
|
||||
@@ -50,6 +50,23 @@ namespace Slic3r {
|
||||
#define SENTRY_KEY_LEVEL "level"
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
// C-style wrapper function for sentry_init to allow use of __try/__except
|
||||
// This function must be C-style because __try/__except cannot be used in functions
|
||||
// that require C++ object unwinding (functions with C++ objects that need destructors)
|
||||
extern "C" {
|
||||
static int safe_sentry_init(sentry_options_t* options) {
|
||||
int result = -1;
|
||||
__try {
|
||||
result = sentry_init(options);
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
// Exception occurred during sentry_init
|
||||
result = -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static sentry_value_t on_crash_callback(const sentry_ucontext_t* uctx, sentry_value_t event, void* closure)
|
||||
{
|
||||
@@ -252,31 +269,66 @@ void initSentryEx()
|
||||
sentry_options_set_logs_with_attributes(options, true);
|
||||
|
||||
// Set release version for symbolication
|
||||
// This must match the release used when uploading symbols
|
||||
sentry_options_set_release(options, Snapmaker_VERSION);
|
||||
bool init_success = false;
|
||||
|
||||
sentry_init(options);
|
||||
sentry_start_session();
|
||||
#ifdef _WIN32
|
||||
// Use C-style wrapper function to safely call sentry_init with SEH exception handling
|
||||
int result = safe_sentry_init(options);
|
||||
std::cout << "sentry_init returned: " << result << std::endl;
|
||||
if (result == 0) {
|
||||
init_success = true;
|
||||
std::cout << "sentry_init succeeded, init_success set to true" << std::endl;
|
||||
} else {
|
||||
std::cout << "Error: sentry_init failed or exception occurred, Sentry initialization failed (result=" << result << ")" << std::endl;
|
||||
// Exception occurred or sentry_init returned error, sentry_init was not successfully called
|
||||
// so we need to free options
|
||||
sentry_options_free(options);
|
||||
set_sentry_flags(false);
|
||||
return; // Exit early if initialization fails
|
||||
}
|
||||
#else
|
||||
int result = sentry_init(options);
|
||||
std::cout << "sentry_init returned: " << result << std::endl;
|
||||
if (result == 0) {
|
||||
init_success = true;
|
||||
std::cout << "sentry_init succeeded, init_success set to true" << std::endl;
|
||||
} else {
|
||||
std::cout << "Warning: sentry_init returned non-zero: " << result << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
sentry_set_tag("snapmaker_version", Snapmaker_VERSION);
|
||||
// Start session and set tags only if initialization succeeded
|
||||
if (init_success) {
|
||||
std::cout << "Starting Sentry session and setting flags..." << std::endl;
|
||||
sentry_start_session();
|
||||
set_sentry_flags(true);
|
||||
|
||||
sentry_set_tag("snapmaker_version", Snapmaker_VERSION);
|
||||
|
||||
std::string flutterVersion = common::get_flutter_version();
|
||||
if (!flutterVersion.empty())
|
||||
sentry_set_tag("flutter_version", flutterVersion.c_str());
|
||||
std::string flutterVersion = common::get_flutter_version();
|
||||
if (!flutterVersion.empty())
|
||||
sentry_set_tag("flutter_version", flutterVersion.c_str());
|
||||
|
||||
std::string machineID = common::getMachineId();
|
||||
if (!machineID.empty())
|
||||
sentry_set_tag("machine_id", machineID.c_str());
|
||||
std::string machineID = common::getMachineId();
|
||||
if (!machineID.empty())
|
||||
sentry_set_tag("machine_id", machineID.c_str());
|
||||
|
||||
std::string pcName = common::get_pc_name();
|
||||
if (!pcName.empty())
|
||||
sentry_set_tag("pc_name", pcName.c_str());
|
||||
std::string pcName = common::get_pc_name();
|
||||
if (!pcName.empty())
|
||||
sentry_set_tag("pc_name", pcName.c_str());
|
||||
} else {
|
||||
set_sentry_flags(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void exitSentryEx()
|
||||
{
|
||||
sentry_close();
|
||||
{
|
||||
if (get_sentry_flags()) {
|
||||
sentry_close();
|
||||
set_sentry_flags(false);
|
||||
}
|
||||
}
|
||||
void sentryReportLogEx(SENTRY_LOG_LEVEL logLevel,
|
||||
const std::string& logContent,
|
||||
@@ -285,6 +337,11 @@ void sentryReportLogEx(SENTRY_LOG_LEVEL logLevel,
|
||||
const std::string& logTagValue,
|
||||
const std::string& logTraceId)
|
||||
{
|
||||
// Check if Sentry is initialized before using it
|
||||
if (!get_sentry_flags()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!get_privacy_policy()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1331,10 +1331,16 @@ void GLCanvas3D::reset_volumes()
|
||||
m_dirty = true;
|
||||
|
||||
auto pLater = wxGetApp().plater();
|
||||
|
||||
if (pLater && wxGetApp().plater()->get_notification_manager())
|
||||
{
|
||||
_set_warning_notification(EWarning::ObjectOutside, false);
|
||||
if (pLater) {
|
||||
auto* notification_mgr = pLater->get_notification_manager();
|
||||
if (notification_mgr) {
|
||||
// Only update notification if we can safely access Plater's current canvas
|
||||
// This ensures Plater::priv structure is still valid
|
||||
auto* canvas = pLater->get_current_canvas3D();
|
||||
if (canvas) {
|
||||
_set_warning_notification(EWarning::ObjectOutside, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3660,6 +3660,8 @@ if (res) {
|
||||
load_current_presets();
|
||||
update_publish_status();
|
||||
mainframe->refresh_plugin_tips();
|
||||
|
||||
m_fltviews.reload_all();
|
||||
// BBS: remove SLA related message
|
||||
}
|
||||
} catch (std::exception &) {
|
||||
@@ -5976,7 +5978,9 @@ void GUI_App::open_preferences(size_t open_on_tab, const std::string& highlight_
|
||||
// so we put it into an inner scope
|
||||
PreferencesDialog dlg(mainframe, open_on_tab, highlight_option);
|
||||
dlg.ShowModal();
|
||||
this->plater_->get_current_canvas3D()->force_set_focus();
|
||||
GLCanvas3D* canvas = this->plater_->get_current_canvas3D();
|
||||
if (canvas)
|
||||
canvas->force_set_focus();
|
||||
// BBS
|
||||
//app_layout_changed = dlg.settings_layout_changed();
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
@@ -6727,6 +6731,7 @@ bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage
|
||||
wxGetApp().sidebar().update_nozzle_settings();
|
||||
update_publish_status();
|
||||
mainframe->refresh_plugin_tips();
|
||||
m_fltviews.reload_all();
|
||||
// BBS: remove SLA related message
|
||||
}
|
||||
auto isAgree = wxGetApp().app_config->get("app", PRIVACY_POLICY_FLAGS);
|
||||
|
||||
@@ -903,7 +903,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void relead_all() {
|
||||
void reload_all() {
|
||||
for (const auto& view : webviews) {
|
||||
auto ptr = view.first;
|
||||
wxString new_url = app->get_international_url(view.second);
|
||||
|
||||
@@ -330,11 +330,25 @@ bool CheckboxFileDialog::get_checkbox_value() const
|
||||
}
|
||||
|
||||
|
||||
// GTK requires width >= -1 and height > 0 for gtk_window_resize/set_size_request.
|
||||
// Use minimum 100 to avoid 0 or negative dimensions from bad config or Intersect().
|
||||
static const int WINDOW_MIN_WIDTH = 100;
|
||||
static const int WINDOW_MIN_HEIGHT = 100;
|
||||
|
||||
static void clamp_rect_to_minimum_size(wxRect &rect)
|
||||
{
|
||||
if (rect.width < WINDOW_MIN_WIDTH)
|
||||
rect.width = WINDOW_MIN_WIDTH;
|
||||
if (rect.height < WINDOW_MIN_HEIGHT)
|
||||
rect.height = WINDOW_MIN_HEIGHT;
|
||||
}
|
||||
|
||||
WindowMetrics WindowMetrics::from_window(wxTopLevelWindow *window)
|
||||
{
|
||||
WindowMetrics res;
|
||||
res.rect = window->GetScreenRect();
|
||||
res.maximized = window->IsMaximized();
|
||||
clamp_rect_to_minimum_size(res.rect);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -362,6 +376,7 @@ boost::optional<WindowMetrics> WindowMetrics::deserialize(const std::string &str
|
||||
|
||||
WindowMetrics res;
|
||||
res.rect = wxRect(metrics[0], metrics[1], metrics[2], metrics[3]);
|
||||
clamp_rect_to_minimum_size(res.rect);
|
||||
res.maximized = metrics[4] != 0;
|
||||
|
||||
return res;
|
||||
@@ -370,6 +385,11 @@ boost::optional<WindowMetrics> WindowMetrics::deserialize(const std::string &str
|
||||
void WindowMetrics::sanitize_for_display(const wxRect &screen_rect)
|
||||
{
|
||||
rect = rect.Intersect(screen_rect);
|
||||
// Intersect can yield 0 or negative width/height; GTK asserts on that.
|
||||
clamp_rect_to_minimum_size(rect);
|
||||
// Keep within display (e.g. after monitor change)
|
||||
rect.x = std::max(screen_rect.x, std::min(rect.x, screen_rect.x + screen_rect.width - rect.width));
|
||||
rect.y = std::max(screen_rect.y, std::min(rect.y, screen_rect.y + screen_rect.height - rect.height));
|
||||
|
||||
// Prevent the window from going too far towards the right and/or bottom edge
|
||||
// It's hardcoded here that the threshold is 80% of the screen size
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#define LOCALHOST_PORT 13618
|
||||
#define PAGE_HTTP_PORT 13619
|
||||
#define LOCALHOST_URL "http://localhost:"
|
||||
#define LOCALHOST_URL "http://127.0.0.1:"
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
|
||||
@@ -270,6 +270,12 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
|
||||
// Load the icon either from the exe, or from the ico file.
|
||||
SetIcon(main_frame_icon(wxGetApp().get_app_mode()));
|
||||
|
||||
#ifdef __WXGTK__
|
||||
// GTK/X11: set minimum size before any layout so gtk_widget_set_size_request and
|
||||
// gtk_window_resize never see 0 or negative dimensions (avoids assertion failures).
|
||||
SetMinSize(wxGetApp().get_min_size());
|
||||
#endif
|
||||
|
||||
// initialize tabpanel and menubar
|
||||
init_tabpanel();
|
||||
if (wxGetApp().is_gcode_viewer())
|
||||
@@ -501,8 +507,11 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
|
||||
//FIXME maybe this is useful for __WXGTK3__ as well?
|
||||
#if __APPLE__
|
||||
Bind(wxEVT_MOVE, [](wxMoveEvent& event) {
|
||||
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
|
||||
wxGetApp().plater()->get_current_canvas3D()->request_extra_frame();
|
||||
GLCanvas3D* canvas = wxGetApp().plater()->get_current_canvas3D();
|
||||
if (canvas) {
|
||||
canvas->set_as_dirty();
|
||||
canvas->request_extra_frame();
|
||||
}
|
||||
event.Skip();
|
||||
});
|
||||
#endif
|
||||
@@ -2240,7 +2249,9 @@ static wxMenu* generate_help_menu()
|
||||
|
||||
append_menu_item(helpMenu, wxID_ANY, _L("Show Tip of the Day"), _L("Show Tip of the Day"), [](wxCommandEvent&) {
|
||||
wxGetApp().plater()->get_dailytips()->open();
|
||||
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
|
||||
GLCanvas3D* canvas = wxGetApp().plater()->get_current_canvas3D();
|
||||
if (canvas)
|
||||
canvas->set_as_dirty();
|
||||
});
|
||||
|
||||
// Report a bug
|
||||
@@ -2515,8 +2526,11 @@ void MainFrame::init_menubar_as_editor()
|
||||
|
||||
auto handle_key_event = [](wxKeyEvent& evt) {
|
||||
if (wxGetApp().imgui()->update_key_data(evt)) {
|
||||
wxGetApp().plater()->get_current_canvas3D()->render();
|
||||
return true;
|
||||
GLCanvas3D* canvas = wxGetApp().plater()->get_current_canvas3D();
|
||||
if (canvas) {
|
||||
canvas->render();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -146,8 +146,15 @@ bool MarkdownTip::ShowTip(wxPoint pos, std::string const &tip, std::string const
|
||||
if (_tipView->GetParent() == this) {
|
||||
wxSize size = wxDisplay(this).GetClientArea().GetSize();
|
||||
_requestPos = pos;
|
||||
// Ensure display size is valid
|
||||
if (size.y <= 0) size.y = 600;
|
||||
if (pos.y + this->GetSize().y > size.y)
|
||||
pos.y = size.y - this->GetSize().y;
|
||||
{
|
||||
pos.y = 0;
|
||||
if( (size.y - this->GetSize().y) > 0)
|
||||
pos.y = (size.y - this->GetSize().y);
|
||||
}
|
||||
|
||||
this->SetPosition(pos);
|
||||
if (tipChanged || _hide) {
|
||||
_hide = false;
|
||||
@@ -258,11 +265,20 @@ void MarkdownTip::OnTitleChanged(wxWebViewEvent& event)
|
||||
_lastHeight = height;
|
||||
height *= 1.25; height += 50;
|
||||
wxSize size = wxDisplay(this).GetClientArea().GetSize();
|
||||
// Ensure display size is valid
|
||||
if (size.y <= 0) size.y = 600;
|
||||
if (height > size.y)
|
||||
height = size.y;
|
||||
wxPoint pos = _requestPos;
|
||||
if (pos.y + height > size.y)
|
||||
pos.y = size.y - height;
|
||||
if (pos.y + height > size.y)
|
||||
{
|
||||
pos.y= 0;
|
||||
if(size.y-height>0)
|
||||
pos.y = size.y - height;
|
||||
}
|
||||
|
||||
// Ensure height is valid
|
||||
if (height <= 0) height = 100;
|
||||
this->SetSize({ 400, (int)height });
|
||||
this->SetPosition(pos);
|
||||
}
|
||||
|
||||
+94
-34
@@ -1903,11 +1903,14 @@ void Sidebar::update_presets(Preset::Type preset_type)
|
||||
}
|
||||
|
||||
Preset& printer_preset = wxGetApp().preset_bundle->printers.get_edited_preset();
|
||||
if (auto printer_structure_opt = printer_preset.config.option<ConfigOptionEnum<PrinterStructure>>("printer_structure")) {
|
||||
wxGetApp().plater()->get_current_canvas3D()->get_arrange_settings().align_to_y_axis = (printer_structure_opt->value == PrinterStructure::psI3);
|
||||
GLCanvas3D* canvas = wxGetApp().plater()->get_current_canvas3D();
|
||||
if (canvas) {
|
||||
if (auto printer_structure_opt = printer_preset.config.option<ConfigOptionEnum<PrinterStructure>>("printer_structure")) {
|
||||
canvas->get_arrange_settings().align_to_y_axis = (printer_structure_opt->value == PrinterStructure::psI3);
|
||||
}
|
||||
else
|
||||
canvas->get_arrange_settings().align_to_y_axis = false;
|
||||
}
|
||||
else
|
||||
wxGetApp().plater()->get_current_canvas3D()->get_arrange_settings().align_to_y_axis = false;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -2749,9 +2752,12 @@ void Sidebar::update_ui_from_settings()
|
||||
// BBS
|
||||
//p->object_manipulation->update_ui_from_settings();
|
||||
// update Cut gizmo, if it's open
|
||||
p->plater->canvas3D()->update_gizmos_on_off_state();
|
||||
p->plater->set_current_canvas_as_dirty();
|
||||
p->plater->get_current_canvas3D()->request_extra_frame();
|
||||
GLCanvas3D* canvas = p->plater->canvas3D();
|
||||
if (canvas) {
|
||||
canvas->update_gizmos_on_off_state();
|
||||
p->plater->set_current_canvas_as_dirty();
|
||||
p->plater->get_current_canvas3D()->request_extra_frame();
|
||||
}
|
||||
#if 0
|
||||
p->object_list->apply_volumes_order();
|
||||
#endif
|
||||
@@ -5671,7 +5677,13 @@ Selection& Plater::priv::get_selection()
|
||||
|
||||
Selection& Plater::priv::get_curr_selection()
|
||||
{
|
||||
return get_current_canvas3D()->get_selection();
|
||||
GLCanvas3D* canvas = get_current_canvas3D();
|
||||
if (!canvas) {
|
||||
// During destruction, return a reference to a static empty selection
|
||||
static Selection empty_selection;
|
||||
return empty_selection;
|
||||
}
|
||||
return canvas->get_selection();
|
||||
}
|
||||
|
||||
int Plater::priv::get_selected_object_idx() const
|
||||
@@ -5701,10 +5713,15 @@ void Plater::priv::selection_changed()
|
||||
}
|
||||
|
||||
// forces a frame render to update the view (to avoid a missed update if, for example, the context menu appears)
|
||||
if (get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
|
||||
assemble_view->render();
|
||||
} else {
|
||||
view3D->render();
|
||||
GLCanvas3D* canvas = get_current_canvas3D();
|
||||
if (canvas) {
|
||||
if (canvas->get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
|
||||
if (assemble_view)
|
||||
assemble_view->render();
|
||||
} else {
|
||||
if (view3D)
|
||||
view3D->render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6473,7 +6490,10 @@ bool Plater::priv::replace_volume_with_stl(int object_idx, int volume_idx, const
|
||||
return false;
|
||||
}
|
||||
|
||||
wxBusyInfo info(_L("Replace from:") + " " + from_u8(path), q->get_current_canvas3D()->get_wxglcanvas());
|
||||
GLCanvas3D* canvas = q->get_current_canvas3D();
|
||||
if (!canvas)
|
||||
return false;
|
||||
wxBusyInfo info(_L("Replace from:") + " " + from_u8(path), canvas->get_wxglcanvas());
|
||||
|
||||
if (!snapshot.empty())
|
||||
q->take_snapshot(snapshot);
|
||||
@@ -6770,7 +6790,13 @@ void Plater::priv::reload_from_disk()
|
||||
if (color_dlg.ShowModal() != wxID_OK) { filament_ids.clear(); }
|
||||
};
|
||||
wxBusyCursor wait;
|
||||
wxBusyInfo info(_L("Reload from:") + " " + from_u8(path), q->get_current_canvas3D()->get_wxglcanvas());
|
||||
GLCanvas3D* canvas = q->get_current_canvas3D();
|
||||
if (!canvas)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "canvas is nullptr";
|
||||
continue;
|
||||
}
|
||||
wxBusyInfo info(_L("Reload from:") + " " + from_u8(path), canvas->get_wxglcanvas());
|
||||
|
||||
Model new_model;
|
||||
try
|
||||
@@ -8839,16 +8865,26 @@ void Plater::priv::set_current_canvas_as_dirty()
|
||||
|
||||
GLCanvas3D* Plater::priv::get_current_canvas3D(bool exclude_preview)
|
||||
{
|
||||
if (current_panel == view3D)
|
||||
// During destruction, these pointers may be null or point to destroyed objects
|
||||
// Add null checks to prevent crashes during shutdown
|
||||
if (current_panel == view3D) {
|
||||
if (view3D)
|
||||
return view3D->get_canvas3d();
|
||||
}
|
||||
else if (!exclude_preview && (current_panel == preview)) {
|
||||
if (preview)
|
||||
return preview->get_canvas3d();
|
||||
}
|
||||
else if (current_panel == assemble_view) {
|
||||
if (assemble_view)
|
||||
return assemble_view->get_canvas3d();
|
||||
}
|
||||
|
||||
//BBS default set to view3D, but check if it's still valid
|
||||
if (view3D)
|
||||
return view3D->get_canvas3d();
|
||||
else if (!exclude_preview && (current_panel == preview))
|
||||
return preview->get_canvas3d();
|
||||
else if (current_panel == assemble_view)
|
||||
return assemble_view->get_canvas3d();
|
||||
else //BBS default set to view3D
|
||||
return view3D->get_canvas3d();
|
||||
|
||||
//return (current_panel == view3D) ? view3D->get_canvas3d() : ((current_panel == preview) ? preview->get_canvas3d() : nullptr);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Plater::priv::unbind_canvas_event_handlers()
|
||||
@@ -9386,7 +9422,13 @@ void Plater::priv::take_snapshot(const std::string& snapshot_name, const UndoRed
|
||||
tower.rotation = proj_cfg.opt_float("wipe_tower_rotation_angle");
|
||||
}
|
||||
}
|
||||
const GLGizmosManager& gizmos = get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_gizmos_manager() : view3D->get_canvas3d()->get_gizmos_manager();
|
||||
GLCanvas3D* canvas = get_current_canvas3D();
|
||||
if (!canvas) {
|
||||
// During destruction, skip snapshot
|
||||
return;
|
||||
}
|
||||
|
||||
const GLGizmosManager& gizmos = canvas->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_gizmos_manager() : view3D->get_canvas3d()->get_gizmos_manager();
|
||||
|
||||
if (snapshot_type == UndoRedo::SnapshotType::ProjectSeparator)
|
||||
this->undo_redo_stack().clear();
|
||||
@@ -9420,7 +9462,9 @@ void Plater::priv::undo()
|
||||
// BBS: undo-redo until modify record
|
||||
while (--it_current != snapshots.begin() && !snapshot_modifies_project(*it_current));
|
||||
if (it_current == snapshots.begin()) return;
|
||||
if (get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
|
||||
GLCanvas3D* canvas = get_current_canvas3D();
|
||||
if (!canvas) return;
|
||||
if (canvas->get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
|
||||
if (it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::GizmoAction &&
|
||||
it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::EnteringGizmo &&
|
||||
it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::LeavingGizmoNoAction &&
|
||||
@@ -9528,9 +9572,13 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
|
||||
// Make a copy of the snapshot, undo/redo could invalidate the iterator
|
||||
const UndoRedo::Snapshot snapshot_copy = *it_snapshot;
|
||||
// Do the jump in time.
|
||||
GLCanvas3D* canvas = get_current_canvas3D();
|
||||
if (!canvas) return;
|
||||
|
||||
bool is_assemble = canvas->get_canvas_type() == GLCanvas3D::CanvasAssembleView;
|
||||
if (it_snapshot->timestamp < this->undo_redo_stack().active_snapshot_time() ?
|
||||
this->undo_redo_stack().undo(model, get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_selection() : this->view3D->get_canvas3d()->get_selection(), get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_gizmos_manager() : this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, top_snapshot_data, it_snapshot->timestamp) :
|
||||
this->undo_redo_stack().redo(model, get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_gizmos_manager() : this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, it_snapshot->timestamp)) {
|
||||
this->undo_redo_stack().undo(model, is_assemble ? assemble_view->get_canvas3d()->get_selection() : this->view3D->get_canvas3d()->get_selection(), is_assemble ? assemble_view->get_canvas3d()->get_gizmos_manager() : this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, top_snapshot_data, it_snapshot->timestamp) :
|
||||
this->undo_redo_stack().redo(model, is_assemble ? assemble_view->get_canvas3d()->get_gizmos_manager() : this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, it_snapshot->timestamp)) {
|
||||
if (printer_technology_changed) {
|
||||
// Switch to the other printer technology. Switch to the last printer active for that particular technology.
|
||||
AppConfig *app_config = wxGetApp().app_config;
|
||||
@@ -9608,7 +9656,11 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
|
||||
|
||||
void Plater::priv::update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bool /* temp_snapshot_was_taken */)
|
||||
{
|
||||
get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_selection().clear() : this->view3D->get_canvas3d()->get_selection().clear();
|
||||
GLCanvas3D* canvas = get_current_canvas3D();
|
||||
if (!canvas) return;
|
||||
|
||||
bool is_assemble = canvas->get_canvas_type() == GLCanvas3D::CanvasAssembleView;
|
||||
is_assemble ? assemble_view->get_canvas3d()->get_selection().clear() : this->view3D->get_canvas3d()->get_selection().clear();
|
||||
// Update volumes from the deserializd model, always stop / update the background processing (for both the SLA and FFF technologies).
|
||||
this->update((unsigned int)UpdateParams::FORCE_BACKGROUND_PROCESSING_UPDATE | (unsigned int)UpdateParams::POSTPONE_VALIDATION_ERROR_MESSAGE);
|
||||
// Release old snapshots if the memory allocated is excessive. This may remove the top most snapshot if jumping to the very first snapshot.
|
||||
@@ -9617,10 +9669,10 @@ void Plater::priv::update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bo
|
||||
// triangle meshes may have gotten released from the scene or the background processing, therefore now being calculated into the Undo / Redo stack size.
|
||||
this->undo_redo_stack().release_least_recently_used();
|
||||
//YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time)
|
||||
get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
|
||||
is_assemble ?
|
||||
assemble_view->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack().selection_deserialized().mode), this->undo_redo_stack().selection_deserialized().volumes_and_instances) :
|
||||
this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack().selection_deserialized().mode), this->undo_redo_stack().selection_deserialized().volumes_and_instances);
|
||||
get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
|
||||
is_assemble ?
|
||||
assemble_view->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot) :
|
||||
this->view3D->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot);
|
||||
|
||||
@@ -11299,7 +11351,9 @@ void Plater::load_gcode(const wxString& filename)
|
||||
p->preview->reload_print(false, m_only_gcode);
|
||||
wxGetApp().mainframe->select_tab(MainFrame::tpPreview);
|
||||
p->set_current_panel(p->preview, true);
|
||||
p->get_current_canvas3D()->render();
|
||||
GLCanvas3D* canvas = p->get_current_canvas3D();
|
||||
if (canvas)
|
||||
canvas->render();
|
||||
//p->notification_manager->bbl_show_plateinfo_notification(into_u8(_L("Preview only mode for gcode file.")));
|
||||
|
||||
wxBusyCursor wait;
|
||||
@@ -12299,7 +12353,9 @@ void Plater::set_selected_visible(bool visible)
|
||||
Plater::TakeSnapshot snapshot(this, "Set Selected Objects Visible in AssembleView");
|
||||
get_ui_job_worker().cancel_all();
|
||||
|
||||
p->get_current_canvas3D()->set_selected_visible(visible);
|
||||
GLCanvas3D* canvas = p->get_current_canvas3D();
|
||||
if (canvas)
|
||||
canvas->set_selected_visible(visible);
|
||||
}
|
||||
|
||||
|
||||
@@ -12319,7 +12375,9 @@ void Plater::remove_selected()
|
||||
|
||||
//BBS delete current selected
|
||||
// p->view3D->delete_selected();
|
||||
p->get_current_canvas3D()->delete_selected();
|
||||
GLCanvas3D* canvas = p->get_current_canvas3D();
|
||||
if (canvas)
|
||||
canvas->delete_selected();
|
||||
}
|
||||
|
||||
void Plater::increase_instances(size_t num)
|
||||
@@ -14592,7 +14650,9 @@ void Plater::changed_object(ModelObject &object){
|
||||
p->schedule_background_process();
|
||||
|
||||
// Check outside bed
|
||||
get_current_canvas3D()->requires_check_outside_state();
|
||||
GLCanvas3D* canvas = get_current_canvas3D();
|
||||
if (canvas)
|
||||
canvas->requires_check_outside_state();
|
||||
}
|
||||
|
||||
void Plater::changed_object(int obj_idx)
|
||||
|
||||
@@ -205,6 +205,9 @@ void PresetComboBox::update_selection()
|
||||
|
||||
// A workaround for a set of issues related to text fitting into gtk widgets:
|
||||
#if defined(__WXGTK20__) || defined(__WXGTK3__)
|
||||
// Guard: m_widget may not be a GtkCellLayout (e.g. not yet realized, or GtkComboBoxText in Flatpak/GTK3)
|
||||
if (!m_widget || !GTK_IS_CELL_LAYOUT(m_widget))
|
||||
return;
|
||||
GList* cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(m_widget));
|
||||
|
||||
// 'cells' contains the GtkCellRendererPixBuf for the icon,
|
||||
|
||||
@@ -1523,7 +1523,11 @@ void SSWCP_Instance::update_filament_info(const json& objects, bool send_message
|
||||
|
||||
// 名称特殊处理
|
||||
if (type == "TPU") {
|
||||
name = vendor + " " + type;
|
||||
if (sub_type == "95A HF") {
|
||||
name = vendor + " " + type + ((sub_type != "NONE" && sub_type != "") ? " " + sub_type : "");
|
||||
} else {
|
||||
name = vendor + " " + type;
|
||||
}
|
||||
} else if (sub_type == "Support") {
|
||||
name = vendor + " Support" + " For " + type;
|
||||
} else {
|
||||
|
||||
@@ -496,7 +496,7 @@ void GuideFrame::OnScriptMessage(wxWebViewEvent &evt)
|
||||
}
|
||||
}
|
||||
|
||||
wxGetApp().fltviews().relead_all();
|
||||
wxGetApp().fltviews().reload_all();
|
||||
}
|
||||
|
||||
this->EndModal(wxID_OK);
|
||||
|
||||
@@ -368,7 +368,12 @@ void DropDown::messureSize()
|
||||
wxWindow::SetSize(szContent);
|
||||
#ifdef __WXGTK__
|
||||
// Gtk has a wrapper window for popup widget
|
||||
gtk_window_resize (GTK_WINDOW (m_widget), szContent.x, szContent.y);
|
||||
// Fix for GNOME Platform 48 X11 backend: ensure size is valid before calling gtk_window_resize
|
||||
int gtk_width = szContent.x;
|
||||
int gtk_height = szContent.y;
|
||||
if (gtk_width <= 0) gtk_width = 100;
|
||||
if (gtk_height <= 0) gtk_height = 100;
|
||||
gtk_window_resize(GTK_WINDOW(m_widget), gtk_width, gtk_height);
|
||||
#endif
|
||||
need_sync = false;
|
||||
}
|
||||
@@ -384,6 +389,10 @@ void DropDown::autoPosition()
|
||||
size = rowSize;
|
||||
size.y *= std::min((size_t)15, texts.size());
|
||||
size.y += texts.size() > 15 ? rowSize.y / 2 : 0;
|
||||
#ifdef __WXGTK__
|
||||
if (size.x < 1) size.x = 1;
|
||||
if (size.y < 1) size.y = 1;
|
||||
#endif
|
||||
if (size != GetSize()) {
|
||||
wxWindow::SetSize(size);
|
||||
offset = wxPoint();
|
||||
@@ -396,6 +405,10 @@ void DropDown::autoPosition()
|
||||
if (GetPosition().y + size.y + 10 > drect.GetBottom()) {
|
||||
if (use_content_width && texts.size() <= 15) size.x += 6;
|
||||
size.y = drect.GetBottom() - GetPosition().y - 10;
|
||||
#ifdef __WXGTK__
|
||||
if (size.y < 1) size.y = 1;
|
||||
if (size.x < 1) size.x = 1;
|
||||
#endif
|
||||
wxWindow::SetSize(size);
|
||||
if (selection >= 0) {
|
||||
if (offset.y + rowSize.y * (selection + 1) > size.y)
|
||||
|
||||
@@ -30,7 +30,7 @@ class DropDown : public PopupWindow
|
||||
|
||||
wxSize textSize;
|
||||
wxSize iconSize;
|
||||
wxSize rowSize;
|
||||
wxSize rowSize{100, 30}; // Initialize with default values
|
||||
|
||||
StateHandler state_handler;
|
||||
StateColor text_color;
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
#endif
|
||||
|
||||
#include "sentry_wrapper/SentryWrapper.hpp"
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
#ifdef __WIN32__
|
||||
#include <WebView2.h>
|
||||
#include <Shellapi.h>
|
||||
@@ -275,10 +280,18 @@ wxWebView* WebView::CreateWebView(wxWindow * parent, wxString const & url)
|
||||
// And the memory: file system
|
||||
webView->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewFSHandler("memory")));
|
||||
#else
|
||||
// With WKWebView handlers need to be registered before creation
|
||||
// Handlers must be registered before Create(). Linux (WebKit2): scheme is process-global, register once to avoid "Cannot register URI scheme ... more than once".
|
||||
// macOS (WKWebView): scheme is per-view, each WebView needs its own handlers.
|
||||
#if defined(__linux__)
|
||||
static std::once_flag s_wxfs_memory_handlers_once;
|
||||
std::call_once(s_wxfs_memory_handlers_once, [webView]() {
|
||||
webView->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewArchiveHandler("wxfs")));
|
||||
webView->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewFSHandler("memory")));
|
||||
});
|
||||
#else
|
||||
webView->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewArchiveHandler("wxfs")));
|
||||
// And the memory: file system
|
||||
webView->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewFSHandler("memory")));
|
||||
#endif
|
||||
webView->Create(parent, wxID_ANY, url2, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
|
||||
webView->SetUserAgent(wxString::Format("SM-Slicer/v%s (%s) Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko)", SLIC3R_VERSION,
|
||||
Slic3r::GUI::wxGetApp().dark_mode() ? "dark" : "light"));
|
||||
|
||||
Reference in New Issue
Block a user