From 2a99d1e077b522201903447d8c93334341b537e7 Mon Sep 17 00:00:00 2001 From: trailcode Date: Fri, 15 May 2026 17:37:02 -0600 Subject: [PATCH 1/2] Code format update. --- .clang-format | 61 +-- CMakeLists.txt | 16 + ezycad_code_style.md | 6 +- scripts/format-src.ps1 | 3 +- src/dbg.h | 94 ++--- src/geom.cpp | 227 +++++----- src/geom.h | 77 ++-- src/geom.inl | 22 +- src/gui.cpp | 903 +++++++++++++++++++--------------------- src/gui.h | 257 ++++++------ src/gui_add.cpp | 17 +- src/gui_mode.cpp | 411 +++++++++--------- src/gui_settings.cpp | 144 +++---- src/log.cpp | 5 +- src/log.h | 6 +- src/lua_console.cpp | 17 +- src/lua_console.h | 26 +- src/main.cpp | 61 ++- src/modes.cpp | 34 +- src/modes.h | 60 +-- src/occt_glfw_win.cpp | 51 +-- src/occt_glfw_win.h | 42 +- src/occt_view.cpp | 558 ++++++++++--------------- src/occt_view.h | 74 ++-- src/occt_view.inl | 10 +- src/ply_io.cpp | 265 ++++++------ src/python_console.cpp | 263 +++++------- src/python_console.h | 21 +- src/settings.cpp | 47 +-- src/settings.h | 2 +- src/shp.cpp | 32 +- src/shp.h | 4 +- src/shp_chamfer.cpp | 108 +++-- src/shp_chamfer.h | 6 +- src/shp_common.cpp | 4 +- src/shp_common.h | 2 +- src/shp_create.cpp | 15 +- src/shp_create.h | 2 +- src/shp_cut.cpp | 6 +- src/shp_cut.h | 2 +- src/shp_extrude.cpp | 43 +- src/shp_extrude.h | 10 +- src/shp_fillet.cpp | 108 +++-- src/shp_fillet.h | 6 +- src/shp_fuse.cpp | 4 +- src/shp_fuse.h | 2 +- src/shp_move.cpp | 20 +- src/shp_move.h | 12 +- src/shp_operation.cpp | 27 +- src/shp_operation.h | 4 +- src/shp_polar_dup.cpp | 10 +- src/shp_polar_dup.h | 28 +- src/shp_rotate.cpp | 54 +-- src/shp_rotate.h | 21 +- src/shp_scale.cpp | 4 +- src/shp_scale.h | 8 +- src/sketch.cpp | 393 +++++++---------- src/sketch.h | 103 +++-- src/sketch_json.cpp | 29 +- src/sketch_json.h | 4 +- src/sketch_nodes.cpp | 115 ++--- src/sketch_nodes.h | 45 +- src/sketch_underlay.cpp | 89 ++-- src/sketch_underlay.h | 37 +- src/types.h | 13 +- src/types.inl | 65 ++- src/utl.cpp | 21 +- src/utl.h | 74 ++-- src/utl.inl | 105 +++-- src/utl_json.cpp | 46 +- src/utl_occt.h | 20 +- 71 files changed, 2436 insertions(+), 3045 deletions(-) diff --git a/.clang-format b/.clang-format index 61ac868..3e06985 100644 --- a/.clang-format +++ b/.clang-format @@ -1,54 +1,13 @@ ---- -Language: Cpp -BasedOnStyle: Google -ColumnLimit: 0 -AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: AcrossComments -AlignConsecutiveDeclarations: AcrossComments -AlignConsecutiveMacros: AcrossComments -AlignEscapedNewlines: Right -AlignOperands: true -AlignTrailingComments: true -AllowAllArgumentsOnNextLine: true # Changed to true -AllowAllParametersOfDeclarationOnNextLine: true # Changed to true -AllowShortBlocksOnASingleLine: Always -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: Never -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterReturnType: None -AlwaysBreakTemplateDeclarations: No # Changed to No -BinPackArguments: true # Changed to true -BinPackParameters: true # Changed to true -BreakBeforeBraces: Custom -BraceWrapping: - AfterControlStatement: Always - AfterFunction: true - AfterClass: true - AfterStruct: true - AfterUnion: true - AfterNamespace: true - AfterEnum: true +BasedOnStyle: LLVM +AllowShortIfStatementsOnASingleLine: false +BreakConstructorInitializers: BeforeComma +BreakBeforeBraces: Allman +ColumnLimit: 128 +IndentCaseLabels: false IndentWidth: 2 +SortIncludes: false TabWidth: 2 -UseTab: Never +AlignConsecutiveDeclarations: true +AlignConsecutiveAssignments: true PointerAlignment: Left -SpaceAfterCStyleCast: true -SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: true -SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: true -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true -SpaceBeforeParens: ControlStatements -SpaceBeforeRangeBasedForLoopColon: true -SpaceInEmptyParentheses: false -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -AlignArrayOfStructures: Right -DerivePointerAlignment: false -# Blank line between adjacent function/class definitions (Always | Never | Leave). -SeparateDefinitionBlocks: Never \ No newline at end of file +AllowShortLambdasOnASingleLine: Inline \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index a6d42ab..6259358 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -668,6 +668,22 @@ if(RES_FILES) set_source_files_properties(${RES_FILES_REL} PROPERTIES HEADER_FILE_ONLY TRUE) endif() +# Utility scripts: show scripts/ in the IDE (not compiled; same pattern as res/) +file(GLOB_RECURSE EZYCAD_SCRIPT_FILES CONFIGURE_DEPENDS + LIST_DIRECTORIES false + "${CMAKE_SOURCE_DIR}/scripts/*") +if(EZYCAD_SCRIPT_FILES) + source_group(TREE "${CMAKE_SOURCE_DIR}/scripts" PREFIX "scripts" FILES ${EZYCAD_SCRIPT_FILES}) + set(EZYCAD_SCRIPT_FILES_REL) + foreach(f ${EZYCAD_SCRIPT_FILES}) + file(RELATIVE_PATH f_rel "${CMAKE_SOURCE_DIR}" "${f}") + list(APPEND EZYCAD_SCRIPT_FILES_REL "${f_rel}") + endforeach() + target_sources(${PROJECT_NAME}_lib PRIVATE ${EZYCAD_SCRIPT_FILES_REL}) + target_sources(${PROJECT_NAME} PRIVATE ${EZYCAD_SCRIPT_FILES_REL}) + set_source_files_properties(${EZYCAD_SCRIPT_FILES_REL} PROPERTIES HEADER_FILE_ONLY TRUE) +endif() + # Add .clang-format and .gitignore to EzyCad and EzyCad_lib so they appear in VS and other IDEs (at project root) set(CLANG_FORMAT_FILE ${CMAKE_SOURCE_DIR}/.clang-format) if(EXISTS ${CLANG_FORMAT_FILE}) diff --git a/ezycad_code_style.md b/ezycad_code_style.md index 54eff45..d84539e 100644 --- a/ezycad_code_style.md +++ b/ezycad_code_style.md @@ -26,11 +26,11 @@ Use this style when editing or adding C/C++ code in the EzyCad project (files un - **Indentation**: 2 spaces (no tabs). - **Access specifiers**: ` public:` and ` private:` (one space before `public`/`private`/`protected`). -- **Braces**: Follow `.clang-format` (source of truth). With current settings, opening braces are on the **next line** for classes/structs/unions, functions, control statements, namespaces, and enums (`BreakBeforeBraces: Custom` with `BraceWrapping.After*` enabled). **Short functions** may still be kept on one line (`AllowShortFunctionsOnASingleLine: All`). -- **Alignment**: Align member declarations in columns when it aids readability (type and name aligned across lines in the same block). +- **Braces**: Follow `.clang-format` (source of truth). **`BreakBeforeBraces: Allman`** with **`BasedOnStyle: LLVM`** elsewhere: opening `{` is on the **next line** for classes/structs/unions, functions, control statements, namespaces, and enums. Constructor initializer lists break with **`BreakConstructorInitializers: BeforeComma`** (comma starts each continuation line). Lambdas use **`AllowShortLambdasOnASingleLine: Inline`**. Other “short construct” behavior inherits LLVM defaults unless overridden in `.clang-format`. +- **Alignment**: **`AlignConsecutiveDeclarations`** / **`AlignConsecutiveAssignments`** are enabled; align member declarations and assignments in columns when it aids readability (type and name aligned across lines in the same block). - **Initialization**: Prefer brace-initialization for members (e.g. `bool is_midpoint {false};`, `size_t m_prev_num_nodes {0};`). - **Local declarations**: Prefer declaring locals close to first use for readability. For values shared by a render block, compute them once immediately before that block. -- **Short control flow**: Single-line `if`/`for` without braces is acceptable when the body is a single statement; use braces for multi-line or nested bodies. +- **Short control flow**: When the body is a single statement you may omit braces; **`AllowShortIfStatementsOnASingleLine: false`** means clang-format will not merge an `if` into one physical line (typically the condition on one line and the statement on the next). Use braces for multi-line or nested bodies. **`for`/`while`** (and other constructs not listed above) follow **`BasedOnStyle: LLVM`** unless overridden in `.clang-format`. - Use **`// clang-format off`** / **`// clang-format on`** only where layout must be preserved (e.g. macro-like blocks, tables). Prefer running clang-format; it is the source of truth for formatting. ## Versioning and releases diff --git a/scripts/format-src.ps1 b/scripts/format-src.ps1 index dca1a1c..5e68406 100644 --- a/scripts/format-src.ps1 +++ b/scripts/format-src.ps1 @@ -6,7 +6,8 @@ if (-not (Test-Path $clang)) { $clang = "clang-format" } -$root = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) +# Script lives at /scripts/format-src.ps1; repo root is one level above scripts/ +$root = Split-Path -Parent $PSScriptRoot $src = Join-Path $root "src" Get-ChildItem -Path $src -Include *.cpp,*.h,*.inl -Recurse -File | ForEach-Object { & $clang -i $_.FullName; Write-Host $_.Name } diff --git a/src/dbg.h b/src/dbg.h index a5609dc..a201907 100644 --- a/src/dbg.h +++ b/src/dbg.h @@ -4,67 +4,65 @@ #include // Platform-specific debug break -#ifdef _MSC_VER // Windows (Visual Studio) +#ifdef _MSC_VER // Windows (Visual Studio) #include #define DEBUG_BREAK __debugbreak() -#else // Unix-like (GDB, etc.) +#else // Unix-like (GDB, etc.) #include #define DEBUG_BREAK raise(SIGTRAP) #endif -#define EZY_ASSERT_MSG(condition, message) \ - do \ - { \ - if (!(condition)) \ - { \ - std::cerr << "Assertion failed: " << #condition \ - << ", message: " << (message) \ - << ", file: " << __FILE__ \ - << ", line: " << __LINE__ << std::endl; \ - DEBUG_BREAK; \ - } \ +#define EZY_ASSERT_MSG(condition, message) \ + do \ + { \ + if (!(condition)) \ + { \ + std::cerr << "Assertion failed: " << #condition << ", message: " << (message) << ", file: " << __FILE__ \ + << ", line: " << __LINE__ << std::endl; \ + DEBUG_BREAK; \ + } \ } while (false) -#define EZY_ASSERT(condition) \ - do \ - { \ - if (!(condition)) \ - { \ - std::cerr << "Assertion failed: " << #condition \ - << ", file: " << __FILE__ \ - << ", line: " << __LINE__ << std::endl; \ - DEBUG_BREAK; \ - } \ +#define EZY_ASSERT(condition) \ + do \ + { \ + if (!(condition)) \ + { \ + std::cerr << "Assertion failed: " << #condition << ", file: " << __FILE__ << ", line: " << __LINE__ << std::endl; \ + DEBUG_BREAK; \ + } \ } while (false) -/// If \a condition is false: assert (programmer error), then \c return \a ret_value so execution does not continue past \ref EZY_ASSERT_MSG. -#define EZY_ASSERT_OR_RETURN(condition, ret_value) \ - do \ - { \ - if (!(condition)) \ - { \ - EZY_ASSERT_MSG(false, "EZY_ASSERT_OR_RETURN failed: " #condition); \ - return (ret_value); \ - } \ +/// If \a condition is false: assert (programmer error), then \c return \a ret_value so execution does not continue past \ref +/// EZY_ASSERT_MSG. +#define EZY_ASSERT_OR_RETURN(condition, ret_value) \ + do \ + { \ + if (!(condition)) \ + { \ + EZY_ASSERT_MSG(false, "EZY_ASSERT_OR_RETURN failed: " #condition); \ + return (ret_value); \ + } \ } while (false) /// Same as \ref EZY_ASSERT_OR_RETURN for \c void functions. -#define EZY_ASSERT_OR_RETURN_VOID(condition) \ - do \ - { \ - if (!(condition)) \ - { \ - EZY_ASSERT_MSG(false, "EZY_ASSERT_OR_RETURN_VOID failed: " #condition); \ - return; \ - } \ +#define EZY_ASSERT_OR_RETURN_VOID(condition) \ + do \ + { \ + if (!(condition)) \ + { \ + EZY_ASSERT_MSG(false, "EZY_ASSERT_OR_RETURN_VOID failed: " #condition); \ + return; \ + } \ } while (false) -#define DBG_MSG(stream_expr) \ - do \ - { \ - std::stringstream ss; \ - ss << stream_expr; \ - std::stringstream msg; \ - msg << "[" << std::filesystem::path(__FILE__).filename().string() << ":" << __LINE__ << " " << __FUNCTION__ << " ] " << ss.str(); \ - std::cout << msg.str() << std::endl; \ +#define DBG_MSG(stream_expr) \ + do \ + { \ + std::stringstream ss; \ + ss << stream_expr; \ + std::stringstream msg; \ + msg << "[" << std::filesystem::path(__FILE__).filename().string() << ":" << __LINE__ << " " << __FUNCTION__ << " ] " \ + << ss.str(); \ + std::cout << msg.str() << std::endl; \ } while (0) \ No newline at end of file diff --git a/src/geom.cpp b/src/geom.cpp index c12b0a6..232709c 100644 --- a/src/geom.cpp +++ b/src/geom.cpp @@ -84,9 +84,9 @@ gp_Pnt to_3d(const gp_Pln& plane, const gp_Pnt2d& point_2d) { // Get the plane's coordinate system gp_Ax3 axes = plane.Position(); - gp_Pnt origin = axes.Location(); // Plane origin - gp_Dir x_dir = axes.XDirection(); // u-axis - gp_Dir y_dir = axes.YDirection(); // v-axis + gp_Pnt origin = axes.Location(); // Plane origin + gp_Dir x_dir = axes.XDirection(); // u-axis + gp_Dir y_dir = axes.YDirection(); // v-axis // Compute 3D point: Origin + u * XDir + v * YDir gp_Vec u_vec(x_dir); @@ -98,18 +98,15 @@ gp_Pnt to_3d(const gp_Pln& plane, const gp_Pnt2d& point_2d) return origin.Translated(u_vec + v_vec); } -gp_Pnt2d to_pnt2d(const boost_geom::point_2d& pt) -{ - return gp_Pnt2d(pt.x(), pt.y()); -} +gp_Pnt2d to_pnt2d(const boost_geom::point_2d& pt) { return gp_Pnt2d(pt.x(), pt.y()); } // Function to create a wire box centered on a point on a plane, returning a TopoDS_Wire TopoDS_Wire create_wire_box(const gp_Pln& plane, const gp_Pnt& center, double width, double height) { // Get the plane's coordinate system gp_Ax3 axes = plane.Position(); - gp_Dir x_dir = axes.XDirection(); // Width along plane's X-axis - gp_Dir y_dir = axes.YDirection(); // Height along plane's Y-axis + gp_Dir x_dir = axes.XDirection(); // Width along plane's X-axis + gp_Dir y_dir = axes.YDirection(); // Height along plane's Y-axis // Half-width and half-height for centering double half_width = width / 2.0; @@ -129,16 +126,16 @@ TopoDS_Wire create_wire_box(const gp_Pln& plane, const gp_Pnt& center, double wi y_vec_minus.Multiply(-half_height); // Define the 4 corner points of the box, centered on 'center' - gp_Pnt p1 = center.Translated(x_vec_minus + y_vec_minus); // Bottom-left - gp_Pnt p2 = center.Translated(x_vec_plus + y_vec_minus); // Bottom-right - gp_Pnt p3 = center.Translated(x_vec_plus + y_vec_plus); // Top-right - gp_Pnt p4 = center.Translated(x_vec_minus + y_vec_plus); // Top-left + gp_Pnt p1 = center.Translated(x_vec_minus + y_vec_minus); // Bottom-left + gp_Pnt p2 = center.Translated(x_vec_plus + y_vec_minus); // Bottom-right + gp_Pnt p3 = center.Translated(x_vec_plus + y_vec_plus); // Top-right + gp_Pnt p4 = center.Translated(x_vec_minus + y_vec_plus); // Top-left // Create the 4 edges of the box - BRepBuilderAPI_MakeEdge edge1(p1, p2); // Bottom - BRepBuilderAPI_MakeEdge edge2(p2, p3); // Right - BRepBuilderAPI_MakeEdge edge3(p3, p4); // Top - BRepBuilderAPI_MakeEdge edge4(p4, p1); // Left + BRepBuilderAPI_MakeEdge edge1(p1, p2); // Bottom + BRepBuilderAPI_MakeEdge edge2(p2, p3); // Right + BRepBuilderAPI_MakeEdge edge3(p3, p4); // Top + BRepBuilderAPI_MakeEdge edge4(p4, p1); // Left // Assemble edges into a wire BRepBuilderAPI_MakeWire wire_maker; @@ -150,7 +147,7 @@ TopoDS_Wire create_wire_box(const gp_Pln& plane, const gp_Pnt& center, double wi if (!wire_maker.IsDone()) { std::cerr << "Failed to create wire box\n"; - return TopoDS_Wire(); // Return empty wire on failure + return TopoDS_Wire(); // Return empty wire on failure } return wire_maker.Wire(); @@ -178,9 +175,7 @@ TopoDS_Shape create_plus_cross_shape(const gp_Pln& plane, const gp_Pnt& center_3 return comp; } -TopoDS_Wire make_square_wire(const gp_Pln& pln, - const gp_Pnt2d& center, - const gp_Pnt2d& edge_midpoint) +TopoDS_Wire make_square_wire(const gp_Pln& pln, const gp_Pnt2d& center, const gp_Pnt2d& edge_midpoint) { std::array corners = square_corners(center, edge_midpoint); @@ -207,8 +202,7 @@ std::array square_corners(const gp_Pnt2d& center, const gp_Pnt2d& e std::array ret; // Compute side length from center to edge midpoint - gp_Vec2d to_midpoint(edge_midpoint.X() - center.X(), - edge_midpoint.Y() - center.Y()); + gp_Vec2d to_midpoint(edge_midpoint.X() - center.X(), edge_midpoint.Y() - center.Y()); Standard_Real half_side = to_midpoint.Magnitude(); @@ -219,14 +213,14 @@ std::array square_corners(const gp_Pnt2d& center, const gp_Pnt2d& e gp_Vec2d perp_dir = edge_dir.Rotated(std::numbers::pi / 2.0); // Compute 2D vertices - ret[0] = gp_Pnt2d(center.X() + half_side * (edge_dir.X() + perp_dir.X()), - center.Y() + half_side * (edge_dir.Y() + perp_dir.Y())); - ret[1] = gp_Pnt2d(center.X() + half_side * (edge_dir.X() - perp_dir.X()), - center.Y() + half_side * (edge_dir.Y() - perp_dir.Y())); - ret[2] = gp_Pnt2d(center.X() - half_side * (edge_dir.X() + perp_dir.X()), - center.Y() - half_side * (edge_dir.Y() + perp_dir.Y())); - ret[3] = gp_Pnt2d(center.X() - half_side * (edge_dir.X() - perp_dir.X()), - center.Y() - half_side * (edge_dir.Y() - perp_dir.Y())); + ret[0] = + gp_Pnt2d(center.X() + half_side * (edge_dir.X() + perp_dir.X()), center.Y() + half_side * (edge_dir.Y() + perp_dir.Y())); + ret[1] = + gp_Pnt2d(center.X() + half_side * (edge_dir.X() - perp_dir.X()), center.Y() + half_side * (edge_dir.Y() - perp_dir.Y())); + ret[2] = + gp_Pnt2d(center.X() - half_side * (edge_dir.X() + perp_dir.X()), center.Y() - half_side * (edge_dir.Y() + perp_dir.Y())); + ret[3] = + gp_Pnt2d(center.X() - half_side * (edge_dir.X() - perp_dir.X()), center.Y() - half_side * (edge_dir.Y() - perp_dir.Y())); return ret; } @@ -237,8 +231,7 @@ std::array xy_stencil_pnts(const gp_Pnt2d& center, const gp_Pnt2d& std::array ret; - gp_Vec2d edge_dir(edge_midpoint.X() - center.X(), - edge_midpoint.Y() - center.Y()); + gp_Vec2d edge_dir(edge_midpoint.X() - center.X(), edge_midpoint.Y() - center.Y()); // Perpendicular direction (90 degrees) gp_Vec2d perp_dir = edge_dir.Rotated(std::numbers::pi / 2.0); @@ -251,13 +244,10 @@ std::array xy_stencil_pnts(const gp_Pnt2d& center, const gp_Pnt2d& return ret; } -TopoDS_Wire make_circle_wire(const gp_Pln& pln, - const gp_Pnt2d& center, - const gp_Pnt2d& edge_point) +TopoDS_Wire make_circle_wire(const gp_Pln& pln, const gp_Pnt2d& center, const gp_Pnt2d& edge_point) { // Compute radius - gp_Vec2d to_edge(edge_point.X() - center.X(), - edge_point.Y() - center.Y()); + gp_Vec2d to_edge(edge_point.X() - center.X(), edge_point.Y() - center.Y()); Standard_Real radius = to_edge.Magnitude(); @@ -276,9 +266,7 @@ TopoDS_Wire make_circle_wire(const gp_Pln& pln, return wire_maker.Wire(); } -Slot_pnts get_slot_points(const gp_Pnt2d& pt_a, - const gp_Pnt2d& pt_b, - const gp_Pnt2d& pt_c) +Slot_pnts get_slot_points(const gp_Pnt2d& pt_a, const gp_Pnt2d& pt_b, const gp_Pnt2d& pt_c) { Slot_pnts ret; @@ -295,28 +283,19 @@ Slot_pnts get_slot_points(const gp_Pnt2d& pt_a, gp_Vec2d perp_dir = dir.Rotated(ninety_degrees_radians); // Arc at pt_a: from +perp_dir (top) to -perp_dir (bottom) - ret.a_top_2d = gp_Pnt2d(pt_a.X() + radius * perp_dir.X(), - pt_a.Y() + radius * perp_dir.Y()); - ret.a_mid_2d = gp_Pnt2d(pt_a.X() - radius * dir.X(), - pt_a.Y() - radius * dir.Y()); - ret.a_bottom_2d = gp_Pnt2d(pt_a.X() - radius * perp_dir.X(), - pt_a.Y() - radius * perp_dir.Y()); + ret.a_top_2d = gp_Pnt2d(pt_a.X() + radius * perp_dir.X(), pt_a.Y() + radius * perp_dir.Y()); + ret.a_mid_2d = gp_Pnt2d(pt_a.X() - radius * dir.X(), pt_a.Y() - radius * dir.Y()); + ret.a_bottom_2d = gp_Pnt2d(pt_a.X() - radius * perp_dir.X(), pt_a.Y() - radius * perp_dir.Y()); // Arc at pt_b: from -perp_dir (bottom) to +perp_dir (top) - ret.b_bottom_2d = gp_Pnt2d(pt_b.X() - radius * perp_dir.X(), - pt_b.Y() - radius * perp_dir.Y()); - ret.b_mid_2d = gp_Pnt2d(pt_b.X() + radius * dir.X(), - pt_b.Y() + radius * dir.Y()); - ret.b_top_2d = gp_Pnt2d(pt_b.X() + radius * perp_dir.X(), - pt_b.Y() + radius * perp_dir.Y()); + ret.b_bottom_2d = gp_Pnt2d(pt_b.X() - radius * perp_dir.X(), pt_b.Y() - radius * perp_dir.Y()); + ret.b_mid_2d = gp_Pnt2d(pt_b.X() + radius * dir.X(), pt_b.Y() + radius * dir.Y()); + ret.b_top_2d = gp_Pnt2d(pt_b.X() + radius * perp_dir.X(), pt_b.Y() + radius * perp_dir.Y()); return ret; } -TopoDS_Wire make_slot_wire(const gp_Pln& plane, - const gp_Pnt2d& pt_a, - const gp_Pnt2d& pt_b, - const gp_Pnt2d& pt_c) +TopoDS_Wire make_slot_wire(const gp_Pln& plane, const gp_Pnt2d& pt_a, const gp_Pnt2d& pt_b, const gp_Pnt2d& pt_c) { Slot_pnts pnts = get_slot_points(pt_a, pt_b, pt_c); @@ -337,8 +316,8 @@ TopoDS_Wire make_slot_wire(const gp_Pln& plane, Geom_TrimmedCurve_ptr arc_b = arc_b_maker.Value(); // Straight segments - BRepBuilderAPI_MakeEdge line_1(a_bottom_3d, b_bottom_3d); // Bottom line - BRepBuilderAPI_MakeEdge line_2(b_top_3d, a_top_3d); // Top line + BRepBuilderAPI_MakeEdge line_1(a_bottom_3d, b_bottom_3d); // Bottom line + BRepBuilderAPI_MakeEdge line_2(b_top_3d, a_top_3d); // Top line // Build wire BRepBuilderAPI_MakeWire wire_maker; @@ -414,12 +393,12 @@ Plane_side side_of_plane(const gp_Pln& plane, const gp_Pnt& point) // Determine the side with tolerance if (signed_distance > 1e-6) - return Plane_side::Front; // Point is on the front side + return Plane_side::Front; // Point is on the front side else if (signed_distance < -1e-6) - return Plane_side::Back; // Point is on the back side + return Plane_side::Back; // Point is on the back side - return Plane_side::On; // Point is on the plane + return Plane_side::On; // Point is on the plane } // Function to get gp_Pln from a TopoDS_Face @@ -473,8 +452,8 @@ gp_Vec project_onto_plane(const gp_Vec& v, const gp_Pln& pln) gp_Pln xy_plane() { - gp_Ax3 xy_system = gp::XOY(); // Predefined XY coordinate system - return gp_Pln(xy_system.Location(), xy_system.Direction()); // XY plane + gp_Ax3 xy_system = gp::XOY(); // Predefined XY coordinate system + return gp_Pln(xy_system.Location(), xy_system.Direction()); // XY plane } // Function to compute the center point between two gp_Pnt2d points @@ -495,8 +474,7 @@ gp_Dir2d get_unit_dir(const gp_Pnt2d& point1, const gp_Pnt2d& point2) gp_Vec2d direction_vector(point1, point2); // Check if the vector is zero-length (points are identical) - EZY_ASSERT_MSG(direction_vector.Magnitude() > Precision::Confusion(), - "Error: Points are coincident"); + EZY_ASSERT_MSG(direction_vector.Magnitude() > Precision::Confusion(), "Error: Points are coincident"); // Normalize the vector and return as gp_Dir2d return gp_Dir2d(direction_vector.Normalized()); @@ -538,12 +516,12 @@ Prs3d_DimensionTextHorizontalPosition edge_dim_text_h_pos_from_index(int idx) { switch (idx) { - // clang-format off + // clang-format off case 0: return Prs3d_DTHP_Left; case 1: return Prs3d_DTHP_Right; case 2: return Prs3d_DTHP_Center; default: return Prs3d_DTHP_Fit; - // clang-format on + // clang-format on } } @@ -615,11 +593,8 @@ void apply_length_dimension_arrow_size(const PrsDim_LengthDimension_ptr& dim, co // OCCT draws the dimension on the side given by (plane_normal x edge_vector) for positive flyout. // When that side faces the sketch interior, negate flyout so the annotation sits outside the loop. -static void orient_length_dimension_flyout_outward(const PrsDim_LengthDimension_ptr& dim, - const gp_Pnt& p1, - const gp_Pnt& p2, - const gp_Pnt& interior_ref, - const gp_Pln& pln) +static void orient_length_dimension_flyout_outward(const PrsDim_LengthDimension_ptr& dim, const gp_Pnt& p1, const gp_Pnt& p2, + const gp_Pnt& interior_ref, const gp_Pln& pln) { if (dim.IsNull()) return; @@ -659,11 +634,9 @@ static bool point_strictly_inside_sketch_faces(const gp_Pnt& p, const std::vecto } // Returns true if flyout sign was chosen from face classification. -static bool orient_length_dimension_flyout_clear_of_faces(const PrsDim_LengthDimension_ptr& dim, - const gp_Pnt& p1, - const gp_Pnt& p2, - const gp_Pln& pln, - const std::vector& faces) +static bool orient_length_dimension_flyout_clear_of_faces(const PrsDim_LengthDimension_ptr& dim, const gp_Pnt& p1, + const gp_Pnt& p2, const gp_Pln& pln, + const std::vector& faces) { if (dim.IsNull() || faces.empty()) return false; @@ -708,14 +681,11 @@ static bool orient_length_dimension_flyout_clear_of_faces(const PrsDim_LengthDim return false; } -PrsDim_LengthDimension_ptr create_distance_annotation(const gp_Pnt& p1, - const gp_Pnt& p2, - const gp_Pln& pln, +PrsDim_LengthDimension_ptr create_distance_annotation(const gp_Pnt& p1, const gp_Pnt& p2, const gp_Pln& pln, const Prs3d_DimensionTextHorizontalPosition text_h_pos, const std::optional& interior_ref, const std::vector* sketch_faces_for_flyout, - const double dimension_line_width, - const double dimension_arrow_size) + const double dimension_line_width, const double dimension_arrow_size) { // Check if points are too close (invalid for dimension) EZY_ASSERT(unique(p1, p2)); @@ -735,14 +705,11 @@ PrsDim_LengthDimension_ptr create_distance_annotation(const gp_Pnt& return dim; } -PrsDim_LengthDimension_ptr create_distance_annotation(const gp_Pnt2d& p1, - const gp_Pnt2d& p2, - const gp_Pln& pln, +PrsDim_LengthDimension_ptr create_distance_annotation(const gp_Pnt2d& p1, const gp_Pnt2d& p2, const gp_Pln& pln, const Prs3d_DimensionTextHorizontalPosition text_h_pos, const std::optional& interior_ref, const std::vector* sketch_faces_for_flyout, - const double dimension_line_width, - const double dimension_arrow_size) + const double dimension_line_width, const double dimension_arrow_size) { gp_Pnt point_1 = to_3d(pln, p1); gp_Pnt point_2 = to_3d(pln, p2); @@ -821,7 +788,7 @@ bool is_face_contained(const TopoDS_Shape& shape_a, const TopoDS_Shape& shape_b) if (!pln_a.Position().Direction().IsParallel(pln_b.Position().Direction(), Precision::Angular()) || Abs(pln_a.Distance(pln_b.Location())) > Precision::Confusion()) { - return Standard_False; // Not coplanar + return Standard_False; // Not coplanar } // Check if face_a's outer wire is contained within face_b @@ -853,10 +820,7 @@ boost_geom::point_2d to_boost(const gp_Pln& plane, const gp_Pnt& point_3d) return {pt.X(), pt.Y()}; } -boost_geom::point_2d to_boost(const gp_Pnt2d& pt) -{ - return {pt.X(), pt.Y()}; -} +boost_geom::point_2d to_boost(const gp_Pnt2d& pt) { return {pt.X(), pt.Y()}; } // Convert a TopoDS_Shape to a boost_geom::polygon_2d boost_geom::polygon_2d to_boost(const TopoDS_Shape& shape, const gp_Pln& pln2) @@ -911,34 +875,34 @@ boost_geom::polygon_2d to_boost(const TopoDS_Shape& shape, const gp_Pln& pln2) GeomAbs_CurveType curveType = curve.GetType(); switch (curveType) { - case GeomAbs_CurveType::GeomAbs_Line: + case GeomAbs_CurveType::GeomAbs_Line: + { + TopExp_Explorer vertexExplorer(edge, TopAbs_VERTEX); + while (vertexExplorer.More()) { - TopExp_Explorer vertexExplorer(edge, TopAbs_VERTEX); - while (vertexExplorer.More()) - { - const TopoDS_Vertex& vertex = TopoDS::Vertex(vertexExplorer.Current()); - gp_Pnt2d pt = to_2d(pln, BRep_Tool::Pnt(vertex)); - add_pt_unique(out, pt); - vertexExplorer.Next(); - } - break; + const TopoDS_Vertex& vertex = TopoDS::Vertex(vertexExplorer.Current()); + gp_Pnt2d pt = to_2d(pln, BRep_Tool::Pnt(vertex)); + add_pt_unique(out, pt); + vertexExplorer.Next(); } - case GeomAbs_CurveType::GeomAbs_Circle: + break; + } + case GeomAbs_CurveType::GeomAbs_Circle: + { + // Get the parameter range of the curve + double u_start = curve.FirstParameter(); + double u_end = curve.LastParameter(); + const size_t num_pts = 25; + double step = (u_end - u_start) / (num_pts - 1); + for (size_t i = 0; i < num_pts; ++i) { - // Get the parameter range of the curve - double u_start = curve.FirstParameter(); - double u_end = curve.LastParameter(); - const size_t num_pts = 25; - double step = (u_end - u_start) / (num_pts - 1); - for (size_t i = 0; i < num_pts; ++i) - { - gp_Pnt2d pt = to_2d(pln, curve.Value(u_start + i * step)); - add_pt_unique(out, pt); - } - break; + gp_Pnt2d pt = to_2d(pln, curve.Value(u_start + i * step)); + add_pt_unique(out, pt); } - default: - EZY_ASSERT(false); // Implement! + break; + } + default: + EZY_ASSERT(false); // Implement! } edge_explorer.Next(); } @@ -946,8 +910,7 @@ boost_geom::polygon_2d to_boost(const TopoDS_Shape& shape, const gp_Pln& pln2) if (wire.Orientation() == TopAbs_FORWARD) std::reverse(out.begin(), out.end()); - EZY_ASSERT_MSG(to_pnt2d(out.front()).IsEqual(to_pnt2d(out.back()), Precision::Confusion()), - "Ring not closed!"); + EZY_ASSERT_MSG(to_pnt2d(out.front()).IsEqual(to_pnt2d(out.back()), Precision::Confusion()), "Ring not closed!"); out.pop_back(); @@ -984,7 +947,7 @@ boost_geom::polygon_2d to_boost(const TopoDS_Shape& shape, const gp_Pln& pln2) while (wire_explorer.More()) { TopoDS_Wire wire = TopoDS::Wire(wire_explorer.Current()); - if (!wire.IsSame(outer_wire)) // TODO Is this expensive? Better way? + if (!wire.IsSame(outer_wire)) // TODO Is this expensive? Better way? { boost_geom::ring_2d inner; get_wire_verts(wire, inner); @@ -1019,7 +982,7 @@ bool operator<(const gp_Pnt2d& lhs, const gp_Pnt2d& rhs) // Check if points are equal within tolerance if (lhs.Distance(rhs) <= tolerance) - return false; // Equal points are not less than each other + return false; // Equal points are not less than each other // Lexicographical ordering: compare X first, then Y if X is equal within tolerance if (std::abs(lhs.X() - rhs.X()) > tolerance) @@ -1077,16 +1040,12 @@ void sort_pnts(std::vector& points) }); } -TopoDS_Wire make_rectangle_wire(const gp_Pln& pln, - const gp_Pnt2d& corner1, - const gp_Pnt2d& corner2) +TopoDS_Wire make_rectangle_wire(const gp_Pln& pln, const gp_Pnt2d& corner1, const gp_Pnt2d& corner2) { // Assert that corners are not too close in either axis - EZY_ASSERT_MSG(std::abs(corner1.X() - corner2.X()) > Precision::Confusion(), - "Rectangle corners too close in X axis"); + EZY_ASSERT_MSG(std::abs(corner1.X() - corner2.X()) > Precision::Confusion(), "Rectangle corners too close in X axis"); - EZY_ASSERT_MSG(std::abs(corner1.Y() - corner2.Y()) > Precision::Confusion(), - "Rectangle corners too close in Y axis"); + EZY_ASSERT_MSG(std::abs(corner1.Y() - corner2.Y()) > Precision::Confusion(), "Rectangle corners too close in Y axis"); std::array corners = rectangle_corners(corner1, corner2); @@ -1113,12 +1072,12 @@ std::array rectangle_corners(const gp_Pnt2d& corner1, const gp_Pnt2 std::array ret; // Calculate the other two corners based on the diagonal - ret[0] = corner1; // First corner - ret[2] = corner2; // Opposite corner (diagonal) + ret[0] = corner1; // First corner + ret[2] = corner2; // Opposite corner (diagonal) // Calculate the other two corners - ret[1] = gp_Pnt2d(corner2.X(), corner1.Y()); // Same X as corner2, same Y as corner1 - ret[3] = gp_Pnt2d(corner1.X(), corner2.Y()); // Same X as corner1, same Y as corner2 + ret[1] = gp_Pnt2d(corner2.X(), corner1.Y()); // Same X as corner2, same Y as corner1 + ret[3] = gp_Pnt2d(corner1.X(), corner2.Y()); // Same X as corner1, same Y as corner2 return ret; } @@ -1143,8 +1102,8 @@ bool point_on_open_segment_2d(const gp_Pnt2d& p, const gp_Pnt2d& a, const gp_Pnt return t > 0.0 && t < 1.0; } -std::optional snap_foot_to_open_segment_interior_if_close( - const gp_Pnt2d& p, const gp_Pnt2d& a, const gp_Pnt2d& b, double max_perp_dist) +std::optional snap_foot_to_open_segment_interior_if_close(const gp_Pnt2d& p, const gp_Pnt2d& a, const gp_Pnt2d& b, + double max_perp_dist) { const double tol = Precision::Confusion(); gp_Vec2d ab(a, b); diff --git a/src/geom.h b/src/geom.h index 8fb54ec..6909576 100644 --- a/src/geom.h +++ b/src/geom.h @@ -9,7 +9,7 @@ #include #include #include -#include // For Pi +#include // For Pi #include #include @@ -31,7 +31,7 @@ typedef boost::geometry::model::d2::point_xy point_2d; typedef boost::geometry::model::ring ring_2d; typedef boost::geometry::model::polygon polygon_2d; typedef boost::geometry::model::linestring linestring_2d; -} // namespace boost_geom +} // namespace boost_geom // Function to project a 3D point onto a plane and get its 2D (u, v) coordinates gp_Pnt2d to_2d(const gp_Pln& plane, const gp_Pnt& point_3d); @@ -47,17 +47,13 @@ TopoDS_Wire create_wire_box(const gp_Pln& plane, const gp_Pnt& position, double /// Two perpendicular segments forming a + on \a plane, centered at \a center_3d, half-length \a half_arm (model units). TopoDS_Shape create_plus_cross_shape(const gp_Pln& plane, const gp_Pnt& center_3d, double half_arm); -TopoDS_Wire make_square_wire(const gp_Pln& pln, - const gp_Pnt2d& center, - const gp_Pnt2d& edge_midpoint); +TopoDS_Wire make_square_wire(const gp_Pln& pln, const gp_Pnt2d& center, const gp_Pnt2d& edge_midpoint); std::array square_corners(const gp_Pnt2d& center, const gp_Pnt2d& edge_midpoint); std::array xy_stencil_pnts(const gp_Pnt2d& center, const gp_Pnt2d& edge_midpoint); -TopoDS_Wire make_circle_wire(const gp_Pln& pln, - const gp_Pnt2d& center, - const gp_Pnt2d& edge_point); +TopoDS_Wire make_circle_wire(const gp_Pln& pln, const gp_Pnt2d& center, const gp_Pnt2d& edge_point); struct Slot_pnts { @@ -70,27 +66,21 @@ struct Slot_pnts gp_Pnt2d b_top_2d; }; -Slot_pnts get_slot_points(const gp_Pnt2d& pt_a, - const gp_Pnt2d& pt_b, - const gp_Pnt2d& pt_c); +Slot_pnts get_slot_points(const gp_Pnt2d& pt_a, const gp_Pnt2d& pt_b, const gp_Pnt2d& pt_c); -TopoDS_Wire make_slot_wire(const gp_Pln& plane, - const gp_Pnt2d& pt_a, - const gp_Pnt2d& pt_b, - const gp_Pnt2d& pt_c); +TopoDS_Wire make_slot_wire(const gp_Pln& plane, const gp_Pnt2d& pt_a, const gp_Pnt2d& pt_b, const gp_Pnt2d& pt_c); - // Function to get the directional vectors at the start and end of a Geom_TrimmedCurve - std::pair - get_start_end_tangents(const Handle(Geom_TrimmedCurve) & curve); +// Function to get the directional vectors at the start and end of a Geom_TrimmedCurve +std::pair get_start_end_tangents(const Handle(Geom_TrimmedCurve) & curve); std::pair get_edge_endpoints(const TopoDS_Edge& edge); std::pair get_edge_endpoints(const gp_Pln& pln, const TopoDS_Edge& edge); enum class Plane_side { - Front, // Positive side (normal direction) - Back, // Negative side (opposite normal) - On // On the plane + Front, // Positive side (normal direction) + Back, // Negative side (opposite normal) + On // On the plane }; Plane_side side_of_plane(const gp_Pln& plane, const gp_Pnt& point); @@ -111,10 +101,7 @@ gp_Pnt2d center_point(const gp_Pnt2d& point1, const gp_Pnt2d& point2); // Function to compute the normalized direction between two gp_Pnt2d points gp_Dir2d get_unit_dir(const gp_Pnt2d& point1, const gp_Pnt2d& point2); -inline glm::dvec2 to_glm(const gp_Dir2d& v) -{ - return {v.X(), v.Y()}; -} +inline glm::dvec2 to_glm(const gp_Dir2d& v) { return {v.X(), v.Y()}; } gp_Pnt2d get_midpoint(const gp_Pnt2d& p1, const gp_Pnt2d& p2); @@ -132,23 +119,17 @@ void apply_length_dimension_arrow_size(const PrsDim_LengthDimension_ptr& dim, do /// void (not TopAbs_IN) relative to those faces - fixes concave / notch edges where the node centroid lies /// on the wrong side. Otherwise `interior_ref` (e.g. node centroid) is used as a weaker heuristic. /// OCCT line width scale factor for dimension lines (1.0 = default). -PrsDim_LengthDimension_ptr create_distance_annotation(const gp_Pnt& p1, - const gp_Pnt& p2, - const gp_Pln& pln, - Prs3d_DimensionTextHorizontalPosition text_h_pos = Prs3d_DTHP_Fit, - const std::optional& interior_ref = std::nullopt, +PrsDim_LengthDimension_ptr create_distance_annotation(const gp_Pnt& p1, const gp_Pnt& p2, const gp_Pln& pln, + Prs3d_DimensionTextHorizontalPosition text_h_pos = Prs3d_DTHP_Fit, + const std::optional& interior_ref = std::nullopt, const std::vector* sketch_faces_for_flyout = nullptr, - double dimension_line_width = 1.0, - double dimension_arrow_size = 6.0); - -PrsDim_LengthDimension_ptr create_distance_annotation(const gp_Pnt2d& p1, - const gp_Pnt2d& p2, - const gp_Pln& pln, - Prs3d_DimensionTextHorizontalPosition text_h_pos = Prs3d_DTHP_Fit, - const std::optional& interior_ref = std::nullopt, + double dimension_line_width = 1.0, double dimension_arrow_size = 6.0); + +PrsDim_LengthDimension_ptr create_distance_annotation(const gp_Pnt2d& p1, const gp_Pnt2d& p2, const gp_Pln& pln, + Prs3d_DimensionTextHorizontalPosition text_h_pos = Prs3d_DTHP_Fit, + const std::optional& interior_ref = std::nullopt, const std::vector* sketch_faces_for_flyout = nullptr, - double dimension_line_width = 1.0, - double dimension_arrow_size = 6.0); + double dimension_line_width = 1.0, double dimension_arrow_size = 6.0); const gp_Pnt& closest_to_camera(const V3d_View_ptr& view, const std::vector& pnts); @@ -158,7 +139,7 @@ double compute_face_area(const AIS_Shape_ptr& shp); // Function to check if shape_a is contained within shape_b (both must be faces, holes are not considered) bool is_face_contained(const TopoDS_Shape& shape_a, const TopoDS_Shape& shape_b); -// Boost related, usefull for debugging using +// Boost related, useful for debugging using // https://marketplace.visualstudio.com/items?itemName=AdamWulkiewicz.GraphicalDebugging // Function to convert a 3D point to 2D in the plane's coordinate system boost_geom::point_2d to_boost(const gp_Pln& plane, const gp_Pnt& point_3d); @@ -171,12 +152,10 @@ boost_geom::polygon_2d to_boost(const TopoDS_Shape& shape, const gp_Pln& pln2); gp_Pnt get_shape_bbox_center(const TopoDS_Shape& shp); // Checks if elements are unique using IsEqual -template -bool unique(const T& first, Args... args); +template bool unique(const T& first, Args... args); // Checks if elements are equal using IsEqual -template -bool equal(const T& first, Args... args); +template bool equal(const T& first, Args... args); // Define custom less-than operator for gp_Pnt2d using Precision::Confusion() bool operator<(const gp_Pnt2d& lhs, const gp_Pnt2d& rhs); @@ -196,16 +175,14 @@ constexpr double to_radians(double degrees); // Convert radians to degrees constexpr double to_degrees(double radians); -TopoDS_Wire make_rectangle_wire(const gp_Pln& pln, - const gp_Pnt2d& corner1, - const gp_Pnt2d& corner2); +TopoDS_Wire make_rectangle_wire(const gp_Pln& pln, const gp_Pnt2d& corner1, const gp_Pnt2d& corner2); std::array rectangle_corners(const gp_Pnt2d& corner1, const gp_Pnt2d& corner2); bool point_on_open_segment_2d(const gp_Pnt2d& p, const gp_Pnt2d& a, const gp_Pnt2d& b); /// If the shortest distance from \a p to segment `a-b` is <= \a max_perp_dist and the foot lies strictly /// inside the segment (not near endpoints), returns that foot; otherwise nullopt. -std::optional snap_foot_to_open_segment_interior_if_close( - const gp_Pnt2d& p, const gp_Pnt2d& a, const gp_Pnt2d& b, double max_perp_dist); +std::optional snap_foot_to_open_segment_interior_if_close(const gp_Pnt2d& p, const gp_Pnt2d& a, const gp_Pnt2d& b, + double max_perp_dist); #include "geom.inl" \ No newline at end of file diff --git a/src/geom.inl b/src/geom.inl index 59dc1a9..1f5153e 100644 --- a/src/geom.inl +++ b/src/geom.inl @@ -1,10 +1,8 @@ // Helper to fill vector (base case: no arguments) -template -inline void fill_vector(std::vector&) {} +template inline void fill_vector(std::vector&) {} // Helper to fill vector (recursive case) -template -inline void fill_vector(std::vector& vec, const T& first, Args... rest) +template inline void fill_vector(std::vector& vec, const T& first, Args... rest) { static_assert((std::is_same_v && ...), "All arguments must be of the same type"); vec.push_back(first); @@ -12,8 +10,7 @@ inline void fill_vector(std::vector& vec, const T& first, Args... rest) } // Checks if elements are unique using IsEqual -template -bool unique(const T& first, Args... args) +template bool unique(const T& first, Args... args) { // Collect arguments into vector std::vector items; @@ -31,8 +28,7 @@ bool unique(const T& first, Args... args) } // Checks if elements are equal using IsEqual -template -bool equal(const T& first, Args... args) +template bool equal(const T& first, Args... args) { // Collect arguments into vector std::vector items; @@ -50,13 +46,7 @@ bool equal(const T& first, Args... args) } // Convert degrees to radians -constexpr double to_radians(double degrees) -{ - return degrees * std::numbers::pi / 180.0; -} +constexpr double to_radians(double degrees) { return degrees * std::numbers::pi / 180.0; } // Convert radians to degrees -constexpr double to_degrees(double radians) -{ - return radians * 180.0 / std::numbers::pi; -} +constexpr double to_degrees(double radians) { return radians * 180.0 / std::numbers::pi; } diff --git a/src/gui.cpp b/src/gui.cpp index 405e354..60f5e37 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -60,7 +60,7 @@ ImFont* GUI::console_font() const } GUI::~GUI() { - cleanup_log_redirection_(); // Clean up stream redirection + cleanup_log_redirection_(); // Clean up stream redirection } ImVec4 GUI::get_clear_color() const { @@ -113,39 +113,40 @@ void GUI::render_gui() settings_(); dbg_(); } -void GUI::render_occt() -{ - m_view->do_frame(); -} +void GUI::render_occt() { m_view->do_frame(); } // Initialize toolbar buttons void GUI::initialize_toolbar_() { m_toolbar_buttons = { - { load_texture("res/icons/User.png"), true, "Inspection mode", Mode::Normal}, - { load_texture("res/icons/Workbench_Sketcher_none.png"), false, "Sketch inspection mode", Mode::Sketch_inspection_mode}, - { load_texture("res/icons/Assembly_AxialMove.png"), false, "Shape move (g)", Mode::Move}, - { load_texture("res/icons/Draft_Rotate.png"), false, "Shape rotate (r)", Mode::Rotate}, - { load_texture("res/icons/Part_Scale.png"), false, "Shape Scale (s)", Mode::Scale}, - { load_texture("res/icons/Macro_FaceToSketch_48.png"), false, "Create a sketch from planar face", Mode::Sketch_from_planar_face}, - { load_texture("res/icons/Sketcher_MirrorSketch.png"), false, "Define operation axis", Mode::Sketch_operation_axis}, - { load_texture("res/icons/Sketcher_CreatePoint.png"), false, "Add node", Mode::Sketch_add_node}, - { load_texture("res/icons/Sketcher_Element_Line_Edge.png"), false, "Add line edge", Mode::Sketch_add_edge}, - { load_texture("res/icons/ls.png"), false, "Add multi-line edge", Mode::Sketch_add_multi_edges}, - { load_texture("res/icons/Sketcher_Element_Arc_Edge.png"), false, "Add arc circle", Mode::Sketch_add_seg_circle_arc}, - { load_texture("res/icons/Sketcher_CreateSquare.png"), false, "Add square", Mode::Sketch_add_square}, - { load_texture("res/icons/Sketcher_CreateRectangle.png"), false, "Add rectangle from two points", Mode::Sketch_add_rectangle}, - {load_texture("res/icons/Sketcher_CreateRectangle_Center.png"), false, "Add rectangle with center point", Mode::Sketch_add_rectangle_center_pt}, - { load_texture("res/icons/Sketcher_CreateCircle.png"), false, "Add circle", Mode::Sketch_add_circle}, - { load_texture("res/icons/Sketcher_Create3PointCircle.png"), false, "Add circle from three points", Mode::Sketch_add_circle_3_pts}, - { load_texture("res/icons/Sketcher_CreateSlot.png"), false, "Add slot", Mode::Sketch_add_slot}, - { load_texture("res/icons/TechDraw_LengthDimension.png"), false, "Length dimension", Mode::Sketch_dim_anno}, - { load_texture("res/icons/Design456_Extrude.png"), false, "Extrude sketch face (e)", Mode::Sketch_face_extrude}, - { load_texture("res/icons/PartDesign_Chamfer.png"), false, "Chamfer", Mode::Shape_chamfer}, - { load_texture("res/icons/PartDesign_Fillet.png"), false, "Fillet", Mode::Shape_fillet}, - { load_texture("res/icons/Draft_PolarArray.png"), false, "Shape polar duplicate", Mode::Shape_polar_duplicate}, - { load_texture("res/icons/Part_Cut.png"), false, "Shape cut", Command::Shape_cut}, - { load_texture("res/icons/Part_Fuse.png"), false, "Shape fuse", Command::Shape_fuse}, - { load_texture("res/icons/Part_Common.png"), false, "Shape common", Command::Shape_common}, + {load_texture("res/icons/User.png"), true, "Inspection mode", Mode::Normal}, + {load_texture("res/icons/Workbench_Sketcher_none.png"), false, "Sketch inspection mode", Mode::Sketch_inspection_mode}, + {load_texture("res/icons/Assembly_AxialMove.png"), false, "Shape move (g)", Mode::Move}, + {load_texture("res/icons/Draft_Rotate.png"), false, "Shape rotate (r)", Mode::Rotate}, + {load_texture("res/icons/Part_Scale.png"), false, "Shape Scale (s)", Mode::Scale}, + {load_texture("res/icons/Macro_FaceToSketch_48.png"), false, "Create a sketch from planar face", + Mode::Sketch_from_planar_face}, + {load_texture("res/icons/Sketcher_MirrorSketch.png"), false, "Define operation axis", Mode::Sketch_operation_axis}, + {load_texture("res/icons/Sketcher_CreatePoint.png"), false, "Add node", Mode::Sketch_add_node}, + {load_texture("res/icons/Sketcher_Element_Line_Edge.png"), false, "Add line edge", Mode::Sketch_add_edge}, + {load_texture("res/icons/ls.png"), false, "Add multi-line edge", Mode::Sketch_add_multi_edges}, + {load_texture("res/icons/Sketcher_Element_Arc_Edge.png"), false, "Add arc circle", Mode::Sketch_add_seg_circle_arc}, + {load_texture("res/icons/Sketcher_CreateSquare.png"), false, "Add square", Mode::Sketch_add_square}, + {load_texture("res/icons/Sketcher_CreateRectangle.png"), false, "Add rectangle from two points", + Mode::Sketch_add_rectangle}, + {load_texture("res/icons/Sketcher_CreateRectangle_Center.png"), false, "Add rectangle with center point", + Mode::Sketch_add_rectangle_center_pt}, + {load_texture("res/icons/Sketcher_CreateCircle.png"), false, "Add circle", Mode::Sketch_add_circle}, + {load_texture("res/icons/Sketcher_Create3PointCircle.png"), false, "Add circle from three points", + Mode::Sketch_add_circle_3_pts}, + {load_texture("res/icons/Sketcher_CreateSlot.png"), false, "Add slot", Mode::Sketch_add_slot}, + {load_texture("res/icons/TechDraw_LengthDimension.png"), false, "Length dimension", Mode::Sketch_dim_anno}, + {load_texture("res/icons/Design456_Extrude.png"), false, "Extrude sketch face (e)", Mode::Sketch_face_extrude}, + {load_texture("res/icons/PartDesign_Chamfer.png"), false, "Chamfer", Mode::Shape_chamfer}, + {load_texture("res/icons/PartDesign_Fillet.png"), false, "Fillet", Mode::Shape_fillet}, + {load_texture("res/icons/Draft_PolarArray.png"), false, "Shape polar duplicate", Mode::Shape_polar_duplicate}, + {load_texture("res/icons/Part_Cut.png"), false, "Shape cut", Command::Shape_cut}, + {load_texture("res/icons/Part_Fuse.png"), false, "Shape fuse", Command::Shape_fuse}, + {load_texture("res/icons/Part_Common.png"), false, "Shape common", Command::Shape_common}, }; } void GUI::load_examples_list_() @@ -170,7 +171,7 @@ void GUI::load_examples_list_() std::string path = p.string(); std::string label = p.filename().string(); - m_example_files.push_back(Example_file {std::move(label), std::move(path)}); + m_example_files.push_back(Example_file{std::move(label), std::move(path)}); } std::sort(m_example_files.begin(), m_example_files.end(), [](const Example_file& a, const Example_file& b) { return a.label < b.label; }); @@ -195,7 +196,7 @@ void GUI::menu_bar_() if (ImGui::MenuItem("Save as")) { - m_last_saved_path.clear(); // Force save as dialog + m_last_saved_path.clear(); // Force save as dialog save_file_dialog_(); } @@ -231,7 +232,7 @@ void GUI::menu_bar_() if (ImGui::MenuItem(ex.label.c_str())) { std::ifstream file(ex.path); - std::string json_str {std::istreambuf_iterator(file), std::istreambuf_iterator()}; + std::string json_str{std::istreambuf_iterator(file), std::istreambuf_iterator()}; if (file.good() && !json_str.empty()) on_file(ex.path, json_str); else @@ -284,8 +285,8 @@ void GUI::menu_bar_() if (ImGui::MenuItem("Add pyramid_prms")) { - m_add_pyramid_origin = glm::dvec3(0.0, 0.0, 0.0); - m_add_pyramid_side = 1.0; + m_add_pyramid_origin = glm::dvec3(0.0, 0.0, 0.0); + m_add_pyramid_side = 1.0; m_open_add_pyramid_popup = true; } @@ -297,8 +298,8 @@ void GUI::menu_bar_() if (ImGui::MenuItem("Add sphere_prms")) { - m_add_sphere_origin = glm::dvec3(0.0, 0.0, 0.0); - m_add_sphere_radius = 1.0; + m_add_sphere_origin = glm::dvec3(0.0, 0.0, 0.0); + m_add_sphere_radius = 1.0; m_open_add_sphere_popup = true; } @@ -323,10 +324,10 @@ void GUI::menu_bar_() if (ImGui::MenuItem("Add cone_prms")) { - m_add_cone_origin = glm::dvec3(0.0, 0.0, 0.0); - m_add_cone_R1 = 1.0; - m_add_cone_R2 = 0.0; - m_add_cone_height = 1.0; + m_add_cone_origin = glm::dvec3(0.0, 0.0, 0.0); + m_add_cone_R1 = 1.0; + m_add_cone_R2 = 0.0; + m_add_cone_height = 1.0; m_open_add_cone_popup = true; } @@ -338,9 +339,9 @@ void GUI::menu_bar_() if (ImGui::MenuItem("Add torus_prms")) { - m_add_torus_origin = glm::dvec3(0.0, 0.0, 0.0); - m_add_torus_R1 = 1.0; - m_add_torus_R2 = 0.5; + m_add_torus_origin = glm::dvec3(0.0, 0.0, 0.0); + m_add_torus_R1 = 1.0; + m_add_torus_R2 = 0.5; m_open_add_torus_popup = true; } @@ -572,7 +573,7 @@ void GUI::ensure_about_assets_() } ImGui::MarkdownImageData GUI::about_markdown_image_(ImGui::MarkdownLinkCallbackData data) { - ImGui::MarkdownImageData out {}; + ImGui::MarkdownImageData out{}; if (!data.isImage) return out; @@ -583,8 +584,8 @@ ImGui::MarkdownImageData GUI::about_markdown_image_(ImGui::MarkdownLinkCallbackD out.isValid = true; out.useLinkCallback = false; - out.user_texture_id = (ImTextureID) (intptr_t) m_about_splash_gl; - out.size = ImVec2((float) m_about_splash_size.x, (float) m_about_splash_size.y); + out.user_texture_id = (ImTextureID)(intptr_t)m_about_splash_gl; + out.size = ImVec2((float)m_about_splash_size.x, (float)m_about_splash_size.y); ImVec2 const avail = ImGui::GetContentRegionAvail(); if (out.size.x > avail.x && avail.x > 1.0f) { @@ -632,31 +633,31 @@ void GUI::toolbar_() // Add a unique string ID (e.g., "button0", "button1", etc.) char button_id[16]; snprintf(button_id, sizeof(button_id), "button%d", i); - if (ImGui::ImageButton(button_id, (ImTextureID) (intptr_t) m_toolbar_buttons[i].texture_id, button_size)) + if (ImGui::ImageButton(button_id, (ImTextureID)(intptr_t)m_toolbar_buttons[i].texture_id, button_size)) { if (m_toolbar_buttons[i].data.index() == 1) switch (std::get(m_toolbar_buttons[i].data)) { - case Command::Shape_cut: - if (Status s = m_view->shp_cut().selected_cut(); !s.is_ok()) - show_message(s.message()); + case Command::Shape_cut: + if (Status s = m_view->shp_cut().selected_cut(); !s.is_ok()) + show_message(s.message()); - break; + break; - case Command::Shape_fuse: - if (Status s = m_view->shp_fuse().selected_fuse(); !s.is_ok()) - show_message(s.message()); + case Command::Shape_fuse: + if (Status s = m_view->shp_fuse().selected_fuse(); !s.is_ok()) + show_message(s.message()); - break; + break; - case Command::Shape_common: - if (Status s = m_view->shp_common().selected_common(); !s.is_ok()) - show_message(s.message()); + case Command::Shape_common: + if (Status s = m_view->shp_common().selected_common(); !s.is_ok()) + show_message(s.message()); - break; + break; - default: - EZY_ASSERT(false); + default: + EZY_ASSERT(false); } else { @@ -683,7 +684,8 @@ void GUI::toolbar_() ImGui::End(); } // Distance edit related -void GUI::set_dist_edit(float dist, std::function&& callback, const std::optional screen_coords) +void GUI::set_dist_edit(float dist, std::function&& callback, + const std::optional screen_coords) { DBG_MSG("dist " << dist); // Sketch calls this every mousemove while TAB length mode is on; do not reset value/position each frame @@ -707,7 +709,7 @@ void GUI::hide_dist_edit() { if (m_dist_callback) { - float parsed {}; + float parsed{}; if (parse_dist_text_to_float_(m_dist_text_buf.data(), parsed)) m_dist_val = parsed; @@ -724,16 +726,15 @@ void GUI::dist_edit_() return; // Set the position of the next window - ImGui::SetNextWindowPos(ImVec2(float(m_dist_edit_loc.unsafe_get_x()), float(m_dist_edit_loc.unsafe_get_y())), ImGuiCond_Always); + ImGui::SetNextWindowPos(ImVec2(float(m_dist_edit_loc.unsafe_get_x()), float(m_dist_edit_loc.unsafe_get_y())), + ImGuiCond_Always); // Set a small size (optional) ImGui::SetNextWindowSize(ImVec2(120.0f, 25.0f), ImGuiCond_Once); // Begin a window with minimal flags ImGui::Begin("FloatEdit##unique_id", nullptr, - ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings); ImGui::SetNextItemWidth(100.0f); @@ -745,18 +746,15 @@ void GUI::dist_edit_() } // Text field: InputFloat applies printf rounding so typed digits can disagree with m_dist_val. - const bool text_changed = ImGui::InputText( - "##dist_edit_text", - m_dist_text_buf.data(), - m_dist_text_buf.size(), - ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific); + const bool text_changed = ImGui::InputText("##dist_edit_text", m_dist_text_buf.data(), m_dist_text_buf.size(), + ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific); if (text_changed && parse_dist_text_to_float_(m_dist_text_buf.data(), m_dist_val)) m_dist_callback(m_dist_val, false); if (ImGui::IsItemDeactivatedAfterEdit() && m_dist_callback) { - float parsed {}; + float parsed{}; if (parse_dist_text_to_float_(m_dist_text_buf.data(), parsed)) m_dist_val = parsed; @@ -768,7 +766,8 @@ void GUI::dist_edit_() ImGui::End(); } // Angle edit related -void GUI::set_angle_edit(float angle, std::function&& callback, const std::optional screen_coords) +void GUI::set_angle_edit(float angle, std::function&& callback, + const std::optional screen_coords) { DBG_MSG("angle " << angle); const bool already_editing = m_angle_callback != nullptr; @@ -790,7 +789,7 @@ void GUI::hide_angle_edit() { if (m_angle_callback) { - float parsed {}; + float parsed{}; if (parse_dist_text_to_float_(m_angle_text_buf.data(), parsed)) m_angle_val = parsed; std::function callback; @@ -798,26 +797,22 @@ void GUI::hide_angle_edit() callback(m_angle_val, true); } } -bool GUI::is_dist_or_angle_edit_active() const -{ - return m_dist_callback != nullptr || m_angle_callback != nullptr; -} +bool GUI::is_dist_or_angle_edit_active() const { return m_dist_callback != nullptr || m_angle_callback != nullptr; } void GUI::angle_edit_() { if (!m_angle_callback) return; // Set the position of the next window - ImGui::SetNextWindowPos(ImVec2(float(m_angle_edit_loc.unsafe_get_x()), float(m_angle_edit_loc.unsafe_get_y())), ImGuiCond_Always); + ImGui::SetNextWindowPos(ImVec2(float(m_angle_edit_loc.unsafe_get_x()), float(m_angle_edit_loc.unsafe_get_y())), + ImGuiCond_Always); // Set a small size (optional) ImGui::SetNextWindowSize(ImVec2(120.0f, 25.0f), ImGuiCond_Once); // Begin a window with minimal flags ImGui::Begin("AngleEdit##unique_id", nullptr, - ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings); ImGui::SetNextItemWidth(100.0f); @@ -827,18 +822,15 @@ void GUI::angle_edit_() m_angle_edit_focus_pending = false; } - const bool text_changed = ImGui::InputText( - "##angle_edit_text", - m_angle_text_buf.data(), - m_angle_text_buf.size(), - ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific); + const bool text_changed = ImGui::InputText("##angle_edit_text", m_angle_text_buf.data(), m_angle_text_buf.size(), + ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific); if (text_changed && parse_dist_text_to_float_(m_angle_text_buf.data(), m_angle_val)) m_angle_callback(m_angle_val, false); if (ImGui::IsItemDeactivatedAfterEdit() && m_angle_callback) { - float parsed {}; + float parsed{}; if (parse_dist_text_to_float_(m_angle_text_buf.data(), parsed)) m_angle_val = parsed; @@ -879,7 +871,8 @@ bool GUI::is_valid_project_json_(const std::string& s) { const nlohmann::json j = nlohmann::json::parse(s); return j.contains("sketches") && j["sketches"].is_array(); - } catch (...) + } + catch (...) { return false; } @@ -901,7 +894,8 @@ void GUI::sketch_list_inspector_(Sketch& sketch, int index) ImGui::Indent(); ImGui::PushID(index); - const auto draw_section = [](const char* title, const std::vector& labels) { + const auto draw_section = [](const char* title, const std::vector& labels) + { const size_t count = labels.size(); ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_SpanAvailWidth; if (count == 0) @@ -925,8 +919,7 @@ void GUI::sketch_list_inspector_(Sketch& sketch, int index) if (ImGui::TreeNodeEx("Dimensions", flags, "Dimensions (%zu)", count)) { - if (count > 0 && ImGui::BeginTable("sketch_dim_rows", 3, - ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingStretchProp)) + if (count > 0 && ImGui::BeginTable("sketch_dim_rows", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingStretchProp)) { ImGui::TableSetupColumn("show", ImGuiTableColumnFlags_WidthFixed, 28.f); ImGui::TableSetupColumn("dim", ImGuiTableColumnFlags_WidthStretch); @@ -988,8 +981,7 @@ void GUI::sketch_list_() { EZY_ASSERT(s); const std::string& nm = s->get_name(); - max_name_text_w = - std::max(max_name_text_w, ImGui::CalcTextSize(nm.c_str(), nm.c_str() + nm.size()).x); + max_name_text_w = std::max(max_name_text_w, ImGui::CalcTextSize(nm.c_str(), nm.c_str() + nm.size()).x); } if (!ImGui::Begin("Sketch List", &m_show_sketch_list, ImGuiWindowFlags_None)) @@ -1012,7 +1004,7 @@ void GUI::sketch_list_() #pragma warning(disable : 4996) char name_buffer[1024]; strncpy(name_buffer, sketch->get_name().c_str(), sizeof(name_buffer) - 1); - name_buffer[sizeof(name_buffer) - 1] = '\0'; // Ensure null-terminated + name_buffer[sizeof(name_buffer) - 1] = '\0'; // Ensure null-terminated #pragma warning(pop) // Unique ID suffix using index @@ -1076,7 +1068,7 @@ void GUI::sketch_list_() ImGui::PushID(("uldisp" + id_suffix).c_str()); { const bool has_ul = sketch->has_underlay(); - bool dummy_off {false}; + bool dummy_off{false}; bool ul_vis = has_ul && sketch->underlay_visible(); if (!has_ul) ImGui::BeginDisabled(); @@ -1093,8 +1085,7 @@ void GUI::sketch_list_() ImGui::EndDisabled(); if (m_show_tool_tips && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) - ImGui::SetTooltip( - has_ul ? "Display underlay" : "Import an image in Sketch properties to enable the underlay."); + ImGui::SetTooltip(has_ul ? "Display underlay" : "Import an image in Sketch properties to enable the underlay."); } ImGui::PopID(); @@ -1133,13 +1124,7 @@ void GUI::sketch_underlay_import_dialog_() { #ifndef __EMSCRIPTEN__ char const* filter_patterns[4] = {"*.png", "*.jpg", "*.jpeg", "*.bmp"}; - char const* selected = tinyfd_openFileDialog( - "Sketch underlay image", - "", - 4, - filter_patterns, - "PNG / JPEG / BMP", - 0); + char const* selected = tinyfd_openFileDialog("Sketch underlay image", "", 4, filter_patterns, "PNG / JPEG / BMP", 0); if (selected) { std::ifstream file(selected, std::ios::binary); @@ -1149,7 +1134,7 @@ void GUI::sketch_underlay_import_dialog_() return; } - const std::string file_bytes {std::istreambuf_iterator(file), std::istreambuf_iterator()}; + const std::string file_bytes{std::istreambuf_iterator(file), std::istreambuf_iterator()}; if (!file_bytes.empty()) on_sketch_underlay_file(selected, file_bytes); else @@ -1215,8 +1200,8 @@ void GUI::sketch_underlay_panel_settings_(const Sketch::sptr& sk) m_underlay_panel_sketch = sk.get(); if (sk->has_underlay()) { - sk->underlay_ui_params( - m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, m_underlay_rot); + sk->underlay_ui_params(m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, + m_underlay_rot); m_underlay_opacity = sk->underlay_opacity(); m_underlay_vis = sk->underlay_visible(); m_underlay_key_white = sk->underlay_key_white_transparent(); @@ -1229,7 +1214,8 @@ void GUI::sketch_underlay_panel_settings_(const Sketch::sptr& sk) m_underlay_tint_col[2] = static_cast(tb) / 255.f; m_underlay_tint_col[3] = static_cast(ta) / 255.f; } - } else + } + else { m_underlay_center = glm::dvec2(0.0, 0.0); m_underlay_half_extents = glm::dvec2(0.0, 0.0); @@ -1271,9 +1257,8 @@ void GUI::sketch_underlay_panel_settings_(const Sketch::sptr& sk) { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextDisabled( - "Import PNG/JPEG/BMP as a sketch underlay. Adjust half-width, half-height, center, and rotation " - "to match real dimensions; changes apply in real time."); + ImGui::TextDisabled("Import PNG/JPEG/BMP as a sketch underlay. Adjust half-width, half-height, center, and rotation " + "to match real dimensions; changes apply in real time."); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } @@ -1285,28 +1270,26 @@ void GUI::sketch_underlay_panel_settings_(const Sketch::sptr& sk) sk->underlay_set_key_white_transparent(m_underlay_key_white); if (m_show_tool_tips && ImGui::IsItemHovered()) - ImGui::SetTooltip( - "Uses brightness: white background becomes clear; dark lines stay visible. " - "Turn off for full-color photos. Inverting the image is not needed for typical scans."); + ImGui::SetTooltip("Uses brightness: white background becomes clear; dark lines stay visible. " + "Turn off for full-color photos. Inverting the image is not needed for typical scans."); if (ImGui::Checkbox("Tint visible lines", &m_underlay_line_tint)) sk->underlay_set_line_tint_enabled(m_underlay_line_tint); if (m_show_tool_tips && ImGui::IsItemHovered()) - ImGui::SetTooltip( - "Paints non-transparent pixels (after white key) with the line color. " - "Default yellow reads well on dark backgrounds."); + ImGui::SetTooltip("Paints non-transparent pixels (after white key) with the line color. " + "Default yellow reads well on dark backgrounds."); if (m_underlay_line_tint) if (ImGui::ColorEdit4("Line color", &m_underlay_tint_col[0])) { - const auto to_u8 = [](float c) -> uint8_t { + const auto to_u8 = [](float c) -> uint8_t + { const float x = std::clamp(c, 0.f, 1.f) * 255.f; return static_cast(x + 0.5f); }; - sk->underlay_set_line_tint_rgba( - to_u8(m_underlay_tint_col[0]), to_u8(m_underlay_tint_col[1]), to_u8(m_underlay_tint_col[2]), - to_u8(m_underlay_tint_col[3])); + sk->underlay_set_line_tint_rgba(to_u8(m_underlay_tint_col[0]), to_u8(m_underlay_tint_col[1]), + to_u8(m_underlay_tint_col[2]), to_u8(m_underlay_tint_col[3])); } if (ImGui::SliderFloat("Opacity", &m_underlay_opacity, 0.f, 1.f, "%.2f")) @@ -1336,34 +1319,33 @@ void GUI::sketch_underlay_panel_settings_(const Sketch::sptr& sk) const char* hint = ""; switch (m_underlay_calib_phase) { - case Underlay_calib_phase::PickX1: - hint = "First click: bitmap corner (0,0) in the current underlay transform (sliders / rotation)."; - break; - case Underlay_calib_phase::PickX2: - hint = "Second click: along bitmap +U from that corner; calibration refines scale from this placement."; - break; - case Underlay_calib_phase::AwaitDistX: - hint = - "Enter the drawing distance for X (dimension popup). If Y is not calibrated yet, its scale still follows " - "image aspect."; - break; - case Underlay_calib_phase::PickY1: - hint = "First click: along bitmap height (+V) using the current underlay transform."; - break; - case Underlay_calib_phase::PickY2: - hint = "Second click: farther along +V; calibration refines Y from this placement."; - break; - case Underlay_calib_phase::AwaitDistY: - hint = "Enter the drawing distance for Y (dimension popup)."; - break; - case Underlay_calib_phase::PickDatumO: - hint = "Datum: first click places bitmap corner (0,0) on the sketch plane (underlay origin)."; - break; - case Underlay_calib_phase::PickDatumU: - hint = "Datum: second click sets direction along bitmap +U from that origin; half width and height are kept."; - break; - default: - break; + case Underlay_calib_phase::PickX1: + hint = "First click: bitmap corner (0,0) in the current underlay transform (sliders / rotation)."; + break; + case Underlay_calib_phase::PickX2: + hint = "Second click: along bitmap +U from that corner; calibration refines scale from this placement."; + break; + case Underlay_calib_phase::AwaitDistX: + hint = "Enter the drawing distance for X (dimension popup). If Y is not calibrated yet, its scale still follows " + "image aspect."; + break; + case Underlay_calib_phase::PickY1: + hint = "First click: along bitmap height (+V) using the current underlay transform."; + break; + case Underlay_calib_phase::PickY2: + hint = "Second click: farther along +V; calibration refines Y from this placement."; + break; + case Underlay_calib_phase::AwaitDistY: + hint = "Enter the drawing distance for Y (dimension popup)."; + break; + case Underlay_calib_phase::PickDatumO: + hint = "Datum: first click places bitmap corner (0,0) on the sketch plane (underlay origin)."; + break; + case Underlay_calib_phase::PickDatumU: + hint = "Datum: second click sets direction along bitmap +U from that origin; half width and height are kept."; + break; + default: + break; } ImGui::TextColored(ImVec4(1.0f, 0.82f, 0.25f, 1.0f), "%s", hint); } @@ -1374,9 +1356,8 @@ void GUI::sketch_underlay_panel_settings_(const Sketch::sptr& sk) ImGui::EndDisabled(); if (m_show_tool_tips && ImGui::IsItemHovered()) - ImGui::SetTooltip( - "Two clicks along width (+U), then type the real drawing distance (same units as sketch dimensions). " - "You can use Set Y before or after; until both are set, the other axis still follows default aspect."); + ImGui::SetTooltip("Two clicks along width (+U), then type the real drawing distance (same units as sketch dimensions). " + "You can use Set Y before or after; until both are set, the other axis still follows default aspect."); ImGui::SameLine(); ImGui::BeginDisabled(!sk_is_cur || pick_x || pick_datum); @@ -1394,9 +1375,8 @@ void GUI::sketch_underlay_panel_settings_(const Sketch::sptr& sk) ImGui::EndDisabled(); if (m_show_tool_tips && ImGui::IsItemHovered()) - ImGui::SetTooltip( - "Two picks on the sketch plane: first sets bitmap corner (0,0); second sets the +U axis direction. " - "Keeps current half width and height; aligns the image to your sketch datum."); + ImGui::SetTooltip("Two picks on the sketch plane: first sets bitmap corner (0,0); second sets the +U axis direction. " + "Keeps current half width and height; aligns the image to your sketch datum."); } ImGui::Separator(); @@ -1410,9 +1390,8 @@ void GUI::sketch_underlay_panel_settings_(const Sketch::sptr& sk) const ImGuiIO& io = ImGui::GetIO(); double min_u = 0., min_v = 0., max_u = 1., max_v = 1.; - const bool have_view = - m_view->sketch_plane_view_aabb_2d(sk->get_plane(), static_cast(io.DisplaySize.x), - static_cast(io.DisplaySize.y), min_u, min_v, max_u, max_v); + const bool have_view = m_view->sketch_plane_view_aabb_2d(sk->get_plane(), static_cast(io.DisplaySize.x), + static_cast(io.DisplaySize.y), min_u, min_v, max_u, max_v); if (!have_view) { constexpr double k_fallback = 250.0; @@ -1423,28 +1402,29 @@ void GUI::sketch_underlay_panel_settings_(const Sketch::sptr& sk) max_v = m_underlay_center.y + k_fallback; } - const double span_u = std::max(max_u - min_u, 1e-6); - const double span_v = std::max(max_v - min_v, 1e-6); - const double half_span_u = 0.5 * span_u; - const double half_span_v = 0.5 * span_v; + const double span_u = std::max(max_u - min_u, 1e-6); + const double span_v = std::max(max_v - min_v, 1e-6); + const double half_span_u = 0.5 * span_u; + const double half_span_v = 0.5 * span_v; // Allow underlay larger than the visible frustum (trace paper / zoomed views). - const double max_half_w = std::max(std::hypot(half_span_u, half_span_v) * 2.5, 1e-3); - const double max_half_h = max_half_w; - constexpr double k_min_half = 1e-6; - double rot_min = -180.0; - double rot_max = 180.0; + const double max_half_w = std::max(std::hypot(half_span_u, half_span_v) * 2.5, 1e-3); + const double max_half_h = max_half_w; + constexpr double k_min_half = 1e-6; + double rot_min = -180.0; + double rot_max = 180.0; - auto apply_ul_xform = [&]() { + auto apply_ul_xform = [&]() + { if (!sk->underlay_axes_orthogonal()) return; - sk->underlay_set_center_extents_rotation( - dvec2(m_underlay_center.x, m_underlay_center.y), - dvec2(m_underlay_half_extents.x, m_underlay_half_extents.y), m_underlay_rot); + sk->underlay_set_center_extents_rotation(dvec2(m_underlay_center.x, m_underlay_center.y), + dvec2(m_underlay_half_extents.x, m_underlay_half_extents.y), m_underlay_rot); }; - auto transform_slider = [&](const char* label, ImGuiDataType type, void* p_data, const void* p_min, - const void* p_max, const char* format, ImGuiSliderFlags flags = 0) { + auto transform_slider = [&](const char* label, ImGuiDataType type, void* p_data, const void* p_min, const void* p_max, + const char* format, ImGuiSliderFlags flags = 0) + { const bool changed = ImGui::SliderScalar(label, type, p_data, p_min, p_max, format, flags); if (ImGui::IsItemActivated()) m_view->push_undo_snapshot(); @@ -1453,8 +1433,8 @@ void GUI::sketch_underlay_panel_settings_(const Sketch::sptr& sk) apply_ul_xform(); }; - auto transform_input_double = [&](const char* label, double* p_data, double v_min, double v_max, - const char* format) { + auto transform_input_double = [&](const char* label, double* p_data, double v_min, double v_max, const char* format) + { const bool changed = ImGui::InputDouble(label, p_data, 0.0, 0.0, format); if (ImGui::IsItemActivated()) m_view->push_undo_snapshot(); @@ -1468,15 +1448,13 @@ void GUI::sketch_underlay_panel_settings_(const Sketch::sptr& sk) ImGui::BeginDisabled(!ul_ortho); // Labels match typical sketch axes on screen: "Center X" drives plane Y (gp_Pnt2d::Y / view v), "Center Y" plane X (u). - transform_slider( - "Center X", ImGuiDataType_Double, &m_underlay_center.y, &min_v, &max_v, "%.4f", ImGuiSliderFlags_ClampOnInput); - transform_slider( - "Center Y", ImGuiDataType_Double, &m_underlay_center.x, &min_u, &max_u, "%.4f", ImGuiSliderFlags_ClampOnInput); - transform_slider( - "Half width", ImGuiDataType_Double, &m_underlay_half_extents.x, &k_min_half, &max_half_w, "%.4f", + transform_slider("Center X", ImGuiDataType_Double, &m_underlay_center.y, &min_v, &max_v, "%.4f", + ImGuiSliderFlags_ClampOnInput); + transform_slider("Center Y", ImGuiDataType_Double, &m_underlay_center.x, &min_u, &max_u, "%.4f", + ImGuiSliderFlags_ClampOnInput); + transform_slider("Half width", ImGuiDataType_Double, &m_underlay_half_extents.x, &k_min_half, &max_half_w, "%.4f", ImGuiSliderFlags_ClampOnInput | ImGuiSliderFlags_Logarithmic); - transform_slider("Half height", ImGuiDataType_Double, &m_underlay_half_extents.y, &k_min_half, &max_half_h, - "%.4f", + transform_slider("Half height", ImGuiDataType_Double, &m_underlay_half_extents.y, &k_min_half, &max_half_h, "%.4f", ImGuiSliderFlags_ClampOnInput | ImGuiSliderFlags_Logarithmic); transform_slider("Rotation (deg)", ImGuiDataType_Double, &m_underlay_rot, &rot_min, &rot_max, "%.1f", ImGuiSliderFlags_ClampOnInput); @@ -1505,12 +1483,11 @@ void GUI::begin_underlay_calib_set_x_(const Sketch::sptr& sk) } cancel_underlay_calib_(); - sk->underlay_ui_params( - m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, m_underlay_rot); + sk->underlay_ui_params(m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, + m_underlay_rot); m_underlay_calib_sketch_wk = sk; m_underlay_calib_phase = Underlay_calib_phase::PickX1; - show_message( - "Underlay X: uses the current transform. Click bitmap corner (0,0), then along +U; then enter the distance."); + show_message("Underlay X: uses the current transform. Click bitmap corner (0,0), then along +U; then enter the distance."); } void GUI::begin_underlay_calib_set_y_(const Sketch::sptr& sk) { @@ -1524,12 +1501,11 @@ void GUI::begin_underlay_calib_set_y_(const Sketch::sptr& sk) } cancel_underlay_calib_(); - sk->underlay_ui_params( - m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, m_underlay_rot); + sk->underlay_ui_params(m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, + m_underlay_rot); m_underlay_calib_sketch_wk = sk; m_underlay_calib_phase = Underlay_calib_phase::PickY1; - show_message( - "Underlay Y: uses the current transform. Click two points along +V; then enter the drawing distance."); + show_message("Underlay Y: uses the current transform. Click two points along +V; then enter the drawing distance."); } void GUI::begin_underlay_calib_define_datum_(const Sketch::sptr& sk) { @@ -1543,8 +1519,8 @@ void GUI::begin_underlay_calib_define_datum_(const Sketch::sptr& sk) } cancel_underlay_calib_(); - sk->underlay_ui_params( - m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, m_underlay_rot); + sk->underlay_ui_params(m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, + m_underlay_rot); m_underlay_calib_sketch_wk = sk; m_underlay_calib_phase = Underlay_calib_phase::PickDatumO; show_message("Datum: click where bitmap corner (0,0) should lie on the sketch plane."); @@ -1557,7 +1533,8 @@ void GUI::underlay_calib_prompt_x_distance_(const Sketch::sptr& sk) const ScreenCoords spos(dvec2(ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y)); Sketch::wptr wk = sk; - auto on_dist = [this, wk](float new_dist, bool is_final) { + auto on_dist = [this, wk](float new_dist, bool is_final) + { if (!is_final) return; @@ -1588,15 +1565,14 @@ void GUI::underlay_calib_prompt_x_distance_(const Sketch::sptr& sk) } m_underlay_calib_axis_u = s->underlay_axis_u_vec(); - s->underlay_ui_params( - m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, m_underlay_rot); + s->underlay_ui_params(m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, + m_underlay_rot); m_underlay_panel_sketch = nullptr; m_dist_callback = nullptr; m_underlay_calib_phase = Underlay_calib_phase::None; - show_message( - "X distance applied to the picked segment. Use Set Y from edge for the vertical span if needed, or adjust " - "transforms."); + show_message("X distance applied to the picked segment. Use Set Y from edge for the vertical span if needed, or adjust " + "transforms."); }; set_dist_edit(dist_show, std::move(on_dist), spos); @@ -1609,7 +1585,8 @@ void GUI::underlay_calib_prompt_y_distance_(const Sketch::sptr& sk) const ScreenCoords spos(dvec2(ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y)); Sketch::wptr wk = sk; - auto on_dist = [this, wk](float new_dist, bool is_final) { + auto on_dist = [this, wk](float new_dist, bool is_final) + { if (!is_final) return; @@ -1635,20 +1612,19 @@ void GUI::underlay_calib_prompt_y_distance_(const Sketch::sptr& sk) if (!s->underlay_rescale_v_chord_to_length(m_underlay_calib_y0, m_underlay_calib_y1, Dy)) { m_view->pop_undo_snapshot(); - show_message( - "Set Y: picks need a clear span along image height (not along the same edge as X only). Try two points further apart in V."); + show_message("Set Y: picks need a clear span along image height (not along the same edge as X only). Try two points " + "further apart in V."); return; } - s->underlay_ui_params( - m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, m_underlay_rot); + s->underlay_ui_params(m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, + m_underlay_rot); m_underlay_panel_sketch = nullptr; m_dist_callback = nullptr; cancel_underlay_calib_(); - show_message( - "Y distance applied to the picked segment. Use Set X from edge for the horizontal span if needed, or adjust " - "transforms."); + show_message("Y distance applied to the picked segment. Use Set X from edge for the horizontal span if needed, or adjust " + "transforms."); }; set_dist_edit(dist_show, std::move(on_dist), spos); @@ -1658,8 +1634,7 @@ bool GUI::try_underlay_calib_click_(const ScreenCoords& screen_coords) if (m_underlay_calib_phase == Underlay_calib_phase::None) return false; - if (m_underlay_calib_phase == Underlay_calib_phase::AwaitDistX || - m_underlay_calib_phase == Underlay_calib_phase::AwaitDistY) + if (m_underlay_calib_phase == Underlay_calib_phase::AwaitDistX || m_underlay_calib_phase == Underlay_calib_phase::AwaitDistY) return true; const Sketch::sptr sk = m_underlay_calib_sketch_wk.lock(); @@ -1681,7 +1656,8 @@ bool GUI::try_underlay_calib_click_(const ScreenCoords& screen_coords) if (!pt) return true; - auto too_short = [](const gp_Pnt2d& a, const gp_Pnt2d& b) { + auto too_short = [](const gp_Pnt2d& a, const gp_Pnt2d& b) + { const double dx = b.X() - a.X(); const double dy = b.Y() - a.Y(); return dx * dx + dy * dy <= 1e-16; @@ -1689,73 +1665,73 @@ bool GUI::try_underlay_calib_click_(const ScreenCoords& screen_coords) switch (m_underlay_calib_phase) { - case Underlay_calib_phase::PickX1: - m_underlay_calib_x0 = *pt; - m_underlay_calib_phase = Underlay_calib_phase::PickX2; - show_message("Underlay X: click second point (end of width / +U)."); - return true; - - case Underlay_calib_phase::PickX2: - if (too_short(m_underlay_calib_x0, *pt)) - { - show_message("X segment too short."); - return true; - } + case Underlay_calib_phase::PickX1: + m_underlay_calib_x0 = *pt; + m_underlay_calib_phase = Underlay_calib_phase::PickX2; + show_message("Underlay X: click second point (end of width / +U)."); + return true; - m_underlay_calib_x1 = *pt; - show_message("Enter drawing distance for X (same unit convention as sketch edge dimensions)."); - underlay_calib_prompt_x_distance_(sk); + case Underlay_calib_phase::PickX2: + if (too_short(m_underlay_calib_x0, *pt)) + { + show_message("X segment too short."); return true; + } - case Underlay_calib_phase::PickY1: - m_underlay_calib_y0 = *pt; - m_underlay_calib_phase = Underlay_calib_phase::PickY2; - show_message("Underlay Y: click second point (end of height / +V)."); - return true; + m_underlay_calib_x1 = *pt; + show_message("Enter drawing distance for X (same unit convention as sketch edge dimensions)."); + underlay_calib_prompt_x_distance_(sk); + return true; - case Underlay_calib_phase::PickY2: - if (too_short(m_underlay_calib_y0, *pt)) - { - show_message("Y segment too short."); - return true; - } + case Underlay_calib_phase::PickY1: + m_underlay_calib_y0 = *pt; + m_underlay_calib_phase = Underlay_calib_phase::PickY2; + show_message("Underlay Y: click second point (end of height / +V)."); + return true; - m_underlay_calib_y1 = *pt; - show_message("Enter drawing distance for Y."); - underlay_calib_prompt_y_distance_(sk); + case Underlay_calib_phase::PickY2: + if (too_short(m_underlay_calib_y0, *pt)) + { + show_message("Y segment too short."); return true; + } - case Underlay_calib_phase::PickDatumO: - m_underlay_calib_datum_o = *pt; - m_underlay_calib_phase = Underlay_calib_phase::PickDatumU; - show_message("Datum: click a second point along bitmap +U from that origin (direction only)."); - return true; + m_underlay_calib_y1 = *pt; + show_message("Enter drawing distance for Y."); + underlay_calib_prompt_y_distance_(sk); + return true; - case Underlay_calib_phase::PickDatumU: - if (too_short(m_underlay_calib_datum_o, *pt)) - { - show_message("Datum direction segment too short."); - return true; - } + case Underlay_calib_phase::PickDatumO: + m_underlay_calib_datum_o = *pt; + m_underlay_calib_phase = Underlay_calib_phase::PickDatumU; + show_message("Datum: click a second point along bitmap +U from that origin (direction only)."); + return true; - m_view->push_undo_snapshot(); - if (!sk->underlay_set_datum_origin_and_u_direction(m_underlay_calib_datum_o, *pt)) - { - m_view->pop_undo_snapshot(); - show_message("Could not set underlay datum (degenerate direction or axes)."); - cancel_underlay_calib_(); - return true; - } + case Underlay_calib_phase::PickDatumU: + if (too_short(m_underlay_calib_datum_o, *pt)) + { + show_message("Datum direction segment too short."); + return true; + } - sk->underlay_ui_params( - m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, m_underlay_rot); - m_underlay_panel_sketch = nullptr; + m_view->push_undo_snapshot(); + if (!sk->underlay_set_datum_origin_and_u_direction(m_underlay_calib_datum_o, *pt)) + { + m_view->pop_undo_snapshot(); + show_message("Could not set underlay datum (degenerate direction or axes)."); cancel_underlay_calib_(); - show_message("Underlay datum set: origin at (0,0) and +U direction; half sizes unchanged."); return true; + } - default: - return false; + sk->underlay_ui_params(m_underlay_center.x, m_underlay_center.y, m_underlay_half_extents.x, m_underlay_half_extents.y, + m_underlay_rot); + m_underlay_panel_sketch = nullptr; + cancel_underlay_calib_(); + show_message("Underlay datum set: origin at (0,0) and +U direction; half sizes unchanged."); + return true; + + default: + return false; } } void GUI::shape_list_() @@ -1768,8 +1744,7 @@ void GUI::shape_list_() { EZY_ASSERT(s); const std::string& nm = s->get_name(); - max_name_text_w = - std::max(max_name_text_w, ImGui::CalcTextSize(nm.c_str(), nm.c_str() + nm.size()).x); + max_name_text_w = std::max(max_name_text_w, ImGui::CalcTextSize(nm.c_str(), nm.c_str() + nm.size()).x); } if (!ImGui::Begin("Shape List", &m_show_shape_list, ImGuiWindowFlags_None)) @@ -1795,14 +1770,11 @@ void GUI::shape_list_() const int nmat = static_cast(mat_names.size()); float mat_label_w_max = 0.0f; for (int mi = 0; mi < nmat; ++mi) - mat_label_w_max = - std::max(mat_label_w_max, ImGui::CalcTextSize(mat_names[static_cast(mi)].c_str()).x); + mat_label_w_max = std::max(mat_label_w_max, ImGui::CalcTextSize(mat_names[static_cast(mi)].c_str()).x); const ImGuiStyle& st_mat = ImGui::GetStyle(); - const float mat_popup_w = std::min( - 440.0f, - std::max(280.0f, - mat_label_w_max + st_mat.WindowPadding.x * 2.0f + st_mat.FramePadding.x * 2.0f + st_mat.ScrollbarSize + 8.0f)); + const float mat_popup_w = std::min(440.0f, std::max(280.0f, mat_label_w_max + st_mat.WindowPadding.x * 2.0f + + st_mat.FramePadding.x * 2.0f + st_mat.ScrollbarSize + 8.0f)); std::unordered_set selected_in_viewer; for (const AIS_Shape_ptr& ais : m_view->get_selected()) @@ -1816,25 +1788,21 @@ void GUI::shape_list_() if (row_selected) { const ImVec4 header = ImGui::GetStyleColorVec4(ImGuiCol_Header); - ImGui::PushStyleColor(ImGuiCol_FrameBg, - ImVec4(header.x, header.y, header.z, 0.40f)); - ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, - ImVec4(header.x, header.y, header.z, 0.55f)); - ImGui::PushStyleColor(ImGuiCol_FrameBgActive, - ImVec4(header.x, header.y, header.z, 0.65f)); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(header.x, header.y, header.z, 0.40f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(header.x, header.y, header.z, 0.55f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(header.x, header.y, header.z, 0.65f)); const ImVec4 text = ImGui::GetStyleColorVec4(ImGuiCol_Text); // Shape List: when a row matches OCCT selection, ImGuiCol_Text is nudged brighter (RGB only). - constexpr float k_shape_list_selected_text_rgb_scale = - 1.08f; // per-channel multiplier for a modest relative lift + constexpr float k_shape_list_selected_text_rgb_scale = 1.08f; // per-channel multiplier for a modest relative lift constexpr float k_shape_list_selected_text_rgb_bias = - 0.04f; // added after scaling so very dark text still reads a bit lighter + 0.04f; // added after scaling so very dark text still reads a bit lighter - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4( - std::min(1.0f, text.x * k_shape_list_selected_text_rgb_scale + k_shape_list_selected_text_rgb_bias), - std::min(1.0f, text.y * k_shape_list_selected_text_rgb_scale + k_shape_list_selected_text_rgb_bias), - std::min(1.0f, text.z * k_shape_list_selected_text_rgb_scale + k_shape_list_selected_text_rgb_bias), - text.w)); + ImGui::PushStyleColor( + ImGuiCol_Text, + ImVec4(std::min(1.0f, text.x * k_shape_list_selected_text_rgb_scale + k_shape_list_selected_text_rgb_bias), + std::min(1.0f, text.y * k_shape_list_selected_text_rgb_scale + k_shape_list_selected_text_rgb_bias), + std::min(1.0f, text.z * k_shape_list_selected_text_rgb_scale + k_shape_list_selected_text_rgb_bias), text.w)); ImGui::BeginGroup(); } @@ -1845,14 +1813,15 @@ void GUI::shape_list_() #pragma warning(disable : 4996) char name_buffer[1024]; strncpy(name_buffer, shape->get_name().c_str(), sizeof(name_buffer) - 1); - name_buffer[sizeof(name_buffer) - 1] = '\0'; // Ensure null-terminated + name_buffer[sizeof(name_buffer) - 1] = '\0'; // Ensure null-terminated #pragma warning(pop) int mat_idx = shape->Material(); if (mat_idx < 0 || mat_idx >= nmat) mat_idx = static_cast(m_view->get_default_material().Name()); - auto apply_shape_material = [&](int i) { + auto apply_shape_material = [&](int i) + { if (i < 0 || i >= nmat) return; @@ -1905,8 +1874,7 @@ void GUI::shape_list_() ImGui::SameLine(); ImGui::PushID(("matbtn" + id_suffix).c_str()); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, - ImVec2(4.0f, ImGui::GetStyle().FramePadding.y)); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4.0f, ImGui::GetStyle().FramePadding.y)); if (ImGui::Button("M")) ImGui::OpenPopup("mat_pick"); @@ -1921,8 +1889,7 @@ void GUI::shape_list_() ImGui::Separator(); const float max_h = ImGui::GetTextLineHeightWithSpacing() * 12.0f; const float sc_w = std::max(1.0f, ImGui::GetContentRegionAvail().x); - if (ImGui::BeginChild("mat_sc", ImVec2(sc_w, max_h), ImGuiChildFlags_Borders, - ImGuiWindowFlags_AlwaysVerticalScrollbar)) + if (ImGui::BeginChild("mat_sc", ImVec2(sc_w, max_h), ImGuiChildFlags_Borders, ImGuiWindowFlags_AlwaysVerticalScrollbar)) { for (int i = 0; i < nmat; ++i) if (ImGui::Selectable(mat_names[static_cast(i)].c_str(), i == mat_idx)) @@ -1961,7 +1928,7 @@ void GUI::shape_list_() } float GUI::list_name_field_width_(const ImGuiStyle& st, const float max_name_text_w) { - constexpr float k_name_field_cap = 480.f; + constexpr float k_name_field_cap = 480.f; // Keep names editable even when all names are short. constexpr float k_name_field_floor = 72.f; const float name_pad_x = st.FramePadding.x * 2.0f; @@ -1979,9 +1946,7 @@ void GUI::dbg_() return; } // Undo / redo stack - ImGui::Text("Undo: %zu (Ctrl+Z) | Redo: %zu (Ctrl+Y) [max 50]", - m_view->undo_stack_size(), - m_view->redo_stack_size()); + ImGui::Text("Undo: %zu (Ctrl+Z) | Redo: %zu (Ctrl+Y) [max 50]", m_view->undo_stack_size(), m_view->redo_stack_size()); ImGui::Separator(); // Get the available content region width float available_width = ImGui::GetContentRegionAvail().x; @@ -2015,7 +1980,7 @@ void GUI::message_status_window_() // Check if 3 seconds have passed auto now = std::chrono::steady_clock::now(); auto elapsed = std::chrono::duration_cast(now - m_message_start_time).count(); - if (elapsed > 3000) // 3 seconds + if (elapsed > 3000) // 3 seconds { m_message_visible = false; m_message.clear(); @@ -2024,23 +1989,19 @@ void GUI::message_status_window_() // Calculate fade effect (optional, for visual polish) float alpha = 1.0f; - if (elapsed > 2500) // Start fading after 2.5 seconds - alpha = 1.0f - (elapsed - 2500.0f) / 500.0f; // Fade over last 0.5 seconds + if (elapsed > 2500) // Start fading after 2.5 seconds + alpha = 1.0f - (elapsed - 2500.0f) / 500.0f; // Fade over last 0.5 seconds // Set window position (bottom-right corner) ImGuiIO& io = ImGui::GetIO(); - ImVec2 window_pos(io.DisplaySize.x - 250.0f, io.DisplaySize.y - 50.0f); // Adjust as needed + ImVec2 window_pos(io.DisplaySize.x - 250.0f, io.DisplaySize.y - 50.0f); // Adjust as needed ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always); ImGui::SetNextWindowSize(ImVec2(240.0f, 40.0f), ImGuiCond_Once); // Begin window with minimal flags ImGui::Begin("MessageStatus##unique_id", nullptr, - ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_AlwaysAutoResize | - ImGuiWindowFlags_NoSavedSettings | - ImGuiWindowFlags_NoFocusOnAppearing | - ImGuiWindowFlags_NoNav); + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav); // Set text color with alpha for fade effect ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, alpha)); @@ -2054,9 +2015,10 @@ void GUI::log_message(const std::string& message) { if (m_log_buffer.size() > 1) { - m_log_buffer.pop_back(); // trailing '\0' + m_log_buffer.pop_back(); // trailing '\0' m_log_buffer.push_back('\n'); - } else if (!m_log_buffer.empty()) + } + else if (!m_log_buffer.empty()) m_log_buffer.pop_back(); m_log_buffer.insert(m_log_buffer.end(), message.begin(), message.end()); @@ -2112,7 +2074,7 @@ void GUI::init(GLFWwindow* window, ImFont* console_font) m_console_font = console_font; initialize_toolbar_(); settings::set_log_callback([this](const std::string& m) { log_message(m); }); - setup_log_redirection_(); // Set up stream redirection + setup_log_redirection_(); // Set up stream redirection log_message("EzyCad: initializing 3D view..."); m_view->init_window(window); m_view->init_viewer(); @@ -2143,7 +2105,8 @@ void GUI::persist_last_opened_project_path_(const std::string& path) m_last_opened_project_path = p.generic_string(); save_occt_view_settings(); - } catch (...) + } + catch (...) { } #endif @@ -2164,7 +2127,7 @@ void GUI::load_default_project_() std::ifstream file(p, std::ios::binary); if (file.is_open()) { - const std::string json_str {std::istreambuf_iterator(file), std::istreambuf_iterator()}; + const std::string json_str{std::istreambuf_iterator(file), std::istreambuf_iterator()}; if (is_valid_project_json_(json_str)) { log_message("EzyCad: loading last opened project: " + p.string()); @@ -2176,9 +2139,11 @@ void GUI::load_default_project_() log_message("EzyCad: last opened project JSON is invalid; falling back to startup/default."); show_message("Last opened project file is invalid; loading startup/default."); } - } else + } + else log_message("EzyCad: last opened project path not found; falling back to startup/default."); - } catch (...) + } + catch (...) { log_message("EzyCad: could not load last opened project; falling back to startup/default."); } @@ -2204,7 +2169,8 @@ void GUI::load_default_project_() { log_message("EzyCad: saved startup project is invalid or incomplete; falling back to install default."); show_message("Saved startup project is invalid; loading install default."); - } else + } + else log_message("EzyCad: no saved startup project; trying bundled default."); std::ifstream file(k_bundled_default, std::ios::binary); @@ -2214,14 +2180,15 @@ void GUI::load_default_project_() return; } - const std::string json_str {std::istreambuf_iterator(file), std::istreambuf_iterator()}; + const std::string json_str{std::istreambuf_iterator(file), std::istreambuf_iterator()}; if (is_valid_project_json_(json_str)) { log_message("EzyCad: loading bundled default project (" + std::string(k_bundled_default) + ")."); on_file(k_bundled_default, json_str, false); m_last_saved_path.clear(); log_message("EzyCad: startup document loaded (bundled default)."); - } else + } + else log_message("EzyCad: bundled " + std::string(k_bundled_default) + " is invalid; keeping initial empty document."); } std::string GUI::serialized_project_json_() const @@ -2258,31 +2225,31 @@ void GUI::on_mouse_pos(const ScreenCoords& screen_coords) switch (get_mode()) { - case Mode::Move: - if (Status s = m_view->shp_move().move_selected(screen_coords); !s.is_ok()) - show_message(s.message()); + case Mode::Move: + if (Status s = m_view->shp_move().move_selected(screen_coords); !s.is_ok()) + show_message(s.message()); - break; + break; - case Mode::Rotate: - if (Status s = m_view->shp_rotate().rotate_selected(screen_coords); !s.is_ok()) - show_message(s.message()); + case Mode::Rotate: + if (Status s = m_view->shp_rotate().rotate_selected(screen_coords); !s.is_ok()) + show_message(s.message()); - break; + break; - case Mode::Scale: - if (Status s = m_view->shp_scale().scale_selected(screen_coords); !s.is_ok()) - show_message(s.message()); + case Mode::Scale: + if (Status s = m_view->shp_scale().scale_selected(screen_coords); !s.is_ok()) + show_message(s.message()); - break; + break; - case Mode::Shape_polar_duplicate: - if (Status s = m_view->shp_polar_dup().move_point(screen_coords); !s.is_ok()) - show_message(s.message()); + case Mode::Shape_polar_duplicate: + if (Status s = m_view->shp_polar_dup().move_point(screen_coords); !s.is_ok()) + show_message(s.message()); - break; + break; - // clang-format off + // clang-format off case Mode::Sketch_add_node: case Mode::Sketch_add_edge: case Mode::Sketch_add_multi_edges: @@ -2295,9 +2262,9 @@ void GUI::on_mouse_pos(const ScreenCoords& screen_coords) case Mode::Sketch_add_seg_circle_arc: case Mode::Sketch_dim_anno: m_view->curr_sketch().sketch_pt_move(screen_coords); break; case Mode::Sketch_face_extrude: m_view->sketch_face_extrude(screen_coords, true); break; - // clang-format on - default: - break; + // clang-format on + default: + break; } } void GUI::on_mouse_button(int button, int action, int mods) @@ -2320,75 +2287,73 @@ void GUI::on_mouse_button(int button, int action, int mods) if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS && mods == 0) switch (m_mode) { - // clang-format off + // clang-format off case Mode::Move: m_view->shp_move().finalize(); break; case Mode::Rotate: m_view->shp_rotate().finalize(); break; case Mode::Scale: m_view->shp_scale().finalize(); break; case Mode::Sketch_face_extrude: m_view->sketch_face_extrude(screen_coords, false); break; - // clang-format on + // clang-format on - case Mode::Sketch_add_node: - case Mode::Sketch_add_edge: - case Mode::Sketch_add_multi_edges: - case Mode::Sketch_add_seg_circle_arc: - case Mode::Sketch_add_square: - case Mode::Sketch_add_rectangle: - case Mode::Sketch_add_rectangle_center_pt: - case Mode::Sketch_operation_axis: - case Mode::Sketch_add_circle: - case Mode::Sketch_add_slot: - hide_dist_edit(); - m_view->curr_sketch().add_sketch_pt(screen_coords); - break; + case Mode::Sketch_add_node: + case Mode::Sketch_add_edge: + case Mode::Sketch_add_multi_edges: + case Mode::Sketch_add_seg_circle_arc: + case Mode::Sketch_add_square: + case Mode::Sketch_add_rectangle: + case Mode::Sketch_add_rectangle_center_pt: + case Mode::Sketch_operation_axis: + case Mode::Sketch_add_circle: + case Mode::Sketch_add_slot: + hide_dist_edit(); + m_view->curr_sketch().add_sketch_pt(screen_coords); + break; - case Mode::Shape_chamfer: - if (Status s = m_view->shp_chamfer().add_chamfer(screen_coords, m_chamfer_mode); !s.is_ok()) - show_message(s.message()); + case Mode::Shape_chamfer: + if (Status s = m_view->shp_chamfer().add_chamfer(screen_coords, m_chamfer_mode); !s.is_ok()) + show_message(s.message()); - break; + break; - case Mode::Shape_fillet: - if (Status s = m_view->shp_fillet().add_fillet(screen_coords, m_fillet_mode); !s.is_ok()) - show_message(s.message()); + case Mode::Shape_fillet: + if (Status s = m_view->shp_fillet().add_fillet(screen_coords, m_fillet_mode); !s.is_ok()) + show_message(s.message()); - break; + break; - case Mode::Shape_polar_duplicate: - if (Status s = m_view->shp_polar_dup().add_point(screen_coords); !s.is_ok()) - show_message(s.message()); + case Mode::Shape_polar_duplicate: + if (Status s = m_view->shp_polar_dup().add_point(screen_coords); !s.is_ok()) + show_message(s.message()); - break; + break; - default: - break; + default: + break; } else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS && mods == 0) // Right button is to finalize the current operation. switch (m_mode) { - // clang-format off + // clang-format off case Mode::Sketch_add_node: case Mode::Sketch_add_edge: case Mode::Sketch_add_multi_edges: m_view->curr_sketch().finalize_elm(); break; - // clang-format on + // clang-format on - default: - break; + default: + break; } } void GUI::on_mouse_scroll(double xoffset, double yoffset) { EZY_ASSERT(m_glfw_window != nullptr); - const bool shift_finer = glfwGetKey(m_glfw_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS || glfwGetKey(m_glfw_window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS; + const bool shift_finer = glfwGetKey(m_glfw_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS || + glfwGetKey(m_glfw_window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS; m_view->on_mouse_scroll(xoffset, yoffset, shift_finer); } -void GUI::on_resize(int width, int height) -{ - m_view->on_resize(width, height); -} +void GUI::on_resize(int width, int height) { m_view->on_resize(width, height); } void GUI::setup_log_redirection_() { // Store original stream buffers @@ -2431,26 +2396,26 @@ void GUI::export_file_dialog_(Export_format fmt) const char* filter_desc = "STEP files"; switch (fmt) { - case Export_format::Step: - break; - case Export_format::Iges: - title = "Export IGES"; - def_name = "export.igs"; - filter_pat = "*.igs"; - filter_desc = "IGES files"; - break; - case Export_format::Stl: - title = "Export STL"; - def_name = "export.stl"; - filter_pat = "*.stl"; - filter_desc = "STL files"; - break; - case Export_format::Ply: - title = "Export PLY"; - def_name = "export.ply"; - filter_pat = "*.ply"; - filter_desc = "PLY files"; - break; + case Export_format::Step: + break; + case Export_format::Iges: + title = "Export IGES"; + def_name = "export.igs"; + filter_pat = "*.igs"; + filter_desc = "IGES files"; + break; + case Export_format::Stl: + title = "Export STL"; + def_name = "export.stl"; + filter_pat = "*.stl"; + filter_desc = "STL files"; + break; + case Export_format::Ply: + title = "Export PLY"; + def_name = "export.ply"; + filter_pat = "*.ply"; + filter_desc = "PLY files"; + break; } char const* filter_patterns[1] = {filter_pat}; @@ -2468,23 +2433,23 @@ void GUI::export_file_dialog_(Export_format fmt) show_message("Exported: " + std::filesystem::path(selected).filename().string()); #else const char* mem_path = "/ezycad_export.step"; - std::string download_name {"export.step"}; + std::string download_name{"export.step"}; switch (fmt) { - case Export_format::Step: - break; - case Export_format::Iges: - mem_path = "/ezycad_export.igs"; - download_name = "export.igs"; - break; - case Export_format::Stl: - mem_path = "/ezycad_export.stl"; - download_name = "export.stl"; - break; - case Export_format::Ply: - mem_path = "/ezycad_export.ply"; - download_name = "export.ply"; - break; + case Export_format::Step: + break; + case Export_format::Iges: + mem_path = "/ezycad_export.igs"; + download_name = "export.igs"; + break; + case Export_format::Stl: + mem_path = "/ezycad_export.stl"; + download_name = "export.stl"; + break; + case Export_format::Ply: + mem_path = "/ezycad_export.ply"; + download_name = "export.ply"; + break; } const Status s = m_view->export_document(fmt, mem_path); if (!s.is_ok()) @@ -2508,13 +2473,7 @@ void GUI::import_file_dialog_() #ifndef __EMSCRIPTEN__ // Native: Use tinyfiledialogs char const* filter_patterns[3] = {"*.step", "*.stp", "*.ply"}; - char const* selected = tinyfd_openFileDialog( - "Import STEP or PLY", - "", - 3, - filter_patterns, - "STEP / PLY files", - 0); + char const* selected = tinyfd_openFileDialog("Import STEP or PLY", "", 3, filter_patterns, "STEP / PLY files", 0); if (selected) { @@ -2526,7 +2485,7 @@ void GUI::import_file_dialog_() return; } - const std::string file_bytes {std::istreambuf_iterator(file), std::istreambuf_iterator()}; + const std::string file_bytes{std::istreambuf_iterator(file), std::istreambuf_iterator()}; if (!file_bytes.empty()) on_import_file(selected, file_bytes); else @@ -2546,19 +2505,18 @@ void GUI::open_file_dialog_() { #ifndef __EMSCRIPTEN__ // Native: Use tinyfiledialogs - char const* filter_patterns[1] = {"*.ezy"}; // Restrict to .ezy files - char const* selected = tinyfd_openFileDialog( - "Open EzyCad project", // Dialog title - "", // Default path (empty for OS default) - 1, // Number of filter patterns - filter_patterns, // Filter patterns (*.ezy) - "EzyCad Files", // Filter description - 0 // Single file selection - ); + char const* filter_patterns[1] = {"*.ezy"}; // Restrict to .ezy files + char const* selected = tinyfd_openFileDialog("Open EzyCad project", // Dialog title + "", // Default path (empty for OS default) + 1, // Number of filter patterns + filter_patterns, // Filter patterns (*.ezy) + "EzyCad Files", // Filter description + 0 // Single file selection + ); if (selected) { std::ifstream file(selected); - const std::string json_str {std::istreambuf_iterator(file), std::istreambuf_iterator()}; + const std::string json_str{std::istreambuf_iterator(file), std::istreambuf_iterator()}; if (file.good() && json_str != "") on_file(selected, json_str); @@ -2577,16 +2535,15 @@ void GUI::save_file_dialog_() #ifndef __EMSCRIPTEN__ std::string file; if (!m_last_saved_path.empty()) - file = m_last_saved_path; // Reuse last saved path + file = m_last_saved_path; // Reuse last saved path else { char const* filter_patterns[1] = {"*.ezy"}; - char const* selected = tinyfd_saveFileDialog( - "Save EzyCad Project", "project.ezy", 1, filter_patterns, "EzyCad Files"); + char const* selected = tinyfd_saveFileDialog("Save EzyCad Project", "project.ezy", 1, filter_patterns, "EzyCad Files"); if (selected) { file = selected; - m_last_saved_path = file; // Update last saved path + m_last_saved_path = file; // Update last saved path } } if (!file.empty()) @@ -2597,12 +2554,15 @@ void GUI::save_file_dialog_() out.write(json_str.data(), json_str.size()); out.close(); show_message("Saved: " + std::filesystem::path(file).filename().string()); - } else + } + else show_message("Failed to save: " + std::filesystem::path(file).filename().string()); - } else + } + else show_message("Save canceled"); #else - std::string default_file = m_last_saved_path.empty() ? "project.ezy" : std::filesystem::path(m_last_saved_path).filename().string(); + std::string default_file = + m_last_saved_path.empty() ? "project.ezy" : std::filesystem::path(m_last_saved_path).filename().string(); save_file_dialog_async("Save EzyCad project", default_file, json_str); #endif } @@ -2665,14 +2625,14 @@ void GUI::open_file_dialog_async() var reader = new FileReader(); reader.onload = function(e) { - var contents = new Uint8Array(e.target.result); - var fileName = file.name; + var contents = new Uint8Array(e.target.result); + var fileName = file.name; // Allocate heap memory for contents var length = contents.length; var contentsPtr = _malloc(length); HEAPU8.set(contents, contentsPtr); // Call C++ callback with path and contents - Module.ccall('on_file_selected', null, ['string', 'number', 'number'], [fileName, contentsPtr, length]); + Module.ccall('on_file_selected', null, [ 'string', 'number', 'number' ], [ fileName, contentsPtr, length ]); _free(contentsPtr); }; reader.readAsArrayBuffer(file); @@ -2703,7 +2663,7 @@ void GUI::import_file_dialog_async() var length = contents.length; var contentsPtr = _malloc(length); HEAPU8.set(contents, contentsPtr); - Module.ccall('on_import_file_selected', null, ['string', 'number', 'number'], [fileName, contentsPtr, length]); + Module.ccall('on_import_file_selected', null, [ 'string', 'number', 'number' ], [ fileName, contentsPtr, length ]); _free(contentsPtr); }; reader.readAsArrayBuffer(file); @@ -2734,7 +2694,8 @@ void GUI::sketch_underlay_file_dialog_async() var length = contents.length; var contentsPtr = _malloc(length); HEAPU8.set(contents, contentsPtr); - Module.ccall('on_sketch_underlay_selected', null, ['string', 'number', 'number'], [fileName, contentsPtr, length]); + Module.ccall('on_sketch_underlay_selected', null, [ 'string', 'number', 'number' ], + [ fileName, contentsPtr, length ]); _free(contentsPtr); }; reader.readAsArrayBuffer(file); @@ -2746,18 +2707,25 @@ void GUI::sketch_underlay_file_dialog_async() } void GUI::save_file_dialog_async(const char* title, const std::string& default_file, const std::string& json_str) { - EM_ASM_ARGS({ - var data = HEAPU8.subarray($0, $0 + $1); - var blob = new Blob([data], { type: 'application/octet-stream' }); - var url = URL.createObjectURL(blob); - var a = document.createElement('a'); - a.href = url; - a.download = UTF8ToString($2); // Default file name - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - URL.revokeObjectURL(url); - Module.ccall('on_save_file_selected', null, ['string'], [UTF8ToString($2)]); }, json_str.data(), json_str.size(), default_file.c_str()); + EM_ASM_ARGS( + { + var data = HEAPU8.subarray($0, $0 + $1); + var blob = new Blob([data], + { + type: + 'application/octet-stream' + }); + var url = URL.createObjectURL(blob); + var a = document.createElement('a'); + a.href = url; + a.download = UTF8ToString($2); // Default file name + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + Module.ccall('on_save_file_selected', null, ['string'], [UTF8ToString($2)]); + }, + json_str.data(), json_str.size(), default_file.c_str()); } void GUI::note_saved_project_filename(const std::string& filename) { @@ -2766,16 +2734,23 @@ void GUI::note_saved_project_filename(const std::string& filename) } void GUI::download_blob_async(const std::string& default_filename, const std::string& data) { - EM_ASM_ARGS({ - var blob = new Blob([HEAPU8.subarray($0, $0 + $1)], { type: 'application/octet-stream' }); - var url = URL.createObjectURL(blob); - var a = document.createElement('a'); - a.href = url; - a.download = UTF8ToString($2); - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - URL.revokeObjectURL(url); }, data.data(), data.size(), default_filename.c_str()); + EM_ASM_ARGS( + { + var blob = new Blob([HEAPU8.subarray($0, $0 + $1)], + { + type: + 'application/octet-stream' + }); + var url = URL.createObjectURL(blob); + var a = document.createElement('a'); + a.href = url; + a.download = UTF8ToString($2); + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + }, + data.data(), data.size(), default_filename.c_str()); } // C-style callback for Emscripten extern "C" void on_file_selected(const char* file_path, char* contents, int length) diff --git a/src/gui.h b/src/gui.h index 359e1ee..c00c3b4 100644 --- a/src/gui.h +++ b/src/gui.h @@ -1,14 +1,14 @@ #pragma once #include -#include // For message status window (from previous request) +#include // For message status window (from previous request) #include #include #include #include #include #include -#include // Added for log messages +#include // Added for log messages #include #include // #include // Added for log storage @@ -54,20 +54,20 @@ struct Example_file std::string path; }; /// Default OCCT line-width scale for length dimensions when `edge_dim_line_width` is missing from settings JSON. -inline constexpr float k_gui_edge_dim_line_width_default = 1.0f; +inline constexpr float k_gui_edge_dim_line_width_default = 1.0f; /// Default OCCT arrow length for length dimensions when `edge_dim_arrow_size` is missing from settings JSON. -inline constexpr float k_gui_edge_dim_arrow_size_default = 6.0f; +inline constexpr float k_gui_edge_dim_arrow_size_default = 6.0f; /// Allowed range and default for `gui.view_roll_step_deg` (view roll and numpad orbit steps; must match Settings slider). -inline constexpr double k_gui_view_roll_step_deg_min = 0.1; -inline constexpr double k_gui_view_roll_step_deg_max = 180.0; -inline constexpr double k_gui_view_roll_step_deg_default = 45.0; +inline constexpr double k_gui_view_roll_step_deg_min = 0.1; +inline constexpr double k_gui_view_roll_step_deg_max = 180.0; +inline constexpr double k_gui_view_roll_step_deg_default = 45.0; /// Allowed range and default for `gui.view_zoom_scroll_scale` (wheel/keyboard zoom units; must match Settings slider). inline constexpr double k_gui_view_zoom_scroll_scale_min = 0.25; inline constexpr double k_gui_view_zoom_scroll_scale_max = 64.0; inline constexpr double k_gui_view_zoom_scroll_scale_default = 4.0; class GUI { - public: +public: GUI(); ~GUI(); @@ -75,7 +75,7 @@ class GUI static GUI& instance(); #endif - void init(GLFWwindow* window, ImFont* console_font); + void init(GLFWwindow* window, ImFont* console_font); /// Monospace font for script console (normally set via init() from main after io.Fonts load). void set_console_font(ImFont* font) { m_console_font = font; } ImFont* console_font() const; @@ -83,7 +83,7 @@ class GUI void render_gui(); void render_occt(); - void on_key(int key, int scancode, int action, int mods); // gui_mode.cpp + void on_key(int key, int scancode, int action, int mods); // gui_mode.cpp void on_mouse_pos(const ScreenCoords& screen_coords); void on_mouse_button(int button, int action, int mods); void on_mouse_scroll(double xoffset, double yoffset); @@ -92,37 +92,39 @@ class GUI Chamfer_mode get_chamfer_mode() const { return m_chamfer_mode; } Fillet_mode get_fillet_mode() const { return m_fillet_mode; } /// Edge dimension value placement (Options panel, toggle-dimension tool): 0 first point, 1 second, 2 center, 3 auto. - int edge_dim_label_h() const { return m_edge_dim_label_h; } + int edge_dim_label_h() const { return m_edge_dim_label_h; } /// OCCT scale factor for sketch/extrude length dimension lines (1.0 = default thickness). - float edge_dim_line_width() const { return m_edge_dim_line_width; } + float edge_dim_line_width() const { return m_edge_dim_line_width; } /// OCCT arrow length for sketch/extrude length dimensions. - float edge_dim_arrow_size() const { return m_edge_dim_arrow_size; } - bool get_hide_all_shapes() const { return m_hide_all_shapes; } - void set_hide_all_shapes(bool hide) { m_hide_all_shapes = hide; } - bool get_dark_mode() const { return m_dark_mode; } - ImVec4 get_clear_color() const; - void set_mode(Mode mode); // gui_mode.cpp - void set_parent_mode(); // gui_mode.cpp - void set_dist_edit(float dist, std::function&& callback, const std::optional screen_coords = std::nullopt); - void hide_dist_edit(); - void set_angle_edit(float angle, std::function&& callback, const std::optional screen_coords = std::nullopt); - void hide_angle_edit(); + float edge_dim_arrow_size() const { return m_edge_dim_arrow_size; } + bool get_hide_all_shapes() const { return m_hide_all_shapes; } + void set_hide_all_shapes(bool hide) { m_hide_all_shapes = hide; } + bool get_dark_mode() const { return m_dark_mode; } + ImVec4 get_clear_color() const; + void set_mode(Mode mode); // gui_mode.cpp + void set_parent_mode(); // gui_mode.cpp + void set_dist_edit(float dist, std::function&& callback, + const std::optional screen_coords = std::nullopt); + void hide_dist_edit(); + void set_angle_edit(float angle, std::function&& callback, + const std::optional screen_coords = std::nullopt); + void hide_angle_edit(); /// True when dist or angle edit is visible; Tab should be routed to on_key() instead of ImGui. - bool is_dist_or_angle_edit_active() const; - void show_message(const std::string& message); - void log_message(const std::string& message); - void set_show_options(bool v) { m_show_options = v; } - void set_show_sketch_list(bool v) { m_show_sketch_list = v; } - void set_show_shape_list(bool v) { m_show_shape_list = v; } - void set_log_window_visible(bool v) { m_log_window_visible = v; } - void set_show_settings_dialog(bool v) { m_show_settings_dialog = v; } + bool is_dist_or_angle_edit_active() const; + void show_message(const std::string& message); + void log_message(const std::string& message); + void set_show_options(bool v) { m_show_options = v; } + void set_show_sketch_list(bool v) { m_show_sketch_list = v; } + void set_show_shape_list(bool v) { m_show_shape_list = v; } + void set_log_window_visible(bool v) { m_log_window_visible = v; } + void set_show_settings_dialog(bool v) { m_show_settings_dialog = v; } #ifndef NDEBUG void set_show_dbg(bool v) { m_show_dbg = v; } #endif #ifdef __EMSCRIPTEN__ - void open_file_dialog_async(); // Emscripten: hidden ; no custom title (browser UI) - void import_file_dialog_async(); // STEP / PLY import (routes to on_import_file) + void open_file_dialog_async(); // Emscripten: hidden ; no custom title (browser UI) + void import_file_dialog_async(); // STEP / PLY import (routes to on_import_file) void save_file_dialog_async(const char* title, const std::string& default_file, const std::string& json_str); void download_blob_async(const std::string& default_filename, const std::string& data); /// After browser download save, remember basename for window title and Save-as default. @@ -141,14 +143,11 @@ class GUI [[nodiscard]] std::string occt_view_settings_json() const; /// Default RGBA (0-255) for sketch underlay line tint when importing a new image (see Settings). - void underlay_highlight_color_rgba(uint8_t& r, uint8_t& g, uint8_t& b, uint8_t& a) const; + void underlay_highlight_color_rgba(uint8_t& r, uint8_t& g, uint8_t& b, uint8_t& a) const; /// For scripting (Lua console): access the 3D view. - Occt_view* get_view() - { - return m_view.get(); - } + Occt_view* get_view() { return m_view.get(); } - private: +private: friend class GUI_access; // Structure to hold button state and texture struct Toolbar_button @@ -229,21 +228,21 @@ class GUI void open_file_dialog_(); void save_file_dialog_(); - void save_startup_project_(); - void clear_saved_startup_project_(); + void save_startup_project_(); + void clear_saved_startup_project_(); /// Native only: store path in settings after a successful Open (for optional startup load). void persist_last_opened_project_path_(const std::string& path); - std::string serialized_project_json_() const; + [[nodiscard]] std::string serialized_project_json_() const; void open_url_(const std::string& url); void update_window_title_(); [[nodiscard]] std::string project_title_segment_() const; /// Parses a float from manual dist/angle ImGui text fields (trimmed, full-string match). - static bool parse_dist_text_to_float_(const char* buf, float& out); - /// True if JSON parses and looks like an EzyCad project document (`sketches` array). - static bool is_valid_project_json_(const std::string& s); + [[nodiscard]] static bool parse_dist_text_to_float_(const char* buf, float& out); + /// True if JSON parses and looks like an EzyCad project document (`sketches` array[). + [[nodiscard]] static bool is_valid_project_json_(const std::string& s); /// OCCT standard material display names for ImGui combos (index matches \c Graphic3d_NameOfMaterial). - static const std::vector& occt_material_combo_labels_(); + static [[nodiscard]] const std::vector& occt_material_combo_labels_(); // Settings (gui_settings.cpp) void load_occt_view_settings_(); @@ -253,34 +252,34 @@ class GUI void imgui_rounding_fallbacks_from_theme_(float& general, float& scroll, float& tabs) const; Occt_view::uptr m_view; - GLFWwindow* m_glfw_window {nullptr}; + GLFWwindow* m_glfw_window{nullptr}; std::string m_cached_window_title; // Sketch segment manual length input related std::function m_dist_callback; - ScreenCoords m_dist_edit_loc {glm::dvec2(0, 0)}; - float m_dist_val {}; - std::array m_dist_text_buf {}; - bool m_dist_edit_focus_pending {false}; + ScreenCoords m_dist_edit_loc{glm::dvec2(0, 0)}; + float m_dist_val{}; + std::array m_dist_text_buf{}; + bool m_dist_edit_focus_pending{false}; // Sketch segment manual angle input related std::function m_angle_callback; - ScreenCoords m_angle_edit_loc {glm::dvec2(0, 0)}; - float m_angle_val {}; - std::array m_angle_text_buf {}; - bool m_angle_edit_focus_pending {false}; + ScreenCoords m_angle_edit_loc{glm::dvec2(0, 0)}; + float m_angle_val{}; + std::array m_angle_text_buf{}; + bool m_angle_edit_focus_pending{false}; // Mode related - Mode m_mode = Mode::Normal; - Chamfer_mode m_chamfer_mode = Chamfer_mode::Shape; - Fillet_mode m_fillet_mode = Fillet_mode::Shape; - int m_edge_dim_label_h {3}; // Prs3d_DTHP_Fit - float m_edge_dim_line_width {k_gui_edge_dim_line_width_default}; - float m_edge_dim_arrow_size {k_gui_edge_dim_arrow_size_default}; + Mode m_mode = Mode::Normal; + Chamfer_mode m_chamfer_mode = Chamfer_mode::Shape; + Fillet_mode m_fillet_mode = Fillet_mode::Shape; + int m_edge_dim_label_h = 3; // Prs3d_DTHP_Fit + float m_edge_dim_line_width = k_gui_edge_dim_line_width_default; + float m_edge_dim_arrow_size = k_gui_edge_dim_arrow_size_default; /// Degrees per numpad orbit (8/2/4/6) and Blender-style roll (Shift+NumPad 4/6); persisted in `gui.view_roll_step_deg`. - double m_view_roll_step_deg {k_gui_view_roll_step_deg_default}; + double m_view_roll_step_deg = k_gui_view_roll_step_deg_default; /// Multiplier for `UpdateZoom(Aspect_ScrollDelta(..., int(y * scale)))`; persisted in `gui.view_zoom_scroll_scale`. - double m_view_zoom_scroll_scale {k_gui_view_zoom_scroll_scale_default}; + double m_view_zoom_scroll_scale = k_gui_view_zoom_scroll_scale_default; std::vector m_toolbar_buttons; // Message status window @@ -289,92 +288,92 @@ class GUI std::chrono::steady_clock::time_point m_message_start_time; // Log window (single buffer for ImGui read-only multiline = selectable / copyable text) - std::vector m_log_buffer {'\0'}; - bool m_log_scroll_to_bottom = false; // Auto-scroll log to bottom on new lines (like Lua console) - bool m_log_window_visible = true; // Control log window visibility + std::vector m_log_buffer{'\0'}; + bool m_log_scroll_to_bottom = false; // Auto-scroll log to bottom on new lines (like Lua console) + bool m_log_window_visible = true; // Control log window visibility // Stream redirection - std::streambuf* m_original_cout_buf = nullptr; // Original stdout buffer - std::streambuf* m_original_cerr_buf = nullptr; // Original stderr buffer - Log_strm* m_cout_log_buf = nullptr; // Custom stdout buffer - Log_strm* m_cerr_log_buf = nullptr; // Custom stderr buffer + std::streambuf* m_original_cout_buf = nullptr; // Original stdout buffer + std::streambuf* m_original_cerr_buf = nullptr; // Original stderr buffer + Log_strm* m_cout_log_buf = nullptr; // Custom stdout buffer + Log_strm* m_cerr_log_buf = nullptr; // Custom stderr buffer - std::string m_last_saved_path; // Session path for Ctrl+S / Save as - bool m_load_last_opened_on_startup {false}; - std::string m_last_opened_project_path; // Persisted in settings (native) + std::string m_last_saved_path; // Session path for Ctrl+S / Save as + bool m_load_last_opened_on_startup{false}; + std::string m_last_opened_project_path; // Persisted in settings (native) using Example_file_list = std::vector; Example_file_list m_example_files; std::unordered_map m_sketch_list_expanded; - bool m_show_sketch_list {true}; - bool m_show_shape_list {true}; - bool m_show_options {true}; - bool m_show_settings_dialog {false}; - bool m_open_about_popup {false}; - bool m_about_popup_open {false}; + bool m_show_sketch_list{true}; + bool m_show_shape_list{true}; + bool m_show_options{true}; + bool m_show_settings_dialog{false}; + bool m_open_about_popup{false}; + bool m_about_popup_open{false}; std::string m_about_markdown; - uint32_t m_about_splash_gl {0}; - glm::ivec2 m_about_splash_size {512, 512}; - bool m_about_assets_loaded {false}; - bool m_open_add_box_popup {false}; - glm::dvec3 m_add_box_origin {0.0, 0.0, 0.0}; - glm::dvec3 m_add_box_size {1.0, 1.0, 1.0}; - bool m_open_add_pyramid_popup {false}; - glm::dvec3 m_add_pyramid_origin {0.0, 0.0, 0.0}; - double m_add_pyramid_side {1}; - bool m_open_add_sphere_popup {false}; - glm::dvec3 m_add_sphere_origin {0.0, 0.0, 0.0}; - double m_add_sphere_radius {1}; - bool m_open_add_cylinder_popup {false}; - glm::dvec3 m_add_cylinder_origin {0.0, 0.0, 0.0}; - double m_add_cylinder_radius {1}, m_add_cylinder_height {1}; - bool m_open_add_cone_popup {false}; - glm::dvec3 m_add_cone_origin {0.0, 0.0, 0.0}; - double m_add_cone_R1 {1}, m_add_cone_R2 {0}, m_add_cone_height {1}; - bool m_open_add_torus_popup {false}; - glm::dvec3 m_add_torus_origin {0.0, 0.0, 0.0}; - double m_add_torus_R1 {1}, m_add_torus_R2 {0.5}; - bool m_hide_all_shapes {false}; - bool m_show_tool_tips {true}; - bool m_dark_mode {false}; + uint32_t m_about_splash_gl{0}; + glm::ivec2 m_about_splash_size{512, 512}; + bool m_about_assets_loaded{false}; + bool m_open_add_box_popup{false}; + glm::dvec3 m_add_box_origin{0.0, 0.0, 0.0}; + glm::dvec3 m_add_box_size{1.0, 1.0, 1.0}; + bool m_open_add_pyramid_popup{false}; + glm::dvec3 m_add_pyramid_origin{0.0, 0.0, 0.0}; + double m_add_pyramid_side{1}; + bool m_open_add_sphere_popup{false}; + glm::dvec3 m_add_sphere_origin{0.0, 0.0, 0.0}; + double m_add_sphere_radius{1}; + bool m_open_add_cylinder_popup{false}; + glm::dvec3 m_add_cylinder_origin{0.0, 0.0, 0.0}; + double m_add_cylinder_radius{1}, m_add_cylinder_height{1}; + bool m_open_add_cone_popup{false}; + glm::dvec3 m_add_cone_origin{0.0, 0.0, 0.0}; + double m_add_cone_R1{1}, m_add_cone_R2{0}, m_add_cone_height{1}; + bool m_open_add_torus_popup{false}; + glm::dvec3 m_add_torus_origin{0.0, 0.0, 0.0}; + double m_add_torus_R1{1}, m_add_torus_R2{0.5}; + bool m_hide_all_shapes{false}; + bool m_show_tool_tips{true}; + bool m_dark_mode{false}; #ifndef NDEBUG - bool m_show_dbg {false}; + bool m_show_dbg{false}; #endif - bool m_show_lua_console {true}; // Lua Console pane; hidden if false in settings + bool m_show_lua_console{true}; // Lua Console pane; hidden if false in settings /// ImGui corner radii (applied after StyleColorsDark/Light each frame). Scroll value sets both scrollbar and grab rounding. - float m_imgui_rounding_general {0.f}; - float m_imgui_rounding_scroll {0.f}; - float m_imgui_rounding_tabs {0.f}; - bool m_sketch_properties_open {false}; + float m_imgui_rounding_general{0.f}; + float m_imgui_rounding_scroll{0.f}; + float m_imgui_rounding_tabs{0.f}; + bool m_sketch_properties_open{false}; std::weak_ptr m_sketch_properties_sketch; // Sketch underlay related - void* m_underlay_panel_sketch {nullptr}; - Underlay_calib_phase m_underlay_calib_phase {Underlay_calib_phase::None}; - std::weak_ptr m_underlay_calib_sketch_wk {}; - gp_Pnt2d m_underlay_calib_x0 {}; - gp_Pnt2d m_underlay_calib_x1 {}; - gp_Vec2d m_underlay_calib_axis_u {}; // After X distance (model units) - gp_Pnt2d m_underlay_calib_y0 {}; - gp_Pnt2d m_underlay_calib_y1 {}; - gp_Pnt2d m_underlay_calib_datum_o {}; + void* m_underlay_panel_sketch{nullptr}; + Underlay_calib_phase m_underlay_calib_phase{Underlay_calib_phase::None}; + std::weak_ptr m_underlay_calib_sketch_wk{}; + gp_Pnt2d m_underlay_calib_x0{}; + gp_Pnt2d m_underlay_calib_x1{}; + gp_Vec2d m_underlay_calib_axis_u{}; // After X distance (model units) + gp_Pnt2d m_underlay_calib_y0{}; + gp_Pnt2d m_underlay_calib_y1{}; + gp_Pnt2d m_underlay_calib_datum_o{}; /// If set, next underlay import (menu or async) applies to this sketch; otherwise current sketch. std::weak_ptr m_underlay_import_sketch_target; - glm::dvec2 m_underlay_center {}; - glm::dvec2 m_underlay_half_extents {}; - double m_underlay_rot {}; - float m_underlay_opacity {0.88f}; - bool m_underlay_vis {true}; - bool m_underlay_key_white {true}; - bool m_underlay_line_tint {true}; - glm::vec4 m_underlay_tint_col {1.f, 220.f / 255.f, 0.f, 1.f}; + glm::dvec2 m_underlay_center{}; + glm::dvec2 m_underlay_half_extents{}; + double m_underlay_rot{}; + float m_underlay_opacity{0.88f}; + bool m_underlay_vis{true}; + bool m_underlay_key_white{true}; + bool m_underlay_line_tint{true}; + glm::vec4 m_underlay_tint_col{1.f, 220.f / 255.f, 0.f, 1.f}; /// Default underlay tint for new imports (0-1, persisted in ezycad_settings.json). - glm::vec4 m_underlay_highlight_color {1.f, 220.f / 255.f, 0.f, 1.f}; + glm::vec4 m_underlay_highlight_color{1.f, 220.f / 255.f, 0.f, 1.f}; std::unique_ptr m_lua_console; - bool m_show_python_console {false}; + bool m_show_python_console{false}; std::unique_ptr m_python_console; - ImFont* m_console_font {nullptr}; // Cousine monospace; set from main + ImFont* m_console_font{nullptr}; // Cousine monospace; set from main }; \ No newline at end of file diff --git a/src/gui_add.cpp b/src/gui_add.cpp index bad0159..c0ab2ac 100644 --- a/src/gui_add.cpp +++ b/src/gui_add.cpp @@ -68,9 +68,8 @@ void GUI::add_box_dialog_() if (m_add_box_size.x > 0 && m_add_box_size.y > 0 && m_add_box_size.z > 0) { const double scale = m_view->get_dimension_scale(); - m_view->add_box( - m_add_box_origin.x * scale, m_add_box_origin.y * scale, m_add_box_origin.z * scale, - m_add_box_size.x * scale, m_add_box_size.y * scale, m_add_box_size.z * scale); + m_view->add_box(m_add_box_origin.x * scale, m_add_box_origin.y * scale, m_add_box_origin.z * scale, + m_add_box_size.x * scale, m_add_box_size.y * scale, m_add_box_size.z * scale); ImGui::CloseCurrentPopup(); } } @@ -125,7 +124,8 @@ void GUI::add_pyramid_dialog_() if (ImGui::Button("Add") && m_add_pyramid_side > 0) { const double scale = m_view->get_dimension_scale(); - m_view->add_pyramid(m_add_pyramid_origin.x * scale, m_add_pyramid_origin.y * scale, m_add_pyramid_origin.z * scale, m_add_pyramid_side * scale); + m_view->add_pyramid(m_add_pyramid_origin.x * scale, m_add_pyramid_origin.y * scale, m_add_pyramid_origin.z * scale, + m_add_pyramid_side * scale); ImGui::CloseCurrentPopup(); } ImGui::SameLine(); @@ -180,7 +180,8 @@ void GUI::add_sphere_dialog_() if (ImGui::Button("Add") && m_add_sphere_radius > 0) { const double scale = m_view->get_dimension_scale(); - m_view->add_sphere(m_add_sphere_origin.x * scale, m_add_sphere_origin.y * scale, m_add_sphere_origin.z * scale, m_add_sphere_radius * scale); + m_view->add_sphere(m_add_sphere_origin.x * scale, m_add_sphere_origin.y * scale, m_add_sphere_origin.z * scale, + m_add_sphere_radius * scale); ImGui::CloseCurrentPopup(); } @@ -304,7 +305,8 @@ void GUI::add_cone_dialog_() if (ImGui::Button("Add") && m_add_cone_R1 >= 0 && m_add_cone_R2 >= 0 && m_add_cone_height > 0) { const double scale = m_view->get_dimension_scale(); - m_view->add_cone(m_add_cone_origin.x * scale, m_add_cone_origin.y * scale, m_add_cone_origin.z * scale, m_add_cone_R1 * scale, m_add_cone_R2 * scale, m_add_cone_height * scale); + m_view->add_cone(m_add_cone_origin.x * scale, m_add_cone_origin.y * scale, m_add_cone_origin.z * scale, + m_add_cone_R1 * scale, m_add_cone_R2 * scale, m_add_cone_height * scale); ImGui::CloseCurrentPopup(); } ImGui::SameLine(); @@ -362,7 +364,8 @@ void GUI::add_torus_dialog_() if (ImGui::Button("Add") && m_add_torus_R1 > 0 && m_add_torus_R2 > 0) { const double scale = m_view->get_dimension_scale(); - m_view->add_torus(m_add_torus_origin.x * scale, m_add_torus_origin.y * scale, m_add_torus_origin.z * scale, m_add_torus_R1 * scale, m_add_torus_R2 * scale); + m_view->add_torus(m_add_torus_origin.x * scale, m_add_torus_origin.y * scale, m_add_torus_origin.z * scale, + m_add_torus_R1 * scale, m_add_torus_R2 * scale); ImGui::CloseCurrentPopup(); } ImGui::SameLine(); diff --git a/src/gui_mode.cpp b/src/gui_mode.cpp index 608ee43..9bb008e 100644 --- a/src/gui_mode.cpp +++ b/src/gui_mode.cpp @@ -41,7 +41,7 @@ void format_double_trim_fraction(char* dst, std::size_t dst_sz, double v, int ma std::snprintf(dst, dst_sz, "%s", tmp); } -} // namespace +} // namespace void GUI::set_mode(Mode mode) { @@ -56,28 +56,28 @@ void GUI::set_mode(Mode mode) void GUI::set_parent_mode() { static std::map parent_modes = { - { Mode::Normal, Mode::Normal}, - { Mode::Move, Mode::Normal}, - { Mode::Scale, Mode::Normal}, - { Mode::Rotate, Mode::Normal}, - { Mode::Sketch_inspection_mode, Mode::Normal}, - { Mode::Sketch_from_planar_face, Mode::Normal}, - { Mode::Sketch_face_extrude, Mode::Normal}, - { Mode::Shape_chamfer, Mode::Normal}, - { Mode::Shape_fillet, Mode::Normal}, - { Mode::Shape_polar_duplicate, Mode::Normal}, - { Mode::Sketch_add_node, Mode::Sketch_inspection_mode}, - { Mode::Sketch_add_edge, Mode::Sketch_inspection_mode}, - { Mode::Sketch_add_multi_edges, Mode::Sketch_inspection_mode}, - { Mode::Sketch_add_seg_circle_arc, Mode::Sketch_inspection_mode}, - { Mode::Sketch_operation_axis, Mode::Sketch_inspection_mode}, - { Mode::Sketch_add_square, Mode::Sketch_inspection_mode}, - { Mode::Sketch_add_rectangle, Mode::Sketch_inspection_mode}, + {Mode::Normal, Mode::Normal}, + {Mode::Move, Mode::Normal}, + {Mode::Scale, Mode::Normal}, + {Mode::Rotate, Mode::Normal}, + {Mode::Sketch_inspection_mode, Mode::Normal}, + {Mode::Sketch_from_planar_face, Mode::Normal}, + {Mode::Sketch_face_extrude, Mode::Normal}, + {Mode::Shape_chamfer, Mode::Normal}, + {Mode::Shape_fillet, Mode::Normal}, + {Mode::Shape_polar_duplicate, Mode::Normal}, + {Mode::Sketch_add_node, Mode::Sketch_inspection_mode}, + {Mode::Sketch_add_edge, Mode::Sketch_inspection_mode}, + {Mode::Sketch_add_multi_edges, Mode::Sketch_inspection_mode}, + {Mode::Sketch_add_seg_circle_arc, Mode::Sketch_inspection_mode}, + {Mode::Sketch_operation_axis, Mode::Sketch_inspection_mode}, + {Mode::Sketch_add_square, Mode::Sketch_inspection_mode}, + {Mode::Sketch_add_rectangle, Mode::Sketch_inspection_mode}, {Mode::Sketch_add_rectangle_center_pt, Mode::Sketch_inspection_mode}, - { Mode::Sketch_add_circle, Mode::Sketch_inspection_mode}, - { Mode::Sketch_add_circle_3_pts, Mode::Sketch_inspection_mode}, - { Mode::Sketch_add_slot, Mode::Sketch_inspection_mode}, - { Mode::Sketch_dim_anno, Mode::Sketch_inspection_mode}, + {Mode::Sketch_add_circle, Mode::Sketch_inspection_mode}, + {Mode::Sketch_add_circle_3_pts, Mode::Sketch_inspection_mode}, + {Mode::Sketch_add_slot, Mode::Sketch_inspection_mode}, + {Mode::Sketch_dim_anno, Mode::Sketch_inspection_mode}, }; static bool check = [&]() @@ -89,7 +89,7 @@ void GUI::set_parent_mode() return true; }(); - (void) check; + (void)check; const auto itr = parent_modes.find(get_mode()); EZY_ASSERT(itr != parent_modes.end()); set_mode(itr->second); @@ -97,7 +97,7 @@ void GUI::set_parent_mode() void GUI::on_key(int key, int scancode, int action, int mods) { - (void) scancode; + (void)scancode; const bool press_or_repeat = (action == GLFW_PRESS || action == GLFW_REPEAT); // Zoom (+/-): scaled like mouse wheel; GLFW_REPEAT while held; Shift = Blender-style finer step. @@ -109,26 +109,25 @@ void GUI::on_key(int key, int scancode, int action, int mods) bool zoom_in_shift_is_structural = false; switch (key) { - case GLFW_KEY_KP_ADD: - zoom_in = true; - break; - case GLFW_KEY_KP_SUBTRACT: - case GLFW_KEY_MINUS: - zoom_out = true; - break; - case GLFW_KEY_EQUAL: - if ((mods & GLFW_MOD_SHIFT) != 0) - { - zoom_in = true; - zoom_in_shift_is_structural = true; - } - break; - default: - break; + case GLFW_KEY_KP_ADD: + zoom_in = true; + break; + case GLFW_KEY_KP_SUBTRACT: + case GLFW_KEY_MINUS: + zoom_out = true; + break; + case GLFW_KEY_EQUAL: + if ((mods & GLFW_MOD_SHIFT) != 0) + { + zoom_in = true; + zoom_in_shift_is_structural = true; + } + break; + default: + break; } - const bool shift_finer = - ((mods & GLFW_MOD_SHIFT) != 0) && !zoom_in_shift_is_structural; + const bool shift_finer = ((mods & GLFW_MOD_SHIFT) != 0) && !zoom_in_shift_is_structural; if (zoom_in) { @@ -146,10 +145,8 @@ void GUI::on_key(int key, int scancode, int action, int mods) // Use PRESS and REPEAT (like zoom) so hold-to-repeat works; route before keypad digit -> selection filter. if (press_or_repeat && (mods & GLFW_MOD_SHIFT) != 0 && (mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)) == 0) { - const bool roll_ccw = - (key == GLFW_KEY_KP_4 || key == GLFW_KEY_4 || key == GLFW_KEY_LEFT); - const bool roll_cw = - (key == GLFW_KEY_KP_6 || key == GLFW_KEY_6 || key == GLFW_KEY_RIGHT); + const bool roll_ccw = (key == GLFW_KEY_KP_4 || key == GLFW_KEY_4 || key == GLFW_KEY_LEFT); + const bool roll_cw = (key == GLFW_KEY_KP_6 || key == GLFW_KEY_6 || key == GLFW_KEY_RIGHT); if (roll_ccw || roll_cw) { const double step = m_view_roll_step_deg; @@ -191,31 +188,31 @@ void GUI::on_key(int key, int scancode, int action, int mods) { switch (key) { - case GLFW_KEY_N: - new_project_(); - break; - - case GLFW_KEY_O: - open_file_dialog_(); - break; - - case GLFW_KEY_S: - save_file_dialog_(); - break; - - case GLFW_KEY_Z: - if ((mods & GLFW_MOD_SHIFT) != 0) - m_view->redo(); - else - m_view->undo(); - break; - - case GLFW_KEY_Y: + case GLFW_KEY_N: + new_project_(); + break; + + case GLFW_KEY_O: + open_file_dialog_(); + break; + + case GLFW_KEY_S: + save_file_dialog_(); + break; + + case GLFW_KEY_Z: + if ((mods & GLFW_MOD_SHIFT) != 0) m_view->redo(); - break; + else + m_view->undo(); + break; - default: - break; + case GLFW_KEY_Y: + m_view->redo(); + break; + + default: + break; } } else @@ -250,65 +247,65 @@ void GUI::on_key(int key, int scancode, int action, int mods) switch (key) { - case GLFW_KEY_ESCAPE: - cancel_underlay_calib_(); - m_view->cancel(Set_parent_mode::Yes); - hide_dist_edit(); - hide_angle_edit(); - break; - - case GLFW_KEY_TAB: - { - bool shift_pressed = (mods & GLFW_MOD_SHIFT) != 0; - if (shift_pressed) - m_view->angle_input(screen_coords); - else - m_view->dimension_input(screen_coords); - break; - } + case GLFW_KEY_ESCAPE: + cancel_underlay_calib_(); + m_view->cancel(Set_parent_mode::Yes); + hide_dist_edit(); + hide_angle_edit(); + break; - case GLFW_KEY_ENTER: - hide_dist_edit(); - hide_angle_edit(); - m_view->on_enter(screen_coords); - break; + case GLFW_KEY_TAB: + { + bool shift_pressed = (mods & GLFW_MOD_SHIFT) != 0; + if (shift_pressed) + m_view->angle_input(screen_coords); + else + m_view->dimension_input(screen_coords); + break; + } - case GLFW_KEY_D: - m_view->delete_selected(); - break; + case GLFW_KEY_ENTER: + hide_dist_edit(); + hide_angle_edit(); + m_view->on_enter(screen_coords); + break; - case GLFW_KEY_G: - set_mode(Mode::Move); - break; + case GLFW_KEY_D: + m_view->delete_selected(); + break; - case GLFW_KEY_R: - set_mode(Mode::Rotate); - break; + case GLFW_KEY_G: + set_mode(Mode::Move); + break; + + case GLFW_KEY_R: + set_mode(Mode::Rotate); + break; - case GLFW_KEY_E: - set_mode(Mode::Sketch_face_extrude); - break; + case GLFW_KEY_E: + set_mode(Mode::Sketch_face_extrude); + break; - case GLFW_KEY_S: - set_mode(Mode::Scale); - break; + case GLFW_KEY_S: + set_mode(Mode::Scale); + break; - default: - break; + default: + break; } switch (get_mode()) { - case Mode::Move: - on_key_move_mode_(key); - break; + case Mode::Move: + on_key_move_mode_(key); + break; - case Mode::Rotate: - on_key_rotate_mode_(key); - break; + case Mode::Rotate: + on_key_rotate_mode_(key); + break; - default: - break; + default: + break; } } } @@ -421,10 +418,9 @@ void GUI::options_() ImGui::EndCombo(); } if (ImGui::IsItemHovered()) - ImGui::SetTooltip( - "Traditional: compact local snap marker.\n" - "Fullscreen: full-view crosshair/axis guides.\n" - "Both: show compact marker and fullscreen guides together."); + ImGui::SetTooltip("Traditional: compact local snap marker.\n" + "Fullscreen: full-view crosshair/axis guides.\n" + "Both: show compact marker and fullscreen guides together."); if (get_mode() == Mode::Sketch_dim_anno) { @@ -441,8 +437,7 @@ void GUI::options_() right_aligned_label("Length value placement"); ImGui::TableSetColumnIndex(1); ImGui::SetNextItemWidth(170.0f); - if (ImGui::BeginCombo("##edge_dim_h", k_edge_dim_label_placement[static_cast(h)], - ImGuiComboFlags_HeightSmall)) + if (ImGui::BeginCombo("##edge_dim_h", k_edge_dim_label_placement[static_cast(h)], ImGuiComboFlags_HeightSmall)) { for (int i = 0; i < int(k_edge_dim_label_placement.size()); ++i) if (ImGui::Selectable(k_edge_dim_label_placement[static_cast(i)], i == h)) @@ -491,8 +486,8 @@ void GUI::options_() right_aligned_label("Material"); ImGui::TableSetColumnIndex(1); ImGui::SetNextItemWidth(120.0f); - if (ImGui::BeginCombo("##default_material_sketch_extrude", - material_names[static_cast(current_item)].data(), ImGuiComboFlags_HeightSmall)) + if (ImGui::BeginCombo("##default_material_sketch_extrude", material_names[static_cast(current_item)].data(), + ImGuiComboFlags_HeightSmall)) { for (int i = 0; i < static_cast(material_names.size()); i++) if (ImGui::Selectable(material_names[static_cast(i)].data(), current_item == i)) @@ -509,35 +504,35 @@ void GUI::options_() switch (get_mode()) { - case Mode::Sketch_dim_anno: - break; - - case Mode::Sketch_face_extrude: - break; - - case Mode::Sketch_add_edge: - case Mode::Sketch_add_multi_edges: - ImGui::Separator(); - ImGui::TextUnformatted("Shortcuts"); - ImGui::TextWrapped("TAB: type edge length. Shift+TAB: type angle (degrees, CCW from +X)."); - break; - - case Mode::Sketch_add_node: - ImGui::Separator(); - ImGui::TextUnformatted("Shortcuts"); - ImGui::TextWrapped("TAB: type length along the rubber band. Shift+TAB: type angle (degrees, CCW from +X)."); - ImGui::TextWrapped( - "Snap the first click to an existing sketch point to start a rubber band, then click to place the node " - "(or press Enter after typing a length). An unsnapped click still places a single node immediately."); - break; - - default: - break; + case Mode::Sketch_dim_anno: + break; + + case Mode::Sketch_face_extrude: + break; + + case Mode::Sketch_add_edge: + case Mode::Sketch_add_multi_edges: + ImGui::Separator(); + ImGui::TextUnformatted("Shortcuts"); + ImGui::TextWrapped("TAB: type edge length. Shift+TAB: type angle (degrees, CCW from +X)."); + break; + + case Mode::Sketch_add_node: + ImGui::Separator(); + ImGui::TextUnformatted("Shortcuts"); + ImGui::TextWrapped("TAB: type length along the rubber band. Shift+TAB: type angle (degrees, CCW from +X)."); + ImGui::TextWrapped( + "Snap the first click to an existing sketch point to start a rubber band, then click to place the node " + "(or press Enter after typing a length). An unsnapped click still places a single node immediately."); + break; + + default: + break; } } - else if (get_mode() != Mode::Normal && get_mode() != Mode::Shape_polar_duplicate && get_mode() != Mode::Shape_chamfer - && get_mode() != Mode::Shape_fillet && get_mode() != Mode::Move && get_mode() != Mode::Rotate - && get_mode() != Mode::Scale) + else if (get_mode() != Mode::Normal && get_mode() != Mode::Shape_polar_duplicate && get_mode() != Mode::Shape_chamfer && + get_mode() != Mode::Shape_fillet && get_mode() != Mode::Move && get_mode() != Mode::Rotate && + get_mode() != Mode::Scale) { ImGui::Separator(); ImGui::TextUnformatted("Material"); @@ -575,8 +570,7 @@ void GUI::options_normal_mode_() right_aligned_label("Selection Mode"); ImGui::TableSetColumnIndex(1); ImGui::SetNextItemWidth(120.0f); - if (ImGui::BeginCombo("##selection_mode", c_names_TopAbs_ShapeEnum[current_item].data(), - ImGuiComboFlags_HeightSmall)) + if (ImGui::BeginCombo("##selection_mode", c_names_TopAbs_ShapeEnum[current_item].data(), ImGuiComboFlags_HeightSmall)) { for (int i = 0; i < static_cast(c_names_TopAbs_ShapeEnum.size()); i++) if (ImGui::Selectable(c_names_TopAbs_ShapeEnum[i].data(), current_item == i)) @@ -590,8 +584,7 @@ void GUI::options_normal_mode_() { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextDisabled( - "Hotkeys: 1-9 (Normal mode) set filter when the 3D view has focus, not while typing in UI."); + ImGui::TextDisabled("Hotkeys: 1-9 (Normal mode) set filter when the 3D view has focus, not while typing in UI."); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } @@ -634,9 +627,7 @@ void GUI::options_move_mode_() ImGui::Checkbox("Z", &opts.constr_axis_z); } -void GUI::options_scale_mode_() -{ -} +void GUI::options_scale_mode_() {} void GUI::options_rotate_mode_() { @@ -709,7 +700,7 @@ void GUI::options_shape_chamfer_mode_() right_aligned_label("Chamfer Mode"); ImGui::TableSetColumnIndex(1); ImGui::SetNextItemWidth(120.0f); - if (ImGui::Combo("##chamfer_mode", ¤t_mode, c_chamfer_mode_strs.data(), (int) c_chamfer_mode_strs.size())) + if (ImGui::Combo("##chamfer_mode", ¤t_mode, c_chamfer_mode_strs.data(), (int)c_chamfer_mode_strs.size())) { m_chamfer_mode = static_cast(current_mode); m_view->on_chamfer_mode(); @@ -730,8 +721,7 @@ void GUI::options_shape_chamfer_mode_() right_aligned_label("Chamfer dist"); ImGui::TableSetColumnIndex(1); ImGui::SetNextItemWidth(100.0f); - constexpr ImGuiInputTextFlags k_dim_flags = - ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific; + constexpr ImGuiInputTextFlags k_dim_flags = ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific; if (ImGui::InputText("##micron", chamfer_buf, sizeof chamfer_buf, k_dim_flags)) { char* end = nullptr; @@ -778,7 +768,7 @@ void GUI::options_shape_fillet_mode_() right_aligned_label("Fillet Mode"); ImGui::TableSetColumnIndex(1); ImGui::SetNextItemWidth(120.0f); - if (ImGui::Combo("##fillet_mode", ¤t_mode, c_fillet_mode_strs.data(), (int) c_fillet_mode_strs.size())) + if (ImGui::Combo("##fillet_mode", ¤t_mode, c_fillet_mode_strs.data(), (int)c_fillet_mode_strs.size())) { m_fillet_mode = static_cast(current_mode); m_view->on_fillet_mode(); @@ -799,8 +789,7 @@ void GUI::options_shape_fillet_mode_() right_aligned_label("Fillet radius"); ImGui::TableSetColumnIndex(1); ImGui::SetNextItemWidth(100.0f); - constexpr ImGuiInputTextFlags k_dim_flags = - ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific; + constexpr ImGuiInputTextFlags k_dim_flags = ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific; if (ImGui::InputText("##micron", fillet_buf, sizeof fillet_buf, k_dim_flags)) { char* end = nullptr; @@ -918,40 +907,40 @@ void GUI::on_key_rotate_mode_(int key) switch (key) { - case GLFW_KEY_ESCAPE: - m_view->shp_rotate().cancel(); - break; - - case GLFW_KEY_ENTER: - case GLFW_KEY_KP_ENTER: - m_view->shp_rotate().finalize(); - break; - - case GLFW_KEY_TAB: - if (Status s = m_view->shp_rotate().show_angle_edit(screen_coords); !s.is_ok()) - show_message(s.message()); - break; - - case GLFW_KEY_X: - if (m_view->shp_rotate().get_rotation_axis() == Rotation_axis::X_axis) - m_view->shp_rotate().set_rotation_axis(Rotation_axis::View_to_object); - else - m_view->shp_rotate().set_rotation_axis(Rotation_axis::X_axis); - break; - - case GLFW_KEY_Y: - if (m_view->shp_rotate().get_rotation_axis() == Rotation_axis::Y_axis) - m_view->shp_rotate().set_rotation_axis(Rotation_axis::View_to_object); - else - m_view->shp_rotate().set_rotation_axis(Rotation_axis::Y_axis); - break; - - case GLFW_KEY_Z: - if (m_view->shp_rotate().get_rotation_axis() == Rotation_axis::Z_axis) - m_view->shp_rotate().set_rotation_axis(Rotation_axis::View_to_object); - else - m_view->shp_rotate().set_rotation_axis(Rotation_axis::Z_axis); - break; + case GLFW_KEY_ESCAPE: + m_view->shp_rotate().cancel(); + break; + + case GLFW_KEY_ENTER: + case GLFW_KEY_KP_ENTER: + m_view->shp_rotate().finalize(); + break; + + case GLFW_KEY_TAB: + if (Status s = m_view->shp_rotate().show_angle_edit(screen_coords); !s.is_ok()) + show_message(s.message()); + break; + + case GLFW_KEY_X: + if (m_view->shp_rotate().get_rotation_axis() == Rotation_axis::X_axis) + m_view->shp_rotate().set_rotation_axis(Rotation_axis::View_to_object); + else + m_view->shp_rotate().set_rotation_axis(Rotation_axis::X_axis); + break; + + case GLFW_KEY_Y: + if (m_view->shp_rotate().get_rotation_axis() == Rotation_axis::Y_axis) + m_view->shp_rotate().set_rotation_axis(Rotation_axis::View_to_object); + else + m_view->shp_rotate().set_rotation_axis(Rotation_axis::Y_axis); + break; + + case GLFW_KEY_Z: + if (m_view->shp_rotate().get_rotation_axis() == Rotation_axis::Z_axis) + m_view->shp_rotate().set_rotation_axis(Rotation_axis::View_to_object); + else + m_view->shp_rotate().set_rotation_axis(Rotation_axis::Z_axis); + break; } } @@ -962,19 +951,19 @@ void GUI::on_key_move_mode_(int key) switch (key) { - case GLFW_KEY_X: - opts.constr_axis_x ^= 1; - break; - case GLFW_KEY_Y: - opts.constr_axis_y ^= 1; - break; - case GLFW_KEY_Z: - opts.constr_axis_z ^= 1; - break; - case GLFW_KEY_TAB: - m_view->shp_move().show_dist_edit(screen_coords); - break; - default: - break; + case GLFW_KEY_X: + opts.constr_axis_x ^= 1; + break; + case GLFW_KEY_Y: + opts.constr_axis_y ^= 1; + break; + case GLFW_KEY_Z: + opts.constr_axis_z ^= 1; + break; + case GLFW_KEY_TAB: + m_view->shp_move().show_dist_edit(screen_coords); + break; + default: + break; } } diff --git a/src/gui_settings.cpp b/src/gui_settings.cpp index 8e6e3b8..6650086 100644 --- a/src/gui_settings.cpp +++ b/src/gui_settings.cpp @@ -18,22 +18,20 @@ namespace { const char* const k_settings_version = "1"; -/// `occt_view` JSON object: view background gradient and grid (shared with `save_occt_view_settings` / `occt_view_settings_json`). +/// `occt_view` JSON object: view background gradient and grid (shared with `save_occt_view_settings` / +/// `occt_view_settings_json`). nlohmann::json build_occt_view_settings_object(const Occt_view& view) { float bg1[3], bg2[3], g1[3], g2[3]; view.get_bg_gradient_colors(bg1, bg2); view.get_grid_colors(g1, g2); const int method = view.get_bg_gradient_method(); - return nlohmann::json { - { "bg_color1", {bg1[0], bg1[1], bg1[2]}}, - { "bg_color2", {bg2[0], bg2[1], bg2[2]}}, - {"bg_gradient_method", method}, - { "grid_color1", {g1[0], g1[1], g1[2]}}, - { "grid_color2", {g2[0], g2[1], g2[2]}}, + return nlohmann::json{ + {"bg_color1", {bg1[0], bg1[1], bg1[2]}}, {"bg_color2", {bg2[0], bg2[1], bg2[2]}}, {"bg_gradient_method", method}, + {"grid_color1", {g1[0], g1[1], g1[2]}}, {"grid_color2", {g2[0], g2[1], g2[2]}}, }; } -} // namespace +} // namespace std::string GUI::occt_view_settings_json() const { @@ -42,15 +40,15 @@ std::string GUI::occt_view_settings_json() const json j; j["occt_view"] = build_occt_view_settings_object(*m_view); j["gui"] = { - { "edge_dim_label_h", m_edge_dim_label_h}, - { "edge_dim_line_width", m_edge_dim_line_width}, - { "edge_dim_arrow_size", m_edge_dim_arrow_size}, - { "view_roll_step_deg", m_view_roll_step_deg}, + {"edge_dim_label_h", m_edge_dim_label_h}, + {"edge_dim_line_width", m_edge_dim_line_width}, + {"edge_dim_arrow_size", m_edge_dim_arrow_size}, + {"view_roll_step_deg", m_view_roll_step_deg}, {"view_zoom_scroll_scale", m_view_zoom_scroll_scale}, {"snap_guide_color", - [&]() - { - float r {}, g {}, b {}; + [&]() + { + float r{}, g{}, b{}; Sketch_nodes::get_snap_guide_color(r, g, b); return nlohmann::json::array({r, g, b}); }()}, @@ -77,36 +75,36 @@ void GUI::save_occt_view_settings() EZY_ASSERT(m_view); j["occt_view"] = build_occt_view_settings_object(*m_view); j["gui"] = { - { "show_options", m_show_options }, - { "show_sketch_list", m_show_sketch_list}, - { "show_shape_list", m_show_shape_list}, - { "log_window_visible", m_log_window_visible}, - { "show_settings_dialog", m_show_settings_dialog}, - { "dark_mode", m_dark_mode}, - { "show_lua_console", m_show_lua_console}, - { "show_python_console", m_show_python_console}, - { "edge_dim_label_h", m_edge_dim_label_h}, - { "edge_dim_line_width", m_edge_dim_line_width}, - { "edge_dim_arrow_size", m_edge_dim_arrow_size}, - {"load_last_opened_on_startup", m_load_last_opened_on_startup}, - { "last_opened_project_path", m_last_opened_project_path}, - { "imgui_rounding_general", m_imgui_rounding_general}, - { "imgui_rounding_scroll", m_imgui_rounding_scroll}, - { "imgui_rounding_tabs", m_imgui_rounding_tabs}, - { "view_roll_step_deg", m_view_roll_step_deg}, - { "view_zoom_scroll_scale", m_view_zoom_scroll_scale}, - { "snap_guide_color", - [&]() - { - float r {}, g {}, b {}; + {"show_options", m_show_options}, + {"show_sketch_list", m_show_sketch_list}, + {"show_shape_list", m_show_shape_list}, + {"log_window_visible", m_log_window_visible}, + {"show_settings_dialog", m_show_settings_dialog}, + {"dark_mode", m_dark_mode}, + {"show_lua_console", m_show_lua_console}, + {"show_python_console", m_show_python_console}, + {"edge_dim_label_h", m_edge_dim_label_h}, + {"edge_dim_line_width", m_edge_dim_line_width}, + {"edge_dim_arrow_size", m_edge_dim_arrow_size}, + {"load_last_opened_on_startup", m_load_last_opened_on_startup}, + {"last_opened_project_path", m_last_opened_project_path}, + {"imgui_rounding_general", m_imgui_rounding_general}, + {"imgui_rounding_scroll", m_imgui_rounding_scroll}, + {"imgui_rounding_tabs", m_imgui_rounding_tabs}, + {"view_roll_step_deg", m_view_roll_step_deg}, + {"view_zoom_scroll_scale", m_view_zoom_scroll_scale}, + {"snap_guide_color", + [&]() + { + float r{}, g{}, b{}; Sketch_nodes::get_snap_guide_color(r, g, b); return nlohmann::json::array({r, g, b}); }()}, {"snap_guide_mode", static_cast(Sketch_nodes::get_snap_guide_mode())}, #ifndef NDEBUG - { "show_dbg", m_show_dbg}, + {"show_dbg", m_show_dbg}, #endif - { "underlay_highlight_color", + {"underlay_highlight_color", {m_underlay_highlight_color[0], m_underlay_highlight_color[1], m_underlay_highlight_color[2], m_underlay_highlight_color[3]}}, }; @@ -238,10 +236,8 @@ void GUI::parse_gui_panes_settings_(const std::string& content) if (v >= k_gui_view_roll_step_deg_min && v <= k_gui_view_roll_step_deg_max) m_view_roll_step_deg = v; else - log_message("EzyCad: settings gui.view_roll_step_deg out of range [" + - std::to_string(k_gui_view_roll_step_deg_min) + ", " + - std::to_string(k_gui_view_roll_step_deg_max) + "], got " + std::to_string(v) + - "; using default."); + log_message("EzyCad: settings gui.view_roll_step_deg out of range [" + std::to_string(k_gui_view_roll_step_deg_min) + + ", " + std::to_string(k_gui_view_roll_step_deg_max) + "], got " + std::to_string(v) + "; using default."); } m_view_zoom_scroll_scale = k_gui_view_zoom_scroll_scale_default; @@ -252,9 +248,8 @@ void GUI::parse_gui_panes_settings_(const std::string& content) m_view_zoom_scroll_scale = v; else log_message("EzyCad: settings gui.view_zoom_scroll_scale out of range [" + - std::to_string(k_gui_view_zoom_scroll_scale_min) + ", " + - std::to_string(k_gui_view_zoom_scroll_scale_max) + "], got " + std::to_string(v) + - "; using default."); + std::to_string(k_gui_view_zoom_scroll_scale_min) + ", " + std::to_string(k_gui_view_zoom_scroll_scale_max) + + "], got " + std::to_string(v) + "; using default."); } if (m_view) m_view->set_zoom_scroll_scale(m_view_zoom_scroll_scale); @@ -267,8 +262,7 @@ void GUI::parse_gui_panes_settings_(const std::string& content) glm::vec3 c(0.0f, 1.0f, 0.0f); for (size_t i = 0; i < 3; ++i) if (a[static_cast(i)].is_number()) - c[static_cast(i)] = - std::clamp(a[static_cast(i)].get(), 0.f, 1.f); + c[static_cast(i)] = std::clamp(a[static_cast(i)].get(), 0.f, 1.f); Sketch_nodes::set_snap_guide_color(c[0], c[1], c[2]); } @@ -281,7 +275,8 @@ void GUI::parse_gui_panes_settings_(const std::string& content) Sketch_nodes::set_snap_guide_mode(static_cast(mode)); } - if (g.contains("underlay_highlight_color") && g["underlay_highlight_color"].is_array() && g["underlay_highlight_color"].size() >= 3) + if (g.contains("underlay_highlight_color") && g["underlay_highlight_color"].is_array() && + g["underlay_highlight_color"].size() >= 3) { const json& a = g["underlay_highlight_color"]; for (int i = 0; i < 3; ++i) @@ -379,7 +374,7 @@ void GUI::settings_() if (!m_show_settings_dialog) return; - ImGui::SetNextWindowSize(ImVec2(520, 0), ImGuiCond_FirstUseEver); // Auto height; width matches res defaults + ImGui::SetNextWindowSize(ImVec2(520, 0), ImGuiCond_FirstUseEver); // Auto height; width matches res defaults if (!ImGui::Begin("Settings", &m_show_settings_dialog, ImGuiWindowFlags_None)) { ImGui::End(); @@ -404,17 +399,16 @@ void GUI::settings_() ImGui::TextUnformatted("View rotation step"); ImGui::TableSetColumnIndex(1); // SliderScalar(ImGuiDataType_Double): drag slider, or Ctrl+click for precise keyboard input (standard ImGui). - if (ImGui::SliderScalar("##view_roll_step", ImGuiDataType_Double, &m_view_roll_step_deg, - &k_gui_view_roll_step_deg_min, &k_gui_view_roll_step_deg_max, "%.2f deg", + if (ImGui::SliderScalar("##view_roll_step", ImGuiDataType_Double, &m_view_roll_step_deg, &k_gui_view_roll_step_deg_min, + &k_gui_view_roll_step_deg_max, "%.2f deg", ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_ClampOnInput)) save_occt_view_settings(); - m_view_roll_step_deg = - std::clamp(m_view_roll_step_deg, k_gui_view_roll_step_deg_min, k_gui_view_roll_step_deg_max); + m_view_roll_step_deg = std::clamp(m_view_roll_step_deg, k_gui_view_roll_step_deg_min, k_gui_view_roll_step_deg_max); if (ImGui::IsItemHovered()) - ImGui::SetTooltip( - "Degrees per key press: NumPad 8/2/4/6 orbit (like LMB drag), Shift+NumPad 4/6, Shift+4/6, or Shift+Left/Right roll. " - "Ctrl+click the slider to type a value."); + ImGui::SetTooltip("Degrees per key press: NumPad 8/2/4/6 orbit (like LMB drag), Shift+NumPad 4/6, Shift+4/6, or " + "Shift+Left/Right roll. " + "Ctrl+click the slider to type a value."); ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); if (ImGui::SmallButton("?##view_roll_help")) @@ -431,8 +425,8 @@ void GUI::settings_() &k_gui_view_zoom_scroll_scale_min, &k_gui_view_zoom_scroll_scale_max, "%.2f", ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_ClampOnInput)) { - m_view_zoom_scroll_scale = std::clamp(m_view_zoom_scroll_scale, k_gui_view_zoom_scroll_scale_min, - k_gui_view_zoom_scroll_scale_max); + m_view_zoom_scroll_scale = + std::clamp(m_view_zoom_scroll_scale, k_gui_view_zoom_scroll_scale_min, k_gui_view_zoom_scroll_scale_max); if (m_view) m_view->set_zoom_scroll_scale(m_view_zoom_scroll_scale); @@ -442,9 +436,8 @@ void GUI::settings_() std::clamp(m_view_zoom_scroll_scale, k_gui_view_zoom_scroll_scale_min, k_gui_view_zoom_scroll_scale_max); if (ImGui::IsItemHovered()) - ImGui::SetTooltip( - "Multiplier for mouse wheel and +/- zoom (same as UpdateZoom scroll delta). " - "Hold Shift while zooming for Blender-style finer steps (x0.1). Ctrl+click to type a value."); + ImGui::SetTooltip("Multiplier for mouse wheel and +/- zoom (same as UpdateZoom scroll delta). " + "Hold Shift while zooming for Blender-style finer steps (x0.1). Ctrl+click to type a value."); ImGui::EndTable(); } @@ -483,8 +476,7 @@ void GUI::settings_() { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextDisabled( - "Scrollbars and sliders applies the same radius to scrollbar tracks and slider grabs."); + ImGui::TextDisabled("Scrollbars and sliders applies the same radius to scrollbar tracks and slider grabs."); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } @@ -534,7 +526,7 @@ void GUI::settings_() ImGui::TextUnformatted("Gradient blend"); ImGui::TableSetColumnIndex(1); const char* gradient_items[] = {"Horizontal", "Vertical", "Diagonal 1", "Diagonal 2", - "Corner 1", "Corner 2", "Corner 3", "Corner 4"}; + "Corner 1", "Corner 2", "Corner 3", "Corner 4"}; int grad = m_view->get_bg_gradient_method(); if (ImGui::Combo("##bg_grad", &grad, gradient_items, 8)) { @@ -614,8 +606,7 @@ void GUI::settings_() { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextDisabled( - "Thickness of sketch edge length dimensions (Open CASCADE line width scale; 1.0 = default)."); + ImGui::TextDisabled("Thickness of sketch edge length dimensions (Open CASCADE line width scale; 1.0 = default)."); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } @@ -639,8 +630,7 @@ void GUI::settings_() { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextDisabled( - "Arrow head length for sketch and extrude length dimensions (Open CASCADE display units)."); + ImGui::TextDisabled("Arrow head length for sketch and extrude length dimensions (Open CASCADE display units)."); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } @@ -658,9 +648,8 @@ void GUI::settings_() { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextDisabled( - "Updates all sketch underlays immediately. Also used as the default when you import a new image. " - "Per-sketch overrides in Sketch List if needed."); + ImGui::TextDisabled("Updates all sketch underlays immediately. Also used as the default when you import a new image. " + "Per-sketch overrides in Sketch List if needed."); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } @@ -684,8 +673,7 @@ void GUI::settings_() { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextDisabled( - "Color used by fullscreen snap guides and snap markers in sketch mode."); + ImGui::TextDisabled("Color used by fullscreen snap guides and snap markers in sketch mode."); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } @@ -766,8 +754,7 @@ void GUI::settings_() { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextDisabled( - "When enabled, EzyCad opens the last .ezy file you opened (path is stored in settings)."); + ImGui::TextDisabled("When enabled, EzyCad opens the last .ezy file you opened (path is stored in settings)."); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } @@ -790,9 +777,8 @@ void GUI::settings_() { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextDisabled( - "Save the current document (geometry, view, and tool mode) as what loads when EzyCad starts. " - "If none is saved, the install default (res/default.ezy) is used."); + ImGui::TextDisabled("Save the current document (geometry, view, and tool mode) as what loads when EzyCad starts. " + "If none is saved, the install default (res/default.ezy) is used."); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } diff --git a/src/log.cpp b/src/log.cpp index 9f23a18..f07bd11 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -4,7 +4,8 @@ #include "gui.h" Log_strm::Log_strm(GUI& gui, std::streambuf* original_buf) - : m_gui(gui), m_original_buf(original_buf) + : m_gui(gui) + , m_original_buf(original_buf) { EZY_ASSERT(original_buf); } @@ -13,7 +14,7 @@ int Log_strm::overflow(int c) { if (c != EOF) { - if (c == '\n') // Treat as flush + if (c == '\n') // Treat as flush { if (!m_buffer.empty()) m_gui.log_message(m_buffer); diff --git a/src/log.h b/src/log.h index a2af6c3..ded9d1f 100644 --- a/src/log.h +++ b/src/log.h @@ -8,14 +8,14 @@ class GUI; // Custom stream buffer to redirect stdout/stderr to log_message class Log_strm : public std::streambuf { - public: +public: Log_strm(GUI& gui, std::streambuf* original_buf); - protected: +protected: int overflow(int c) override; int sync() override; - private: +private: GUI& m_gui; std::streambuf* m_original_buf; std::string m_buffer; diff --git a/src/lua_console.cpp b/src/lua_console.cpp index d31f1d4..8306290 100644 --- a/src/lua_console.cpp +++ b/src/lua_console.cpp @@ -41,10 +41,7 @@ void push_shp(lua_State* L, const Shp_ptr& shp) luaL_setmetatable(L, k_shp_metatable); } -Shp_ptr* to_shp(lua_State* L, int index) -{ - return static_cast(luaL_testudata(L, index, k_shp_metatable)); -} +Shp_ptr* to_shp(lua_State* L, int index) { return static_cast(luaL_testudata(L, index, k_shp_metatable)); } // ezy.log(msg) -> append to console and log window int l_ezy_log(lua_State* L) @@ -369,7 +366,7 @@ int l_ezy_help(lua_State* L) con->append_line_from_lua(help_text); return 0; } -} // namespace +} // namespace // Called from C callback; we need to store Lua_console* in registry to get back void Lua_console::append_line_from_lua(const std::string& line) @@ -415,7 +412,7 @@ void Lua_console::register_bindings() luaL_newmetatable(m_L, k_shp_metatable); lua_pushcfunction(m_L, l_shp_gc); lua_setfield(m_L, -2, "__gc"); - lua_newtable(m_L); // __index + lua_newtable(m_L); // __index lua_pushcfunction(m_L, l_shp_name); lua_setfield(m_L, -2, "name"); lua_pushcfunction(m_L, l_shp_set_name); @@ -665,13 +662,9 @@ void Lua_console::render(bool* p_open) } ImGui::SetNextItemWidth(-1); - bool run = ImGui::InputTextWithHint("##lua_input", - "Enter Lua code (e.g. ezy.log('hi'))", - m_input_buf, - k_input_buf_size, + bool run = ImGui::InputTextWithHint("##lua_input", "Enter Lua code (e.g. ezy.log('hi'))", m_input_buf, k_input_buf_size, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackHistory, - &Lua_console::text_edit_callback, - this); + &Lua_console::text_edit_callback, this); if (run) { diff --git a/src/lua_console.h b/src/lua_console.h index 26e7d35..df55af0 100644 --- a/src/lua_console.h +++ b/src/lua_console.h @@ -12,26 +12,26 @@ class GUI; /// One editable script file loaded from scripts/lua (path, filename, TextEditor buffer). struct Script_editor { - std::string path; // full path for load/save - std::string filename; // tab title (e.g. "basic.lua") - std::unique_ptr editor; // syntax-highlighted buffer (Lua) + std::string path; // full path for load/save + std::string filename; // tab title (e.g. "basic.lua") + std::unique_ptr editor; // syntax-highlighted buffer (Lua) }; /// ImGui Lua console: run Lua snippets with bindings to EzyCad (ezy.*, view.*). /// Built for native and Emscripten (Lua C sources compile with emcc). class Lua_console { - public: +public: explicit Lua_console(GUI* gui); ~Lua_console(); - void render(bool* p_open = nullptr); + void render(bool* p_open = nullptr); static int text_edit_callback(struct ImGuiInputTextCallbackData* data); /// Called from Lua ezy.log(); appends to console history. void append_line_from_lua(const std::string& line); - private: +private: void register_bindings(); void load_scripts(); void execute(const std::string& code); @@ -40,12 +40,12 @@ class Lua_console GUI* m_gui = nullptr; lua_State* m_L = nullptr; - std::vector m_history; // output lines (result or error) - std::vector m_cmd_history; // entered Lua commands - int m_cmd_history_pos = -1; // -1 when not browsing - static constexpr int k_input_buf_size = 1024; - char m_input_buf[k_input_buf_size] {}; - bool m_scroll_to_bottom = false; + std::vector m_history; // output lines (result or error) + std::vector m_cmd_history; // entered Lua commands + int m_cmd_history_pos = -1; // -1 when not browsing + static constexpr int k_input_buf_size = 1024; + char m_input_buf[k_input_buf_size]{}; + bool m_scroll_to_bottom = false; - std::vector m_script_editors; // one per .lua in scripts/lua + std::vector m_script_editors; // one per .lua in scripts/lua }; diff --git a/src/main.cpp b/src/main.cpp index 5888e9c..c74ec6e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,11 +16,12 @@ #if defined(IMGUI_IMPL_OPENGL_ES2) #include #endif -#include // Will drag system OpenGL headers +#include // Will drag system OpenGL headers -// [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers. -// To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do using this pragma. -// Your own project should not be affected, as you are likely to link with a newer binary of GLFW that is adequate for your version of Visual Studio. +// [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with +// old VS compilers. To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do +// using this pragma. Your own project should not be affected, as you are likely to link with a newer binary of GLFW that is +// adequate for your version of Visual Studio. #if defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) #pragma comment(lib, "legacy_stdio_definitions") #endif @@ -51,11 +52,7 @@ static std::function static std::function windowSizeCallback; static std::function scroll_callback; -void key_callback_wrapper(GLFWwindow* window, - int key, - int scancode, - int action, - int mods) +void key_callback_wrapper(GLFWwindow* window, int key, int scancode, int action, int mods) { if (keyCallback) keyCallback(window, key, scancode, action, mods); @@ -67,10 +64,7 @@ void cursor_pos_callback_wrapper(GLFWwindow* window, double xpos, double ypos) cursorPosCallback(window, xpos, ypos); } -void mouse_button_callback_wrapper(GLFWwindow* window, - int button, - int action, - int mods) +void mouse_button_callback_wrapper(GLFWwindow* window, int button, int action, int mods) { if (mouseButtonCallback) mouseButtonCallback(window, button, action, mods); @@ -115,8 +109,8 @@ int main(int, char**) const char* glsl_version = "#version 150"; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac #else // GL 3.0 + GLSL 130 const char* glsl_version = "#version 130"; @@ -127,12 +121,12 @@ int main(int, char**) #endif // Create window with graphics context - float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only - GLFWwindow* window = glfwCreateWindow((int) (1280 * main_scale), (int) (800 * main_scale), "EzyCad", nullptr, nullptr); + float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only + GLFWwindow* window = glfwCreateWindow((int)(1280 * main_scale), (int)(800 * main_scale), "EzyCad", nullptr, nullptr); if (window == nullptr) return 1; glfwMakeContextCurrent(window); - glfwSwapInterval(1); // Enable vsync + glfwSwapInterval(1); // Enable vsync #ifndef __EMSCRIPTEN__ glfwMaximizeWindow(window); #endif @@ -146,7 +140,7 @@ int main(int, char**) glfwGetFramebufferSize(window, &fbw, &fbh); float fb_scale = 1.0f; if (ww > 0 && wh > 0) - fb_scale = ((float) fbw / (float) ww + (float) fbh / (float) wh) * 0.5f; + fb_scale = ((float)fbw / (float)ww + (float)fbh / (float)wh) * 0.5f; const float dpr = emscripten_get_device_pixel_ratio(); if (main_scale <= 1.0f) main_scale = (fb_scale > 1.01f) ? fb_scale : dpr; @@ -157,9 +151,9 @@ int main(int, char**) IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); - (void) io; - io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + (void)io; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls // Setup Dear ImGui style ImGui::StyleColorsDark(); @@ -167,8 +161,10 @@ int main(int, char**) // Setup scaling ImGuiStyle& style = ImGui::GetStyle(); - style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again) - style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor) + style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing + // this requires resetting Style + calling this again) + style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true + // automatically overrides this for every window depending on the current monitor) // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForOpenGL(window, true); @@ -198,17 +194,16 @@ int main(int, char**) #endif IM_ASSERT(console_font != nullptr); - io.IniFilename = nullptr; // Layout persisted via ezycad_settings.json (see GUI) + io.IniFilename = nullptr; // Layout persisted via ezycad_settings.json (see GUI) GUI gui; gui.init(window, console_font); #ifdef __EMSCRIPTEN__ s_gui_for_unload = &gui; - EM_ASM( - { - window.addEventListener('beforeunload', function() { Module.ccall('emscripten_save_settings_on_unload', null, [], []); }); - }); + EM_ASM({ + window.addEventListener('beforeunload', function() { Module.ccall('emscripten_save_settings_on_unload', null, [], []); }); + }); #endif keyCallback = [&](GLFWwindow* window, int key, int scancode, int action, int mods) @@ -260,9 +255,11 @@ int main(int, char**) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. - // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your + // copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite + // your copy of the keyboard data. Generally you may always pass all inputs to dear imgui, and hide them from your + // application based on those two flags. glfwPollEvents(); if (glfwGetWindowAttrib(window, GLFW_ICONIFIED) != 0) { diff --git a/src/modes.cpp b/src/modes.cpp index b5a55eb..a3bcfcd 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -13,23 +13,23 @@ bool is_sketch_mode(const Mode mode) { switch (mode) { - case Mode::Sketch_inspection_mode: - case Mode::Sketch_add_node: - case Mode::Sketch_add_edge: - case Mode::Sketch_add_seg_circle_arc: - case Mode::Sketch_add_multi_edges: - case Mode::Sketch_add_square: - case Mode::Sketch_add_rectangle: - case Mode::Sketch_add_rectangle_center_pt: - case Mode::Sketch_add_circle: - case Mode::Sketch_add_circle_3_pts: - case Mode::Sketch_add_slot: - case Mode::Sketch_operation_axis: - case Mode::Sketch_dim_anno: - case Mode::Sketch_face_extrude: - return true; + case Mode::Sketch_inspection_mode: + case Mode::Sketch_add_node: + case Mode::Sketch_add_edge: + case Mode::Sketch_add_seg_circle_arc: + case Mode::Sketch_add_multi_edges: + case Mode::Sketch_add_square: + case Mode::Sketch_add_rectangle: + case Mode::Sketch_add_rectangle_center_pt: + case Mode::Sketch_add_circle: + case Mode::Sketch_add_circle_3_pts: + case Mode::Sketch_add_slot: + case Mode::Sketch_operation_axis: + case Mode::Sketch_dim_anno: + case Mode::Sketch_face_extrude: + return true; - default: - return false; + default: + return false; } } diff --git a/src/modes.h b/src/modes.h index d25abb2..4ec626b 100644 --- a/src/modes.h +++ b/src/modes.h @@ -7,28 +7,28 @@ // --- Mode ------------------------------------------------------------------ // Single source of truth: order here defines enum numeric values and c_mode_strs indices // (mode_from_string, persistence, etc.). Do not reorder without migrating saved data. -#define EZY_MODE_LIST(X) \ - X(Normal) \ - X(Move) \ - X(Scale) \ - X(Rotate) \ - X(Sketch_inspection_mode) /* inspecting sketch elements */ \ - X(Sketch_from_planar_face) /* sketch from a planar face */ \ - X(Sketch_face_extrude) /* extrude a sketch face */ \ - X(Shape_chamfer) \ - X(Shape_fillet) \ - X(Shape_polar_duplicate) \ - X(Sketch_add_node) \ - X(Sketch_add_edge) \ - X(Sketch_add_multi_edges) \ - X(Sketch_add_seg_circle_arc) \ - X(Sketch_operation_axis) /* mirror / revolve */ \ - X(Sketch_add_square) \ - X(Sketch_add_rectangle) \ - X(Sketch_add_rectangle_center_pt) \ - X(Sketch_add_circle) \ - X(Sketch_add_circle_3_pts) \ - X(Sketch_add_slot) \ +#define EZY_MODE_LIST(X) \ + X(Normal) \ + X(Move) \ + X(Scale) \ + X(Rotate) \ + X(Sketch_inspection_mode) /* inspecting sketch elements */ \ + X(Sketch_from_planar_face) /* sketch from a planar face */ \ + X(Sketch_face_extrude) /* extrude a sketch face */ \ + X(Shape_chamfer) \ + X(Shape_fillet) \ + X(Shape_polar_duplicate) \ + X(Sketch_add_node) \ + X(Sketch_add_edge) \ + X(Sketch_add_multi_edges) \ + X(Sketch_add_seg_circle_arc) \ + X(Sketch_operation_axis) /* mirror / revolve */ \ + X(Sketch_add_square) \ + X(Sketch_add_rectangle) \ + X(Sketch_add_rectangle_center_pt) \ + X(Sketch_add_circle) \ + X(Sketch_add_circle_3_pts) \ + X(Sketch_add_slot) \ X(Sketch_dim_anno) enum class Mode @@ -36,10 +36,10 @@ enum class Mode #define EZY_MODE_ENUM(name) name, EZY_MODE_LIST(EZY_MODE_ENUM) #undef EZY_MODE_ENUM - _count // must be last; equals number of EZY_MODE_LIST entries + _count // must be last; equals number of EZY_MODE_LIST entries }; -constexpr std::array(Mode::_count)> c_mode_strs { +constexpr std::array(Mode::_count)> c_mode_strs{ #define EZY_MODE_STR(name) #name, EZY_MODE_LIST(EZY_MODE_STR) #undef EZY_MODE_STR @@ -50,10 +50,10 @@ static_assert(c_mode_strs.size() == static_cast(Mode::_count)); #undef EZY_MODE_LIST // --- Chamfer_mode / Fillet_mode (shared member set) ------------------------ -#define EZY_CHAMFER_FILLET_MODE_LIST(X) \ - X(Edge) \ - X(Wire) \ - X(Face) \ +#define EZY_CHAMFER_FILLET_MODE_LIST(X) \ + X(Edge) \ + X(Wire) \ + X(Face) \ X(Shape) enum class Chamfer_mode @@ -64,7 +64,7 @@ enum class Chamfer_mode _count }; -constexpr std::array(Chamfer_mode::_count)> c_chamfer_mode_strs { +constexpr std::array(Chamfer_mode::_count)> c_chamfer_mode_strs{ #define EZY_CF_STR(name) #name, EZY_CHAMFER_FILLET_MODE_LIST(EZY_CF_STR) #undef EZY_CF_STR @@ -80,7 +80,7 @@ enum class Fillet_mode _count }; -constexpr std::array(Fillet_mode::_count)> c_fillet_mode_strs { +constexpr std::array(Fillet_mode::_count)> c_fillet_mode_strs{ #define EZY_CF_STR2(name) #name, EZY_CHAMFER_FILLET_MODE_LIST(EZY_CF_STR2) #undef EZY_CF_STR2 diff --git a/src/occt_glfw_win.cpp b/src/occt_glfw_win.cpp index 671984f..21161e3 100644 --- a/src/occt_glfw_win.cpp +++ b/src/occt_glfw_win.cpp @@ -22,7 +22,7 @@ #include "occt_glfw_win.h" #if defined(__APPLE__) -#undef Handle // avoid name collisions in macOS headers +#undef Handle // avoid name collisions in macOS headers #define GLFW_EXPOSE_NATIVE_COCOA #define GLFW_EXPOSE_NATIVE_NSGL #elif defined(_WIN32) @@ -38,11 +38,11 @@ #endif Occt_glfw_win::Occt_glfw_win(int theWidth, int theHeight, const TCollection_AsciiString& theTitle) - : myGlfwWindow(glfwCreateWindow(theWidth, theHeight, theTitle.ToCString(), NULL, NULL)), - myXLeft(0), - myYTop(0), - myXRight(0), - myYBottom(0) + : myGlfwWindow(glfwCreateWindow(theWidth, theHeight, theTitle.ToCString(), NULL, NULL)) + , myXLeft(0) + , myYTop(0) + , myXRight(0) + , myYBottom(0) { if (myGlfwWindow != nullptr) { @@ -53,17 +53,17 @@ Occt_glfw_win::Occt_glfw_win(int theWidth, int theHeight, const TCollection_Asci myYBottom = myYTop + aHeight; #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__) - myDisplay = new Aspect_DisplayConnection((Aspect_XDisplay*) glfwGetX11Display()); + myDisplay = new Aspect_DisplayConnection((Aspect_XDisplay*)glfwGetX11Display()); #endif } } Occt_glfw_win::Occt_glfw_win(GLFWwindow* GlfwWindow) - : myGlfwWindow(GlfwWindow), - myXLeft(0), - myYTop(0), - myXRight(0), - myYBottom(0) + : myGlfwWindow(GlfwWindow) + , myXLeft(0) + , myYTop(0) + , myXRight(0) + , myYBottom(0) { if (myGlfwWindow != nullptr) { @@ -75,7 +75,7 @@ Occt_glfw_win::Occt_glfw_win(GLFWwindow* GlfwWindow) #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__) // TODO break emscripten? - myDisplay = new Aspect_DisplayConnection((Aspect_XDisplay*) glfwGetX11Display()); + myDisplay = new Aspect_DisplayConnection((Aspect_XDisplay*)glfwGetX11Display()); #endif } } @@ -93,11 +93,11 @@ void Occt_glfw_win::Close() Aspect_Drawable Occt_glfw_win::NativeHandle() const { #if defined(__APPLE__) - return (Aspect_Drawable) glfwGetCocoaWindow(myGlfwWindow); + return (Aspect_Drawable)glfwGetCocoaWindow(myGlfwWindow); #elif defined(_WIN32) - return (Aspect_Drawable) glfwGetWin32Window(myGlfwWindow); + return (Aspect_Drawable)glfwGetWin32Window(myGlfwWindow); #else - return (Aspect_Drawable) glfwGetX11Window(myGlfwWindow); + return (Aspect_Drawable)glfwGetX11Window(myGlfwWindow); #endif } #endif @@ -106,7 +106,7 @@ Aspect_Drawable Occt_glfw_win::NativeHandle() const Aspect_RenderingContext Occt_glfw_win::NativeGlContext() const { #if defined(__APPLE__) - return (NSOpenGLContext*) glfwGetNSGLContext(myGlfwWindow); + return (NSOpenGLContext*)glfwGetNSGLContext(myGlfwWindow); #elif defined(_WIN32) return glfwGetWGLContext(myGlfwWindow); #else @@ -115,20 +115,11 @@ Aspect_RenderingContext Occt_glfw_win::NativeGlContext() const } #endif -Standard_Boolean Occt_glfw_win::IsMapped() const -{ - return glfwGetWindowAttrib(myGlfwWindow, GLFW_VISIBLE) != 0; -} +Standard_Boolean Occt_glfw_win::IsMapped() const { return glfwGetWindowAttrib(myGlfwWindow, GLFW_VISIBLE) != 0; } -void Occt_glfw_win::Map() const -{ - glfwShowWindow(myGlfwWindow); -} +void Occt_glfw_win::Map() const { glfwShowWindow(myGlfwWindow); } -void Occt_glfw_win::Unmap() const -{ - glfwHideWindow(myGlfwWindow); -} +void Occt_glfw_win::Unmap() const { glfwHideWindow(myGlfwWindow); } Aspect_TypeOfResize Occt_glfw_win::DoResize() { @@ -149,5 +140,5 @@ Graphic3d_Vec2i Occt_glfw_win::CursorPosition() const { Graphic3d_Vec2d aPos; glfwGetCursorPos(myGlfwWindow, &aPos.x(), &aPos.y()); - return Graphic3d_Vec2i((int) aPos.x(), (int) aPos.y()); + return Graphic3d_Vec2i((int)aPos.x(), (int)aPos.y()); } diff --git a/src/occt_glfw_win.h b/src/occt_glfw_win.h index 4a4953e..996c494 100644 --- a/src/occt_glfw_win.h +++ b/src/occt_glfw_win.h @@ -34,31 +34,22 @@ struct GLFWwindow; class Occt_glfw_win : public Aspect_Window { DEFINE_STANDARD_RTTI_INLINE(Occt_glfw_win, Aspect_Window) - public: +public: //! Main constructor. Occt_glfw_win(int theWidth, int theHeight, const TCollection_AsciiString& theTitle); Occt_glfw_win(GLFWwindow* GlfwWindow); //! Close the window. - virtual ~Occt_glfw_win() - { - Close(); - } + virtual ~Occt_glfw_win() { Close(); } //! Close the window. void Close(); //! Return X Display connection. - const Handle(Aspect_DisplayConnection) & GetDisplay() const - { - return myDisplay; - } + const Handle(Aspect_DisplayConnection) & GetDisplay() const { return myDisplay; } //! Return GLFW window. - GLFWwindow* getGlfwWindow() - { - return myGlfwWindow; - } + GLFWwindow* getGlfwWindow() { return myGlfwWindow; } #ifndef __EMSCRIPTEN__ //! Return native OpenGL context. @@ -68,17 +59,14 @@ class Occt_glfw_win : public Aspect_Window //! Return cursor position. Graphic3d_Vec2i CursorPosition() const; - public: +public: #ifndef __EMSCRIPTEN__ //! Returns native Window handle virtual Aspect_Drawable NativeHandle() const Standard_OVERRIDE; #endif //! Returns parent of native Window handle. - virtual Aspect_Drawable NativeParentHandle() const Standard_OVERRIDE - { - return 0; - } + virtual Aspect_Drawable NativeParentHandle() const Standard_OVERRIDE { return 0; } //! Applies the resizing to the window virtual Aspect_TypeOfResize DoResize() Standard_OVERRIDE; @@ -87,10 +75,7 @@ class Occt_glfw_win : public Aspect_Window virtual Standard_Boolean IsMapped() const Standard_OVERRIDE; //! Apply the mapping change to the window and returns TRUE if the window is mapped at screen. - virtual Standard_Boolean DoMapping() const Standard_OVERRIDE - { - return Standard_True; - } + virtual Standard_Boolean DoMapping() const Standard_OVERRIDE { return Standard_True; } //! Opens the window . virtual void Map() const Standard_OVERRIDE; @@ -98,8 +83,8 @@ class Occt_glfw_win : public Aspect_Window //! Closes the window . virtual void Unmap() const Standard_OVERRIDE; - virtual void Position(Standard_Integer& theX1, Standard_Integer& theY1, - Standard_Integer& theX2, Standard_Integer& theY2) const Standard_OVERRIDE + virtual void Position(Standard_Integer& theX1, Standard_Integer& theY1, Standard_Integer& theX2, + Standard_Integer& theY2) const Standard_OVERRIDE { theX1 = myXLeft; theX2 = myXRight; @@ -120,12 +105,9 @@ class Occt_glfw_win : public Aspect_Window theHeight = myYBottom - myYTop; } - virtual Aspect_FBConfig NativeFBConfig() const Standard_OVERRIDE - { - return NULL; - } + virtual Aspect_FBConfig NativeFBConfig() const Standard_OVERRIDE { return NULL; } - protected: +protected: Handle(Aspect_DisplayConnection) myDisplay; GLFWwindow* myGlfwWindow; Standard_Integer myXLeft; @@ -134,4 +116,4 @@ class Occt_glfw_win : public Aspect_Window Standard_Integer myYBottom; }; -#endif // _Occt_glfw_win_Header +#endif // _Occt_glfw_win_Header diff --git a/src/occt_view.cpp b/src/occt_view.cpp index b5bfc07..e8f5d79 100644 --- a/src/occt_view.cpp +++ b/src/occt_view.cpp @@ -65,7 +65,17 @@ using namespace glm; Occt_view::Occt_view(GUI& gui) - : m_gui(gui), m_shp_move(*this), m_shp_rotate(*this), m_shp_scale(*this), m_shp_chamfer(*this), m_shp_fillet(*this), m_shp_cut(*this), m_shp_fuse(*this), m_shp_common(*this), m_shp_polar_dup(*this), m_shp_extrude(*this) + : m_gui(gui) + , m_shp_move(*this) + , m_shp_rotate(*this) + , m_shp_scale(*this) + , m_shp_chamfer(*this) + , m_shp_fillet(*this) + , m_shp_cut(*this) + , m_shp_fuse(*this) + , m_shp_common(*this) + , m_shp_polar_dup(*this) + , m_shp_extrude(*this) { } @@ -81,17 +91,15 @@ void Occt_view::init_window(GLFWwindow* GlfwWindow) void Occt_view::init_viewer() { - double myDevicePixelRatio = 1.0; // TODO + double myDevicePixelRatio = 1.0; // TODO #ifndef __EMSCRIPTEN__ if (m_occt_window.IsNull() || m_occt_window->getGlfwWindow() == nullptr) { // create graphic driver - Handle(Aspect_DisplayConnection) aDisp = - new Aspect_DisplayConnection(); - Handle(OpenGl_GraphicDriver) aDriver = - new OpenGl_GraphicDriver(aDisp, true); - aDriver->ChangeOptions().swapInterval = 0; // no window, no swap - Handle(V3d_Viewer) myViewer = new V3d_Viewer(aDriver); + Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection(); + Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver(aDisp, true); + aDriver->ChangeOptions().swapInterval = 0; // no window, no swap + Handle(V3d_Viewer) myViewer = new V3d_Viewer(aDriver); // create offscreen window const TCollection_AsciiString aWinName("OCCT offscreen window"); @@ -99,19 +107,13 @@ void Occt_view::init_viewer() #if defined(_WIN32) const TCollection_AsciiString aClassName("OffscreenClass"); // empty callback! - Handle(WNT_WClass) aWinClass = - new WNT_WClass(aClassName.ToCString(), nullptr, 0); - Handle(WNT_Window) aWindow = - new WNT_Window(aWinName.ToCString(), aWinClass, 0x80000000, // WS_POPUP - 64, 64, aWinSize.x(), aWinSize.y(), - Quantity_NOC_BLACK); + Handle(WNT_WClass) aWinClass = new WNT_WClass(aClassName.ToCString(), nullptr, 0); + Handle(WNT_Window) aWindow = new WNT_Window(aWinName.ToCString(), aWinClass, 0x80000000, // WS_POPUP + 64, 64, aWinSize.x(), aWinSize.y(), Quantity_NOC_BLACK); #elif defined(__APPLE__) - Handle(Cocoa_Window) aWindow = - new Cocoa_Window(aWinName.ToCString(), - 64, 64, aWinSize.x(), aWinSize.y()); + Handle(Cocoa_Window) aWindow = new Cocoa_Window(aWinName.ToCString(), 64, 64, aWinSize.x(), aWinSize.y()); #else - Handle(Xw_Window) aWindow = new Xw_Window(aDisp, aWinName.ToCString(), - 64, 64, aWinSize.x(), aWinSize.y()); + Handle(Xw_Window) aWindow = new Xw_Window(aDisp, aWinName.ToCString(), 64, 64, aWinSize.x(), aWinSize.y()); #endif aWindow->SetVirtual(true); m_view = new V3d_View(myViewer); @@ -120,13 +122,11 @@ void Occt_view::init_viewer() return; } - Handle(OpenGl_GraphicDriver) aGraphicDriver = - new OpenGl_GraphicDriver(m_occt_window->GetDisplay(), false); + Handle(OpenGl_GraphicDriver) aGraphicDriver = new OpenGl_GraphicDriver(m_occt_window->GetDisplay(), false); aGraphicDriver->ChangeOptions().buffersNoSwap = true; aGraphicDriver->ChangeOptions().buffersOpaqueAlpha = true; - aGraphicDriver->ChangeOptions().sRGBDisable = - true; // Otherwise colors are wrong when native. + aGraphicDriver->ChangeOptions().sRGBDisable = true; // Otherwise colors are wrong when native. Handle(V3d_Viewer) aViewer = new V3d_Viewer(aGraphicDriver); @@ -143,28 +143,23 @@ void Occt_view::init_viewer() m_ctx = new AIS_InteractiveContext(aViewer); #else Handle(Aspect_DisplayConnection) aDisp; - Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver(aDisp, false); - aDriver->ChangeOptions().buffersNoSwap = true; // swap has no effect in WebGL - aDriver->ChangeOptions().buffersOpaqueAlpha = - true; // avoid unexpected blending of canvas with page background + Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver(aDisp, false); + aDriver->ChangeOptions().buffersNoSwap = true; // swap has no effect in WebGL + aDriver->ChangeOptions().buffersOpaqueAlpha = true; // avoid unexpected blending of canvas with page background // Match native OpenGL path (sRGBDisable) so shading/material gamma is consistent vs desktop. aDriver->ChangeOptions().sRGBDisable = true; if (!aDriver->InitContext()) { - Message::DefaultMessenger()->Send( - TCollection_AsciiString("Error: EGL initialization failed"), - Message_Fail); + Message::DefaultMessenger()->Send(TCollection_AsciiString("Error: EGL initialization failed"), Message_Fail); return; } Handle(V3d_Viewer) aViewer = new V3d_Viewer(aDriver); - aViewer->SetDefaultComputedMode(Standard_True); // Enable better quality rendering + aViewer->SetDefaultComputedMode(Standard_True); // Enable better quality rendering aViewer->SetDefaultShadingModel(Graphic3d_TypeOfShadingModel_Phong); aViewer->SetDefaultLights(); aViewer->SetLightOn(); - for (V3d_ListOfLight::Iterator aLightIter(aViewer->ActiveLights()); - aLightIter.More(); - aLightIter.Next()) + for (V3d_ListOfLight::Iterator aLightIter(aViewer->ActiveLights()); aLightIter.More(); aLightIter.Next()) { const Handle(V3d_Light)& aLight = aLightIter.Value(); if (aLight->Type() == Graphic3d_TypeOfLightSource_Directional) @@ -193,8 +188,8 @@ void Occt_view::init_viewer() for (const char* alias : {Font_NOF_SERIF, Font_NOF_SANS_SERIF, Font_NOF_MONOSPACE}) { const TCollection_AsciiString alias_str(alias); - (void) font_mgr->RemoveFontAlias(alias_str, TCollection_AsciiString()); - (void) font_mgr->AddFontAlias(alias_str, family); + (void)font_mgr->RemoveFontAlias(alias_str, TCollection_AsciiString()); + (void)font_mgr->AddFontAlias(alias_str, family); } } } @@ -203,13 +198,13 @@ void Occt_view::init_viewer() m_view->SetImmediateUpdate(false); auto& params = m_view->ChangeRenderingParams(); params.ToShowStats = true; - params.NbMsaaSamples = 8; // Set MSAA samples - params.RenderResolutionScale = 2.0; // Increase resolution scale - params.IsShadowEnabled = true; // Enable shadows - params.ShadowMapResolution = 1024; // Shadow map resolution - params.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED; // Better transparency - params.OitDepthFactor = 0.0; // Depth peeling for better transparency - params.Resolution = (unsigned int) (96.0 * myDevicePixelRatio + 0.5); + params.NbMsaaSamples = 8; // Set MSAA samples + params.RenderResolutionScale = 2.0; // Increase resolution scale + params.IsShadowEnabled = true; // Enable shadows + params.ShadowMapResolution = 1024; // Shadow map resolution + params.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED; // Better transparency + params.OitDepthFactor = 0.0; // Depth peeling for better transparency + params.Resolution = (unsigned int)(96.0 * myDevicePixelRatio + 0.5); // m_view->SetScale(1000.0); // Treat coordinates as millimeters // m_view->SetScale(39.3701); @@ -227,16 +222,16 @@ void Occt_view::init_viewer() aViewer->SetDefaultLights(); aViewer->SetLightOn(); - m_ctx->SetAutoActivateSelection(Standard_True); // Enable automatic selection + m_ctx->SetAutoActivateSelection(Standard_True); // Enable automatic selection - auto highlight_style = m_ctx->HighlightStyle(); + auto highlight_style = m_ctx->HighlightStyle(); // highlight_style->SetDisplayMode(1); Handle(Graphic3d_AspectFillArea3d) fill_aspect = new Graphic3d_AspectFillArea3d(); fill_aspect->SetAlphaMode(Graphic3d_AlphaMode::Graphic3d_AlphaMode_Blend); fill_aspect->SetColor(Quantity_Color(0.1, 0.1, 0.1, Quantity_TOC_RGB)); highlight_style->SetColor(Quantity_NOC_YELLOW); highlight_style->SetBasicFillAreaAspect(fill_aspect); - highlight_style->SetTransparency(0.8f); // Seems to not do anything + highlight_style->SetTransparency(0.8f); // Seems to not do anything /* Handle(Prs3d_LineAspect) line_aspect = new Prs3d_LineAspect( @@ -251,23 +246,21 @@ void Occt_view::init_viewer() m_ctx->SetHighlightStyle(highlight_style); // m_ctx->SetAutomaticHilight(false); // m_ctx->SetSelectionStyle(highlight_style); - m_ctx->SetPixelTolerance(10); // Picking? + m_ctx->SetPixelTolerance(10); // Picking? m_ctx->UpdateCurrentViewer(); // Set initial colors to match what OCCT renders (light gradient + grid) m_bg_color1 = glm::vec3(0.85f, 0.88f, 0.90f); m_bg_color2 = glm::vec3(0.45f, 0.55f, 0.60f); - m_bg_gradient_method = 1; // Vertical + m_bg_gradient_method = 1; // Vertical m_grid_color1 = glm::vec3(0.1f, 0.1f, 0.1f); m_grid_color2 = glm::vec3(0.1f, 0.1f, 0.3f); update_view_background_(); Handle(AIS_ViewCube) myViewCube = new AIS_ViewCube(); myViewCube->SetTransformPersistence( - new Graphic3d_TransformPers(Graphic3d_TMF_TriedronPers, - Aspect_TOTP_RIGHT_LOWER, - Graphic3d_Vec2i(100, 100))); + new Graphic3d_TransformPers(Graphic3d_TMF_TriedronPers, Aspect_TOTP_RIGHT_LOWER, Graphic3d_Vec2i(100, 100))); myViewCube->Attributes()->SetDatumAspect(new Prs3d_DatumAspect()); // myViewCube->Attributes()->DatumAspect()->SetTextAspect(myTextStyle); // animation parameters @@ -350,12 +343,7 @@ void Occt_view::snap_view_to_nearest_standard_axis() gp_Dir fwd(to_center); static const gp_Dir k_axes[6] = { - gp_Dir(1, 0, 0), - gp_Dir(-1, 0, 0), - gp_Dir(0, 1, 0), - gp_Dir(0, -1, 0), - gp_Dir(0, 0, 1), - gp_Dir(0, 0, -1), + gp_Dir(1, 0, 0), gp_Dir(-1, 0, 0), gp_Dir(0, 1, 0), gp_Dir(0, -1, 0), gp_Dir(0, 0, 1), gp_Dir(0, 0, -1), }; int best_i = 0; @@ -396,8 +384,7 @@ void Occt_view::init_default() if (m_ctx.IsNull()) return; - m_view->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, - Quantity_NOC_GOLD, + m_view->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, Quantity_NOC_GOLD, // 0.08, 0.01 / 5, // 0.5, @@ -407,27 +394,22 @@ void Occt_view::init_default() { TColStd_IndexedDataMapOfStringString aRendInfo; m_view->DiagnosticInformation(aRendInfo, Graphic3d_DiagnosticInfo_Basic); - for (TColStd_IndexedDataMapOfStringString::Iterator aValueIter(aRendInfo); - aValueIter.More(); - aValueIter.Next()) + for (TColStd_IndexedDataMapOfStringString::Iterator aValueIter(aRendInfo); aValueIter.More(); aValueIter.Next()) { if (!aGlInfo.IsEmpty()) aGlInfo += "\n"; - aGlInfo += TCollection_AsciiString(" ") + aValueIter.Key() + ": " + - aValueIter.Value(); + aGlInfo += TCollection_AsciiString(" ") + aValueIter.Key() + ": " + aValueIter.Value(); } } - Message::DefaultMessenger()->Send( - TCollection_AsciiString("OpenGL info:\n") + aGlInfo, - Message_Info); + Message::DefaultMessenger()->Send(TCollection_AsciiString("OpenGL info:\n") + aGlInfo, Message_Info); SetStickToRayOnRotation(true); SetStickToRayOnZoom(true); SetRotationMode(AIS_RotationMode_PickLast); - m_view->SetProj(0, 0, 1); // Look up the Z-axis (top view) - m_view->SetUp(0, 1, 0); // Up direction along Y-axis + m_view->SetProj(0, 0, 1); // Look up the Z-axis (top view) + m_view->SetUp(0, 1, 0); // Up direction along Y-axis // Optional: Adjust zoom or fit content m_view->SetZoom(2.0); @@ -451,11 +433,8 @@ std::optional Occt_view::pt3d_on_plane(const ScreenCoords& screen_coords // TODO there must be a way to do this using the MVP matrixes. // Convert 2D screen coordinates to 3D world coordinates near the camera Standard_Real x_near, y_near, z_near; - m_view->Convert((Standard_Integer) screen_coords.unsafe_get_x(), - (Standard_Integer) screen_coords.unsafe_get_y(), - x_near, - y_near, - z_near); + m_view->Convert((Standard_Integer)screen_coords.unsafe_get_x(), (Standard_Integer)screen_coords.unsafe_get_y(), x_near, + y_near, z_near); gp_Pnt near_point(x_near, y_near, z_near); const Graphic3d_Camera_ptr& camera = m_view->Camera(); @@ -467,7 +446,7 @@ std::optional Occt_view::pt3d_on_plane(const ScreenCoords& screen_coords GeomAPI_IntCS intersection(ray_line, geom_plane); if (intersection.NbPoints() > 0) - return intersection.Point(1); // First intersection point + return intersection.Point(1); // First intersection point // No intersection with plane. return std::nullopt; @@ -475,28 +454,28 @@ std::optional Occt_view::pt3d_on_plane(const ScreenCoords& screen_coords switch (camera->ProjectionType()) { - case Graphic3d_Camera::Projection::Projection_Orthographic: - { - gp_Dir view_dir = camera->Direction().Reversed(); // Reverse to point into the scene + case Graphic3d_Camera::Projection::Projection_Orthographic: + { + gp_Dir view_dir = camera->Direction().Reversed(); // Reverse to point into the scene - // Define the ray as a line from near_point along view_dir - Geom_Line_ptr ray_line = new Geom_Line(near_point, view_dir); - return get_intersection(ray_line); - } + // Define the ray as a line from near_point along view_dir + Geom_Line_ptr ray_line = new Geom_Line(near_point, view_dir); + return get_intersection(ray_line); + } - case Graphic3d_Camera::Projection::Projection_Perspective: - { - gp_Pnt eye_pos = m_view->Camera()->Eye(); - // Define the ray direction from eye through the near point - gp_Vec ray_dir(eye_pos, near_point); - ray_dir.Normalize(); + case Graphic3d_Camera::Projection::Projection_Perspective: + { + gp_Pnt eye_pos = m_view->Camera()->Eye(); + // Define the ray direction from eye through the near point + gp_Vec ray_dir(eye_pos, near_point); + ray_dir.Normalize(); - Geom_Line_ptr ray_line = new Geom_Line(eye_pos, gp_Dir(ray_dir)); - return get_intersection(ray_line); - } + Geom_Line_ptr ray_line = new Geom_Line(eye_pos, gp_Dir(ray_dir)); + return get_intersection(ray_line); + } - default: - EZY_ASSERT(false); + default: + EZY_ASSERT(false); } // Should not get here. @@ -513,9 +492,7 @@ void Occt_view::bake_transform_into_geometry(AIS_Shape_ptr& shape) TopoDS_Shape original_shape = shape->Shape(); // Apply the transformation to the geometry - BRepBuilderAPI_Transform transformer(original_shape, - current_transform, - true); + BRepBuilderAPI_Transform transformer(original_shape, current_transform, true); TopoDS_Shape transformed_shape = transformer.Shape(); @@ -541,13 +518,13 @@ void Occt_view::on_enter(const ScreenCoords& screen_coords) { switch (get_mode()) { - case Mode::Sketch_face_extrude: - // Apply typed distance (dist edit) and refresh preview only. LMB finalizes the extrusion (see on_mouse_button / GUI). - sketch_face_extrude(screen_coords, true); - break; - default: - curr_sketch().on_enter(); - break; + case Mode::Sketch_face_extrude: + // Apply typed distance (dist edit) and refresh preview only. LMB finalizes the extrusion (see on_mouse_button / GUI). + sketch_face_extrude(screen_coords, true); + break; + default: + curr_sketch().on_enter(); + break; } } @@ -557,22 +534,22 @@ void Occt_view::cancel(Set_parent_mode set_parent_mode) switch (get_mode()) { - case Mode::Move: - shp_move().cancel(); - gui().set_mode(Mode::Normal); - break; - case Mode::Rotate: - shp_rotate().cancel(); - gui().set_mode(Mode::Normal); - break; - case Mode::Scale: - shp_scale().cancel(); - gui().set_mode(Mode::Normal); - break; - default: - operation_canceled |= cancel_sketch_extrude_(); - operation_canceled |= curr_sketch().cancel_elm(); - break; + case Mode::Move: + shp_move().cancel(); + gui().set_mode(Mode::Normal); + break; + case Mode::Rotate: + shp_rotate().cancel(); + gui().set_mode(Mode::Normal); + break; + case Mode::Scale: + shp_scale().cancel(); + gui().set_mode(Mode::Normal); + break; + default: + operation_canceled |= cancel_sketch_extrude_(); + operation_canceled |= curr_sketch().cancel_elm(); + break; } if (set_parent_mode == Set_parent_mode::Yes) @@ -627,10 +604,7 @@ void Occt_view::finalize_sketch_extrude_() m_shp_extrude.finalize(); } -bool Occt_view::cancel_sketch_extrude_() -{ - return m_shp_extrude.cancel(); -} +bool Occt_view::cancel_sketch_extrude_() { return m_shp_extrude.cancel(); } void Occt_view::create_default_sketch_() { @@ -693,12 +667,7 @@ bool Occt_view::sketch_plane_view_aabb_2d(const gp_Pln& pln, double display_w, d struct { double x, y; - } corners[4] = { - {x0, y0}, - {x1, y0}, - {x1, y1}, - {x0, y1} - }; + } corners[4] = {{x0, y0}, {x1, y0}, {x1, y1}, {x0, y1}}; bool any = false; double min_u = 0., min_v = 0., max_u = 0., max_v = 0.; @@ -777,9 +746,8 @@ void Occt_view::set_camera(const gp_Pnt& eye, const gp_Pnt& center, const gp_Dir const TopoDS_Shape* Occt_view::get_(const ScreenCoords& screen_coords) const { - AIS_StatusOfDetection detection_status = m_ctx->MoveTo( - Standard_Integer(screen_coords.unsafe_get_x()), - Standard_Integer(screen_coords.unsafe_get_y()), m_view, true); + AIS_StatusOfDetection detection_status = m_ctx->MoveTo(Standard_Integer(screen_coords.unsafe_get_x()), + Standard_Integer(screen_coords.unsafe_get_y()), m_view, true); if (detection_status == AIS_SOD_Nothing) return nullptr; @@ -833,11 +801,8 @@ Ray Occt_view::get_hit_test_ray_(const ScreenCoords& screen_coords) const Graphic3d_Camera_ptr camera = m_view->Camera(); gp_Pnt eye_pos = camera->Eye(); Standard_Real x_near, y_near, z_near; - m_view->Convert((Standard_Integer) screen_coords.unsafe_get_x(), - (Standard_Integer) screen_coords.unsafe_get_y(), - x_near, - y_near, - z_near); + m_view->Convert((Standard_Integer)screen_coords.unsafe_get_x(), (Standard_Integer)screen_coords.unsafe_get_y(), x_near, + y_near, z_near); gp_Pnt near_point(x_near, y_near, z_near); gp_Vec ray_dir(eye_pos, near_point); ray_dir.Normalize(); @@ -868,7 +833,7 @@ std::optional Occt_view::get_hit_point_(const AIS_Shape_ptr& shp, const void Occt_view::add_shp_(Shp_ptr& shp) { shp->SetMaterial(m_default_material); - shp->set_selection_mode(m_shp_selection_mode); // Adds to m_ctx + shp->set_selection_mode(m_shp_selection_mode); // Adds to m_ctx m_shps.push_back(shp); } @@ -886,8 +851,8 @@ std::string Occt_view::unique_shape_name_(const char* base_name) const else if (n.size() > prefix.size() && n.compare(0, prefix.size(), prefix) == 0) { const std::string suffix = n.substr(prefix.size()); - if (!suffix.empty() && std::all_of(suffix.begin(), suffix.end(), [](char c) - { return std::isdigit(static_cast(c)); })) + if (!suffix.empty() && + std::all_of(suffix.begin(), suffix.end(), [](char c) { return std::isdigit(static_cast(c)); })) { int idx = 0; try @@ -898,7 +863,7 @@ std::string Occt_view::unique_shape_name_(const char* base_name) const } catch (...) { - EZY_ASSERT(false); // Should not happen due to the isdigit check, but just in case. + EZY_ASSERT(false); // Should not happen due to the isdigit check, but just in case. } } } @@ -916,10 +881,7 @@ std::string Occt_view::unique_shape_name_(const char* base_name) const return base + buf; } -std::string Occt_view::get_unique_shape_name(const char* base_name) const -{ - return unique_shape_name_(base_name); -} +std::string Occt_view::get_unique_shape_name(const char* base_name) const { return unique_shape_name_(base_name); } void Occt_view::add_box(double ox, double oy, double oz, double width, double length, double height) { @@ -1028,7 +990,7 @@ bool Occt_view::fit_face_in_view(const TopoDS_Face& face) // Set camera direction to look down the normal gp_Dir normal = pln->Axis().Direction(); - gp_Pnt center = pln->Location(); // Use plane origin as initial center + gp_Pnt center = pln->Location(); // Use plane origin as initial center // Compute the bounding box of the face to refine the center and size Bnd_Box bbox; @@ -1045,14 +1007,14 @@ bool Occt_view::fit_face_in_view(const TopoDS_Face& face) center.SetCoord((x_min + x_max) / 2.0, (y_min + y_max) / 2.0, (z_min + z_max) / 2.0); // Set the view direction (looking "down" means opposite to normal) - gp_Dir view_dir = normal.Reversed(); // Look down at the face + gp_Dir view_dir = normal.Reversed(); // Look down at the face m_view->SetAt(center.X(), center.Y(), center.Z()); - gp_Pnt eye = center.Translated(gp_Vec(view_dir).Multiplied(100.0)); // Target point (center of face) - m_view->SetEye(eye.X(), eye.Y(), eye.Z()); // Eye 100 units above + gp_Pnt eye = center.Translated(gp_Vec(view_dir).Multiplied(100.0)); // Target point (center of face) + m_view->SetEye(eye.X(), eye.Y(), eye.Z()); // Eye 100 units above m_view->SetUp(0, 0, 1); // Fit the face in view - m_view->FitAll(bbox, 0.5); // 0.5 is margin factor (50% padding) - m_view->Redraw(); // Update the view + m_view->FitAll(bbox, 0.5); // 0.5 is margin factor (50% padding) + m_view->Redraw(); // Update the view return true; } @@ -1075,45 +1037,27 @@ void Occt_view::dimension_input(const ScreenCoords& screen_coords) { switch (get_mode()) { - case Mode::Sketch_face_extrude: - m_show_dim_input = true; - sketch_face_extrude(screen_coords, true); - break; - default: - curr_sketch().dimension_input(screen_coords); - break; + case Mode::Sketch_face_extrude: + m_show_dim_input = true; + sketch_face_extrude(screen_coords, true); + break; + default: + curr_sketch().dimension_input(screen_coords); + break; } } -void Occt_view::angle_input(const ScreenCoords& screen_coords) -{ - curr_sketch().angle_input(screen_coords); -} +void Occt_view::angle_input(const ScreenCoords& screen_coords) { curr_sketch().angle_input(screen_coords); } -double Occt_view::get_dimension_scale() const -{ - return m_dimension_scale; -} +double Occt_view::get_dimension_scale() const { return m_dimension_scale; } -bool Occt_view::get_show_dim_input() const -{ - return m_show_dim_input; -} +bool Occt_view::get_show_dim_input() const { return m_show_dim_input; } -void Occt_view::set_show_dim_input(bool show) -{ - m_show_dim_input = show; -} +void Occt_view::set_show_dim_input(bool show) { m_show_dim_input = show; } -std::optional Occt_view::get_entered_dim() const -{ - return m_entered_dim; -} +std::optional Occt_view::get_entered_dim() const { return m_entered_dim; } -void Occt_view::set_entered_dim(const std::optional& dim) -{ - m_entered_dim = dim; -} +void Occt_view::set_entered_dim(const std::optional& dim) { m_entered_dim = dim; } void Occt_view::sketch_face_extrude(const ScreenCoords& screen_coords, bool is_mouse_move) { @@ -1126,7 +1070,7 @@ void Occt_view::delete_selected() remove_selected_length_dimensions_from_sketches_(); auto selected = get_selected(); delete_(selected); - cancel(Set_parent_mode::No); // In case we are in the middle of a operation. + cancel(Set_parent_mode::No); // In case we are in the middle of a operation. } void Occt_view::remove_selected_length_dimensions_from_sketches_() @@ -1171,10 +1115,10 @@ void Occt_view::delete_(std::vector& to_delete) static Aspect_GradientFillMethod gradient_method_from_int(int i) { - static const Aspect_GradientFillMethod methods[] = { - Aspect_GFM_HOR, Aspect_GFM_VER, Aspect_GFM_DIAG1, Aspect_GFM_DIAG2, - Aspect_GFM_CORNER1, Aspect_GFM_CORNER2, Aspect_GFM_CORNER3, Aspect_GFM_CORNER4}; - const int n = static_cast(sizeof(methods) / sizeof(methods[0])); + static const Aspect_GradientFillMethod methods[] = {Aspect_GFM_HOR, Aspect_GFM_VER, Aspect_GFM_DIAG1, + Aspect_GFM_DIAG2, Aspect_GFM_CORNER1, Aspect_GFM_CORNER2, + Aspect_GFM_CORNER3, Aspect_GFM_CORNER4}; + const int n = static_cast(sizeof(methods) / sizeof(methods[0])); if (i < 0 || i >= n) return Aspect_GFM_VER; return methods[i]; @@ -1185,11 +1129,9 @@ void Occt_view::update_view_background_() if (m_view.IsNull()) return; - m_view->SetBgGradientColors( - Quantity_Color(m_bg_color1.x, m_bg_color1.y, m_bg_color1.z, Quantity_TOC_RGB), - Quantity_Color(m_bg_color2.x, m_bg_color2.y, m_bg_color2.z, Quantity_TOC_RGB), - gradient_method_from_int(m_bg_gradient_method), - Standard_True); + m_view->SetBgGradientColors(Quantity_Color(m_bg_color1.x, m_bg_color1.y, m_bg_color1.z, Quantity_TOC_RGB), + Quantity_Color(m_bg_color2.x, m_bg_color2.y, m_bg_color2.z, Quantity_TOC_RGB), + gradient_method_from_int(m_bg_gradient_method), Standard_True); Handle(V3d_Viewer) viewer = m_view->Viewer(); if (!viewer.IsNull() && !viewer->Grid().IsNull()) @@ -1216,10 +1158,7 @@ void Occt_view::set_bg_gradient_colors(float r1, float g1, float b1, float r2, f update_view_background_(); } -int Occt_view::get_bg_gradient_method() const -{ - return m_bg_gradient_method; -} +int Occt_view::get_bg_gradient_method() const { return m_bg_gradient_method; } void Occt_view::set_bg_gradient_method(int method) { @@ -1282,19 +1221,17 @@ namespace { // Blender-style: Shift held while zooming uses a finer step (same idea as precision transforms). constexpr double k_zoom_shift_finer_factor = 0.1; -} // namespace +} // namespace void Occt_view::set_zoom_scroll_scale(double scale) { - m_zoom_scroll_scale = - std::clamp(scale, k_gui_view_zoom_scroll_scale_min, k_gui_view_zoom_scroll_scale_max); + m_zoom_scroll_scale = std::clamp(scale, k_gui_view_zoom_scroll_scale_min, k_gui_view_zoom_scroll_scale_max); } int Occt_view::zoom_scroll_delta_int_(double wheel_y, bool shift_finer_zoom) const { - const double scaled = - wheel_y * m_zoom_scroll_scale * (shift_finer_zoom ? k_zoom_shift_finer_factor : 1.0); - long r = std::lround(scaled); + const double scaled = wheel_y * m_zoom_scroll_scale * (shift_finer_zoom ? k_zoom_shift_finer_factor : 1.0); + long r = std::lround(scaled); if (r == 0 && wheel_y != 0.0) r = wheel_y > 0.0 ? 1L : -1L; @@ -1303,10 +1240,9 @@ int Occt_view::zoom_scroll_delta_int_(double wheel_y, bool shift_finer_zoom) con void Occt_view::on_mouse_scroll(double theOffsetX, double theOffsetY, bool shift_finer_zoom) { - (void) theOffsetX; + (void)theOffsetX; if (!m_view.IsNull()) - UpdateZoom(Aspect_ScrollDelta(m_occt_window->CursorPosition(), - zoom_scroll_delta_int_(theOffsetY, shift_finer_zoom))); + UpdateZoom(Aspect_ScrollDelta(m_occt_window->CursorPosition(), zoom_scroll_delta_int_(theOffsetY, shift_finer_zoom))); } void Occt_view::zoom_view_wheel_notches(double wheel_notches, bool shift_finer_zoom) @@ -1314,8 +1250,7 @@ void Occt_view::zoom_view_wheel_notches(double wheel_notches, bool shift_finer_z if (m_view.IsNull()) return; - UpdateZoom(Aspect_ScrollDelta(m_occt_window->CursorPosition(), - zoom_scroll_delta_int_(wheel_notches, shift_finer_zoom))); + UpdateZoom(Aspect_ScrollDelta(m_occt_window->CursorPosition(), zoom_scroll_delta_int_(wheel_notches, shift_finer_zoom))); } void Occt_view::on_mouse_button(int theButton, int theAction, int theMods) @@ -1336,10 +1271,7 @@ void Occt_view::on_mouse_button(int theButton, int theAction, int theMods) return; } - PressMouseButton(pos, - mouse_button_from_glfw_(theButton), - key_flags_from_glfw_(theMods), - false); + PressMouseButton(pos, mouse_button_from_glfw_(theButton), key_flags_from_glfw_(theMods), false); if (m_shp_extrude.has_active_extrusion()) { @@ -1349,11 +1281,11 @@ void Occt_view::on_mouse_button(int theButton, int theAction, int theMods) switch (get_mode()) { - case Mode::Sketch_dim_anno: - return curr_sketch().toggle_edge_dim_anno(ScreenCoords(dvec2(pos.x(), pos.y()))); + case Mode::Sketch_dim_anno: + return curr_sketch().toggle_edge_dim_anno(ScreenCoords(dvec2(pos.x(), pos.y()))); - default: - break; + default: + break; } } else @@ -1364,10 +1296,7 @@ void Occt_view::on_mouse_button(int theButton, int theAction, int theMods) return; } - ReleaseMouseButton(pos, - mouse_button_from_glfw_(theButton), - key_flags_from_glfw_(theMods), - false); + ReleaseMouseButton(pos, mouse_button_from_glfw_(theButton), key_flags_from_glfw_(theMods), false); } } @@ -1375,9 +1304,7 @@ void Occt_view::on_mouse_move(const ScreenCoords& screen_coords) { EZY_ASSERT(!m_view.IsNull()); UpdateMousePosition(Graphic3d_Vec2i(int(screen_coords.unsafe_get_x()), int(screen_coords.unsafe_get_y())), - PressedMouseButtons(), - LastMouseFlags(), - false); + PressedMouseButtons(), LastMouseFlags(), false); } // Selection related @@ -1397,15 +1324,12 @@ std::vector Occt_view::get_selected() const shapes.emplace_back(std::move(selected_shape)); } - m_ctx->NextSelected(); // Move to the next selected object + m_ctx->NextSelected(); // Move to the next selected object } return shapes; } -TopAbs_ShapeEnum Occt_view::get_shp_selection_mode() const -{ - return m_shp_selection_mode; -} +TopAbs_ShapeEnum Occt_view::get_shp_selection_mode() const { return m_shp_selection_mode; } void Occt_view::set_shp_selection_mode(const TopAbs_ShapeEnum mode) { @@ -1422,26 +1346,14 @@ void Occt_view::set_shp_selection_mode(const TopAbs_ShapeEnum mode) } // Material related -const Graphic3d_MaterialAspect& Occt_view::get_default_material() const -{ - return m_default_material; -} +const Graphic3d_MaterialAspect& Occt_view::get_default_material() const { return m_default_material; } -void Occt_view::set_default_material(const Graphic3d_MaterialAspect& mat) -{ - m_default_material = mat; -} +void Occt_view::set_default_material(const Graphic3d_MaterialAspect& mat) { m_default_material = mat; } -bool Occt_view::is_headless() const -{ - return m_headless_view; -} +bool Occt_view::is_headless() const { return m_headless_view; } // Mode related -Mode Occt_view::get_mode() const -{ - return m_gui.get_mode(); -} +Mode Occt_view::get_mode() const { return m_gui.get_mode(); } void Occt_view::on_mode() { @@ -1481,36 +1393,36 @@ void Occt_view::on_mode() switch (get_mode()) { - case Mode::Sketch_operation_axis: - show_only_current_sketch(); - break; + case Mode::Sketch_operation_axis: + show_only_current_sketch(); + break; - default: - show_sketches(true); - break; + default: + show_sketches(true); + break; } } else { switch (get_mode()) { - case Mode::Shape_polar_duplicate: - show_only_current_sketch(); - break; + case Mode::Shape_polar_duplicate: + show_only_current_sketch(); + break; - default: - show_sketches(false); - break; + default: + show_sketches(false); + break; } switch (get_mode()) { - // clang-format off + // clang-format off case Mode::Sketch_from_planar_face: set_shp_selection_mode(TopAbs_FACE); break; case Mode::Shape_chamfer: on_chamfer_mode(); break; // Will update selection mode case Mode::Shape_fillet: on_fillet_mode(); break; // Will update selection mode default: break; - // clang-format on + // clang-format on } for (auto shp : m_shps) @@ -1535,7 +1447,7 @@ void Occt_view::on_chamfer_mode() EZY_ASSERT(get_mode() == Mode::Shape_chamfer); switch (gui().get_chamfer_mode()) { - // clang-format off + // clang-format off case Chamfer_mode::Edge: set_shp_selection_mode(TopAbs_EDGE); break; case Chamfer_mode::Wire: set_shp_selection_mode(TopAbs_WIRE); break; case Chamfer_mode::Face: set_shp_selection_mode(TopAbs_FACE); break; @@ -1587,10 +1499,7 @@ Aspect_VKeyFlags Occt_view::key_flags_from_glfw_(int theFlags) return flags; } -Occt_view::Sketch_list& Occt_view::get_sketches() -{ - return m_sketches; -} +Occt_view::Sketch_list& Occt_view::get_sketches() { return m_sketches; } void Occt_view::remove_sketch(const Sketch_ptr& sketch) { @@ -1637,13 +1546,10 @@ void Occt_view::set_curr_sketch(const Sketch_ptr& to_set) return; } - EZY_ASSERT(false); // Sketch does not belong to this view. + EZY_ASSERT(false); // Sketch does not belong to this view. } -std::list& Occt_view::get_shapes() -{ - return m_shps; -} +std::list& Occt_view::get_shapes() { return m_shps; } // clang-format off Shp_move& Occt_view::shp_move() { return m_shp_move; } @@ -1696,7 +1602,7 @@ bool Occt_view::undo() redo_entry.json = to_json(); redo_entry.mode = m_gui.get_mode(); m_redo_stack.push_back(std::move(redo_entry)); - load(state.json, false); // Keep current view so undo/redo keeps a single perspective + load(state.json, false); // Keep current view so undo/redo keeps a single perspective m_gui.set_mode(state.mode); if (state.mode == Mode::Sketch_inspection_mode) m_gui.set_show_sketch_list(true); @@ -1717,7 +1623,7 @@ bool Occt_view::redo() undo_entry.json = to_json(); undo_entry.mode = m_gui.get_mode(); m_undo_stack.push_back(std::move(undo_entry)); - load(state.json, false); // Keep current view so undo/redo keeps a single perspective + load(state.json, false); // Keep current view so undo/redo keeps a single perspective m_gui.set_mode(state.mode); if (state.mode == Mode::Sketch_inspection_mode) m_gui.set_show_sketch_list(true); @@ -1726,25 +1632,13 @@ bool Occt_view::redo() return true; } -bool Occt_view::can_undo() const -{ - return !m_undo_stack.empty(); -} +bool Occt_view::can_undo() const { return !m_undo_stack.empty(); } -bool Occt_view::can_redo() const -{ - return !m_redo_stack.empty(); -} +bool Occt_view::can_redo() const { return !m_redo_stack.empty(); } -size_t Occt_view::undo_stack_size() const -{ - return m_undo_stack.size(); -} +size_t Occt_view::undo_stack_size() const { return m_undo_stack.size(); } -size_t Occt_view::redo_stack_size() const -{ - return m_redo_stack.size(); -} +size_t Occt_view::redo_stack_size() const { return m_redo_stack.size(); } // --------------------------------------------------------------------------- // Document format: 1 = legacy sketch edges could carry a 4th "dim" flag; 2 = length_dimensions array + 3-tuple edges. @@ -1776,7 +1670,7 @@ std::string Occt_view::to_json() const { const TopoDS_Shape& shape = s->Shape(); std::ostringstream oss; - BRepTools::Write(shape, oss, false, false, TopTools_FormatVersion_CURRENT); // Write BREP data to the stream + BRepTools::Write(shape, oss, false, false, TopTools_FormatVersion_CURRENT); // Write BREP data to the stream json shp_json; shp_json["name"] = s->get_name(); shp_json["material"] = s->Material(); @@ -1823,7 +1717,7 @@ void Occt_view::load(const std::string& json_str, bool restore_view) clear_all(m_sketches, m_cur_sketch, m_shps); const json j = json::parse(json_str); - (void) j.value("ezyFormat", 1); // Reserved for future migrations; sketch JSON migrates per-edge dim flags in Sketch_json. + (void)j.value("ezyFormat", 1); // Reserved for future migrations; sketch JSON migrates per-edge dim flags in Sketch_json. EZY_ASSERT(j.contains("sketches") && j["sketches"].is_array()); for (const auto& s : j["sketches"]) { @@ -1960,50 +1854,50 @@ Status Occt_view::export_document(Export_format fmt, const std::string& file_pat switch (fmt) { - case Export_format::Step: - { - STEPControl_Writer writer; - IFSelect_ReturnStatus tr = writer.Transfer(shape, STEPControl_AsIs); - if (tr != IFSelect_RetDone) - return Status::user_error("STEP transfer failed."); + case Export_format::Step: + { + STEPControl_Writer writer; + IFSelect_ReturnStatus tr = writer.Transfer(shape, STEPControl_AsIs); + if (tr != IFSelect_RetDone) + return Status::user_error("STEP transfer failed."); - tr = writer.Write(file_path.c_str()); - if (tr != IFSelect_RetDone) - return Status::user_error("STEP write failed."); + tr = writer.Write(file_path.c_str()); + if (tr != IFSelect_RetDone) + return Status::user_error("STEP write failed."); - return Status::ok(); - } - case Export_format::Iges: - { - IGESControl_Writer writer; - if (!writer.AddShape(shape)) - return Status::user_error("IGES does not support this shape."); + return Status::ok(); + } + case Export_format::Iges: + { + IGESControl_Writer writer; + if (!writer.AddShape(shape)) + return Status::user_error("IGES does not support this shape."); - if (!writer.Write(file_path.c_str())) - return Status::user_error("IGES write failed."); + if (!writer.Write(file_path.c_str())) + return Status::user_error("IGES write failed."); - return Status::ok(); - } - case Export_format::Stl: - { - // Tessellate for mesh export (linear deflection in model units). - constexpr Standard_Real k_lin_deflection = 0.1; - const BRepMesh_IncrementalMesh mesher(shape, k_lin_deflection); - (void) mesher; - StlAPI_Writer stl_writer; - stl_writer.ASCIIMode() = Standard_False; - if (!stl_writer.Write(shape, file_path.c_str())) - return Status::user_error("STL write failed."); - - return Status::ok(); - } - case Export_format::Ply: - { - constexpr Standard_Real k_lin_deflection = 0.1; - const BRepMesh_IncrementalMesh mesher(shape, k_lin_deflection); - (void) mesher; - return export_ply_binary_file(shape, file_path); - } + return Status::ok(); + } + case Export_format::Stl: + { + // Tessellate for mesh export (linear deflection in model units). + constexpr Standard_Real k_lin_deflection = 0.1; + const BRepMesh_IncrementalMesh mesher(shape, k_lin_deflection); + (void)mesher; + StlAPI_Writer stl_writer; + stl_writer.ASCIIMode() = Standard_False; + if (!stl_writer.Write(shape, file_path.c_str())) + return Status::user_error("STL write failed."); + + return Status::ok(); + } + case Export_format::Ply: + { + constexpr Standard_Real k_lin_deflection = 0.1; + const BRepMesh_IncrementalMesh mesher(shape, k_lin_deflection); + (void)mesher; + return export_ply_binary_file(shape, file_path); + } } return Status::user_error("Unknown export format."); } @@ -2060,15 +1954,9 @@ bool Occt_view::import_ply(const std::string& ply_bytes) return true; } -GUI& Occt_view::gui() -{ - return m_gui; -} +GUI& Occt_view::gui() { return m_gui; } -AIS_InteractiveContext& Occt_view::ctx() -{ - return *m_ctx; -} +AIS_InteractiveContext& Occt_view::ctx() { return *m_ctx; } void Occt_view::new_file() { diff --git a/src/occt_view.h b/src/occt_view.h index 58bc7c6..497f745 100644 --- a/src/occt_view.h +++ b/src/occt_view.h @@ -40,7 +40,10 @@ struct Ray gp_Dir direction; Ray(const gp_Pnt& orig, const gp_Dir& dir) - : origin(orig), direction(dir) {} + : origin(orig) + , direction(dir) + { + } }; enum class Set_parent_mode @@ -51,7 +54,7 @@ enum class Set_parent_mode class Occt_view : protected AIS_ViewController { - public: +public: DECL_PTR(Occt_view); using Sketch_ptr = std::shared_ptr; using Sketch_list = std::list; @@ -75,7 +78,7 @@ class Occt_view : protected AIS_ViewController // Undo / redo (document snapshot stack). /// Saves current document (full JSON) and mode. A future delta-based approach would save memory /// (store only changes per step) and CPU (apply/invert deltas instead of full serialize/load). - void push_undo_snapshot(); + void push_undo_snapshot(); /// Removes the last snapshot without restoring (e.g. aborted edit that did not change the document). void pop_undo_snapshot(); bool undo(); @@ -138,7 +141,7 @@ class Occt_view : protected AIS_ViewController // Revolve related void revolve_selected(const double angle); - void on_enter(const ScreenCoords& screen_coords); // For manual dimension distance keyboard input. + void on_enter(const ScreenCoords& screen_coords); // For manual dimension distance keyboard input. bool fit_face_in_view(const TopoDS_Face& face); // Dimension related @@ -172,8 +175,8 @@ class Occt_view : protected AIS_ViewController /// Axis-aligned bounds in sketch-plane 2D (gp_Pln UV) for the current view frustum intersecting \a pln. /// Uses \a display_w / \a display_h in the same pixel space as ImGui / GLFW cursor (full window). /// Returns false if the plane is not visible (e.g. headless or parallel view). - bool sketch_plane_view_aabb_2d(const gp_Pln& pln, double display_w, double display_h, double& out_min_u, - double& out_min_v, double& out_max_u, double& out_max_v) const; + bool sketch_plane_view_aabb_2d(const gp_Pln& pln, double display_w, double display_h, double& out_min_u, double& out_min_v, + double& out_max_u, double& out_max_v) const; bool get_camera(gp_Pnt& out_eye, gp_Pnt& out_center, gp_Dir& out_up) const; void set_camera(const gp_Pnt& eye, const gp_Pnt& center, const gp_Dir& up); @@ -218,11 +221,11 @@ class Occt_view : protected AIS_ViewController void new_file(); - private: +private: friend class Shp_operation_base; - friend class Shp_chamfer; // TODO remove - friend class Shp_fillet; // TODO remove - friend class Shp_extrude; // TODO remove + friend class Shp_chamfer; // TODO remove + friend class Shp_fillet; // TODO remove + friend class Shp_extrude; // TODO remove friend class View_access; // Sketch related @@ -264,53 +267,54 @@ class Occt_view : protected AIS_ViewController V3d_View_ptr m_view; Occt_glfw_win_ptr m_occt_window; // Undo / redo - static constexpr size_t k_max_undo {50}; + static constexpr size_t k_max_undo{50}; struct Undo_entry { std::string json; - Mode mode; // Mode at time of operation; restored when navigating stacks + Mode mode; // Mode at time of operation; restored when navigating stacks }; std::vector m_undo_stack; std::vector m_redo_stack; - bool m_restoring {false}; + bool m_restoring{false}; // -------------------------------------------------------------------- // Dimension related - bool m_show_dim_input {false}; - double m_dimension_scale {100.0}; + bool m_show_dim_input{false}; + double m_dimension_scale{100.0}; std::optional m_entered_dim; std::list m_shps; Sketch_list m_sketches; std::shared_ptr m_cur_sketch; - TopAbs_ShapeEnum m_shp_selection_mode {TopAbs_SHAPE}; + TopAbs_ShapeEnum m_shp_selection_mode{TopAbs_SHAPE}; Graphic3d_MaterialAspect m_default_material; - bool m_headless_view {false}; - /// True when LMB press was handled by planar-face sketch creation without AIS_ViewController::PressMouseButton (pair with release skip). - bool m_planar_face_lmb_skipped_view_controller {false}; + bool m_headless_view{false}; + /// True when LMB press was handled by planar-face sketch creation without AIS_ViewController::PressMouseButton (pair with + /// release skip). + bool m_planar_face_lmb_skipped_view_controller{false}; // OCCT view colors; defaults match what we render (set explicitly in init_viewer()) - glm::vec3 m_bg_color1 {0.85f, 0.88f, 0.90f}; - glm::vec3 m_bg_color2 {0.45f, 0.55f, 0.60f}; - int m_bg_gradient_method {1}; // 0=HOR, 1=VER, 2=DIAG1, ... - glm::vec3 m_grid_color1 {0.1f, 0.1f, 0.1f}; - glm::vec3 m_grid_color2 {0.1f, 0.1f, 0.3f}; + glm::vec3 m_bg_color1{0.85f, 0.88f, 0.90f}; + glm::vec3 m_bg_color2{0.45f, 0.55f, 0.60f}; + int m_bg_gradient_method{1}; // 0=HOR, 1=VER, 2=DIAG1, ... + glm::vec3 m_grid_color1{0.1f, 0.1f, 0.1f}; + glm::vec3 m_grid_color2{0.1f, 0.1f, 0.3f}; /// User setting: same role as former literal in `UpdateZoom(Aspect_ScrollDelta(..., int(y * scale)))`. - double m_zoom_scroll_scale {4.0}; + double m_zoom_scroll_scale{4.0}; // -------------------------------------------------------------------- // Operations - Shp_move m_shp_move; - Shp_rotate m_shp_rotate; - Shp_scale m_shp_scale; + Shp_move m_shp_move; + Shp_rotate m_shp_rotate; + Shp_scale m_shp_scale; // -------------------------------------------------------------------- // Commands - Shp_chamfer m_shp_chamfer; - Shp_fillet m_shp_fillet; - Shp_cut m_shp_cut; - Shp_fuse m_shp_fuse; - Shp_common m_shp_common; - Shp_polar_dup m_shp_polar_dup; - Shp_extrude m_shp_extrude; + Shp_chamfer m_shp_chamfer; + Shp_fillet m_shp_fillet; + Shp_cut m_shp_cut; + Shp_fuse m_shp_fuse; + Shp_common m_shp_common; + Shp_polar_dup m_shp_polar_dup; + Shp_extrude m_shp_extrude; }; template diff --git a/src/occt_view.inl b/src/occt_view.inl index 157ca46..6c951e2 100644 --- a/src/occt_view.inl +++ b/src/occt_view.inl @@ -2,16 +2,10 @@ // Member function to delete variable arguments template void Occt_view::remove(Args&&... args) { - for_each_flat( - [&](AIS_Shape_ptr& s) - { - m_ctx->Remove(s, true); - }, - std::forward(args)...); + for_each_flat([&](AIS_Shape_ptr& s) { m_ctx->Remove(s, true); }, std::forward(args)...); } -template -void show(AIS_InteractiveContext& ctx, Shp_ptr_t& shp, const T& obj, bool redraw) +template void show(AIS_InteractiveContext& ctx, Shp_ptr_t& shp, const T& obj, bool redraw) { if (shp) { diff --git a/src/ply_io.cpp b/src/ply_io.cpp index e19e908..7cdb79e 100644 --- a/src/ply_io.cpp +++ b/src/ply_io.cpp @@ -81,124 +81,123 @@ int size_of_scalar(ScalarType t) { switch (t) { - case ScalarType::Int8: - case ScalarType::UInt8: - return 1; - case ScalarType::Int16: - case ScalarType::UInt16: - return 2; - case ScalarType::Int32: - case ScalarType::UInt32: - case ScalarType::Float32: - return 4; - case ScalarType::Float64: - return 8; - default: - return 0; + case ScalarType::Int8: + case ScalarType::UInt8: + return 1; + case ScalarType::Int16: + case ScalarType::UInt16: + return 2; + case ScalarType::Int32: + case ScalarType::UInt32: + case ScalarType::Float32: + return 4; + case ScalarType::Float64: + return 8; + default: + return 0; } } struct ScalarProp { - ScalarType type {ScalarType::Unknown}; + ScalarType type{ScalarType::Unknown}; std::string name; }; struct ListProp { - ScalarType count_type {ScalarType::Unknown}; - ScalarType value_type {ScalarType::Unknown}; + ScalarType count_type{ScalarType::Unknown}; + ScalarType value_type{ScalarType::Unknown}; std::string name; }; struct ElementDesc { std::string name; - int count {0}; + int count{0}; std::vector scalars; std::vector lists; }; -bool read_scalar_bin_at(const unsigned char* base, - size_t off, - const unsigned char* endbuf, - ScalarType t, - double& out) +bool read_scalar_bin_at(const unsigned char* base, size_t off, const unsigned char* endbuf, ScalarType t, double& out) { const unsigned char* p = base + off; if (p >= endbuf) return false; - auto need = [&](size_t n) -> bool { return static_cast(endbuf - p) >= n; }; + auto need = [&](size_t n) -> bool + { + return static_cast(endbuf - p) >= n; + }; switch (t) { - case ScalarType::Int8: - { - if (!need(1)) - return false; - out = static_cast(*reinterpret_cast(p)); - return true; - } - case ScalarType::UInt8: - { - if (!need(1)) - return false; - out = static_cast(*p); - return true; - } - case ScalarType::Int16: - { - if (!need(2)) - return false; - std::int16_t v; - std::memcpy(&v, p, 2); - out = static_cast(v); - return true; - } - case ScalarType::UInt16: - { - if (!need(2)) - return false; - std::uint16_t v; - std::memcpy(&v, p, 2); - out = static_cast(v); - return true; - } - case ScalarType::Int32: - { - if (!need(4)) - return false; - std::int32_t v; - std::memcpy(&v, p, 4); - out = static_cast(v); - return true; - } - case ScalarType::UInt32: - { - if (!need(4)) - return false; - std::uint32_t v; - std::memcpy(&v, p, 4); - out = static_cast(v); - return true; - } - case ScalarType::Float32: - { - if (!need(4)) - return false; - float v; - std::memcpy(&v, p, 4); - out = static_cast(v); - return true; - } - case ScalarType::Float64: - { - if (!need(8)) - return false; - std::memcpy(&out, p, 8); - return true; - } - default: + case ScalarType::Int8: + { + if (!need(1)) + return false; + out = static_cast(*reinterpret_cast(p)); + return true; + } + case ScalarType::UInt8: + { + if (!need(1)) + return false; + out = static_cast(*p); + return true; + } + case ScalarType::Int16: + { + if (!need(2)) + return false; + std::int16_t v; + std::memcpy(&v, p, 2); + out = static_cast(v); + return true; + } + case ScalarType::UInt16: + { + if (!need(2)) return false; + std::uint16_t v; + std::memcpy(&v, p, 2); + out = static_cast(v); + return true; + } + case ScalarType::Int32: + { + if (!need(4)) + return false; + std::int32_t v; + std::memcpy(&v, p, 4); + out = static_cast(v); + return true; + } + case ScalarType::UInt32: + { + if (!need(4)) + return false; + std::uint32_t v; + std::memcpy(&v, p, 4); + out = static_cast(v); + return true; + } + case ScalarType::Float32: + { + if (!need(4)) + return false; + float v; + std::memcpy(&v, p, 4); + out = static_cast(v); + return true; + } + case ScalarType::Float64: + { + if (!need(8)) + return false; + std::memcpy(&out, p, 8); + return true; + } + default: + return false; } } @@ -206,42 +205,39 @@ std::uint32_t read_list_count_bin(const unsigned char*& p, const unsigned char* { switch (ct) { - case ScalarType::UInt8: - { - if (static_cast(end - p) < 1) - return 0; - std::uint32_t v = *p; - ++p; - return v; - } - case ScalarType::UInt16: - { - if (static_cast(end - p) < 2) - return 0; - std::uint16_t v; - std::memcpy(&v, p, 2); - p += 2; - return v; - } - case ScalarType::UInt32: - { - if (static_cast(end - p) < 4) - return 0; - std::uint32_t v; - std::memcpy(&v, p, 4); - p += 4; - return v; - } - default: + case ScalarType::UInt8: + { + if (static_cast(end - p) < 1) + return 0; + std::uint32_t v = *p; + ++p; + return v; + } + case ScalarType::UInt16: + { + if (static_cast(end - p) < 2) return 0; + std::uint16_t v; + std::memcpy(&v, p, 2); + p += 2; + return v; + } + case ScalarType::UInt32: + { + if (static_cast(end - p) < 4) + return 0; + std::uint32_t v; + std::memcpy(&v, p, 4); + p += 4; + return v; + } + default: + return 0; } } -bool read_face_indices_bin(const unsigned char*& p, - const unsigned char* end, - ScalarType vt, - std::uint32_t n, - std::vector& idx_out) +bool read_face_indices_bin(const unsigned char*& p, const unsigned char* end, ScalarType vt, std::uint32_t n, + std::vector& idx_out) { idx_out.clear(); idx_out.reserve(n); @@ -259,12 +255,7 @@ bool read_face_indices_bin(const unsigned char*& p, return true; } -bool append_triangle(TopoDS_Compound& comp, - BRep_Builder& bb, - const gp_Pnt& p0, - const gp_Pnt& p1, - const gp_Pnt& p2, - int& ntri) +bool append_triangle(TopoDS_Compound& comp, BRep_Builder& bb, const gp_Pnt& p0, const gp_Pnt& p1, const gp_Pnt& p2, int& ntri) { if (p0.IsEqual(p1, Precision::Confusion()) || p1.IsEqual(p2, Precision::Confusion()) || p2.IsEqual(p0, Precision::Confusion())) @@ -285,7 +276,7 @@ bool append_triangle(TopoDS_Compound& comp, return true; } -} // namespace +} // namespace Status import_ply_shape(const std::string& file_bytes, TopoDS_Shape& out_shape) { @@ -345,7 +336,7 @@ Status import_ply_shape(const std::string& file_bytes, TopoDS_Shape& out_shape) std::string name; int cnt = 0; iss >> name >> cnt; - elements.push_back(ElementDesc {}); + elements.push_back(ElementDesc{}); cur_el = &elements.back(); cur_el->name = std::move(name); cur_el->count = cnt; @@ -569,8 +560,8 @@ Status export_ply_binary_file(const TopoDS_Shape& shape, const std::string& file for (TopExp_Explorer exp(shape, TopAbs_FACE); exp.More(); exp.Next()) { - const TopoDS_Face& face = TopoDS::Face(exp.Current()); - TopLoc_Location loc; + const TopoDS_Face& face = TopoDS::Face(exp.Current()); + TopLoc_Location loc; const Handle(Poly_Triangulation)& tri = BRep_Tool::Triangulation(face, loc); if (tri.IsNull()) continue; @@ -585,7 +576,7 @@ Status export_ply_binary_file(const TopoDS_Shape& shape, const std::string& file const gp_Pnt p1 = tri->Node(i1).Transformed(tr); const gp_Pnt p2 = tri->Node(i2).Transformed(tr); const gp_Pnt p3 = tri->Node(i3).Transformed(tr); - tris.push_back(Tri {p1.X(), p1.Y(), p1.Z(), p2.X(), p2.Y(), p2.Z(), p3.X(), p3.Y(), p3.Z()}); + tris.push_back(Tri{p1.X(), p1.Y(), p1.Z(), p2.X(), p2.Y(), p2.Z(), p3.X(), p3.Y(), p3.Z()}); } } @@ -620,9 +611,9 @@ Status export_ply_binary_file(const TopoDS_Shape& shape, const std::string& file for (size_t fi = 0; fi < nf; ++fi) { const unsigned char three = 3; - const std::int32_t i0 = static_cast(fi * 3); - const std::int32_t i1 = static_cast(fi * 3 + 1); - const std::int32_t i2 = static_cast(fi * 3 + 2); + const std::int32_t i0 = static_cast(fi * 3); + const std::int32_t i1 = static_cast(fi * 3 + 1); + const std::int32_t i2 = static_cast(fi * 3 + 2); out.write(reinterpret_cast(&three), 1); out.write(reinterpret_cast(&i0), 4); out.write(reinterpret_cast(&i1), 4); diff --git a/src/python_console.cpp b/src/python_console.cpp index 9896092..21febd6 100644 --- a/src/python_console.cpp +++ b/src/python_console.cpp @@ -153,25 +153,16 @@ _ezycad_bootstrap() del _ezycad_bootstrap )PY"; -} // namespace +} // namespace PYBIND11_EMBEDDED_MODULE(ezycad_native, m) { py::class_(m, "Shp") - .def("name", [](const Ezy_shp& s) - { return s.shp->get_name(); }) - .def("set_name", [](Ezy_shp& s, const std::string& n) - { s.shp->set_name(n); }) - .def("visible", [](const Ezy_shp& s) - { return s.shp->get_visible(); }) - .def("set_visible", [](Ezy_shp& s, bool v) - { s.shp->set_visible(v); }) - .def( - "__repr__", - [](const Ezy_shp& s) - { - return ""; - }); + .def("name", [](const Ezy_shp& s) { return s.shp->get_name(); }) + .def("set_name", [](Ezy_shp& s, const std::string& n) { s.shp->set_name(n); }) + .def("visible", [](const Ezy_shp& s) { return s.shp->get_visible(); }) + .def("set_visible", [](Ezy_shp& s, bool v) { s.shp->set_visible(v); }) + .def("__repr__", [](const Ezy_shp& s) { return ""; }); m.def( "ezy_log", @@ -194,15 +185,14 @@ PYBIND11_EMBEDDED_MODULE(ezycad_native, m) }, py::arg("text")); - m.def( - "ezy_get_mode", - [] - { - if (!g_py_gui) - return std::string("Normal"); - Mode mmode = g_py_gui->get_mode(); - return std::string(c_mode_strs[static_cast(mmode)]); - }); + m.def("ezy_get_mode", + [] + { + if (!g_py_gui) + return std::string("Normal"); + Mode mmode = g_py_gui->get_mode(); + return std::string(c_mode_strs[static_cast(mmode)]); + }); m.def( "ezy_set_mode", @@ -213,78 +203,72 @@ PYBIND11_EMBEDDED_MODULE(ezycad_native, m) }, py::arg("name")); - m.def( - "ezy_help", - [] - { - if (!g_py_console) - return; - const char* help_text = - "ezy:\n" - " ezy.log(msg) - append message to console and log window\n" - " ezy.msg(text) - show status message\n" - " ezy.get_mode() - return current mode name\n" - " ezy.set_mode(name) - set mode by name\n" - " ezy.save_occt_view_settings() - write settings JSON (incl. view colors)\n" - " ezy.occt_view_settings_json() - JSON: occt_view + gui edge_dim_*, view_roll_step_deg, view_zoom_scroll_scale\n" - " ezy.help() - print this help\n" - "view:\n" - " view.sketch_count() - number of sketches\n" - " view.shape_count() - number of shapes\n" - " view.curr_sketch_name() - current sketch name\n" - " view.add_box(ox,oy,oz,w,l,h) - add box\n" - " view.add_sphere(ox,oy,oz,r) - add sphere\n" - " view.get_shape(i) - get shape by 0-based index (raises IndexError if out of range)\n" - " view.get_camera() - get camera eye/center/up vectors\n" - " view.set_camera(ex,ey,ez,cx,cy,cz,ux,uy,uz) - set camera vectors\n" - "Shp:\n" - " s.name() - get shape name\n" - " s.set_name(s) - set shape name\n" - " s.visible() - get visibility\n" - " s.set_visible(b) - set visibility"; - g_py_console->append_line_from_python(help_text); - }); - - m.def( - "ezy_save_occt_view_settings", - [] - { - if (g_py_gui) - g_py_gui->save_occt_view_settings(); - }); + m.def("ezy_help", + [] + { + if (!g_py_console) + return; + const char* help_text = + "ezy:\n" + " ezy.log(msg) - append message to console and log window\n" + " ezy.msg(text) - show status message\n" + " ezy.get_mode() - return current mode name\n" + " ezy.set_mode(name) - set mode by name\n" + " ezy.save_occt_view_settings() - write settings JSON (incl. view colors)\n" + " ezy.occt_view_settings_json() - JSON: occt_view + gui edge_dim_*, view_roll_step_deg, view_zoom_scroll_scale\n" + " ezy.help() - print this help\n" + "view:\n" + " view.sketch_count() - number of sketches\n" + " view.shape_count() - number of shapes\n" + " view.curr_sketch_name() - current sketch name\n" + " view.add_box(ox,oy,oz,w,l,h) - add box\n" + " view.add_sphere(ox,oy,oz,r) - add sphere\n" + " view.get_shape(i) - get shape by 0-based index (raises IndexError if out of range)\n" + " view.get_camera() - get camera eye/center/up vectors\n" + " view.set_camera(ex,ey,ez,cx,cy,cz,ux,uy,uz) - set camera vectors\n" + "Shp:\n" + " s.name() - get shape name\n" + " s.set_name(s) - set shape name\n" + " s.visible() - get visibility\n" + " s.set_visible(b) - set visibility"; + g_py_console->append_line_from_python(help_text); + }); + + m.def("ezy_save_occt_view_settings", + [] + { + if (g_py_gui) + g_py_gui->save_occt_view_settings(); + }); - m.def( - "ezy_occt_view_settings_json", - [] - { - if (!g_py_gui) - return std::string("{}"); - return g_py_gui->occt_view_settings_json(); - }); + m.def("ezy_occt_view_settings_json", + [] + { + if (!g_py_gui) + return std::string("{}"); + return g_py_gui->occt_view_settings_json(); + }); - m.def( - "view_sketch_count", - [] - { - Occt_view* view = g_py_gui && g_py_gui->get_view() ? g_py_gui->get_view() : nullptr; - return view ? static_cast(view->get_sketches().size()) : std::size_t {0}; - }); + m.def("view_sketch_count", + [] + { + Occt_view* view = g_py_gui && g_py_gui->get_view() ? g_py_gui->get_view() : nullptr; + return view ? static_cast(view->get_sketches().size()) : std::size_t{0}; + }); - m.def( - "view_shape_count", - [] - { - Occt_view* view = g_py_gui && g_py_gui->get_view() ? g_py_gui->get_view() : nullptr; - return view ? static_cast(view->get_shapes().size()) : std::size_t {0}; - }); + m.def("view_shape_count", + [] + { + Occt_view* view = g_py_gui && g_py_gui->get_view() ? g_py_gui->get_view() : nullptr; + return view ? static_cast(view->get_shapes().size()) : std::size_t{0}; + }); - m.def( - "view_curr_sketch_name", - [] - { - Occt_view* view = g_py_gui && g_py_gui->get_view() ? g_py_gui->get_view() : nullptr; - return view ? view->curr_sketch().get_name() : std::string {}; - }); + m.def("view_curr_sketch_name", + [] + { + Occt_view* view = g_py_gui && g_py_gui->get_view() ? g_py_gui->get_view() : nullptr; + return view ? view->curr_sketch().get_name() : std::string{}; + }); m.def( "view_add_box", @@ -294,12 +278,7 @@ PYBIND11_EMBEDDED_MODULE(ezycad_native, m) if (view) view->add_box(ox, oy, oz, w, len, h); }, - py::arg("ox"), - py::arg("oy"), - py::arg("oz"), - py::arg("w"), - py::arg("l"), - py::arg("h")); + py::arg("ox"), py::arg("oy"), py::arg("oz"), py::arg("w"), py::arg("l"), py::arg("h")); m.def( "view_add_sphere", @@ -309,10 +288,7 @@ PYBIND11_EMBEDDED_MODULE(ezycad_native, m) if (view) view->add_sphere(ox, oy, oz, r); }, - py::arg("ox"), - py::arg("oy"), - py::arg("oz"), - py::arg("r")); + py::arg("ox"), py::arg("oy"), py::arg("oz"), py::arg("r")); m.def( "view_get_shape", @@ -329,28 +305,27 @@ PYBIND11_EMBEDDED_MODULE(ezycad_native, m) ; if (it == shapes.end()) throw py::index_error("shape index out of range"); - return Ezy_shp {*it}; + return Ezy_shp{*it}; }, py::arg("i")); - m.def( - "view_get_camera", - []() -> py::dict - { - Occt_view* view = g_py_gui && g_py_gui->get_view() ? g_py_gui->get_view() : nullptr; - if (!view) - throw std::runtime_error("no 3D view available"); - gp_Pnt eye; - gp_Pnt center; - gp_Dir up; - if (!view->get_camera(eye, center, up)) - throw std::runtime_error("camera is not available"); - py::dict out; - out["eye"] = py::make_tuple(eye.X(), eye.Y(), eye.Z()); - out["center"] = py::make_tuple(center.X(), center.Y(), center.Z()); - out["up"] = py::make_tuple(up.X(), up.Y(), up.Z()); - return out; - }); + m.def("view_get_camera", + []() -> py::dict + { + Occt_view* view = g_py_gui && g_py_gui->get_view() ? g_py_gui->get_view() : nullptr; + if (!view) + throw std::runtime_error("no 3D view available"); + gp_Pnt eye; + gp_Pnt center; + gp_Dir up; + if (!view->get_camera(eye, center, up)) + throw std::runtime_error("camera is not available"); + py::dict out; + out["eye"] = py::make_tuple(eye.X(), eye.Y(), eye.Z()); + out["center"] = py::make_tuple(center.X(), center.Y(), center.Z()); + out["up"] = py::make_tuple(up.X(), up.Y(), up.Z()); + return out; + }); m.def( "view_set_camera", @@ -361,14 +336,7 @@ PYBIND11_EMBEDDED_MODULE(ezycad_native, m) throw std::runtime_error("no 3D view available"); view->set_camera(gp_Pnt(ex, ey, ez), gp_Pnt(cx, cy, cz), gp_Dir(ux, uy, uz)); }, - py::arg("ex"), - py::arg("ey"), - py::arg("ez"), - py::arg("cx"), - py::arg("cy"), - py::arg("cz"), - py::arg("ux"), - py::arg("uy"), + py::arg("ex"), py::arg("ey"), py::arg("ez"), py::arg("cx"), py::arg("cy"), py::arg("cz"), py::arg("ux"), py::arg("uy"), py::arg("uz")); } @@ -377,12 +345,9 @@ struct Python_console::Ezycad_python_runtime py::scoped_interpreter guard; }; -#endif // EZYCAD_HAVE_PYTHON +#endif // EZYCAD_HAVE_PYTHON -void Python_console::append_line_from_python(const std::string& line) -{ - append_line(line, false); -} +void Python_console::append_line_from_python(const std::string& line) { append_line(line, false); } void Python_console::append_line(const std::string& line, bool is_error) { @@ -533,8 +498,7 @@ void Python_console::execute(const std::string& code) try { - py::object result = - py::eval(py::str(code), py::globals(), py::globals()); + py::object result = py::eval(py::str(code), py::globals(), py::globals()); if (result.ptr() != nullptr && !result.is_none()) append_line(py::repr(result).cast()); } @@ -547,10 +511,7 @@ void Python_console::execute(const std::string& code) #else void Python_console::load_scripts() {} -void Python_console::execute(const std::string& code) -{ - (void) code; -} +void Python_console::execute(const std::string& code) { (void)code; } #endif int Python_console::text_edit_callback(ImGuiInputTextCallbackData* data) @@ -652,14 +613,10 @@ void Python_console::render(bool* p_open) ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.f, 0.f, 0.f, 0.f)); ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0.f, 0.f, 0.f, 0.f)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.f, 0.f)); - ImGui::InputTextMultiline( - "##python_log", - m_log_display_buf.data(), - m_log_display_buf.size(), - ImVec2(-1.f, -1.f), - ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CallbackResize | ImGuiInputTextFlags_NoUndoRedo, - &Python_console::log_display_resize_callback, - this); + ImGui::InputTextMultiline("##python_log", m_log_display_buf.data(), m_log_display_buf.size(), ImVec2(-1.f, -1.f), + ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CallbackResize | + ImGuiInputTextFlags_NoUndoRedo, + &Python_console::log_display_resize_callback, this); ImGui::PopStyleVar(); ImGui::PopStyleColor(3); if (m_scroll_to_bottom) @@ -677,13 +634,9 @@ void Python_console::render(bool* p_open) const bool can_run = false; #endif ImGui::BeginDisabled(!can_run); - bool run = ImGui::InputTextWithHint("##python_input", - "Enter Python code (e.g. ezy.log('hi'))", - m_input_buf, - k_input_buf_size, - ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackHistory, - &Python_console::text_edit_callback, - this); + bool run = ImGui::InputTextWithHint( + "##python_input", "Enter Python code (e.g. ezy.log('hi'))", m_input_buf, k_input_buf_size, + ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackHistory, &Python_console::text_edit_callback, this); ImGui::EndDisabled(); if (run && can_run) diff --git a/src/python_console.h b/src/python_console.h index 2765714..f46c949 100644 --- a/src/python_console.h +++ b/src/python_console.h @@ -20,17 +20,17 @@ struct Python_script_editor /// Available when built with EZYCAD_HAVE_PYTHON (native builds with Python development libraries). class Python_console { - public: +public: explicit Python_console(GUI* gui); ~Python_console(); - void render(bool* p_open = nullptr); + void render(bool* p_open = nullptr); static int text_edit_callback(struct ImGuiInputTextCallbackData* data); static int log_display_resize_callback(struct ImGuiInputTextCallbackData* data); void append_line_from_python(const std::string& line); - private: +private: void load_scripts(); void execute(const std::string& code); void append_line(const std::string& line, bool is_error = false); @@ -43,13 +43,13 @@ class Python_console std::unique_ptr m_py_runtime; #endif - std::vector m_history; - std::vector m_cmd_history; - int m_cmd_history_pos = -1; - static constexpr int k_input_buf_size = 1024; - char m_input_buf[k_input_buf_size] {}; - bool m_scroll_to_bottom = false; - bool m_python_ok = false; + std::vector m_history; + std::vector m_cmd_history; + int m_cmd_history_pos = -1; + static constexpr int k_input_buf_size = 1024; + char m_input_buf[k_input_buf_size]{}; + bool m_scroll_to_bottom = false; + bool m_python_ok = false; std::string m_log_display_buf; uint64_t m_log_display_version = 0; @@ -57,4 +57,3 @@ class Python_console std::vector m_script_editors; }; - diff --git a/src/settings.cpp b/src/settings.cpp index 8aff50c..4e8d87e 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -17,10 +17,7 @@ namespace settings { static std::function s_log_callback; -void set_log_callback(std::function cb) -{ - s_log_callback = std::move(cb); -} +void set_log_callback(std::function cb) { s_log_callback = std::move(cb); } std::filesystem::path user_settings_json_path() { @@ -37,18 +34,17 @@ std::filesystem::path user_settings_json_path() std::string load() { #ifdef __EMSCRIPTEN__ - void* ptr = (void*) (intptr_t) EM_ASM_INT( - { - var s = localStorage.getItem('ezycad_settings') || ''; - var len = lengthBytesUTF8(s) + 1; - var buf = _malloc(len); - if (buf) - stringToUTF8(s, buf, len); - return buf; - }); + void* ptr = (void*)(intptr_t)EM_ASM_INT({ + var s = localStorage.getItem('ezycad_settings') || ''; + var len = lengthBytesUTF8(s) + 1; + var buf = _malloc(len); + if (buf) + stringToUTF8(s, buf, len); + return buf; + }); if (!ptr) return {}; - std::string result((const char*) ptr); + std::string result((const char*)ptr); free(ptr); return result; #else @@ -146,7 +142,7 @@ void save(const std::string& content) std::filesystem::path user_config_directory() { #ifdef __EMSCRIPTEN__ - (void) 0; + (void)0; return {}; #elif defined(_WIN32) const char* appdata = std::getenv("APPDATA"); @@ -180,18 +176,17 @@ std::filesystem::path user_startup_project_path() std::string load_user_startup_project() { #ifdef __EMSCRIPTEN__ - void* ptr = (void*) (intptr_t) EM_ASM_INT( - { - var s = localStorage.getItem('ezycad_startup_ezy') || ''; - var len = lengthBytesUTF8(s) + 1; - var buf = _malloc(len); - if (buf) - stringToUTF8(s, buf, len); - return buf; - }); + void* ptr = (void*)(intptr_t)EM_ASM_INT({ + var s = localStorage.getItem('ezycad_startup_ezy') || ''; + var len = lengthBytesUTF8(s) + 1; + var buf = _malloc(len); + if (buf) + stringToUTF8(s, buf, len); + return buf; + }); if (!ptr) return {}; - std::string result((const char*) ptr); + std::string result((const char*)ptr); free(ptr); return result; #else @@ -241,4 +236,4 @@ void clear_user_startup_project() } #endif } -} // namespace settings +} // namespace settings diff --git a/src/settings.h b/src/settings.h index 331c216..326f9b2 100644 --- a/src/settings.h +++ b/src/settings.h @@ -37,4 +37,4 @@ std::filesystem::path user_startup_project_path(); std::string load_user_startup_project(); bool save_user_startup_project(const std::string& json); void clear_user_startup_project(); -} // namespace settings +} // namespace settings diff --git a/src/shp.cpp b/src/shp.cpp index fe3d07c..61f95ca 100644 --- a/src/shp.cpp +++ b/src/shp.cpp @@ -3,31 +3,22 @@ #include Shp::Shp(AIS_InteractiveContext& ctx, const TopoDS_Shape& shp) - : AIS_Shape(shp), - m_ctx(ctx), - m_name("Shape"), - m_disp_mode(AIS_Shaded), - m_visible(true), - m_selection_mode(TopAbs_SHAPE) + : AIS_Shape(shp) + , m_ctx(ctx) + , m_name("Shape") + , m_disp_mode(AIS_Shaded) + , m_visible(true) + , m_selection_mode(TopAbs_SHAPE) { } Shp::~Shp() {} -const std::string& Shp::get_name() const -{ - return m_name; -} +const std::string& Shp::get_name() const { return m_name; } -void Shp::set_name(const std::string& name) -{ - m_name = name; -} +void Shp::set_name(const std::string& name) { m_name = name; } -AIS_DisplayMode Shp::get_disp_mode() const -{ - return m_disp_mode; -} +AIS_DisplayMode Shp::get_disp_mode() const { return m_disp_mode; } void Shp::set_disp_mode(const AIS_DisplayMode mode) { @@ -35,10 +26,7 @@ void Shp::set_disp_mode(const AIS_DisplayMode mode) update_display_(); } -bool Shp::get_visible() const -{ - return m_visible; -} +bool Shp::get_visible() const { return m_visible; } void Shp::set_visible(const bool visible) { diff --git a/src/shp.h b/src/shp.h index 8bc914a..3a75dc5 100644 --- a/src/shp.h +++ b/src/shp.h @@ -8,7 +8,7 @@ class AIS_InteractiveContext; class Shp : public AIS_Shape { - public: +public: Shp(AIS_InteractiveContext& ctx, const TopoDS_Shape& shp); virtual ~Shp(); @@ -20,7 +20,7 @@ class Shp : public AIS_Shape void set_visible(const bool visible); void set_selection_mode(const TopAbs_ShapeEnum mode); - protected: +protected: void update_display_(); AIS_InteractiveContext& m_ctx; diff --git a/src/shp_chamfer.cpp b/src/shp_chamfer.cpp index 4e49bda..7f19f84 100644 --- a/src/shp_chamfer.cpp +++ b/src/shp_chamfer.cpp @@ -11,7 +11,9 @@ #include "occt_view.h" Shp_chamfer::Shp_chamfer(Occt_view& view) - : Shp_operation_base(view) {} + : Shp_operation_base(view) +{ +} Status Shp_chamfer::add_chamfer(const ScreenCoords& screen_coords, const Chamfer_mode chamfer_mode) { @@ -27,64 +29,64 @@ Status Shp_chamfer::add_chamfer(const ScreenCoords& screen_coords, const Chamfer switch (chamfer_mode) { - case Chamfer_mode::Shape: + case Chamfer_mode::Shape: + { + TopExp_Explorer edge_explorer(chamfer_src_shp->Shape(), TopAbs_EDGE); + while (edge_explorer.More()) { - TopExp_Explorer edge_explorer(chamfer_src_shp->Shape(), TopAbs_EDGE); - while (edge_explorer.More()) - { - const TopoDS_Edge& edge = TopoDS::Edge(edge_explorer.Current()); - chamfer_maker.Add(setback_dist, edge); - edge_explorer.Next(); - } - break; + const TopoDS_Edge& edge = TopoDS::Edge(edge_explorer.Current()); + chamfer_maker.Add(setback_dist, edge); + edge_explorer.Next(); } + break; + } + + case Chamfer_mode::Face: + { + const TopoDS_Face* face = get_face_(screen_coords); + if (!face) + return Status::user_error("No chamfer face detected."); - case Chamfer_mode::Face: + TopExp_Explorer edge_explorer(*face, TopAbs_EDGE); + while (edge_explorer.More()) { - const TopoDS_Face* face = get_face_(screen_coords); - if (!face) - return Status::user_error("No chamfer face detected."); - - TopExp_Explorer edge_explorer(*face, TopAbs_EDGE); - while (edge_explorer.More()) - { - const TopoDS_Edge& edge = TopoDS::Edge(edge_explorer.Current()); - chamfer_maker.Add(setback_dist, edge); - edge_explorer.Next(); - } - break; + const TopoDS_Edge& edge = TopoDS::Edge(edge_explorer.Current()); + chamfer_maker.Add(setback_dist, edge); + edge_explorer.Next(); } + break; + } - case Chamfer_mode::Wire: + case Chamfer_mode::Wire: + { + const TopoDS_Wire* wire = get_wire_(screen_coords); + if (!wire) + return Status::user_error("No chamfer wire detected."); + + // Chamfer all edges in the wire + TopExp_Explorer edge_explorer(*wire, TopAbs_EDGE); + while (edge_explorer.More()) { - const TopoDS_Wire* wire = get_wire_(screen_coords); - if (!wire) - return Status::user_error("No chamfer wire detected."); - - // Chamfer all edges in the wire - TopExp_Explorer edge_explorer(*wire, TopAbs_EDGE); - while (edge_explorer.More()) - { - const TopoDS_Edge& wire_edge = TopoDS::Edge(edge_explorer.Current()); - chamfer_maker.Add(setback_dist, wire_edge); - edge_explorer.Next(); - } - - break; + const TopoDS_Edge& wire_edge = TopoDS::Edge(edge_explorer.Current()); + chamfer_maker.Add(setback_dist, wire_edge); + edge_explorer.Next(); } - case Chamfer_mode::Edge: - { - const TopoDS_Edge* edge = get_edge_(screen_coords); - if (!edge) - return Status::user_error("No chamfer edge detected."); + break; + } - chamfer_maker.Add(setback_dist, *edge); - break; - } + case Chamfer_mode::Edge: + { + const TopoDS_Edge* edge = get_edge_(screen_coords); + if (!edge) + return Status::user_error("No chamfer edge detected."); - default: - EZY_ASSERT(false); + chamfer_maker.Add(setback_dist, *edge); + break; + } + + default: + EZY_ASSERT(false); } try @@ -112,12 +114,6 @@ Status Shp_chamfer::add_chamfer(const ScreenCoords& screen_coords, const Chamfer return Status::ok(); } -void Shp_chamfer::set_chamfer_dist(const double dist) -{ - m_chamfer_dist = dist; -} +void Shp_chamfer::set_chamfer_dist(const double dist) { m_chamfer_dist = dist; } -double Shp_chamfer::get_chamfer_dist() const -{ - return m_chamfer_dist; -} \ No newline at end of file +double Shp_chamfer::get_chamfer_dist() const { return m_chamfer_dist; } \ No newline at end of file diff --git a/src/shp_chamfer.h b/src/shp_chamfer.h index 6f9e6d9..d5d036f 100644 --- a/src/shp_chamfer.h +++ b/src/shp_chamfer.h @@ -6,7 +6,7 @@ enum class Chamfer_mode; class Shp_chamfer : private Shp_operation_base { - public: +public: Shp_chamfer(Occt_view& view); [[nodiscard]] Status add_chamfer(const ScreenCoords& screen_coords, const Chamfer_mode chamfer_mode); @@ -14,6 +14,6 @@ class Shp_chamfer : private Shp_operation_base void set_chamfer_dist(const double dist); double get_chamfer_dist() const; - private: - double m_chamfer_dist {1.0}; +private: + double m_chamfer_dist{1.0}; }; \ No newline at end of file diff --git a/src/shp_common.cpp b/src/shp_common.cpp index 8e06938..8d38b81 100644 --- a/src/shp_common.cpp +++ b/src/shp_common.cpp @@ -6,7 +6,9 @@ #include "utl.h" Shp_common::Shp_common(Occt_view& view) - : Shp_operation_base(view) {} + : Shp_operation_base(view) +{ +} Status Shp_common::selected_common() { diff --git a/src/shp_common.h b/src/shp_common.h index 48d8157..8365496 100644 --- a/src/shp_common.h +++ b/src/shp_common.h @@ -4,7 +4,7 @@ class Shp_common : private Shp_operation_base { - public: +public: Shp_common(Occt_view& view); [[nodiscard]] Status selected_common(); diff --git a/src/shp_create.cpp b/src/shp_create.cpp index a461f38..5fee9f3 100644 --- a/src/shp_create.cpp +++ b/src/shp_create.cpp @@ -42,8 +42,7 @@ TopoDS_Shape create_pyramid(double side) base_wire.Add(BRepBuilderAPI_MakeEdge(p1, p2).Edge()); base_wire.Add(BRepBuilderAPI_MakeEdge(p2, p3).Edge()); base_wire.Add(BRepBuilderAPI_MakeEdge(p3, p0).Edge()); - TopoDS_Face base_face = - BRepBuilderAPI_MakeFace(gp_Pln(gp_Pnt(0, 0, 0), gp_Dir(0, 0, -1)), base_wire.Wire(), true).Face(); + TopoDS_Face base_face = BRepBuilderAPI_MakeFace(gp_Pln(gp_Pnt(0, 0, 0), gp_Dir(0, 0, -1)), base_wire.Wire(), true).Face(); auto make_triangle_face = [](const gp_Pnt& a, const gp_Pnt& b, const gp_Pnt& c) -> TopoDS_Face { @@ -88,10 +87,7 @@ TopoDS_Shape create_pyramid(double side) return BRepBuilderAPI_Transform(pyramid, trsf).Shape(); } -TopoDS_Shape create_sphere(double radius) -{ - return BRepPrimAPI_MakeSphere(radius).Shape(); -} +TopoDS_Shape create_sphere(double radius) { return BRepPrimAPI_MakeSphere(radius).Shape(); } TopoDS_Shape create_cylinder(double radius, double height) { @@ -109,8 +105,5 @@ TopoDS_Shape create_cone(double R1, double R2, double height) return BRepBuilderAPI_Transform(cone, trsf).Shape(); } -TopoDS_Shape create_torus(double R1, double R2) -{ - return BRepPrimAPI_MakeTorus(R1, R2).Shape(); -} -} // namespace shp_create +TopoDS_Shape create_torus(double R1, double R2) { return BRepPrimAPI_MakeTorus(R1, R2).Shape(); } +} // namespace shp_create diff --git a/src/shp_create.h b/src/shp_create.h index 66aa95c..4e108b0 100644 --- a/src/shp_create.h +++ b/src/shp_create.h @@ -21,4 +21,4 @@ TopoDS_Shape create_cone(double R1, double R2, double height); // Torus: major radius R1, minor radius R2 (display units), centered at origin. TopoDS_Shape create_torus(double R1, double R2); -} // namespace shp_create +} // namespace shp_create diff --git a/src/shp_cut.cpp b/src/shp_cut.cpp index 2d81518..fde1dab 100644 --- a/src/shp_cut.cpp +++ b/src/shp_cut.cpp @@ -7,7 +7,9 @@ #include "utl.h" Shp_cut::Shp_cut(Occt_view& view) - : Shp_operation_base(view) {} + : Shp_operation_base(view) +{ +} Status Shp_cut::selected_cut() { @@ -24,7 +26,7 @@ Status Shp_cut::selected_cut() BRepAlgoAPI_Cut cut_op; cut_op.SetArguments(arguments); - cut_op.SetTools(tool_list); // Set tool shapes + cut_op.SetTools(tool_list); // Set tool shapes // Perform difference operation cut_op.Build(); diff --git a/src/shp_cut.h b/src/shp_cut.h index c9cd74c..e625574 100644 --- a/src/shp_cut.h +++ b/src/shp_cut.h @@ -4,7 +4,7 @@ class Shp_cut : private Shp_operation_base { - public: +public: Shp_cut(Occt_view& view); [[nodiscard]] Status selected_cut(); diff --git a/src/shp_extrude.cpp b/src/shp_extrude.cpp index 15c8eee..19e8cf1 100644 --- a/src/shp_extrude.cpp +++ b/src/shp_extrude.cpp @@ -14,7 +14,10 @@ #include "utl.h" Shp_extrude::Shp_extrude(Occt_view& view) - : Shp_operation_base(view), m_extrude_side(Plane_side::Front) {} + : Shp_operation_base(view) + , m_extrude_side(Plane_side::Front) +{ +} void Shp_extrude::sketch_face_extrude(const ScreenCoords& screen_coords, bool is_mouse_move) { @@ -43,7 +46,8 @@ void Shp_extrude::sketch_face_extrude(const ScreenCoords& screen_coords, bool is rotation_axis.Normalize(); rotation_axis *= to_radians(45.0); // rotate around arbitrary axis - view().m_view->Rotate(rotation_axis.X(), rotation_axis.Y(), rotation_axis.Z(), m_to_extrude_pt->X(), m_to_extrude_pt->Y(), m_to_extrude_pt->Z()); + view().m_view->Rotate(rotation_axis.X(), rotation_axis.Y(), rotation_axis.Z(), m_to_extrude_pt->X(), + m_to_extrude_pt->Y(), m_to_extrude_pt->Z()); // request redraw view().m_view->Redraw(); m_curr_view_pln = view().get_view_plane(*m_to_extrude_pt); @@ -82,31 +86,19 @@ bool Shp_extrude::cancel() return did_cancel; } -bool Shp_extrude::has_active_extrusion() const -{ - return !m_extruded.IsNull(); -} +bool Shp_extrude::has_active_extrusion() const { return !m_extruded.IsNull(); } -bool Shp_extrude::get_both_sides() const -{ - return m_extrude_both_sides; -} +bool Shp_extrude::get_both_sides() const { return m_extrude_both_sides; } -void Shp_extrude::set_both_sides(const bool both_sides) -{ - m_extrude_both_sides = both_sides; -} +void Shp_extrude::set_both_sides(const bool both_sides) { m_extrude_both_sides = both_sides; } -void Shp_extrude::set_curr_view_pln(const gp_Pln& pln) -{ - m_curr_view_pln = pln; -} +void Shp_extrude::set_curr_view_pln(const gp_Pln& pln) { m_curr_view_pln = pln; } void Shp_extrude::_update_extrude(const ScreenCoords& screen_coords) { // Extrude the face std::optional p = view().pt3d_on_plane(screen_coords, m_curr_view_pln); - if (p) // TODO report error! + if (p) // TODO report error! { double extrude_dist = m_to_extrude_pln.Distance(*p); if (auto entered_dim = view().get_entered_dim(); entered_dim) @@ -150,7 +142,7 @@ void Shp_extrude::_update_extrude_preview_(const double extrude_dist, const Plan EZY_ASSERT(side != Plane_side::On); const gp_Vec normal_dir(m_to_extrude_pln.Axis().Direction()); - const double side_sign = (side == Plane_side::Front) ? 1.0 : -1.0; + const double side_sign = (side == Plane_side::Front) ? 1.0 : -1.0; const gp_Vec extrude_vec = normal_dir * (side_sign * extrude_dist); gp_Vec face_offset(0.0, 0.0, 0.0); @@ -159,13 +151,8 @@ void Shp_extrude::_update_extrude_preview_(const double extrude_dist, const Plan ctx().Remove(m_tmp_dim, false); m_tmp_dim = create_distance_annotation(gp_Pnt(m_to_extrude_pt->XYZ() + face_offset.XYZ() + extrude_vec.XYZ()), - gp_Pnt(m_to_extrude_pt->XYZ() + face_offset.XYZ()), - m_curr_view_pln, - Prs3d_DTHP_Fit, - std::nullopt, - nullptr, - gui().edge_dim_line_width(), - gui().edge_dim_arrow_size()); + gp_Pnt(m_to_extrude_pt->XYZ() + face_offset.XYZ()), m_curr_view_pln, Prs3d_DTHP_Fit, + std::nullopt, nullptr, gui().edge_dim_line_width(), gui().edge_dim_arrow_size()); m_tmp_dim->SetCustomValue(extrude_dist / view().get_dimension_scale()); @@ -177,7 +164,7 @@ void Shp_extrude::_update_extrude_preview_(const double extrude_dist, const Plan gp_Trsf trsf; trsf.SetTranslation(face_offset); TopoDS_Shape shifted_face = BRepBuilderAPI_Transform(face, trsf, true).Shape(); - face = TopoDS::Face(shifted_face); + face = TopoDS::Face(shifted_face); } TopoDS_Shape body = BRepPrimAPI_MakePrism(face, extrude_vec); diff --git a/src/shp_extrude.h b/src/shp_extrude.h index 5e5ddc1..c94aa9c 100644 --- a/src/shp_extrude.h +++ b/src/shp_extrude.h @@ -13,7 +13,7 @@ enum class Plane_side; class Shp_extrude : private Shp_operation_base { - public: +public: Shp_extrude(Occt_view& view); void sketch_face_extrude(const ScreenCoords& screen_coords, bool is_mouse_move); @@ -26,9 +26,9 @@ class Shp_extrude : private Shp_operation_base // For testing void set_curr_view_pln(const gp_Pln& pln); - private: - void _update_extrude(const ScreenCoords& screen_coords); - void _update_extrude_preview_(double extrude_dist, Plane_side side); +private: + void _update_extrude(const ScreenCoords& screen_coords); + void _update_extrude_preview_(double extrude_dist, Plane_side side); // Face extrude related AIS_Shape_ptr m_to_extrude; gp_Pln m_to_extrude_pln; @@ -37,5 +37,5 @@ class Shp_extrude : private Shp_operation_base gp_Pln m_curr_view_pln; PrsDim_LengthDimension_ptr m_tmp_dim; Plane_side m_extrude_side; - bool m_extrude_both_sides {false}; + bool m_extrude_both_sides{false}; }; diff --git a/src/shp_fillet.cpp b/src/shp_fillet.cpp index 9e7f095..eeaf792 100644 --- a/src/shp_fillet.cpp +++ b/src/shp_fillet.cpp @@ -10,7 +10,9 @@ #include "occt_view.h" Shp_fillet::Shp_fillet(Occt_view& view) - : Shp_operation_base(view) {} + : Shp_operation_base(view) +{ +} Status Shp_fillet::add_fillet(const ScreenCoords& screen_coords, const Fillet_mode fillet_mode) { @@ -23,64 +25,64 @@ Status Shp_fillet::add_fillet(const ScreenCoords& screen_coords, const Fillet_mo switch (fillet_mode) { - case Fillet_mode::Shape: + case Fillet_mode::Shape: + { + TopExp_Explorer edge_explorer(fillet_src_shp->Shape(), TopAbs_EDGE); + while (edge_explorer.More()) { - TopExp_Explorer edge_explorer(fillet_src_shp->Shape(), TopAbs_EDGE); - while (edge_explorer.More()) - { - const TopoDS_Edge& edge = TopoDS::Edge(edge_explorer.Current()); - fillet_maker.Add(m_fillet_radius, edge); - edge_explorer.Next(); - } - break; + const TopoDS_Edge& edge = TopoDS::Edge(edge_explorer.Current()); + fillet_maker.Add(m_fillet_radius, edge); + edge_explorer.Next(); } + break; + } + + case Fillet_mode::Face: + { + const TopoDS_Face* face = get_face_(screen_coords); + if (!face) + return Status::user_error("No fillet face detected."); - case Fillet_mode::Face: + TopExp_Explorer edge_explorer(*face, TopAbs_EDGE); + while (edge_explorer.More()) { - const TopoDS_Face* face = get_face_(screen_coords); - if (!face) - return Status::user_error("No fillet face detected."); - - TopExp_Explorer edge_explorer(*face, TopAbs_EDGE); - while (edge_explorer.More()) - { - const TopoDS_Edge& edge = TopoDS::Edge(edge_explorer.Current()); - fillet_maker.Add(m_fillet_radius, edge); - edge_explorer.Next(); - } - break; + const TopoDS_Edge& edge = TopoDS::Edge(edge_explorer.Current()); + fillet_maker.Add(m_fillet_radius, edge); + edge_explorer.Next(); } + break; + } - case Fillet_mode::Wire: + case Fillet_mode::Wire: + { + const TopoDS_Wire* wire = get_wire_(screen_coords); + if (!wire) + return Status::user_error("No fillet wire detected."); + + // Fillet all edges in the wire + TopExp_Explorer edge_explorer(*wire, TopAbs_EDGE); + while (edge_explorer.More()) { - const TopoDS_Wire* wire = get_wire_(screen_coords); - if (!wire) - return Status::user_error("No fillet wire detected."); - - // Fillet all edges in the wire - TopExp_Explorer edge_explorer(*wire, TopAbs_EDGE); - while (edge_explorer.More()) - { - const TopoDS_Edge& wire_edge = TopoDS::Edge(edge_explorer.Current()); - fillet_maker.Add(m_fillet_radius, wire_edge); - edge_explorer.Next(); - } - - break; + const TopoDS_Edge& wire_edge = TopoDS::Edge(edge_explorer.Current()); + fillet_maker.Add(m_fillet_radius, wire_edge); + edge_explorer.Next(); } - case Fillet_mode::Edge: - { - const TopoDS_Edge* edge = get_edge_(screen_coords); - if (!edge) - return Status::user_error("No fillet edge detected."); + break; + } - fillet_maker.Add(m_fillet_radius, *edge); - break; - } + case Fillet_mode::Edge: + { + const TopoDS_Edge* edge = get_edge_(screen_coords); + if (!edge) + return Status::user_error("No fillet edge detected."); + + fillet_maker.Add(m_fillet_radius, *edge); + break; + } - default: - EZY_ASSERT(false); + default: + EZY_ASSERT(false); } try @@ -108,12 +110,6 @@ Status Shp_fillet::add_fillet(const ScreenCoords& screen_coords, const Fillet_mo return Status::ok(); } -void Shp_fillet::set_fillet_radius(const double radius) -{ - m_fillet_radius = radius; -} +void Shp_fillet::set_fillet_radius(const double radius) { m_fillet_radius = radius; } -double Shp_fillet::get_fillet_radius() const -{ - return m_fillet_radius; -} +double Shp_fillet::get_fillet_radius() const { return m_fillet_radius; } diff --git a/src/shp_fillet.h b/src/shp_fillet.h index fabd58f..9fc7edd 100644 --- a/src/shp_fillet.h +++ b/src/shp_fillet.h @@ -6,7 +6,7 @@ enum class Fillet_mode; class Shp_fillet : private Shp_operation_base { - public: +public: Shp_fillet(Occt_view& view); [[nodiscard]] Status add_fillet(const ScreenCoords& screen_coords, const Fillet_mode fillet_mode); @@ -14,6 +14,6 @@ class Shp_fillet : private Shp_operation_base void set_fillet_radius(const double radius); double get_fillet_radius() const; - private: - double m_fillet_radius {1.0}; +private: + double m_fillet_radius{1.0}; }; diff --git a/src/shp_fuse.cpp b/src/shp_fuse.cpp index d7f072e..1c320c6 100644 --- a/src/shp_fuse.cpp +++ b/src/shp_fuse.cpp @@ -6,7 +6,9 @@ #include "utl.h" Shp_fuse::Shp_fuse(Occt_view& view) - : Shp_operation_base(view) {} + : Shp_operation_base(view) +{ +} Status Shp_fuse::selected_fuse() { diff --git a/src/shp_fuse.h b/src/shp_fuse.h index 102c461..eecc9cd 100644 --- a/src/shp_fuse.h +++ b/src/shp_fuse.h @@ -4,7 +4,7 @@ class Shp_fuse : private Shp_operation_base { - public: +public: Shp_fuse(Occt_view& view); [[nodiscard]] Status selected_fuse(); diff --git a/src/shp_move.cpp b/src/shp_move.cpp index 604c090..6eb5840 100644 --- a/src/shp_move.cpp +++ b/src/shp_move.cpp @@ -6,7 +6,9 @@ #include "utl.h" Shp_move::Shp_move(Occt_view& view) - : Shp_operation_base(view) {} + : Shp_operation_base(view) +{ +} Status Shp_move::move_selected(const ScreenCoords& screen_coords) { @@ -59,7 +61,7 @@ void Shp_move::show_dist_edit(const ScreenCoords& screen_coords) auto dist_edit_axis_x = [&, screen_coords](float new_dist, bool is_final) { m_delta.override_x = new_dist * view().get_dimension_scale(); - EZY_ASSERT(move_selected(screen_coords).is_ok()); // Status should always be valid here + EZY_ASSERT(move_selected(screen_coords).is_ok()); // Status should always be valid here if (is_final) check_finalize_(); }; @@ -81,13 +83,16 @@ void Shp_move::show_dist_edit(const ScreenCoords& screen_coords) }; if (!m_delta.override_x.has_value() && (no_axis_constraints || m_opts.constr_axis_x)) - gui().set_dist_edit(float(m_delta.delta.X() / view().get_dimension_scale()), std::move(std::function(dist_edit_axis_x))); + gui().set_dist_edit(float(m_delta.delta.X() / view().get_dimension_scale()), + std::move(std::function(dist_edit_axis_x))); else if (!m_delta.override_y.has_value() && (no_axis_constraints || m_opts.constr_axis_y)) - gui().set_dist_edit(float(m_delta.delta.Y() / view().get_dimension_scale()), std::move(std::function(dist_edit_axis_y))); + gui().set_dist_edit(float(m_delta.delta.Y() / view().get_dimension_scale()), + std::move(std::function(dist_edit_axis_y))); else if (!m_delta.override_z.has_value() && (no_axis_constraints || m_opts.constr_axis_z)) - gui().set_dist_edit(float(m_delta.delta.Z() / view().get_dimension_scale()), std::move(std::function(dist_edit_axis_z))); + gui().set_dist_edit(float(m_delta.delta.Z() / view().get_dimension_scale()), + std::move(std::function(dist_edit_axis_z))); } void Shp_move::check_finalize_() @@ -137,7 +142,4 @@ void Shp_move::reset() gui().set_mode(Mode::Normal); } -Move_options& Shp_move::get_opts() -{ - return m_opts; -} \ No newline at end of file +Move_options& Shp_move::get_opts() { return m_opts; } \ No newline at end of file diff --git a/src/shp_move.h b/src/shp_move.h index 9a5e508..f61ed15 100644 --- a/src/shp_move.h +++ b/src/shp_move.h @@ -7,9 +7,9 @@ struct Move_options { - bool constr_axis_x {false}; - bool constr_axis_y {false}; - bool constr_axis_z {false}; + bool constr_axis_x{false}; + bool constr_axis_y{false}; + bool constr_axis_z{false}; }; class Shp_move : private Shp_operation_base @@ -17,7 +17,7 @@ class Shp_move : private Shp_operation_base // Responsible for handling the movement of selected shapes in a 3D view. // It handles user interactions for moving shapes, including axis constraints, direct value entry, // and finalizing or canceling the move operation. - public: +public: Shp_move(Occt_view& view); [[nodiscard]] Status move_selected(const ScreenCoords& screen_coords); @@ -27,7 +27,7 @@ class Shp_move : private Shp_operation_base void reset(); Move_options& get_opts(); - private: +private: struct Deltas { // User entered values; @@ -35,7 +35,7 @@ class Shp_move : private Shp_operation_base std::optional override_y; std::optional override_z; - gp_XYZ delta {0, 0, 0}; + gp_XYZ delta{0, 0, 0}; }; void check_finalize_(); diff --git a/src/shp_operation.cpp b/src/shp_operation.cpp index d098725..fa39ae6 100644 --- a/src/shp_operation.cpp +++ b/src/shp_operation.cpp @@ -5,22 +5,15 @@ #include "occt_view.h" Shp_operation_base::Shp_operation_base(Occt_view& view) - : m_view(view) {} - -GUI& Shp_operation_base::gui() + : m_view(view) { - return m_view.gui(); } -Occt_view& Shp_operation_base::view() -{ - return m_view; -} +GUI& Shp_operation_base::gui() { return m_view.gui(); } -AIS_InteractiveContext& Shp_operation_base::ctx() -{ - return view().ctx(); -} +Occt_view& Shp_operation_base::view() { return m_view; } + +AIS_InteractiveContext& Shp_operation_base::ctx() { return view().ctx(); } std::vector Shp_operation_base::get_selected_shps_() const { @@ -84,10 +77,7 @@ void Shp_operation_base::operation_shps_cancel_() shape->ResetTransformation(); } -AIS_Shape_ptr Shp_operation_base::get_shape_(const ScreenCoords& screen_coords) -{ - return m_view.get_shape(screen_coords); -} +AIS_Shape_ptr Shp_operation_base::get_shape_(const ScreenCoords& screen_coords) { return m_view.get_shape(screen_coords); } const TopoDS_Face* Shp_operation_base::get_face_(const ScreenCoords& screen_coords) const { @@ -104,10 +94,7 @@ const TopoDS_Edge* Shp_operation_base::get_edge_(const ScreenCoords& screen_coor return m_view.get_edge_(screen_coords); } -void Shp_operation_base::add_shp_(Shp_ptr& shp) -{ - m_view.add_shp_(shp); -} +void Shp_operation_base::add_shp_(Shp_ptr& shp) { m_view.add_shp_(shp); } void Shp_operation_base::copy_shape_material_from_(Shp_ptr& dest, const Shp_ptr& src) { diff --git a/src/shp_operation.h b/src/shp_operation.h index 0c81997..4d30ba2 100644 --- a/src/shp_operation.h +++ b/src/shp_operation.h @@ -12,7 +12,7 @@ class TopoDS_Edge; class Shp_operation_base { - protected: +protected: Shp_operation_base(Occt_view& view); GUI& gui(); Occt_view& view(); @@ -40,6 +40,6 @@ class Shp_operation_base std::vector m_shps; - private: +private: Occt_view& m_view; }; \ No newline at end of file diff --git a/src/shp_polar_dup.cpp b/src/shp_polar_dup.cpp index 4def832..8878c9e 100644 --- a/src/shp_polar_dup.cpp +++ b/src/shp_polar_dup.cpp @@ -15,7 +15,9 @@ #include "sketch_nodes.h" Shp_polar_dup::Shp_polar_dup(Occt_view& view) - : Shp_operation_base(view) {} + : Shp_operation_base(view) +{ +} Status Shp_polar_dup::move_point(const ScreenCoords& screen_coords) { @@ -93,8 +95,8 @@ Status Shp_polar_dup::dup() // Create copies and rotate them for (size_t i = 0; i < m_num_elms; ++i) { - const double current_angle_degrees = step_angle * (i + 1); // Skip 0 since that's the original - const double current_angle_radians = current_angle_degrees * std::numbers::pi / 180.0; // Convert to radians + const double current_angle_degrees = step_angle * (i + 1); // Skip 0 since that's the original + const double current_angle_radians = current_angle_degrees * std::numbers::pi / 180.0; // Convert to radians for (const AIS_Shape_ptr& shape : m_shps) { @@ -161,7 +163,7 @@ Status Shp_polar_dup::dup() } delete_operation_shps_(); - gui().set_mode(Mode::Normal); // Will call reset() + gui().set_mode(Mode::Normal); // Will call reset() return Status::ok(); } diff --git a/src/shp_polar_dup.h b/src/shp_polar_dup.h index bbf5637..7cefc46 100644 --- a/src/shp_polar_dup.h +++ b/src/shp_polar_dup.h @@ -4,31 +4,31 @@ class Shp_polar_dup : private Shp_operation_base { - public: +public: Shp_polar_dup(Occt_view& view); [[nodiscard]] Status move_point(const ScreenCoords& screen_coords); [[nodiscard]] Status add_point(const ScreenCoords& screen_coords); // bool can_polar_dup() const; - double get_polar_angle() const; - void set_polar_angle(const double angle); - size_t get_num_elms() const; - void set_num_elms(const size_t num); - bool get_rotate_dups() const; - void set_rotate_dups(const bool rotate); - bool get_combine_dups() const; - void set_combine_dups(const bool combine); + double get_polar_angle() const; + void set_polar_angle(const double angle); + size_t get_num_elms() const; + void set_num_elms(const size_t num); + bool get_rotate_dups() const; + void set_rotate_dups(const bool rotate); + bool get_combine_dups() const; + void set_combine_dups(const bool combine); [[nodiscard]] Status dup(); void reset(); - private: +private: gp_Pnt m_shps_center; AIS_Shape_ptr m_polar_arm; std::optional m_polar_arm_end; std::optional m_polar_arm_origin; - double m_polar_angle {360.0}; - bool m_rotate_dups {true}; - bool m_combine_dups {true}; - size_t m_num_elms {5}; + double m_polar_angle{360.0}; + bool m_rotate_dups{true}; + bool m_combine_dups{true}; + size_t m_num_elms{5}; }; \ No newline at end of file diff --git a/src/shp_rotate.cpp b/src/shp_rotate.cpp index 1f068b0..7a92a3a 100644 --- a/src/shp_rotate.cpp +++ b/src/shp_rotate.cpp @@ -11,7 +11,9 @@ #include "utl.h" Shp_rotate::Shp_rotate(Occt_view& view) - : Shp_operation_base(view) {} + : Shp_operation_base(view) +{ +} Status Shp_rotate::rotate_selected(const ScreenCoords& screen_coords) { @@ -88,17 +90,17 @@ void Shp_rotate::update_rotation_axis_() }; switch (m_rotation_axis) { - case Rotation_axis::X_axis: - set_axis_and_color(1, 0, 0); - break; - case Rotation_axis::Y_axis: - set_axis_and_color(0, 1, 0); - break; - case Rotation_axis::Z_axis: - set_axis_and_color(0, 0, 1); - break; - case Rotation_axis::View_to_object: - return; // Already handled above + case Rotation_axis::X_axis: + set_axis_and_color(1, 0, 0); + break; + case Rotation_axis::Y_axis: + set_axis_and_color(0, 1, 0); + break; + case Rotation_axis::Z_axis: + set_axis_and_color(0, 0, 1); + break; + case Rotation_axis::View_to_object: + return; // Already handled above } // Create a line representing the rotation axis @@ -156,18 +158,18 @@ void Shp_rotate::preview_rotate_() gp_Dir axis_dir; switch (m_rotation_axis) { - case Rotation_axis::X_axis: - axis_dir = gp_Dir(1, 0, 0); - break; - case Rotation_axis::Y_axis: - axis_dir = gp_Dir(0, 1, 0); - break; - case Rotation_axis::Z_axis: - axis_dir = gp_Dir(0, 0, 1); - break; - case Rotation_axis::View_to_object: - axis_dir = m_rotate_pln->Axis().Direction(); - break; + case Rotation_axis::X_axis: + axis_dir = gp_Dir(1, 0, 0); + break; + case Rotation_axis::Y_axis: + axis_dir = gp_Dir(0, 1, 0); + break; + case Rotation_axis::Z_axis: + axis_dir = gp_Dir(0, 0, 1); + break; + case Rotation_axis::View_to_object: + axis_dir = m_rotate_pln->Axis().Direction(); + break; } // Create rotation transformation @@ -192,9 +194,7 @@ Status Shp_rotate::show_angle_edit(const ScreenCoords& screen_coords) if (is_final) finalize(); }; - gui().set_dist_edit( - float(to_degrees(m_angle)), - std::move(std::function(angle_edit))); + gui().set_dist_edit(float(to_degrees(m_angle)), std::move(std::function(angle_edit))); return Status::ok(); } diff --git a/src/shp_rotate.h b/src/shp_rotate.h index 733631d..98293d4 100644 --- a/src/shp_rotate.h +++ b/src/shp_rotate.h @@ -4,15 +4,15 @@ enum class Rotation_axis { - View_to_object, // Rotate around view axis through object center - X_axis, // Rotate around global X axis - Y_axis, // Rotate around global Y axis - Z_axis // Rotate around global Z axis + View_to_object, // Rotate around view axis through object center + X_axis, // Rotate around global X axis + Y_axis, // Rotate around global Y axis + Z_axis // Rotate around global Z axis }; class Shp_rotate : private Shp_operation_base { - public: +public: Shp_rotate(Occt_view& view); [[nodiscard]] Status rotate_selected(const ScreenCoords& screen_coords); @@ -21,12 +21,9 @@ class Shp_rotate : private Shp_operation_base void cancel(); void set_rotation_axis(Rotation_axis axis); - Rotation_axis get_rotation_axis() const - { - return m_rotation_axis; - } + Rotation_axis get_rotation_axis() const { return m_rotation_axis; } - private: +private: [[nodiscard]] Status ensure_start_state_(); void preview_rotate_(); void reset(); @@ -36,8 +33,8 @@ class Shp_rotate : private Shp_operation_base std::optional m_rotate_pln; std::optional m_initial_mouse_pos; std::optional m_center; - double m_angle {0}; - Rotation_axis m_rotation_axis {Rotation_axis::View_to_object}; + double m_angle{0}; + Rotation_axis m_rotation_axis{Rotation_axis::View_to_object}; AIS_Shape_ptr m_rotation_axis_vis; AIS_Shape_ptr m_rotation_center_vis; }; \ No newline at end of file diff --git a/src/shp_scale.cpp b/src/shp_scale.cpp index 11cd48f..3f44995 100644 --- a/src/shp_scale.cpp +++ b/src/shp_scale.cpp @@ -7,7 +7,9 @@ #include "utl.h" Shp_scale::Shp_scale(Occt_view& view) - : Shp_operation_base(view) {} + : Shp_operation_base(view) +{ +} Status Shp_scale::scale_selected(const ScreenCoords& screen_coords) { diff --git a/src/shp_scale.h b/src/shp_scale.h index fc0c650..01ec557 100644 --- a/src/shp_scale.h +++ b/src/shp_scale.h @@ -8,7 +8,7 @@ class Shp_scale : private Shp_operation_base { - public: +public: Shp_scale(Occt_view& view); [[nodiscard]] Status scale_selected(const ScreenCoords& screen_coords); @@ -16,12 +16,12 @@ class Shp_scale : private Shp_operation_base void cancel(); void reset(); - private: +private: [[nodiscard]] Status ensure_start_state_(); void preview_scale_(); std::optional m_scale_pln; std::optional m_center; - double m_initial_distance {0}; - double m_scale_factor {1.0}; + double m_initial_distance{0}; + double m_scale_factor{1.0}; }; diff --git a/src/sketch.cpp b/src/sketch.cpp index 5b70b1c..66e41e5 100644 --- a/src/sketch.cpp +++ b/src/sketch.cpp @@ -34,12 +34,20 @@ using namespace glm; Sketch::Sketch(const std::string& name, Occt_view& view, const gp_Pln& pln) - : m_view(view), m_ctx(view.ctx()), m_pln(pln), m_name(name), m_nodes(view, pln) + : m_view(view) + , m_ctx(view.ctx()) + , m_pln(pln) + , m_name(name) + , m_nodes(view, pln) { } Sketch::Sketch(const std::string& name, Occt_view& view, const gp_Pln& pln, const TopoDS_Wire& outer_wire) - : m_view(view), m_ctx(view.ctx()), m_pln(pln), m_name(name), m_nodes(view, pln) + : m_view(view) + , m_ctx(view.ctx()) + , m_pln(pln) + , m_name(name) + , m_nodes(view, pln) { m_originating_face = new AIS_Shape(outer_wire); m_ctx.Display(m_originating_face, true); @@ -52,7 +60,9 @@ Sketch::~Sketch() m_underlay->erase(m_ctx); auto remove_edge = [&](Edge& e) - { m_ctx.Remove(e.shp, false); }; + { + m_ctx.Remove(e.shp, false); + }; for (Edge& e : m_edges) remove_edge(e); @@ -85,7 +95,7 @@ void Sketch::add_sketch_pt(const ScreenCoords& screen_coords) { switch (get_mode()) { - // clang-format off + // clang-format off case Mode::Sketch_add_square: case Mode::Sketch_add_circle: case Mode::Sketch_add_rectangle: @@ -100,7 +110,7 @@ void Sketch::add_sketch_pt(const ScreenCoords& screen_coords) case Mode::Sketch_operation_axis: add_operation_axis_pt_(screen_coords); break; default: EZY_ASSERT(false); - // clang-format on + // clang-format on } } @@ -108,7 +118,7 @@ void Sketch::sketch_pt_move(const ScreenCoords& screen_coords) { switch (get_mode()) { - // clang-format off + // clang-format off case Mode::Sketch_add_node: move_add_node_pt_ (screen_coords); break; case Mode::Sketch_add_seg_circle_arc: move_arc_circle_pt_ (screen_coords); break; case Mode::Sketch_add_square: move_square_pt_ (screen_coords); break; @@ -131,9 +141,9 @@ void Sketch::sketch_pt_move(const ScreenCoords& screen_coords) move_rectangle_pt_(screen_coords); break; - // clang-format on - default: - break; + // clang-format on + default: + break; } } @@ -174,22 +184,22 @@ void Sketch::update_edge_style_(AIS_Shape_ptr& shp) { switch (m_edge_style) { - case Edge_style::Full: - // shp->SetWidth(1.5); - shp->SetWidth(1.0); - shp->SetColor(Quantity_Color(0.0, 1.0, 0.0, Quantity_TOC_RGB)); - shp->SetTransparency(0.0); + case Edge_style::Full: + // shp->SetWidth(1.5); + shp->SetWidth(1.0); + shp->SetColor(Quantity_Color(0.0, 1.0, 0.0, Quantity_TOC_RGB)); + shp->SetTransparency(0.0); - break; + break; - case Edge_style::Background: - shp->SetWidth(1.0); - shp->SetColor(Quantity_Color(0.3, 0.3, 0.3, Quantity_TOC_RGB)); - shp->SetTransparency(0.7); - break; + case Edge_style::Background: + shp->SetWidth(1.0); + shp->SetColor(Quantity_Color(0.3, 0.3, 0.3, Quantity_TOC_RGB)); + shp->SetTransparency(0.7); + break; - default: - EZY_ASSERT(false); + default: + EZY_ASSERT(false); } } @@ -197,20 +207,20 @@ void Sketch::update_node_mark_style_(AIS_Shape_ptr& shp) { switch (m_edge_style) { - case Edge_style::Full: - shp->SetWidth(1.25); - shp->SetColor(Quantity_NOC_RED); - shp->SetTransparency(0.0); - break; + case Edge_style::Full: + shp->SetWidth(1.25); + shp->SetColor(Quantity_NOC_RED); + shp->SetTransparency(0.0); + break; - case Edge_style::Background: - shp->SetWidth(1.0); - shp->SetColor(Quantity_Color(0.55, 0.12, 0.12, Quantity_TOC_RGB)); - shp->SetTransparency(0.5); - break; + case Edge_style::Background: + shp->SetWidth(1.0); + shp->SetColor(Quantity_Color(0.55, 0.12, 0.12, Quantity_TOC_RGB)); + shp->SetTransparency(0.5); + break; - default: - EZY_ASSERT(false); + default: + EZY_ASSERT(false); } } @@ -219,8 +229,7 @@ void Sketch::sync_permanent_node_annos_() if (m_permanent_node_marks.size() < m_nodes.size()) m_permanent_node_marks.resize(m_nodes.size()); - const double half_arm = - std::max(plane_pick_snap_radius_world_() * 0.45, Precision::Confusion() * 50.0); + const double half_arm = std::max(plane_pick_snap_radius_world_() * 0.45, Precision::Confusion() * 50.0); const Mode mode = get_mode(); // Show "+" markers for permanent user nodes in sketch modes and polar duplicate (which snaps to sketch nodes). @@ -283,29 +292,27 @@ void Sketch::update_originating_face_style() switch (m_edge_style) { - case Edge_style::Full: - m_originating_face->SetWidth(1.0); - m_originating_face->SetColor(Quantity_Color(0.3, 0.0, 0.0, Quantity_TOC_RGB)); - m_originating_face->SetTransparency(0.0); + case Edge_style::Full: + m_originating_face->SetWidth(1.0); + m_originating_face->SetColor(Quantity_Color(0.3, 0.0, 0.0, Quantity_TOC_RGB)); + m_originating_face->SetTransparency(0.0); - break; + break; - case Edge_style::Background: - m_originating_face->SetWidth(1.0); - m_originating_face->SetColor(Quantity_Color(0.3, 0.3, 0.3, Quantity_TOC_RGB)); - m_originating_face->SetTransparency(0.7); - break; + case Edge_style::Background: + m_originating_face->SetWidth(1.0); + m_originating_face->SetColor(Quantity_Color(0.3, 0.3, 0.3, Quantity_TOC_RGB)); + m_originating_face->SetTransparency(0.7); + break; - default: - EZY_ASSERT(false); + default: + EZY_ASSERT(false); } m_ctx.Redisplay(m_originating_face, true); } -void Sketch::update_face_style_(AIS_Shape_ptr& shp) const -{ -} +void Sketch::update_face_style_(AIS_Shape_ptr& shp) const {} void Sketch::update_edge_shp_(Edge& edge, const gp_Pnt2d& pt_a, const gp_Pnt2d& pt_b) { @@ -331,7 +338,7 @@ void Sketch::on_enter() { switch (get_mode()) { - // clang-format off + // clang-format off case Mode::Sketch_add_square: case Mode::Sketch_add_rectangle: case Mode::Sketch_add_rectangle_center_pt: @@ -342,9 +349,9 @@ void Sketch::on_enter() case Mode::Sketch_add_edge: check_dimension_seg_(Linestring_type::Single); break; case Mode::Sketch_add_slot: check_dimension_seg_(Linestring_type::Two); break; case Mode::Sketch_add_multi_edges: check_dimension_seg_(Linestring_type::Multiple); break; - // clang-format on - default: - break; + // clang-format on + default: + break; } } @@ -476,9 +483,8 @@ void Sketch::move_line_string_pt_(const ScreenCoords& screen_coords) { m_tmp_dim_anno = create_distance_annotation( pt_a, final_pt_b, m_pln, edge_dim_text_h_pos_from_index(m_view.gui().edge_dim_label_h()), - approx_sketch_interior_ref_3d_(), - m_dim_classifier_faces.empty() ? nullptr : &m_dim_classifier_faces, m_view.gui().edge_dim_line_width(), - m_view.gui().edge_dim_arrow_size()); + approx_sketch_interior_ref_3d_(), m_dim_classifier_faces.empty() ? nullptr : &m_dim_classifier_faces, + m_view.gui().edge_dim_line_width(), m_view.gui().edge_dim_arrow_size()); m_tmp_dim_anno->SetCustomValue(dist); m_ctx.Display(m_tmp_dim_anno, true); @@ -493,9 +499,7 @@ void Sketch::move_line_string_pt_(const ScreenCoords& screen_coords) auto l = [&, edge_dir](float new_dist, bool is_finial) { - m_entered_edge_len = { - edge_dir, - new_dist * m_view.get_dimension_scale()}; + m_entered_edge_len = {edge_dir, new_dist * m_view.get_dimension_scale()}; m_show_dim_input = !is_finial; if (is_finial) @@ -579,8 +583,8 @@ void Sketch::finalize_edges_() if (!itr->node_idx_arc.has_value()) { // Split the edge. - Edge edge_a {itr->node_idx_a, mid_pt_idx}; - Edge edge_b {mid_pt_idx, *itr->node_idx_b}; + Edge edge_a{itr->node_idx_a, mid_pt_idx}; + Edge edge_b{mid_pt_idx, *itr->node_idx_b}; update_edge_shp_(edge_a, m_nodes[itr->node_idx_a], m_nodes[mid_pt_idx]); update_edge_shp_(edge_b, m_nodes[itr->node_idx_b], m_nodes[mid_pt_idx]); // Set midpoints for the new split edges so they can be snapped to @@ -698,8 +702,7 @@ double Sketch::plane_pick_snap_radius_world_() const const gp_Pnt2d ref2(0.0, 0.0); const ScreenCoords s0 = m_view.get_screen_coords(to_3d(m_pln, ref2)); const dvec2 base = s0.unsafe_get(); - std::optional p1 = - m_view.pt_on_plane(ScreenCoords(dvec2(base.x + px, base.y)), m_pln); + std::optional p1 = m_view.pt_on_plane(ScreenCoords(dvec2(base.x + px, base.y)), m_pln); if (!p1) return std::max(px, Precision::Confusion() * 1e9); return ref2.Distance(*p1); @@ -733,8 +736,7 @@ void Sketch::snap_placed_node_to_closest_linear_edge_interior_(size_t node_idx) if (node_idx == a || node_idx == b) continue; - std::optional proj = - snap_foot_to_open_segment_interior_if_close(p, pa, pb, max_d); + std::optional proj = snap_foot_to_open_segment_interior_if_close(p, pa, pb, max_d); if (!proj) continue; @@ -787,9 +789,9 @@ void Sketch::split_linear_edges_at_node_if_interior_(size_t node_idx) if (!point_on_open_segment_2d(p, pa, pb)) continue; - Edge edge_a {a}; + Edge edge_a{a}; update_edge_end_pt_(edge_a, node_idx); - Edge edge_b {node_idx}; + Edge edge_b{node_idx}; update_edge_end_pt_(edge_b, b); m_ctx.Remove(itr->shp, false); @@ -894,8 +896,7 @@ void Sketch::move_rectangle_pt_(const ScreenCoords& screen_coords) { EZY_ASSERT(m_tmp_edges.size()); - if (std::abs(pt_a.X() - pt_b.X()) > Precision::Confusion() && - std::abs(pt_a.Y() - pt_b.Y()) > Precision::Confusion()) + if (std::abs(pt_a.X() - pt_b.X()) > Precision::Confusion() && std::abs(pt_a.Y() - pt_b.Y()) > Precision::Confusion()) { TopoDS_Wire rectangle = make_rectangle_wire(m_pln, pt_a, pt_b); show(m_ctx, m_tmp_shp, rectangle); @@ -914,8 +915,7 @@ void Sketch::finalize_rectangle_() { auto l = [&](Edge& e, const gp_Pnt2d& pt_a, const gp_Pnt2d& pt_b) { - if (std::abs(pt_a.X() - pt_b.X()) > Precision::Confusion() && - std::abs(pt_a.Y() - pt_b.Y()) > Precision::Confusion()) + if (std::abs(pt_a.X() - pt_b.X()) > Precision::Confusion() && std::abs(pt_a.Y() - pt_b.Y()) > Precision::Confusion()) { std::array corners = rectangle_corners(pt_a, pt_b); add_edge_(corners[0], corners[1]); @@ -957,10 +957,8 @@ void Sketch::finalize_slot_() EZY_ASSERT(m_tmp_edges.size() == 2); EZY_ASSERT(m_tmp_edges[1].node_idx_b.has_value()); - Slot_pnts pnts = get_slot_points( - m_nodes[m_tmp_edges[0].node_idx_a], - m_nodes[m_tmp_edges[1].node_idx_a], - m_nodes[m_tmp_edges[1].node_idx_b]); + Slot_pnts pnts = get_slot_points(m_nodes[m_tmp_edges[0].node_idx_a], m_nodes[m_tmp_edges[1].node_idx_a], + m_nodes[m_tmp_edges[1].node_idx_b]); add_edge_(pnts.a_top_2d, pnts.b_top_2d); add_edge_(pnts.a_bottom_2d, pnts.b_bottom_2d); @@ -983,7 +981,7 @@ void Sketch::add_operation_axis_pt_(const ScreenCoords& screen_coords) void Sketch::finalize_operation_axis_() { m_operation_axis = std::move(m_tmp_edges.back()); - cancel_elm(); // Reset state, we have the operation axis + cancel_elm(); // Reset state, we have the operation axis } void Sketch::clear_operation_axis() @@ -994,10 +992,7 @@ void Sketch::clear_operation_axis() m_operation_axis = std::nullopt; } -bool Sketch::has_operation_axis() const -{ - return m_operation_axis.has_value(); -} +bool Sketch::has_operation_axis() const { return m_operation_axis.has_value(); } void Sketch::mirror_selected_edges() { @@ -1063,8 +1058,7 @@ void Sketch::mirror_selected_edges() Shp_rslt Sketch::revolve_selected(const double angle) { - EZY_ASSERT_MSG(m_operation_axis.has_value(), - "No defined operation axis."); + EZY_ASSERT_MSG(m_operation_axis.has_value(), "No defined operation axis."); TopoDS_Compound compound; BRep_Builder builder; @@ -1132,8 +1126,7 @@ void Sketch::add_sketch_pt_(const ScreenCoords& screen_coords, size_t required_n move_sketch_pt_(screen_coords, l); } -template -void Sketch::move_sketch_pt_(const ScreenCoords& screen_coords, Callback&& callback) +template void Sketch::move_sketch_pt_(const ScreenCoords& screen_coords, Callback&& callback) { m_last_pt = m_view.pt_on_plane(screen_coords, m_pln); if (!m_last_pt) @@ -1146,8 +1139,7 @@ void Sketch::move_sketch_pt_(const ScreenCoords& screen_coords, Callback&& callb } /// Invokes callback(e, pt_a, pt_b) with the last tmp edge only when it exists and is non-degenerate. -template -void Sketch::if_edge_pt_valid_(Callback&& callback) +template void Sketch::if_edge_pt_valid_(Callback&& callback) { if (m_tmp_edges.empty()) return; @@ -1186,17 +1178,17 @@ void Sketch::check_dimension_seg_(Linestring_type linestring_type) { switch (m_tmp_edges.size()) { - case 1: - m_entered_edge_angle = std::nullopt; - m_show_angle_input = false; - m_view.gui().hide_angle_edit(); - m_tmp_edges.push_back({*edge.node_idx_b}); - break; - case 2: - finalize_elm(); - break; - default: - EZY_ASSERT(false); + case 1: + m_entered_edge_angle = std::nullopt; + m_show_angle_input = false; + m_view.gui().hide_angle_edit(); + m_tmp_edges.push_back({*edge.node_idx_b}); + break; + case 2: + finalize_elm(); + break; + default: + EZY_ASSERT(false); } } else @@ -1267,7 +1259,7 @@ void Sketch::finalize_add_node_elm_cleanup_() void Sketch::add_edge_(const gp_Pnt2d& pt_a, const gp_Pnt2d& pt_b) { - Edge edge {m_nodes.get_node_exact(pt_a)}; + Edge edge{m_nodes.get_node_exact(pt_a)}; update_edge_end_pt_(edge, m_nodes.get_node_exact(pt_b)); m_edges.emplace_back(edge); m_nodes.finalize(); @@ -1277,7 +1269,7 @@ void Sketch::sketch_json_add_linear_edge_(size_t idx_a, size_t idx_b, size_t idx { EZY_ASSERT(idx_a < m_nodes.size() && idx_b < m_nodes.size() && idx_mid < m_nodes.size()); - Edge edge {idx_a}; + Edge edge{idx_a}; edge.node_idx_b = idx_b; edge.node_idx_mid = idx_mid; const gp_Pnt2d& pt_a = m_nodes[idx_a]; @@ -1350,7 +1342,7 @@ void Sketch::update_len_dim_rubber_line_(const ScreenCoords& screen_coords) return; gp_Pnt2d pt_b = *pt_opt; - (void) m_nodes.try_get_node_idx_snap(pt_b); + (void)m_nodes.try_get_node_idx_snap(pt_b); if (!unique(pt_a, pt_b)) { @@ -1396,10 +1388,9 @@ void Sketch::rebuild_length_dimension_display_(Length_dimension& d) m_ctx.Remove(d.dim, false); d.dim = create_distance_annotation( - m_nodes[d.node_idx_lo], m_nodes[d.node_idx_hi], m_pln, - edge_dim_text_h_pos_from_index(m_view.gui().edge_dim_label_h()), approx_sketch_interior_ref_3d_(), - m_dim_classifier_faces.empty() ? nullptr : &m_dim_classifier_faces, m_view.gui().edge_dim_line_width(), - m_view.gui().edge_dim_arrow_size()); + m_nodes[d.node_idx_lo], m_nodes[d.node_idx_hi], m_pln, edge_dim_text_h_pos_from_index(m_view.gui().edge_dim_label_h()), + approx_sketch_interior_ref_3d_(), m_dim_classifier_faces.empty() ? nullptr : &m_dim_classifier_faces, + m_view.gui().edge_dim_line_width(), m_view.gui().edge_dim_arrow_size()); const double dist = m_nodes[d.node_idx_lo].Distance(m_nodes[d.node_idx_hi]); d.dim->SetCustomValue(dist / m_view.get_dimension_scale()); @@ -1479,11 +1470,8 @@ void Sketch::add_or_toggle_length_dim_between_node_indices_(size_t node_a, size_ rebuild_length_dimension_display_(m_length_dimensions.back()); } -void Sketch::json_add_length_dimension_(size_t node_a, - size_t node_b, - const bool visible, - const std::optional flyout_offset, - const std::string& name) +void Sketch::json_add_length_dimension_(size_t node_a, size_t node_b, const bool visible, + const std::optional flyout_offset, const std::string& name) { const size_t lo = std::min(node_a, node_b); const size_t hi = std::max(node_a, node_b); @@ -1558,7 +1546,7 @@ void Sketch::finalize_elm() switch (get_mode()) { - // clang-format off + // clang-format off case Mode::Sketch_add_node: finalize_add_node_elm_cleanup_(); break; case Mode::Sketch_add_edge: case Mode::Sketch_add_multi_edges: finalize_edges_(); break; @@ -1577,9 +1565,9 @@ void Sketch::finalize_elm() case Mode::Sketch_add_slot: finalize_slot_(); break; case Mode::Sketch_operation_axis: finalize_operation_axis_(); break; - // clang-format on - default: - EZY_ASSERT(false); + // clang-format on + default: + EZY_ASSERT(false); } } @@ -1704,7 +1692,7 @@ void Sketch::update_faces_() excluded_edges.insert(to_exclude.begin(), to_exclude.end()); } -#if 1 // TODO study AI generated, seems to work. +#if 1 // TODO study AI generated, seems to work. // Remove bridge edges that connect two separate cycles. // A bridge edge connects two cycles and has both endpoints with degree >= 3. // We detect this by checking if the edge is the only connection between two cycles. @@ -1882,9 +1870,9 @@ void Sketch::update_faces_() } auto f = create_face_shape_(face); - f->SetColor(Quantity_NOC_GRAY7); // Base color - f->SetTransparency(0.5); // 0.5 = 50% transparent (0.0 = opaque, 1.0 = invisible) - f->SetMaterial(Graphic3d_NOM_PLASTIC); // Optional: material for shading + f->SetColor(Quantity_NOC_GRAY7); // Base color + f->SetTransparency(0.5); // 0.5 = 50% transparent (0.0 = opaque, 1.0 = invisible) + f->SetMaterial(Graphic3d_NOM_PLASTIC); // Optional: material for shading m_ctx.Display(f, AIS_Shaded, AIS_Shape::SelectionMode(TopAbs_FACE), true); m_ctx.Activate(f, AIS_Shape::SelectionMode(TopAbs_FACE)); @@ -1949,7 +1937,7 @@ void Sketch::update_faces_() std::sort(face_metas.begin(), face_metas.end(), [](const Face_meta& a, const Face_meta& b) { - return a.area > b.area; // Descending by area + return a.area > b.area; // Descending by area }); // Classify faces @@ -2172,10 +2160,7 @@ void Sketch::update_edge_end_pt_(Edge& edge, size_t end_pt_idx) void Sketch::add_arc_circle_(const gp_Pnt2d& pt_a, const gp_Pnt2d& pt_b, const gp_Pnt2d& pt_c) { - std::vector node_idxs { - m_nodes.get_node_exact(pt_a), - m_nodes.get_node_exact(pt_c), - m_nodes.get_node_exact(pt_b)}; + std::vector node_idxs{m_nodes.get_node_exact(pt_a), m_nodes.get_node_exact(pt_c), m_nodes.get_node_exact(pt_b)}; add_arc_circle_(node_idxs); } @@ -2183,10 +2168,7 @@ void Sketch::add_arc_circle_(const gp_Pnt2d& pt_a, const gp_Pnt2d& pt_b, const g void Sketch::add_arc_circle_(const std::vector& node_idxs) { EZY_ASSERT(node_idxs.size() == 3); - Geom_TrimmedCurve_ptr arc_of_circle = GC_MakeArcOfCircle( - to_3d_(node_idxs[0]), - to_3d_(node_idxs[2]), - to_3d_(node_idxs[1])); + Geom_TrimmedCurve_ptr arc_of_circle = GC_MakeArcOfCircle(to_3d_(node_idxs[0]), to_3d_(node_idxs[2]), to_3d_(node_idxs[1])); /* auto l = get_start_end_tangents(anArcOfCircle); @@ -2195,17 +2177,13 @@ void Sketch::add_arc_circle_(const std::vector& node_idxs) l.second *= 10.0; { - TopoDS_Shape edge_shape = BRepBuilderAPI_MakeEdge(anArcOfCircle->StartPoint(), anArcOfCircle->StartPoint().XYZ() + l.first.XYZ()).Edge(); - AIS_Shape_ptr s = new AIS_Shape(edge_shape); - s->SetWidth(2.0); - s->SetColor(Quantity_Color(1, 0.0, 0.7, Quantity_TOC_RGB)); - m_view.display(s); + TopoDS_Shape edge_shape = BRepBuilderAPI_MakeEdge(anArcOfCircle->StartPoint(), anArcOfCircle->StartPoint().XYZ() + + l.first.XYZ()).Edge(); AIS_Shape_ptr s = new AIS_Shape(edge_shape); s->SetWidth(2.0); s->SetColor(Quantity_Color(1, 0.0, + 0.7, Quantity_TOC_RGB)); m_view.display(s); } - TopoDS_Shape edge_shape = BRepBuilderAPI_MakeEdge(anArcOfCircle->EndPoint(), anArcOfCircle->EndPoint().XYZ() + l.second.XYZ()).Edge(); - AIS_Shape_ptr s = new AIS_Shape(edge_shape); - s->SetWidth(2.0); - s->SetColor(Quantity_Color(1, 0.0, 0.7, Quantity_TOC_RGB)); - m_view.display(s); + TopoDS_Shape edge_shape = BRepBuilderAPI_MakeEdge(anArcOfCircle->EndPoint(), anArcOfCircle->EndPoint().XYZ() + + l.second.XYZ()).Edge(); AIS_Shape_ptr s = new AIS_Shape(edge_shape); s->SetWidth(2.0); s->SetColor(Quantity_Color(1, 0.0, + 0.7, Quantity_TOC_RGB)); m_view.display(s); */ Sketch_AIS_edge_ptr shp = new Sketch_AIS_edge(*this, BRepBuilderAPI_MakeEdge(arc_of_circle)); @@ -2255,7 +2233,8 @@ bool Sketch::clear_tmps_() } bool operation_canceled = m_tmp_edges.size(); - clear_all(m_tmp_node_idxs, m_tmp_shp, m_tmp_edges, m_entered_edge_len, m_show_dim_input, m_entered_edge_angle, m_show_angle_input); + clear_all(m_tmp_node_idxs, m_tmp_shp, m_tmp_edges, m_entered_edge_len, m_show_dim_input, m_entered_edge_angle, + m_show_angle_input); return operation_canceled; } @@ -2267,20 +2246,11 @@ void Sketch::on_mode() sync_permanent_node_annos_(); } -Mode Sketch::get_mode() const -{ - return m_view.get_mode(); -} +Mode Sketch::get_mode() const { return m_view.get_mode(); } -const gp_Pln& Sketch::get_plane() const -{ - return m_pln; -} +const gp_Pln& Sketch::get_plane() const { return m_pln; } -Sketch_nodes& Sketch::get_nodes() -{ - return m_nodes; -} +Sketch_nodes& Sketch::get_nodes() { return m_nodes; } void Sketch::get_snap_pts_3d_(std::vector& out) { @@ -2395,10 +2365,7 @@ void Sketch::set_visible(bool state) m_view.curr_sketch().set_current(); } -bool Sketch::is_visible() const -{ - return m_visible; -} +bool Sketch::is_visible() const { return m_visible; } void Sketch::set_show_faces(bool show) { @@ -2535,10 +2502,7 @@ void Sketch::refresh_edge_dimension_arrow_sizes(const double arrow_size) } } -bool Sketch::is_current() const -{ - return this == &m_view.curr_sketch(); -} +bool Sketch::is_current() const { return this == &m_view.curr_sketch(); } void Sketch::set_current() { @@ -2590,10 +2554,7 @@ void Sketch::set_edge_style(Edge_style style) update_originating_face_style(); } -gp_Pnt Sketch::to_3d_(size_t node_idx) const -{ - return to_3d(m_pln, m_nodes[node_idx]); -} +gp_Pnt Sketch::to_3d_(size_t node_idx) const { return to_3d(m_pln, m_nodes[node_idx]); } gp_Pnt Sketch::to_3d_(const std::optional& node_idx) const { @@ -2601,35 +2562,17 @@ gp_Pnt Sketch::to_3d_(const std::optional& node_idx) const return to_3d_(*node_idx); } -const std::string& Sketch::get_name() const -{ - return m_name; -} +const std::string& Sketch::get_name() const { return m_name; } -void Sketch::set_name(const std::string& name) -{ - m_name = name; -} +void Sketch::set_name(const std::string& name) { m_name = name; } -bool Sketch::has_edges() const -{ - return !m_edges.empty(); -} +bool Sketch::has_edges() const { return !m_edges.empty(); } -size_t Sketch::edge_count() const -{ - return m_edges.size(); -} +size_t Sketch::edge_count() const { return m_edges.size(); } -size_t Sketch::face_count() const -{ - return m_faces.size(); -} +size_t Sketch::face_count() const { return m_faces.size(); } -size_t Sketch::length_dimension_count() const -{ - return m_length_dimensions.size(); -} +size_t Sketch::length_dimension_count() const { return m_length_dimensions.size(); } std::vector Sketch::inspector_edge_labels() const { @@ -2686,20 +2629,11 @@ std::vector Sketch::inspector_node_labels() const return labels; } -bool Sketch::has_underlay() const -{ - return m_underlay && m_underlay->has_image(); -} +bool Sketch::has_underlay() const { return m_underlay && m_underlay->has_image(); } -int Sketch::underlay_image_w() const -{ - return (m_underlay && m_underlay->has_image()) ? m_underlay->image_w() : 0; -} +int Sketch::underlay_image_w() const { return (m_underlay && m_underlay->has_image()) ? m_underlay->image_w() : 0; } -int Sketch::underlay_image_h() const -{ - return (m_underlay && m_underlay->has_image()) ? m_underlay->image_h() : 0; -} +int Sketch::underlay_image_h() const { return (m_underlay && m_underlay->has_image()) ? m_underlay->image_h() : 0; } bool Sketch::load_underlay_image(const std::string& file_bytes) { @@ -2756,8 +2690,8 @@ void Sketch::underlay_set_affine_plane(const gp_Pnt2d& base, const gp_Vec2d& axi namespace { -bool underlay_plane_to_uv(const gp_Pnt2d& base, const gp_Vec2d& au, const gp_Vec2d& av, const gp_Pnt2d& p, - double& out_u, double& out_v) +bool underlay_plane_to_uv(const gp_Pnt2d& base, const gp_Vec2d& au, const gp_Vec2d& av, const gp_Pnt2d& p, double& out_u, + double& out_v) { const double det = au.X() * av.Y() - au.Y() * av.X(); if (std::abs(det) < 1e-18) @@ -2767,7 +2701,7 @@ bool underlay_plane_to_uv(const gp_Pnt2d& base, const gp_Vec2d& au, const gp_Vec out_v = (-r.X() * au.Y() + r.Y() * au.X()) / det; return true; } -} // namespace +} // namespace bool Sketch::underlay_rescale_uv_chord_to_length(const gp_Pnt2d& p0, const gp_Pnt2d& p1, double target_len) { @@ -2778,10 +2712,10 @@ bool Sketch::underlay_rescale_uv_chord_to_length(const gp_Pnt2d& p0, const gp_Pn const gp_Pnt2d base = m_underlay->base(); const gp_Vec2d au = m_underlay->axis_u(); const gp_Vec2d av = m_underlay->axis_v(); - double u0 {}; - double v0 {}; - double u1 {}; - double v1 {}; + double u0{}; + double v0{}; + double u1{}; + double v1{}; if (!underlay_plane_to_uv(base, au, av, p0, u0, v0) || !underlay_plane_to_uv(base, au, av, p1, u1, v1)) return false; const double L = p0.Distance(p1); @@ -2805,10 +2739,10 @@ bool Sketch::underlay_rescale_v_chord_to_length(const gp_Pnt2d& y0, const gp_Pnt const gp_Pnt2d base = m_underlay->base(); const gp_Vec2d au = m_underlay->axis_u(); const gp_Vec2d av = m_underlay->axis_v(); - double u0 {}; - double v0 {}; - double u1 {}; - double v1 {}; + double u0{}; + double v0{}; + double u1{}; + double v1{}; if (!underlay_plane_to_uv(base, au, av, y0, u0, v0) || !underlay_plane_to_uv(base, au, av, y1, u1, v1)) return false; const double du = u1 - u0; @@ -2852,8 +2786,8 @@ bool Sketch::underlay_set_datum_origin_and_u_direction(const gp_Pnt2d& origin, c const double uy = du.Y(); const double det_old = au_old.X() * av_old.Y() - au_old.Y() * av_old.X(); - double px {}; - double py {}; + double px{}; + double py{}; if (det_old >= 0.0) { px = -uy; @@ -2872,8 +2806,7 @@ bool Sketch::underlay_set_datum_origin_and_u_direction(const gp_Pnt2d& origin, c return true; } -void Sketch::underlay_set_center_extents_rotation(const dvec2& center, const dvec2& half_extents, - double rot_deg) +void Sketch::underlay_set_center_extents_rotation(const dvec2& center, const dvec2& half_extents, double rot_deg) { EZY_ASSERT(m_underlay); EZY_ASSERT(m_underlay->has_image()); @@ -2903,15 +2836,9 @@ void Sketch::underlay_set_visible(bool v) m_ctx.UpdateCurrentViewer(); } -float Sketch::underlay_opacity() const -{ - return m_underlay ? m_underlay->opacity() : 1.f; -} +float Sketch::underlay_opacity() const { return m_underlay ? m_underlay->opacity() : 1.f; } -bool Sketch::underlay_visible() const -{ - return m_underlay && m_underlay->visible(); -} +bool Sketch::underlay_visible() const { return m_underlay && m_underlay->visible(); } void Sketch::underlay_set_key_white_transparent(bool on) { @@ -2921,10 +2848,7 @@ void Sketch::underlay_set_key_white_transparent(bool on) underlay_rebuild_display(); } -bool Sketch::underlay_key_white_transparent() const -{ - return m_underlay ? m_underlay->key_white_transparent() : true; -} +bool Sketch::underlay_key_white_transparent() const { return m_underlay ? m_underlay->key_white_transparent() : true; } void Sketch::underlay_set_line_tint_enabled(bool on) { @@ -2950,10 +2874,7 @@ void Sketch::underlay_set_line_tint_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_ underlay_rebuild_display(); } -bool Sketch::underlay_line_tint_enabled() const -{ - return m_underlay ? m_underlay->line_tint_enabled() : true; -} +bool Sketch::underlay_line_tint_enabled() const { return m_underlay ? m_underlay->line_tint_enabled() : true; } void Sketch::underlay_line_tint_rgb(uint8_t& r, uint8_t& g, uint8_t& b) const { @@ -3032,14 +2953,20 @@ bool Sketch::Edge::reversed(size_t idx_a, size_t idx_b) const } Sketch_AIS_edge::Sketch_AIS_edge(Sketch& owner, const TopoDS_Shape& shp) - : AIS_Shape(shp), owner_sketch(owner) + : AIS_Shape(shp) + , owner_sketch(owner) { } Sketch_AIS_node_mark::Sketch_AIS_node_mark(Sketch& owner, size_t node_idx, const TopoDS_Shape& shp) - : AIS_Shape(shp), owner_sketch(owner), node_idx(node_idx) + : AIS_Shape(shp) + , owner_sketch(owner) + , node_idx(node_idx) { } Sketch_face_shp::Sketch_face_shp(Sketch& owner, const TopoDS_Shape& face) - : owner_sketch(owner), AIS_Shape(face) {} \ No newline at end of file + : owner_sketch(owner) + , AIS_Shape(face) +{ +} \ No newline at end of file diff --git a/src/sketch.h b/src/sketch.h index e821f49..41700b7 100644 --- a/src/sketch.h +++ b/src/sketch.h @@ -35,7 +35,7 @@ struct Sketch_AIS_node_mark : public AIS_Shape { Sketch_AIS_node_mark(Sketch& owner, size_t node_idx, const TopoDS_Shape& shp); Sketch& owner_sketch; - size_t node_idx {}; + size_t node_idx{}; }; struct Sketch_face_shp : public AIS_Shape @@ -43,7 +43,7 @@ struct Sketch_face_shp : public AIS_Shape Sketch_face_shp(Sketch& owner, const TopoDS_Shape& face); Sketch& owner_sketch; - std::vector verts_3d; // Used for extruding the face + std::vector verts_3d; // Used for extruding the face std::vector vert_idxs; std::string name; }; @@ -58,9 +58,9 @@ using Sketch_face_shp_ptr = opencascade::handle; // and extracting faces from the sketch. class Sketch { - public: +public: DECL_PTR(Sketch); - using Sketch_ptr = sptr; // Compatibility alias for existing code. + using Sketch_ptr = sptr; // Compatibility alias for existing code. // `view` must exist for the lifetime of this `Sketch` Sketch(const std::string& name, Occt_view& view, const gp_Pln& pln); @@ -84,7 +84,7 @@ class Sketch bool cancel_elm(); void clear_operation_axis(); bool has_operation_axis() const; - void on_enter(); // For finalizing manual distance input. + void on_enter(); // For finalizing manual distance input. // Visibility related void set_visible(bool state); @@ -108,7 +108,7 @@ class Sketch Shp_rslt revolve_selected(const double angle); bool is_current() const; - void set_current(); // Make current in m_view + void set_current(); // Make current in m_view void set_edge_style(Edge_style style); void remove_edge(const Sketch_AIS_edge& edge); void remove_permanent_node_mark(Sketch_AIS_node_mark& mark); @@ -142,14 +142,14 @@ class Sketch const gp_Pln& get_plane() const; Sketch_nodes& get_nodes(); - [[nodiscard]] bool has_underlay() const; - [[nodiscard]] int underlay_image_w() const; - [[nodiscard]] int underlay_image_h() const; - [[nodiscard]] bool load_underlay_image(const std::string& file_bytes); - void clear_underlay(); - void underlay_set_center_extents_rotation(const glm::dvec2& center, const glm::dvec2& half_extents, double rot_deg); - void underlay_set_opacity(float opaque01); - void underlay_set_visible(bool v); + [[nodiscard]] bool has_underlay() const; + [[nodiscard]] int underlay_image_w() const; + [[nodiscard]] int underlay_image_h() const; + [[nodiscard]] bool load_underlay_image(const std::string& file_bytes); + void clear_underlay(); + void underlay_set_center_extents_rotation(const glm::dvec2& center, const glm::dvec2& half_extents, double rot_deg); + void underlay_set_opacity(float opaque01); + void underlay_set_visible(bool v); [[nodiscard]] float underlay_opacity() const; [[nodiscard]] bool underlay_visible() const; void underlay_set_key_white_transparent(bool on); @@ -162,33 +162,33 @@ class Sketch void underlay_line_tint_rgba(uint8_t& r, uint8_t& g, uint8_t& b, uint8_t& a) const; void underlay_ui_params(double& cx, double& cy, double& half_w, double& half_h, double& rot_deg) const; /// True when texture U and V directions are perpendicular (no shear). Orthogonal UI assumes this. - [[nodiscard]] bool underlay_axes_orthogonal() const; - void underlay_rebuild_display(); + [[nodiscard]] bool underlay_axes_orthogonal() const; + void underlay_rebuild_display(); /// Same snap / plane rules as the line-edge tool (for underlay calibration clicks). [[nodiscard]] std::optional pick_point_for_underlay_calib(const ScreenCoords& screen_coords); /// Set underlay from texture corner \a base, U edge vector \a axis_u, V edge vector \a axis_v (plane 2D). - void underlay_set_affine_plane(const gp_Pnt2d& base, const gp_Vec2d& axis_u, const gp_Vec2d& axis_v); + void underlay_set_affine_plane(const gp_Pnt2d& base, const gp_Vec2d& axis_u, const gp_Vec2d& axis_v); /// Uniformly scale texture axes so plane segment \a p0-\a p1 has length \a target_len; UV at \a p0 stays fixed. - [[nodiscard]] bool underlay_rescale_uv_chord_to_length(const gp_Pnt2d& p0, const gp_Pnt2d& p1, double target_len); + [[nodiscard]] bool underlay_rescale_uv_chord_to_length(const gp_Pnt2d& p0, const gp_Pnt2d& p1, double target_len); /// Keep U axis; adjust V and base so segment \a y0-\a y1 has length \a target_len (after X calibration). - [[nodiscard]] bool underlay_rescale_v_chord_to_length(const gp_Pnt2d& y0, const gp_Pnt2d& y1, double target_len); - [[nodiscard]] gp_Vec2d underlay_axis_u_vec() const; + [[nodiscard]] bool underlay_rescale_v_chord_to_length(const gp_Pnt2d& y0, const gp_Pnt2d& y1, double target_len); + [[nodiscard]] gp_Vec2d underlay_axis_u_vec() const; /// Datum on sketch plane: bitmap (0,0) at \a origin; +U toward \a along_u_point; keeps |axis_u|, |axis_v| and winding. - [[nodiscard]] bool underlay_set_datum_origin_and_u_direction(const gp_Pnt2d& origin, const gp_Pnt2d& along_u_point); + [[nodiscard]] bool underlay_set_datum_origin_and_u_direction(const gp_Pnt2d& origin, const gp_Pnt2d& along_u_point); // private: friend class Sketch_json; friend class Sketch_access; - friend class Sketch_test; // TEST_F(Sketch_test, JsonSerializationDeserialization) + friend class Sketch_test; // TEST_F(Sketch_test, JsonSerializationDeserialization) /// Linear distance between two sketch nodes (independent of which edge connects them). struct Length_dimension { - size_t node_idx_lo {}; - size_t node_idx_hi {}; + size_t node_idx_lo{}; + size_t node_idx_hi{}; PrsDim_LengthDimension_ptr dim; - bool visible {true}; + bool visible{true}; std::optional flyout_offset; std::string name; }; @@ -197,12 +197,12 @@ class Sketch { size_t node_idx_a; std::optional node_idx_b; - std::optional node_idx_arc; // Only valid for circle arc edges. - std::optional node_idx_mid; // Midpoint of edge, used for snapping. + std::optional node_idx_arc; // Only valid for circle arc edges. + std::optional node_idx_mid; // Midpoint of edge, used for snapping. // Used to identify the two `Edges` defining a circle arc. Geom_TrimmedCurve_ptr circle_arc; - Sketch_AIS_edge_ptr shp; // Current edge annotation. + Sketch_AIS_edge_ptr shp; // Current edge annotation. std::string name; @@ -278,12 +278,10 @@ class Sketch // General sketch point related template void add_sketch_pt_(const ScreenCoords& screen_coords, size_t required_num_pts, Callback&& callback); - template - void move_sketch_pt_(const ScreenCoords& screen_coords, Callback&& callback); + template void move_sketch_pt_(const ScreenCoords& screen_coords, Callback&& callback); /// Invokes callback(e, pt_a, pt_b) with the last tmp edge only when it exists and is non-degenerate. - template - void if_edge_pt_valid_(Callback&& callback); - void check_dimension_seg_(Linestring_type linestring_type); + template void if_edge_pt_valid_(Callback&& callback); + void check_dimension_seg_(Linestring_type linestring_type); /// Typed distance (Enter) while add-node rubber band is active - places node B, no edge. /// Enter key / dist popup commit for rubber-band tmp edge (add node, square, circle, rectangle, ...). void check_dimension_rubber_(); @@ -326,11 +324,8 @@ class Sketch void remove_length_dimensions_referencing_node_(size_t node_idx); /// Add if missing, remove if present (same unordered node pair). void add_or_toggle_length_dim_between_node_indices_(size_t node_a, size_t node_b); - void json_add_length_dimension_(size_t node_a, - size_t node_b, - bool visible = true, - std::optional flyout_offset = std::nullopt, - const std::string& name = {}); + void json_add_length_dimension_(size_t node_a, size_t node_b, bool visible = true, + std::optional flyout_offset = std::nullopt, const std::string& name = {}); /// Average of non-deleted node positions (3D on sketch plane); used to place edge dimensions outside loops. std::optional approx_sketch_interior_ref_3d_() const; @@ -347,7 +342,7 @@ class Sketch void clear_len_dim_pick_state_(); // Style related - Edge_style m_edge_style {Edge_style::Full}; + Edge_style m_edge_style{Edge_style::Full}; // Arc circle related. std::optional m_start_arc_circle_node_idx; @@ -361,7 +356,7 @@ class Sketch std::string m_dbg_str; std::string m_name; - bool m_visible {true}; + bool m_visible{true}; // Extrusion related. std::optional m_to_extrude_pt; @@ -372,16 +367,16 @@ class Sketch // Dimensions related std::optional m_entered_edge_len; - bool m_show_dim_input {false}; - std::optional m_entered_edge_angle; // Angle in degrees - bool m_show_angle_input {false}; + bool m_show_dim_input{false}; + std::optional m_entered_edge_angle; // Angle in degrees + bool m_show_angle_input{false}; // Geometry related - AIS_Shape_ptr m_originating_face; // If this sketch was created from a face. - gp_Pln m_pln; // Plane this sketch is on. + AIS_Shape_ptr m_originating_face; // If this sketch was created from a face. + gp_Pln m_pln; // Plane this sketch is on. - std::optional m_last_pt; - Sketch_nodes m_nodes; + std::optional m_last_pt; + Sketch_nodes m_nodes; /// One entry per node index; only indices with permanent, non-deleted nodes hold a displayed + marker. std::vector m_permanent_node_marks; std::list m_edges; @@ -390,13 +385,13 @@ class Sketch std::vector m_length_dimensions; std::optional m_len_dim_pick_anchor_node; /// Preview segment from anchor node to cursor while picking the second node (dim mode). - AIS_Shape_ptr m_len_dim_rubber_shp; - std::vector m_tmp_node_idxs; - std::vector m_tmp_edges; - AIS_Shape_ptr m_tmp_shp; - PrsDim_LengthDimension_ptr m_tmp_dim_anno; - bool m_show_faces {true}; - bool m_show_dims {true}; + AIS_Shape_ptr m_len_dim_rubber_shp; + std::vector m_tmp_node_idxs; + std::vector m_tmp_edges; + AIS_Shape_ptr m_tmp_shp; + PrsDim_LengthDimension_ptr m_tmp_dim_anno; + bool m_show_faces{true}; + bool m_show_dims{true}; std::unique_ptr m_underlay; }; diff --git a/src/sketch_json.cpp b/src/sketch_json.cpp index b4d5d40..5be91ff 100644 --- a/src/sketch_json.cpp +++ b/src/sketch_json.cpp @@ -47,7 +47,7 @@ json node_to_json_(const Sketch_nodes::Node& nd) return o; } -} // namespace +} // namespace void Sketch_json::load_nodes_(Sketch& sketch, const json& nodes_json) { @@ -62,12 +62,11 @@ void Sketch_json::load_nodes_(Sketch& sketch, const json& nodes_json) continue; } EZY_ASSERT(el.is_object()); - const gp_Pnt2d pt = ::from_json_pnt2d(el); - const bool midpoint = - el.contains("midpoint") && el["midpoint"].is_boolean() && el["midpoint"].get(); - const bool permanent = - el.contains("permanent") && el["permanent"].is_boolean() && el["permanent"].get(); - sketch.get_nodes().json_set_node(i, pt, false, midpoint, permanent, el.contains("name") && el["name"].is_string() ? el["name"].get() : ""); + const gp_Pnt2d pt = ::from_json_pnt2d(el); + const bool midpoint = el.contains("midpoint") && el["midpoint"].is_boolean() && el["midpoint"].get(); + const bool permanent = el.contains("permanent") && el["permanent"].is_boolean() && el["permanent"].get(); + sketch.get_nodes().json_set_node(i, pt, false, midpoint, permanent, + el.contains("name") && el["name"].is_string() ? el["name"].get() : ""); } } @@ -100,7 +99,7 @@ void Sketch_json::from_json_indexed_(Sketch& ret, const json& j, const std::size_t iarc = edge_json[1].get(); const std::size_t ib = edge_json[2].get(); // Matches `add_arc_circle_(pt_a, pt_b, pt_c)` -> node_idxs [a, c, b] for (json0, json1, json2) = (start, arc, end). - ret.add_arc_circle_(std::vector {ia, ib, iarc}); + ret.add_arc_circle_(std::vector{ia, ib, iarc}); } } @@ -184,8 +183,7 @@ nlohmann::json Sketch_json::to_json(const Sketch& sketch) if (!edge.circle_arc) { EZY_ASSERT(edge.node_idx_mid.has_value()); - edges_json.push_back( - json::array({remap(edge.node_idx_a), remap(*edge.node_idx_b), remap(*edge.node_idx_mid)})); + edges_json.push_back(json::array({remap(edge.node_idx_a), remap(*edge.node_idx_b), remap(*edge.node_idx_mid)})); } else { @@ -193,9 +191,8 @@ nlohmann::json Sketch_json::to_json(const Sketch& sketch) { EZY_ASSERT(last_arc_circle_edge->circle_arc.get() == edge.circle_arc.get()); EZY_ASSERT(last_arc_circle_edge->node_idx_arc.has_value()); - arc_edges_json.push_back(json::array({remap(last_arc_circle_edge->node_idx_a), - remap(*last_arc_circle_edge->node_idx_arc), - remap(*edge.node_idx_b)})); + arc_edges_json.push_back(json::array( + {remap(last_arc_circle_edge->node_idx_a), remap(*last_arc_circle_edge->node_idx_arc), remap(*edge.node_idx_b)})); last_arc_circle_edge = nullptr; } else @@ -267,7 +264,7 @@ Sketch::sptr Sketch_json::from_json(Occt_view& view, const nlohmann::json& j) for (const auto& pair_json : j["length_dimensions"]) { EZY_ASSERT(pair_json.is_array() && (pair_json.size() >= 2 && pair_json.size() <= 5)); - const bool visible = pair_json.size() >= 3 ? pair_json[2].get() : true; + const bool visible = pair_json.size() >= 3 ? pair_json[2].get() : true; std::optional flyout_offset; std::string dim_name; if (pair_json.size() >= 4) @@ -283,8 +280,8 @@ Sketch::sptr Sketch_json::from_json(Occt_view& view, const nlohmann::json& j) } if (pair_json.size() == 5 && pair_json[4].is_string()) dim_name = pair_json[4].get(); - ret->json_add_length_dimension_(pair_json[0].get(), pair_json[1].get(), visible, - flyout_offset, dim_name); + ret->json_add_length_dimension_(pair_json[0].get(), pair_json[1].get(), visible, flyout_offset, + dim_name); } if (j.contains("underlay") && j["underlay"].is_object()) diff --git a/src/sketch_json.h b/src/sketch_json.h index c89fa92..1d4a956 100644 --- a/src/sketch_json.h +++ b/src/sketch_json.h @@ -12,12 +12,12 @@ class Occt_view; class Sketch_json { - public: +public: static nlohmann::json to_json(const Sketch& sketch); static std::shared_ptr from_json(Occt_view& view, const nlohmann::json& j); - private: +private: Sketch_json() = default; ~Sketch_json() = default; diff --git a/src/sketch_nodes.cpp b/src/sketch_nodes.cpp index 81c34f3..2b56a72 100644 --- a/src/sketch_nodes.cpp +++ b/src/sketch_nodes.cpp @@ -13,13 +13,15 @@ #include "occt_view.h" Sketch_nodes::Sketch_nodes(Occt_view& view, const gp_Pln& pln) - : m_view(view), m_ctx(m_view.ctx()), m_pln(pln) + : m_view(view) + , m_ctx(m_view.ctx()) + , m_pln(pln) { } Sketch_nodes::~Sketch_nodes() { - hide_snap_annos(); // Deletes them from context + hide_snap_annos(); // Deletes them from context } std::optional Sketch_nodes::snap(const ScreenCoords& screen_coords) @@ -54,7 +56,7 @@ size_t Sketch_nodes::get_node_exact(const gp_Pnt2d& pt, bool permanent_for_new) // If only a deleted exact match exists, revive it instead of appending a duplicate index. if (deleted_match.has_value()) { - Node& n = m_nodes[*deleted_match]; + Node& n = m_nodes[*deleted_match]; n.deleted = false; if (permanent_for_new) n.permanent = true; @@ -62,7 +64,7 @@ size_t Sketch_nodes::get_node_exact(const gp_Pnt2d& pt, bool permanent_for_new) } Node n(pt); - n.permanent = permanent_for_new; + n.permanent = permanent_for_new; const size_t ret = m_nodes.size(); m_nodes.push_back(n); return ret; @@ -109,8 +111,8 @@ bool Sketch_nodes::view_bounds_2d_(double& min_u, double& min_v, double& max_u, return false; const ImGuiIO& io = ImGui::GetIO(); - return m_view.sketch_plane_view_aabb_2d(m_pln, static_cast(io.DisplaySize.x), - static_cast(io.DisplaySize.y), min_u, min_v, max_u, max_v); + return m_view.sketch_plane_view_aabb_2d(m_pln, static_cast(io.DisplaySize.x), static_cast(io.DisplaySize.y), + min_u, min_v, max_u, max_v); } std::optional Sketch_nodes::try_pick_existing_node(const ScreenCoords& screen_coords) @@ -153,7 +155,7 @@ std::optional Sketch_nodes::try_pick_existing_node(const ScreenCoords& s } std::optional Sketch_nodes::try_get_node_idx_snap( - gp_Pnt2d& pt, // `pt` could be snapped to a node, an axis of another node, or an outside snap point. + gp_Pnt2d& pt, // `pt` could be snapped to a node, an axis of another node, or an outside snap point. const std::vector& to_exclude) { const double snap_dist = snap_radius_world_(pt); @@ -199,7 +201,7 @@ std::optional Sketch_nodes::try_get_node_idx_snap( auto try_nd_pt = [&](const gp_Pnt2d& nd_pt) { - double dist = pt_original.SquareDistance(nd_pt); + double dist = pt_original.SquareDistance(nd_pt); // axis_dist needs to be compared against a linear snap distance in screen pixels. // This part becomes tricky because axis_dist is a world coordinate difference. // We'd ideally convert m_snap_dist_pixels * 0.5 to a world distance along the axis. @@ -263,7 +265,7 @@ size_t Sketch_nodes::add_new_node(const gp_Pnt2d& pt, bool is_edge_mid_point, bo n.midpoint = is_edge_mid_point; n.permanent = is_permanent; m_nodes.emplace_back(n); - //DBG_MSG("Add node: " << pt.Coord().X() << "," << pt.Coord().Y() << " midpoint: " << (int) is_edge_mid_point); + // DBG_MSG("Add node: " << pt.Coord().X() << "," << pt.Coord().Y() << " midpoint: " << (int) is_edge_mid_point); return ret; } @@ -281,15 +283,13 @@ void Sketch_nodes::update_node_snap_anno_(const gp_Pnt2d& pt, const double snap_ m_last_snap_pt = pt; - const bool show_traditional = - s_snap_guide_mode == Snap_guide_mode::Traditional || s_snap_guide_mode == Snap_guide_mode::Both; - const bool show_fullscreen = - s_snap_guide_mode == Snap_guide_mode::Fullscreen || s_snap_guide_mode == Snap_guide_mode::Both; + const bool show_traditional = s_snap_guide_mode == Snap_guide_mode::Traditional || s_snap_guide_mode == Snap_guide_mode::Both; + const bool show_fullscreen = s_snap_guide_mode == Snap_guide_mode::Fullscreen || s_snap_guide_mode == Snap_guide_mode::Both; TopoDS_Shape fullscreen_shape; if (show_fullscreen) { - double min_u {}, min_v {}, max_u {}, max_v {}; + double min_u{}, min_v{}, max_u{}, max_v{}; if (view_bounds_2d_(min_u, min_v, max_u, max_v)) { BRep_Builder builder; @@ -306,7 +306,7 @@ void Sketch_nodes::update_node_snap_anno_(const gp_Pnt2d& pt, const double snap_ } } - TopoDS_Shape anno_shape; + TopoDS_Shape anno_shape; const TopoDS_Shape traditional_shape = create_wire_box(m_pln, to_3d(m_pln, pt), snap_dist, snap_dist); if (show_traditional && !fullscreen_shape.IsNull()) { @@ -326,8 +326,7 @@ void Sketch_nodes::update_node_snap_anno_(const gp_Pnt2d& pt, const double snap_ { m_snap_anno = new AIS_Shape(anno_shape); m_snap_anno->SetWidth(3.0); - m_snap_anno->SetColor( - Quantity_Color(s_snap_guide_color.x, s_snap_guide_color.y, s_snap_guide_color.z, Quantity_TOC_RGB)); + m_snap_anno->SetColor(Quantity_Color(s_snap_guide_color.x, s_snap_guide_color.y, s_snap_guide_color.z, Quantity_TOC_RGB)); m_ctx.Display(m_snap_anno, true); } else @@ -339,35 +338,32 @@ void Sketch_nodes::update_node_snap_anno_(const gp_Pnt2d& pt, const double snap_ void Sketch_nodes::update_axis_snap_anno_(int axis_index, const gp_Pnt2d& axis_pt, double snap_dist) { - const bool show_traditional = - s_snap_guide_mode == Snap_guide_mode::Traditional || s_snap_guide_mode == Snap_guide_mode::Both; - const bool show_fullscreen = - s_snap_guide_mode == Snap_guide_mode::Fullscreen || s_snap_guide_mode == Snap_guide_mode::Both; + const bool show_traditional = s_snap_guide_mode == Snap_guide_mode::Traditional || s_snap_guide_mode == Snap_guide_mode::Both; + const bool show_fullscreen = s_snap_guide_mode == Snap_guide_mode::Fullscreen || s_snap_guide_mode == Snap_guide_mode::Both; TopoDS_Shape fullscreen_shape; if (show_fullscreen) { - double min_u {}, min_v {}, max_u {}, max_v {}; + double min_u{}, min_v{}, max_u{}, max_v{}; if (view_bounds_2d_(min_u, min_v, max_u, max_v)) { if (axis_index == 0) { - const gp_Pnt p0 = to_3d(m_pln, gp_Pnt2d(axis_pt.X(), min_v)); - const gp_Pnt p1 = to_3d(m_pln, gp_Pnt2d(axis_pt.X(), max_v)); + const gp_Pnt p0 = to_3d(m_pln, gp_Pnt2d(axis_pt.X(), min_v)); + const gp_Pnt p1 = to_3d(m_pln, gp_Pnt2d(axis_pt.X(), max_v)); fullscreen_shape = BRepBuilderAPI_MakeEdge(p0, p1).Edge(); } else { - const gp_Pnt p0 = to_3d(m_pln, gp_Pnt2d(min_u, axis_pt.Y())); - const gp_Pnt p1 = to_3d(m_pln, gp_Pnt2d(max_u, axis_pt.Y())); + const gp_Pnt p0 = to_3d(m_pln, gp_Pnt2d(min_u, axis_pt.Y())); + const gp_Pnt p1 = to_3d(m_pln, gp_Pnt2d(max_u, axis_pt.Y())); fullscreen_shape = BRepBuilderAPI_MakeEdge(p0, p1).Edge(); } } } - TopoDS_Shape anno_shape; - const TopoDS_Shape traditional_shape = - create_wire_box(m_pln, to_3d(m_pln, axis_pt), snap_dist * 0.5, snap_dist * 0.5); + TopoDS_Shape anno_shape; + const TopoDS_Shape traditional_shape = create_wire_box(m_pln, to_3d(m_pln, axis_pt), snap_dist * 0.5, snap_dist * 0.5); if (show_traditional && !fullscreen_shape.IsNull()) { BRep_Builder builder; @@ -447,22 +443,14 @@ const Sketch_nodes::Node& Sketch_nodes::operator[](const std::optional i return m_nodes[idx.value()]; } -bool Sketch_nodes::empty() const -{ - return m_nodes.empty(); -} +bool Sketch_nodes::empty() const { return m_nodes.empty(); } -size_t Sketch_nodes::size() const -{ - return m_nodes.size(); -} +size_t Sketch_nodes::size() const { return m_nodes.size(); } -void Sketch_nodes::json_resize(size_t count) -{ - m_nodes.assign(count, Node {}); -} +void Sketch_nodes::json_resize(size_t count) { m_nodes.assign(count, Node{}); } -void Sketch_nodes::json_set_node(size_t idx, const gp_Pnt2d& pt, bool deleted, bool midpoint, bool permanent, const std::string& name) +void Sketch_nodes::json_set_node(size_t idx, const gp_Pnt2d& pt, bool deleted, bool midpoint, bool permanent, + const std::string& name) { EZY_ASSERT(idx < m_nodes.size()); Node& n = m_nodes[idx]; @@ -474,50 +462,26 @@ void Sketch_nodes::json_set_node(size_t idx, const gp_Pnt2d& pt, bool deleted, b n.name = name; } -void Sketch_nodes::finalize() -{ - m_prev_num_nodes = m_nodes.size(); -} +void Sketch_nodes::finalize() { m_prev_num_nodes = m_nodes.size(); } -void Sketch_nodes::cancel() -{ - m_nodes.resize(m_prev_num_nodes); -} +void Sketch_nodes::cancel() { m_nodes.resize(m_prev_num_nodes); } -void Sketch_nodes::clear_outside_snap_pnts() -{ - m_outside_snap_pts.clear(); -} +void Sketch_nodes::clear_outside_snap_pnts() { m_outside_snap_pts.clear(); } -void Sketch_nodes::add_outside_snap_pnt(const gp_Pnt& pt3d) -{ - m_outside_snap_pts.insert(to_2d(m_pln, pt3d)); -} +void Sketch_nodes::add_outside_snap_pnt(const gp_Pnt& pt3d) { m_outside_snap_pts.insert(to_2d(m_pln, pt3d)); } // Snap distance related double Sketch_nodes::s_snap_dist_pixels = 35.0; Sketch_nodes::Snap_guide_mode Sketch_nodes::s_snap_guide_mode = Snap_guide_mode::Traditional; -glm::vec3 Sketch_nodes::s_snap_guide_color {0.0f, 1.0f, 0.0f}; +glm::vec3 Sketch_nodes::s_snap_guide_color{0.0f, 1.0f, 0.0f}; -void Sketch_nodes::set_snap_dist(double snap_dist_pixels) -{ - s_snap_dist_pixels = snap_dist_pixels; -} +void Sketch_nodes::set_snap_dist(double snap_dist_pixels) { s_snap_dist_pixels = snap_dist_pixels; } -double Sketch_nodes::get_snap_dist() -{ - return s_snap_dist_pixels; -} +double Sketch_nodes::get_snap_dist() { return s_snap_dist_pixels; } -void Sketch_nodes::set_snap_guide_mode(Snap_guide_mode mode) -{ - s_snap_guide_mode = mode; -} +void Sketch_nodes::set_snap_guide_mode(Snap_guide_mode mode) { s_snap_guide_mode = mode; } -Sketch_nodes::Snap_guide_mode Sketch_nodes::get_snap_guide_mode() -{ - return s_snap_guide_mode; -} +Sketch_nodes::Snap_guide_mode Sketch_nodes::get_snap_guide_mode() { return s_snap_guide_mode; } void Sketch_nodes::set_snap_guide_color(float r, float g, float b) { @@ -532,4 +496,3 @@ void Sketch_nodes::get_snap_guide_color(float& r, float& g, float& b) g = s_snap_guide_color.y; b = s_snap_guide_color.z; } - diff --git a/src/sketch_nodes.h b/src/sketch_nodes.h index ed9f940..efe4ac9 100644 --- a/src/sketch_nodes.h +++ b/src/sketch_nodes.h @@ -17,7 +17,7 @@ class Sketch_json; class Sketch_nodes { - public: +public: enum class Snap_guide_mode : int { Traditional = 0, @@ -27,8 +27,8 @@ class Sketch_nodes struct Node : public gp_Pnt2d { - bool midpoint = false; - bool deleted = false; + bool midpoint = false; + bool deleted = false; bool permanent = false; std::string name; }; @@ -40,14 +40,14 @@ class Sketch_nodes size_t add_new_node(const gp_Pnt2d& pt, bool is_edge_mid_point = false, bool is_permanent = false); std::optional snap(const ScreenCoords& screen_coords); // If no node exists at `pt`, appends one; `permanent_for_new` sets Node::permanent on that new node only. - size_t get_node_exact(const gp_Pnt2d& pt, bool permanent_for_new = false); - std::optional get_node(const ScreenCoords& screen_coords); + size_t get_node_exact(const gp_Pnt2d& pt, bool permanent_for_new = false); + std::optional get_node(const ScreenCoords& screen_coords); /// Projects the click onto the sketch plane and returns a node index only if within snap range of an /// existing non-deleted node. Never creates nodes (unlike `get_node`). - std::optional try_pick_existing_node(const ScreenCoords& screen_coords); - std::optional try_get_node_idx_snap( - gp_Pnt2d& pt, // `pt` could be snapped to a node, an axis of another node, or an outside snap point. - const std::vector& to_exclude = {}); + std::optional try_pick_existing_node(const ScreenCoords& screen_coords); + std::optional + try_get_node_idx_snap(gp_Pnt2d& pt, // `pt` could be snapped to a node, an axis of another node, or an outside snap point. + const std::vector& to_exclude = {}); void get_snap_pts_3d(std::vector& out); void hide_snap_annos(); @@ -61,16 +61,16 @@ class Sketch_nodes void finalize(); void cancel(); - void clear_outside_snap_pnts(); - void add_outside_snap_pnt(const gp_Pnt& pt3d); + void clear_outside_snap_pnts(); + void add_outside_snap_pnt(const gp_Pnt& pt3d); // Snap distance related - static void set_snap_dist(double snap_dist_pixels); - static double get_snap_dist(); - static void set_snap_guide_mode(Snap_guide_mode mode); + static void set_snap_dist(double snap_dist_pixels); + static double get_snap_dist(); + static void set_snap_guide_mode(Snap_guide_mode mode); static Snap_guide_mode get_snap_guide_mode(); - static void set_snap_guide_color(float r, float g, float b); - static void get_snap_guide_color(float& r, float& g, float& b); + static void set_snap_guide_color(float r, float g, float b); + static void get_snap_guide_color(float& r, float& g, float& b); // Methods for range-based for loop support // clang-format off @@ -82,7 +82,7 @@ class Sketch_nodes auto cend() const { return m_nodes.cend(); } // clang-format on - private: +private: friend class Sketch_json; /// Resize storage so indices `0..count-1` exist (JSON load). @@ -95,17 +95,18 @@ class Sketch_nodes /// World-space snap radius at `pt` (same convention as `try_get_node_idx_snap` / `try_pick_existing_node`). double snap_radius_world_(const gp_Pnt2d& pt) const; bool view_bounds_2d_(double& min_u, double& min_v, double& max_u, double& max_v) const; - bool try_snap_outside_(gp_Pnt2d& pt, const double snap_dist); // Use points in `m_outside_snap_pts` `pt` will be modified if snapped. + bool try_snap_outside_(gp_Pnt2d& pt, + const double snap_dist); // Use points in `m_outside_snap_pts` `pt` will be modified if snapped. std::vector m_nodes; - static double s_snap_dist_pixels; // Global to all sketches + static double s_snap_dist_pixels; // Global to all sketches static Snap_guide_mode s_snap_guide_mode; static glm::vec3 s_snap_guide_color; - std::set m_outside_snap_pts; // Projected snap points from other sketches. + std::set m_outside_snap_pts; // Projected snap points from other sketches. AIS_Shape_ptr m_snap_anno_axis[2]; - std::optional m_last_snap_pt; // Used for snap annotation + std::optional m_last_snap_pt; // Used for snap annotation AIS_Shape_ptr m_snap_anno; - size_t m_prev_num_nodes {0}; // Used when a operation is canceled. + size_t m_prev_num_nodes{0}; // Used when a operation is canceled. // Owner related Occt_view& m_view; diff --git a/src/sketch_underlay.cpp b/src/sketch_underlay.cpp index 1523b0b..af978ab 100644 --- a/src/sketch_underlay.cpp +++ b/src/sketch_underlay.cpp @@ -26,13 +26,12 @@ namespace { constexpr int k_max_image_dim = 8192; -constexpr std::size_t k_max_rgba_bytes = 64u * 1024u * 1024u; // 64 MiB safety cap +constexpr std::size_t k_max_rgba_bytes = 64u * 1024u * 1024u; // 64 MiB safety cap std::string base64_encode(const uint8_t* data, std::size_t len) { - static const char tbl[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - std::string out; + static const char tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + std::string out; out.reserve(((len + 2) / 3) * 4); for (std::size_t i = 0; i < len; i += 3) { @@ -114,9 +113,9 @@ inline void apply_key_and_tint(uint8_t& r, uint8_t& g, uint8_t& b, uint8_t& a, b if (line_tint_enabled && a2 > 0) { - r = tr; - g = tg; - b = tb; + r = tr; + g = tg; + b = tb; a2 = (a2 * static_cast(ta)) / 255u; } a = static_cast(a2); @@ -152,15 +151,8 @@ inline void sample_rgba_bilinear(const uint8_t* rgba, int w, int h, double xf, d } /// Straight copy of the image to a bottom-up pixmap (optional row flip for OCCT/OpenGL), with key + tint. -Handle(Image_PixMap) make_pixmap_bottom_up_linear(const uint8_t* rgba, - int w, - int h, - bool key_white_transparent, - bool line_tint_enabled, - uint8_t tr, - uint8_t tg, - uint8_t tb, - uint8_t ta) +Handle(Image_PixMap) make_pixmap_bottom_up_linear(const uint8_t* rgba, int w, int h, bool key_white_transparent, + bool line_tint_enabled, uint8_t tr, uint8_t tg, uint8_t tb, uint8_t ta) { if (w <= 0 || h <= 0) return {}; @@ -192,17 +184,9 @@ Handle(Image_PixMap) make_pixmap_bottom_up_linear(const uint8_t* rgba, /// Builds a bottom-up pixmap for AIS_TexturedShape when the underlay axes are sheared (non-orthogonal): uses an /// axis-aligned face in the sketch plane and inverse-rotated sampling so the bitmap matches OCCT UV on the AABB. -Handle(Image_PixMap) make_pixmap_bottom_up_warped(const uint8_t* rgba, - int w, - int h, - const gp_Vec2d& axis_u, - const gp_Vec2d& axis_v, - bool key_white_transparent, - bool line_tint_enabled, - uint8_t tr, - uint8_t tg, - uint8_t tb, - uint8_t ta) +Handle(Image_PixMap) make_pixmap_bottom_up_warped(const uint8_t* rgba, int w, int h, const gp_Vec2d& axis_u, + const gp_Vec2d& axis_v, bool key_white_transparent, bool line_tint_enabled, + uint8_t tr, uint8_t tg, uint8_t tb, uint8_t ta) { const double hw = 0.5 * axis_u.Magnitude(); const double hh = 0.5 * axis_v.Magnitude(); @@ -236,8 +220,8 @@ Handle(Image_PixMap) make_pixmap_bottom_up_warped(const uint8_t* rgba, uint8_t* dstRow = dst + static_cast(rj) * rowBytes; for (int ox = 0; ox < out_w; ++ox) { - const double s01 = (static_cast(ox) + 0.5) / static_cast(out_w); - const double du = (2.0 * s01 - 1.0) * hx; + const double s01 = (static_cast(ox) + 0.5) / static_cast(out_w); + const double du = (2.0 * s01 - 1.0) * hx; // Inverse rotate from plane (du,dv) to image (u,v) offsets from quad center. const double img_u = du * c + dv * s; const double img_v = -du * s + dv * c; @@ -266,7 +250,7 @@ Handle(Image_PixMap) make_pixmap_bottom_up_warped(const uint8_t* rgba, return pix; } -} // namespace +} // namespace void Sketch_underlay::remove_ais_(AIS_InteractiveContext& ctx) { @@ -326,9 +310,7 @@ void Sketch_underlay::set_center_extents_rotation(const dvec2& center, const dve const double s = std::sin(rad); const gp_Vec2d axis_u(2.0 * half_w * c, 2.0 * half_w * s); const gp_Vec2d axis_v(-2.0 * half_h * s, 2.0 * half_h * c); - const gp_Pnt2d base( - center.x - 0.5 * (axis_u.X() + axis_v.X()), - center.y - 0.5 * (axis_u.Y() + axis_v.Y())); + const gp_Pnt2d base(center.x - 0.5 * (axis_u.X() + axis_v.X()), center.y - 0.5 * (axis_u.Y() + axis_v.Y())); set_affine(base, axis_u, axis_v); } @@ -344,20 +326,11 @@ void Sketch_underlay::set_opacity(float opaque01) m_ais->SetTransparency(1.0 - static_cast(m_opacity)); } -void Sketch_underlay::set_visible(bool v) -{ - m_visible = v; -} +void Sketch_underlay::set_visible(bool v) { m_visible = v; } -void Sketch_underlay::set_key_white_transparent(bool on) -{ - m_key_white_transparent = on; -} +void Sketch_underlay::set_key_white_transparent(bool on) { m_key_white_transparent = on; } -void Sketch_underlay::set_line_tint_enabled(bool on) -{ - m_line_tint_enabled = on; -} +void Sketch_underlay::set_line_tint_enabled(bool on) { m_line_tint_enabled = on; } void Sketch_underlay::set_line_tint_rgb(uint8_t r, uint8_t g, uint8_t b) { @@ -435,8 +408,8 @@ void Sketch_underlay::build_ais_(const gp_Pln& pln, AIS_InteractiveContext& ctx) return; face = faceMk.Face(); - pix = make_pixmap_bottom_up_linear(m_rgba.data(), m_w, m_h, m_key_white_transparent, m_line_tint_enabled, - m_tint_r, m_tint_g, m_tint_b, m_tint_a); + pix = make_pixmap_bottom_up_linear(m_rgba.data(), m_w, m_h, m_key_white_transparent, m_line_tint_enabled, m_tint_r, + m_tint_g, m_tint_b, m_tint_a); } else { @@ -504,10 +477,7 @@ void Sketch_underlay::rebuild_and_display(const gp_Pln& pln, AIS_InteractiveCont build_ais_(pln, ctx); } -void Sketch_underlay::erase(AIS_InteractiveContext& ctx) -{ - remove_ais_(ctx); -} +void Sketch_underlay::erase(AIS_InteractiveContext& ctx) { remove_ais_(ctx); } void Sketch_underlay::sync_visibility(const gp_Pln& pln, AIS_InteractiveContext& ctx) { @@ -534,18 +504,9 @@ nlohmann::json Sketch_underlay::to_json() const j["rgba_b64"] = base64_encode(m_rgba.data(), m_rgba.size()); j["w"] = m_w; j["h"] = m_h; - j["base"] = json::object({ - {"x", m_base.X()}, - {"y", m_base.Y()} - }); - j["axis_u"] = json::object({ - {"x", m_axis_u.X()}, - {"y", m_axis_u.Y()} - }); - j["axis_v"] = json::object({ - {"x", m_axis_v.X()}, - {"y", m_axis_v.Y()} - }); + j["base"] = json::object({{"x", m_base.X()}, {"y", m_base.Y()}}); + j["axis_u"] = json::object({{"x", m_axis_u.X()}, {"y", m_axis_u.Y()}}); + j["axis_v"] = json::object({{"x", m_axis_v.X()}, {"y", m_axis_v.Y()}}); j["opacity"] = m_opacity; j["visible"] = m_visible; j["key_white_transparent"] = m_key_white_transparent; @@ -587,7 +548,7 @@ bool Sketch_underlay::from_json(const nlohmann::json& j) m_visible = j.value("visible", true); m_key_white_transparent = j.value("key_white_transparent", true); m_line_tint_enabled = j.value("line_tint_enabled", true); - m_tint_a = 255; + m_tint_a = 255; if (j.contains("line_tint_rgba") && j["line_tint_rgba"].is_array() && j["line_tint_rgba"].size() >= 4) { m_tint_r = static_cast(j["line_tint_rgba"][0].get()); diff --git a/src/sketch_underlay.h b/src/sketch_underlay.h index 889fb10..81fa226 100644 --- a/src/sketch_underlay.h +++ b/src/sketch_underlay.h @@ -18,7 +18,7 @@ class gp_Pln; /// Raster image drawn in the sketch plane (below sketch edges) for tracing / digitizing. class Sketch_underlay { - public: +public: Sketch_underlay() = default; Sketch_underlay(const Sketch_underlay&) = delete; @@ -26,10 +26,7 @@ class Sketch_underlay Sketch_underlay(Sketch_underlay&&) = delete; Sketch_underlay& operator=(Sketch_underlay&&) = delete; - [[nodiscard]] bool has_image() const - { - return !m_rgba.empty() && m_w > 0 && m_h > 0; - } + [[nodiscard]] bool has_image() const { return !m_rgba.empty() && m_w > 0 && m_h > 0; } /// Replace image (RGBA8). Sets a default axis-aligned rectangle in plane coords (0.1 unit per pixel). [[nodiscard]] bool set_image_rgba(std::vector&& rgba, int w, int h); @@ -69,32 +66,32 @@ class Sketch_underlay /// Force viewer update after live property changes (e.g. threshold) without a full rebuild. void redisplay(AIS_InteractiveContext& ctx); - nlohmann::json to_json() const; + nlohmann::json to_json() const; /// Returns false if JSON is invalid or image decode fails. [[nodiscard]] bool from_json(const nlohmann::json& j); - private: +private: void remove_ais_(AIS_InteractiveContext& ctx); void build_ais_(const gp_Pln& pln, AIS_InteractiveContext& ctx); std::vector m_rgba; - int m_w {0}; - int m_h {0}; + int m_w{0}; + int m_h{0}; - gp_Pnt2d m_base {0., 0.}; - gp_Vec2d m_axis_u {100., 0.}; - gp_Vec2d m_axis_v {0., 100.}; + gp_Pnt2d m_base{0., 0.}; + gp_Vec2d m_axis_u{100., 0.}; + gp_Vec2d m_axis_v{0., 100.}; - float m_opacity {0.88f}; - bool m_visible {true}; + float m_opacity{0.88f}; + bool m_visible{true}; /// Luminance key applied only when building the GPU texture (stored pixels stay raw). - bool m_key_white_transparent {true}; + bool m_key_white_transparent{true}; /// Recolor pixels that remain visible (alpha > 0 after key) for contrast on dark views. - bool m_line_tint_enabled {true}; - uint8_t m_tint_r {255}; - uint8_t m_tint_g {220}; - uint8_t m_tint_b {0}; - uint8_t m_tint_a {255}; + bool m_line_tint_enabled{true}; + uint8_t m_tint_r{255}; + uint8_t m_tint_g{220}; + uint8_t m_tint_b{0}; + uint8_t m_tint_a{255}; opencascade::handle m_ais; }; diff --git a/src/types.h b/src/types.h index b4f3079..8c3699c 100644 --- a/src/types.h +++ b/src/types.h @@ -34,19 +34,18 @@ using PrsDim_LengthDimension_ptr = opencascade::handle; using Graphic3d_Camera_ptr = opencascade::handle; using StdSelect_BRepOwner_ptr = opencascade::handle; -#define DECL_PTR(TypeName) \ - using uptr = std::unique_ptr; \ - using sptr = std::shared_ptr; \ +#define DECL_PTR(TypeName) \ + using uptr = std::unique_ptr; \ + using sptr = std::shared_ptr; \ using wptr = std::weak_ptr; // Primary template for non-vector types -template -class SafeType +template class SafeType { - private: +private: T m_value; - public: +public: // clang-format off explicit SafeType(T initial_value) : m_value(initial_value) {} T& unsafe_get() { return m_value; } diff --git a/src/types.inl b/src/types.inl index 23b9177..e35f636 100644 --- a/src/types.inl +++ b/src/types.inl @@ -1,13 +1,14 @@ // Base template for vectors (not a specialization of Safe_container) -template -class Vector_container +template class Vector_container { - private: +private: Vec m_value; - public: +public: explicit Vector_container(Vec initial_value) - : m_value(initial_value) {} + : m_value(initial_value) + { + } // clang-format off Vec& unsafe_get() { return m_value; } @@ -26,55 +27,73 @@ class Vector_container // Explicit specializations for GLM vector types template <> class SafeType : public Vector_container { - public: +public: explicit SafeType(glm::ivec2 initial_value) - : Vector_container(initial_value) {} + : Vector_container(initial_value) + { + } }; template <> class SafeType : public Vector_container { - public: +public: explicit SafeType(glm::fvec2 initial_value) - : Vector_container(initial_value) {} + : Vector_container(initial_value) + { + } }; template <> class SafeType : public Vector_container { - public: +public: explicit SafeType(glm::dvec2 initial_value) - : Vector_container(initial_value) {} + : Vector_container(initial_value) + { + } }; template <> class SafeType : public Vector_container { - public: +public: explicit SafeType(glm::ivec3 initial_value) - : Vector_container(initial_value) {} + : Vector_container(initial_value) + { + } }; template <> class SafeType : public Vector_container { - public: +public: explicit SafeType(glm::fvec3 initial_value) - : Vector_container(initial_value) {} + : Vector_container(initial_value) + { + } }; template <> class SafeType : public Vector_container { - public: +public: explicit SafeType(glm::dvec3 initial_value) - : Vector_container(initial_value) {} + : Vector_container(initial_value) + { + } }; template <> class SafeType : public Vector_container { - public: +public: explicit SafeType(glm::ivec4 initial_value) - : Vector_container(initial_value) {} + : Vector_container(initial_value) + { + } }; template <> class SafeType : public Vector_container { - public: +public: explicit SafeType(glm::fvec4 initial_value) - : Vector_container(initial_value) {} + : Vector_container(initial_value) + { + } }; template <> class SafeType : public Vector_container { - public: +public: explicit SafeType(glm::dvec4 initial_value) - : Vector_container(initial_value) {} + : Vector_container(initial_value) + { + } }; diff --git a/src/utl.cpp b/src/utl.cpp index 7d2c7ae..7711b29 100644 --- a/src/utl.cpp +++ b/src/utl.cpp @@ -13,7 +13,7 @@ uint32_t load_texture(const std::string& path) { int width, height, channels; EZY_ASSERT_MSG(std::filesystem::exists(path), "Error cannot open: " + std::string(path)); - unsigned char* data = stbi_load(path.c_str(), &width, &height, &channels, 4); // Force RGBA + unsigned char* data = stbi_load(path.c_str(), &width, &height, &channels, 4); // Force RGBA EZY_ASSERT_MSG(data, "l"); GLuint texture_id; @@ -22,7 +22,7 @@ uint32_t load_texture(const std::string& path) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); // Using GL_CLAMP + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); // Using GL_CLAMP glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); @@ -36,30 +36,25 @@ std::optional, int, int>> decode_image_bytes(con if (file_bytes.empty()) return std::nullopt; int w = 0, h = 0, ch = 0; - unsigned char* data = stbi_load_from_memory( - reinterpret_cast(file_bytes.data()), - static_cast(file_bytes.size()), - &w, - &h, - &ch, - 4); + unsigned char* data = stbi_load_from_memory(reinterpret_cast(file_bytes.data()), + static_cast(file_bytes.size()), &w, &h, &ch, 4); if (!data || w <= 0 || h <= 0) { if (data) stbi_image_free(data); return std::nullopt; } - const std::size_t n = static_cast(w) * static_cast(h) * 4u; + const std::size_t n = static_cast(w) * static_cast(h) * 4u; std::vector rgba(n); std::memcpy(rgba.data(), data, n); stbi_image_free(data); - return std::tuple {std::move(rgba), w, h}; + return std::tuple{std::move(rgba), w, h}; } std::size_t Pair_hash::operator()(const std::pair& p) const { std::size_t seed = 0; - seed ^= std::hash {}(p.first) + 0x9e3779b9 + (seed << 6) + (seed >> 2); - seed ^= std::hash {}(p.second) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= std::hash{}(p.first) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= std::hash{}(p.second) + 0x9e3779b9 + (seed << 6) + (seed >> 2); return seed; } \ No newline at end of file diff --git a/src/utl.h b/src/utl.h index b334c5e..5824faa 100644 --- a/src/utl.h +++ b/src/utl.h @@ -27,48 +27,32 @@ enum class Result_status : uint8_t class Status { - public: +public: Status(const Result_status status, const std::string& msg = "") - : m_v(status), m_msg(msg) {} - - static Status ok(const std::string& msg = "") + : m_v(status) + , m_msg(msg) { - return Status(Result_status::Success, msg); } - static Status user_error(const std::string& msg) - { - return Status(Result_status::User_error, msg); - } + static Status ok(const std::string& msg = "") { return Status(Result_status::Success, msg); } - Result_status status() const noexcept - { - return m_v; - } + static Status user_error(const std::string& msg) { return Status(Result_status::User_error, msg); } - bool is_ok() const noexcept - { - return m_v == Result_status::Success; - } + Result_status status() const noexcept { return m_v; } - const std::string& message() const noexcept - { - return m_msg; - } + bool is_ok() const noexcept { return m_v == Result_status::Success; } - bool operator==(const Result_status v) const noexcept - { - return status() == v; - } + const std::string& message() const noexcept { return m_msg; } + + bool operator==(const Result_status v) const noexcept { return status() == v; } Result_status m_v; std::string m_msg; }; -template -class Result : public Status +template class Result : public Status { - public: +public: Result(); Result(const T& value); Result(T&& value); @@ -82,17 +66,17 @@ class Result : public Status T& operator*(); const T& operator*() const; - private: +private: std::optional m_value; }; /// Early return if not ok. Binds the expression once (safe for calls like `ensure_operation_shps_()`). -#define CHK_RET(expr) \ - do \ - { \ - auto&& _ezy_chk_ret = (expr); \ - if (!_ezy_chk_ret.is_ok()) \ - return _ezy_chk_ret; \ +#define CHK_RET(expr) \ + do \ + { \ + auto&& _ezy_chk_ret = (expr); \ + if (!_ezy_chk_ret.is_ok()) \ + return _ezy_chk_ret; \ } while (0) /** @@ -105,12 +89,10 @@ class Result : public Status * * Fails at compile time for unsupported types. */ -template -void clear_all(T& arg, Args&... args); +template void clear_all(T& arg, Args&... args); // Templated function to pop and return the back element of a container -template -typename Container::value_type&& pop_back(Container& container) +template typename Container::value_type&& pop_back(Container& container) { EZY_ASSERT(container.size()); auto value = std::move(container.back()); @@ -122,8 +104,7 @@ typename Container::value_type&& pop_back(Container& container) * Applies a lambda function to each non-container element in the provided arguments, flattening * containers by iterating their contents. */ -template -void for_each_flat(Lambda&& lambda, Args&&... args) +template void for_each_flat(Lambda&& lambda, Args&&... args) { (handle_arg(std::forward(lambda), std::forward(args)), ...); } @@ -131,16 +112,14 @@ void for_each_flat(Lambda&& lambda, Args&&... args) /** * @brief Appends elements to a target container from a source. */ -template -void append(Container& target, const T& source); +template void append(Container& target, const T& source); struct Pair_hash { std::size_t operator()(const std::pair& p) const; }; -template -bool contains(const Container& container, const Value& value) +template bool contains(const Container& container, const Value& value) { auto it = std::find(container.begin(), container.end(), value); return it != container.end(); @@ -151,8 +130,7 @@ uint32_t load_texture(const std::string& path); /// Decode PNG/JPEG/BMP/etc. from memory into RGBA8 (via stb_image). Empty if unsupported or corrupt. std::optional, int, int>> decode_image_bytes(const std::string& file_bytes); -void disable_shape_highlighting(const AIS_Shape_ptr& ais_shape, - const AIS_InteractiveContext_ptr& context, - Standard_Boolean disable_selection = Standard_False); +void disable_shape_highlighting(const AIS_Shape_ptr& ais_shape, const AIS_InteractiveContext_ptr& context, + Standard_Boolean disable_selection = Standard_False); #include "utl.inl" diff --git a/src/utl.inl b/src/utl.inl index 2825300..44b7769 100644 --- a/src/utl.inl +++ b/src/utl.inl @@ -1,9 +1,11 @@ // Helper function for `for_each_flat` -template -void handle_arg(Lambda&& lambda, T&& arg) +template void handle_arg(Lambda&& lambda, T&& arg) { // Check if T is a container (has begin() and end()) - if constexpr (requires { arg.begin(); arg.end(); }) + if constexpr (requires { + arg.begin(); + arg.end(); + }) for (auto&& elem : arg) lambda(std::forward(elem)); @@ -12,49 +14,40 @@ void handle_arg(Lambda&& lambda, T&& arg) } // Trait to detect if a type has a clear() method -template -struct has_clear : std::false_type +template struct has_clear : std::false_type { }; -template -struct has_clear().clear())>> : std::true_type +template struct has_clear().clear())>> : std::true_type { }; -template -struct has_reset : std::false_type +template struct has_reset : std::false_type { }; -template -struct has_reset().reset())>> : std::true_type +template struct has_reset().reset())>> : std::true_type { }; -template -struct has_nullify : std::false_type +template struct has_nullify : std::false_type { }; -template -struct has_nullify().Nullify())>> : std::true_type +template struct has_nullify().Nullify())>> : std::true_type { }; // Helper trait to check if a type is std::optional -template -struct is_optional : std::false_type +template struct is_optional : std::false_type { }; -template -struct is_optional> : std::true_type +template struct is_optional> : std::true_type { }; -template -inline constexpr bool is_optional_v = is_optional::value; +template inline constexpr bool is_optional_v = is_optional::value; // Base case for recursion inline void clear_all() {} @@ -71,8 +64,7 @@ inline void clear_all() {} * * Fails at compile time for unsupported types. */ -template -void clear_all(T& arg, Args&... args) +template void clear_all(T& arg, Args&... args) { if constexpr (std::is_pointer_v) // Raw pointer: set to nullptr @@ -107,21 +99,23 @@ void clear_all(T& arg, Args&... args) * * Fails at compile time for unsupported source types. */ -template -void append(Container& target, const T& source) +template void append(Container& target, const T& source) { // Extract the value_type of the target container using target_value_type = typename Container::value_type; // Case 1: T is the same as the container's value_type (single element) if constexpr (std::is_same_v>, target_value_type>) - target.push_back(source); // Append the single element + target.push_back(source); // Append the single element // Case 2: T is a container with the same value_type - else if constexpr (requires { source.begin(); source.end(); } && - std::is_same_v) - target.insert(target.end(), source.begin(), source.end()); // Append all elements from source + else if constexpr (requires { + source.begin(); + source.end(); + } && std::is_same_v) + target.insert(target.end(), source.begin(), source.end()); // Append all elements from source else - static_assert(false, "Source must be either a single element of Container::value_type or a container with the same value_type"); + static_assert(false, + "Source must be either a single element of Container::value_type or a container with the same value_type"); } // --------------------------------------------------------------------------- @@ -130,67 +124,62 @@ void append(Container& target, const T& source) template Result::Result() - : Status(Result_status::Null), m_value(std::nullopt) {} + : Status(Result_status::Null) + , m_value(std::nullopt) +{ +} template Result::Result(const T& value) - : Status(Result_status::Success), m_value(value) {} + : Status(Result_status::Success) + , m_value(value) +{ +} template Result::Result(T&& value) - : Status(Result_status::Success), m_value(std::move(value)) {} + : Status(Result_status::Success) + , m_value(std::move(value)) +{ +} template Result::Result(const Result_status status, const std::string& error_msg) - : Status(status, error_msg), m_value(std::nullopt) + : Status(status, error_msg) + , m_value(std::nullopt) { - EZY_ASSERT_MSG(status != Result_status::Success, - "Success status requires a value"); + EZY_ASSERT_MSG(status != Result_status::Success, "Success status requires a value"); - EZY_ASSERT_MSG(status != Result_status::Null || error_msg.empty(), - "Null status should not have an error message"); + EZY_ASSERT_MSG(status != Result_status::Null || error_msg.empty(), "Null status should not have an error message"); } -template -bool Result::has_value() const noexcept +template bool Result::has_value() const noexcept { return m_v == Result_status::Success && m_value.has_value(); } -template -T& Result::value() +template T& Result::value() { if (!has_value()) { - EZY_ASSERT_MSG(m_v != Result_status::Null, - "Result is in Null state"); + EZY_ASSERT_MSG(m_v != Result_status::Null, "Result is in Null state"); EZY_ASSERT_MSG(false, m_msg.empty() ? "No value available" : m_msg); } return *m_value; } -template -const T& Result::value() const +template const T& Result::value() const { if (!has_value()) { - EZY_ASSERT_MSG(m_v != Result_status::Null, - "Result is in Null state"); + EZY_ASSERT_MSG(m_v != Result_status::Null, "Result is in Null state"); EZY_ASSERT_MSG(false, m_msg.empty() ? "No value available" : m_msg); } return *m_value; } -template -T& Result::operator*() -{ - return value(); -} +template T& Result::operator*() { return value(); } -template -const T& Result::operator*() const -{ - return value(); -} +template const T& Result::operator*() const { return value(); } diff --git a/src/utl_json.cpp b/src/utl_json.cpp index 31d181e..2c83fd0 100644 --- a/src/utl_json.cpp +++ b/src/utl_json.cpp @@ -3,45 +3,28 @@ #include #include -using json = nlohmann::json; // Alias for convenience +using json = nlohmann::json; // Alias for convenience // Helper function to serialize a gp_Pnt (3D point) -json to_json(const gp_Pnt& point) -{ - return { - {"x", point.X()}, - {"y", point.Y()}, - {"z", point.Z()} - }; -} +json to_json(const gp_Pnt& point) { return {{"x", point.X()}, {"y", point.Y()}, {"z", point.Z()}}; } // Helper function to serialize a gp_Dir (direction) -json to_json(const gp_Dir& direction) -{ - return { - {"x", direction.X()}, - {"y", direction.Y()}, - {"z", direction.Z()} - }; -} +json to_json(const gp_Dir& direction) { return {{"x", direction.X()}, {"y", direction.Y()}, {"z", direction.Z()}}; } // Serialize a gp_Pln to JSON with origin and normal json to_json(const gp_Pln& pln) { return { - {"origin", to_json(pln.Location())}, // Origin of the plane - {"normal", to_json(pln.Axis().Direction())}, // Plane normal direction - { "xAxis", to_json(pln.XAxis().Direction())} // Plane X axis direction + {"origin", to_json(pln.Location())}, // Origin of the plane + {"normal", to_json(pln.Axis().Direction())}, // Plane normal direction + {"xAxis", to_json(pln.XAxis().Direction())} // Plane X axis direction }; } json to_json(const gp_Pnt2d& point) { // Create JSON object for the point - json point_json = { - {"x", point.X()}, - {"y", point.Y()} - }; + json point_json = {{"x", point.X()}, {"y", point.Y()}}; return point_json; } @@ -49,19 +32,13 @@ json to_json(const gp_Pnt2d& point) // Deserialize a gp_Pnt from JSON gp_Pnt from_json_pnt(const json& j) { - return gp_Pnt( - j.at("x").get(), - j.at("y").get(), - j.at("z").get()); + return gp_Pnt(j.at("x").get(), j.at("y").get(), j.at("z").get()); } // Deserialize a gp_Dir from JSON gp_Dir from_json_dir(const json& j) { - return gp_Dir( - j.at("x").get(), - j.at("y").get(), - j.at("z").get()); + return gp_Dir(j.at("x").get(), j.at("y").get(), j.at("z").get()); } // Deserialize a gp_Pln from JSON @@ -74,7 +51,4 @@ gp_Pln from_json_pln(const json& j) } // Deserializes a JSON object into a gp_Pnt2d -gp_Pnt2d from_json_pnt2d(const json& j) -{ - return gp_Pnt2d(j.at("x").get(), j.at("y").get()); -} +gp_Pnt2d from_json_pnt2d(const json& j) { return gp_Pnt2d(j.at("x").get(), j.at("y").get()); } diff --git a/src/utl_occt.h b/src/utl_occt.h index c350d90..d7a068c 100644 --- a/src/utl_occt.h +++ b/src/utl_occt.h @@ -6,18 +6,18 @@ #include // Parallel to Open CASCADE TopAbs_ShapeEnum (TopAbs_ShapeEnum.hxx). Order must stay in sync with OCCT. -#define EZY_TOPABS_SHAPE_ENUM_LIST(X) \ - X(Compound) \ - X(CompSolid) \ - X(Solid) \ - X(Shell) \ - X(Face) \ - X(Wire) \ - X(Edge) \ - X(Vertex) \ +#define EZY_TOPABS_SHAPE_ENUM_LIST(X) \ + X(Compound) \ + X(CompSolid) \ + X(Solid) \ + X(Shell) \ + X(Face) \ + X(Wire) \ + X(Edge) \ + X(Vertex) \ X(Shape) -constexpr std::array(TopAbs_SHAPE) + 1u> c_names_TopAbs_ShapeEnum { +constexpr std::array(TopAbs_SHAPE) + 1u> c_names_TopAbs_ShapeEnum{ #define EZY_TOPABS_SHAPE_STR(name) #name, EZY_TOPABS_SHAPE_ENUM_LIST(EZY_TOPABS_SHAPE_STR) #undef EZY_TOPABS_SHAPE_STR From 0bf85f2fdd58bc390b4495544433c96ac0088742 Mon Sep 17 00:00:00 2001 From: trailcode Date: Fri, 15 May 2026 17:41:33 -0600 Subject: [PATCH 2/2] Add issue draft for format-src.ps1 repo-root fix under agents/issues. Keeps repo-local draft next to other GitHub issue templates; links to #104. Co-authored-by: Cursor --- .../005-format-src-repo-root-split-path.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 agents/issues/005-format-src-repo-root-split-path.md diff --git a/agents/issues/005-format-src-repo-root-split-path.md b/agents/issues/005-format-src-repo-root-split-path.md new file mode 100644 index 0000000..3310a83 --- /dev/null +++ b/agents/issues/005-format-src-repo-root-split-path.md @@ -0,0 +1,53 @@ +# [Draft] Fix `scripts/format-src.ps1` repo root detection + +**Suggested GitHub labels:** `bug`, `windows`, `tooling` + +**Status:** Resolved in-repo (see **Fix** below). Use this text for a changelog note, a retrospective issue, or copy into GitHub then close. + +**GitHub:** https://github.com/trailcode/EzyCad/issues/104 + +--- + +## Title + +`format-src.ps1` used wrong source tree root (`Split-Path` one level too many) + +## Body + +### Summary + +Running `scripts/format-src.ps1` after bypassing execution policy succeeded in starting the script, but **`Get-ChildItem` failed**: it looked under **`C:\src\src`** instead of **`\src`** (for a clone such as `C:\src\EzyCad`). + +### Root cause + +`$PSScriptRoot` is **`…/EzyCad/scripts`**. The script computed the repo root with **two** `Split-Path -Parent` calls: + +- First parent → `…/EzyCad` (correct repo root). +- Second parent → `…/src` (wrong). + +`Join-Path $root "src"` then pointed at **`C:\src\src`**. + +### Fix + +Use **one** parent of `$PSScriptRoot` as the repo root, then **`Join-Path`** to `src`. Updated in **`scripts/format-src.ps1`** with an inline comment documenting layout: `/scripts/format-src.ps1`. + +### How to verify + +From `scripts/`: + +```powershell +powershell -ExecutionPolicy Bypass -File .\format-src.ps1 +``` + +Confirm `clang-format` runs on files under **`(repo)/src`** (requires LLVM `clang-format` on PATH or the path at the top of the script). + +### Related (not a repo bug) + +**PowerShell:** If `.\format-src.ps1` is blocked, either use `Bypass`/`Process` scope for one run or set **`Set-ExecutionPolicy RemoteSigned -Scope CurrentUser`** (see Microsoft `about_Execution_Policies`). + +--- + +## Metadata (do not paste) + +- Draft lives under **`agents/issues/`** (repo-local companion to GitHub). +- Repo: `trailcode/EzyCad`.