diff --git a/Designer/Data/CommandsConfig.xml b/Designer/Data/CommandsConfig.xml
index 188da069..f57ebca1 100644
--- a/Designer/Data/CommandsConfig.xml
+++ b/Designer/Data/CommandsConfig.xml
@@ -229,7 +229,6 @@
diff --git a/Designer/Data/Scripts/generate_solid_designer_commands.py b/Designer/Data/Scripts/generate_solid_designer_commands.py
new file mode 100644
index 00000000..a5955d96
--- /dev/null
+++ b/Designer/Data/Scripts/generate_solid_designer_commands.py
@@ -0,0 +1,236 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#Author: Yoichiro Nambu
+#Date: 2025.12.12
+"""
+Generate SolidDesignerCommands.h from CommandsConfig.xml
+
+Usage:
+ python generate_solid_designer_commands.py \
+ --xml path/to/CommandsConfig.xml \
+ --out path/to/SolidDesignerCommands.h
+"""
+
+import argparse
+import sys
+import textwrap
+import xml.etree.ElementTree as ET
+from dataclasses import dataclass
+from pathlib import Path
+from typing import List, Dict, Set
+
+print("[DEBUG] argv:", sys.argv)
+
+@dataclass
+class CommandSpec:
+ id: str
+ label: str
+ category: str
+
+
+def parse_commands(xml_path: Path) -> List[CommandSpec]:
+ """
+ Parse CommandsConfig.xml and return a flat list of CommandSpec.
+ """
+ try:
+ tree = ET.parse(str(xml_path))
+ except ET.ParseError as e:
+ print(f"[ERROR] Failed to parse XML '{xml_path}': {e}", file=sys.stderr)
+ sys.exit(1)
+
+ root = tree.getroot()
+
+ # 兼容两种写法: 或
+ commands_nodes = []
+ if root.tag.lower().endswith("commandsconfig"):
+ commands_nodes = root.findall(".//commands/command")
+ else:
+ commands_nodes = root.findall(".//command")
+
+ specs: List[CommandSpec] = []
+
+ for elem in commands_nodes:
+ cid = elem.get("id")
+ if not cid:
+ continue
+ label = elem.get("label", "")
+ category = elem.get("category", "")
+
+ specs.append(CommandSpec(id=cid.strip(),
+ label=label.strip(),
+ category=category.strip()))
+
+ if not specs:
+ print(f"[WARN] No elements found in '{xml_path}'", file=sys.stderr)
+
+ # 检查重复 id
+ seen_ids: Set[str] = set()
+ duplicates: Set[str] = set()
+ for c in specs:
+ if c.id in seen_ids:
+ duplicates.add(c.id)
+ seen_ids.add(c.id)
+ if duplicates:
+ print("[ERROR] Duplicate command id(s) detected:", file=sys.stderr)
+ for d in sorted(duplicates):
+ print(f" - {d}", file=sys.stderr)
+ sys.exit(1)
+
+ # 排序:按 id 排一下,保证生成文件稳定
+ specs.sort(key=lambda c: c.id)
+ return specs
+
+
+def id_to_const_name(cmd_id: str) -> str:
+ """
+ Convert 'file.save' -> 'FILE_SAVE'
+ """
+ result_chars = []
+ for ch in cmd_id:
+ if ch.isalnum():
+ result_chars.append(ch.upper())
+ else:
+ # '.' '-' ' ' 等全部归一成 '_'
+ result_chars.append('_')
+ name = "".join(result_chars)
+
+ # 去掉重复的 '_'(比如 "..")
+ # 連続する '_' を除去(例:"..")
+ while "__" in name:
+ name = name.replace("__", "_")
+
+ # 去掉头尾 '_'
+ # 先頭・末尾の '_' を削除
+ name = name.strip("_")
+
+ # 如果第一个字符是数字,前面加前缀
+ # 先頭が数字の場合は接頭辞を付与
+ if name and name[0].isdigit():
+ name = "CMD_" + name
+
+ if not name:
+ raise ValueError(f"Cannot convert command id '{cmd_id}' to a valid C++ name")
+
+ return name
+
+
+def generate_header(specs: List[CommandSpec],
+ out_path: Path,
+ namespace_root: str = "sdr",
+ namespace_leaf: str = "Cmd") -> None:
+ """
+ Generate SolidDesignerCommands.h into out_path.
+ """
+ # 检查常量名是否冲突
+ # 定数名の衝突をチェック
+ const_map: Dict[str, CommandSpec] = {}
+ collisions: Dict[str, List[str]] = {}
+
+ for c in specs:
+ const_name = id_to_const_name(c.id)
+ if const_name in const_map:
+ collisions.setdefault(const_name, []).append(c.id)
+ else:
+ const_map[const_name] = c
+
+ if collisions:
+ print("[ERROR] Different command ids mapped to the same C++ name:", file=sys.stderr)
+ for cname, ids in collisions.items():
+ all_ids = [const_map[cname].id] + ids
+ print(f" {cname}: {', '.join(all_ids)}", file=sys.stderr)
+ sys.exit(1)
+
+ lines: List[str] = []
+
+ lines.extend(
+ [
+ "// -----------------------------------------------------------------------------",
+ "// SolidDesignerCommands.h",
+ "//",
+ "// AUTO-GENERATED FILE. DO NOT EDIT BY HAND.",
+ "//",
+ "// Generated from: CommandsConfig.xml",
+ "// -----------------------------------------------------------------------------",
+ "",
+ "#pragma once",
+ "#include ",
+ "",
+ f"namespace {namespace_root}",
+ "{",
+ f" namespace {namespace_leaf}",
+ " {",
+ " // NOTE:",
+ " // - Each constant is a std::string_view to the command id as defined",
+ " // in CommandsConfig.xml.",
+ " // - Use these constants in ICommand::Id() implementations, Ribbon/Menu",
+ " // bindings, etc. Never hard-code string literals like \"file.save\".",
+ "",
+ ]
+ )
+
+ # 按 category 分组输出,便于阅读
+ # category ごとにグループ化して出力(可読性向上)
+ by_category: Dict[str, List[CommandSpec]] = {}
+ for c in specs:
+ cat = c.category or "uncategorized"
+ by_category.setdefault(cat, []).append(c)
+
+ for cat in sorted(by_category.keys()):
+ lines.append(f" // === Category: {cat} ===")
+ for c in by_category[cat]:
+ const_name = id_to_const_name(c.id)
+
+ # label 作为注释
+ # label をコメントとして付与
+ label_comment = f" // {c.label}" if c.label else ""
+ lines.append(
+ f' inline constexpr std::string_view {const_name:<30} = "{c.id}";{label_comment}'
+ )
+ lines.append("")
+
+ lines.extend(
+ [
+ " }} // namespace {0}".format(namespace_leaf),
+ "}} // namespace {0}".format(namespace_root),
+ "",
+ ]
+ )
+
+ out_path.write_text("\n".join(lines), encoding="utf-8")
+ print(f"[INFO] Generated {out_path} ({len(specs)} commands).")
+
+
+def main(argv: List[str]) -> int:
+ parser = argparse.ArgumentParser(
+ description="Generate SolidDesignerCommands.h from CommandsConfig.xml"
+ )
+ parser.add_argument("--xml", required=True, help="Path to CommandsConfig.xml")
+ parser.add_argument("--out", required=True, help="Path to SolidDesignerCommands.h")
+ parser.add_argument(
+ "--namespace-root", default="sdr", help="Root namespace (default: sdr)"
+ )
+ parser.add_argument(
+ "--namespace-leaf", default="Cmd", help="Leaf namespace (default: Cmd)"
+ )
+
+ args = parser.parse_args(argv)
+
+ xml_path = Path(args.xml).resolve()
+ out_path = Path(args.out).resolve()
+
+ if not xml_path.is_file():
+ print(f"[ERROR] XML file not found: {xml_path}", file=sys.stderr)
+ return 1
+
+ specs = parse_commands(xml_path)
+ generate_header(
+ specs,
+ out_path,
+ namespace_root=args.namespace_root,
+ namespace_leaf=args.namespace_leaf,
+ )
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
diff --git a/Designer/UI/SolidDesignerCommand/CMakeLists.txt b/Designer/UI/SolidDesignerCommand/CMakeLists.txt
index 5f0160dd..24c6f1a7 100644
--- a/Designer/UI/SolidDesignerCommand/CMakeLists.txt
+++ b/Designer/UI/SolidDesignerCommand/CMakeLists.txt
@@ -8,6 +8,16 @@ message("*--*--*--*--*--*--*--*--*--*--*--*--*--Start SolidDesignerCommand--*--*
add_definitions(-DSOLID_DESIGNER_UI_HOME)
add_definitions(-DSOLID_DESIGNER_COMMAND_HOME)
+message("CMAKE_SOURCE_DIR = ${CMAKE_SOURCE_DIR}")
+# 先指定你项目内置的 Python 解释器
+set(_SD_PY_ROOT "${CMAKE_SOURCE_DIR}/ToolChain/Python310")
+set(Python3_EXECUTABLE "${_SD_PY_ROOT}/python.exe" CACHE FILEPATH "SolidDesigner bundled Python" FORCE)
+
+# 然后再找 Python3
+find_package(Python3 REQUIRED COMPONENTS Interpreter)
+
+message(STATUS "Using Python3_EXECUTABLE = ${Python3_EXECUTABLE}")
+
message("${PROJECT_SOURCE_DIR}")
set(ABS_SDC "${PROJECT_SOURCE_DIR}/Designer/UI/SolidDesignerCommand")
@@ -99,14 +109,15 @@ endif()
#-----------------------------------------------------------------------------
# Automatically generate SolidDesignerCommands.h
#-----------------------------------------------------------------------------
-set(COMMANDS_XML ${CMAKE_SOURCE_DIR}/config/CommandsConfig.xml)
-set(COMMANDS_GEN_DIR ${CMAKE_BINARY_DIR}/generated/$)
-set(COMMANDS_HDR ${COMMANDS_GEN_DIR}/SolidDesignerCommands.h)
-set(COMMANDS_PY ${CMAKE_SOURCE_DIR}/tools/generate_solid_designer_commands.py)
+set(COMMANDS_XML ${PROJECT_SOURCE_DIR}/Designer/Data/CommandsConfig.xml)
+set(COMMANDS_HDR ${PROJECT_SOURCE_DIR}/Designer/UI/SolidDesignerCommand/SolidDesignerCommands.h)
+set(COMMANDS_PY ${CMAKE_SOURCE_DIR}/Designer/Data/Scripts/generate_solid_designer_commands.py)
+
+message(STATUS "COMMANDS_XML = ${COMMANDS_XML}")
+message(STATUS "COMMANDS_PY = ${COMMANDS_PY}")
add_custom_command(
OUTPUT ${COMMANDS_HDR}
- COMMAND ${CMAKE_COMMAND} -E make_directory ${COMMANDS_GEN_DIR}
COMMAND ${Python3_EXECUTABLE} ${COMMANDS_PY}
--xml ${COMMANDS_XML}
--out ${COMMANDS_HDR}
@@ -116,8 +127,6 @@ add_custom_command(
)
add_custom_target(GenerateSolidDesignerCommands DEPENDS ${COMMANDS_HDR})
-
-target_include_directories(SolidDesignerCommand PRIVATE ${COMMANDS_GEN_DIR})
add_dependencies(SolidDesignerCommand GenerateSolidDesignerCommands)
# 可选:让 IDE 看到生成文件
diff --git a/Designer/UI/SolidDesignerCommand/SolidDesignerCommands.h b/Designer/UI/SolidDesignerCommand/SolidDesignerCommands.h
new file mode 100644
index 00000000..c3074c86
--- /dev/null
+++ b/Designer/UI/SolidDesignerCommand/SolidDesignerCommands.h
@@ -0,0 +1,221 @@
+// -----------------------------------------------------------------------------
+// SolidDesignerCommands.h
+//
+// AUTO-GENERATED FILE. DO NOT EDIT BY HAND.
+//
+// Generated from: CommandsConfig.xml
+// -----------------------------------------------------------------------------
+
+#pragma once
+#include
+
+namespace sdr
+{
+ namespace Cmd
+ {
+ // NOTE:
+ // - Each constant is a std::string_view to the command id as defined
+ // in CommandsConfig.xml.
+ // - Use these constants in ICommand::Id() implementations, Ribbon/Menu
+ // bindings, etc. Never hard-code string literals like "file.save".
+
+ // === Category: analysis ===
+ inline constexpr std::string_view ANALYSIS_BODYCHECK = "analysis.bodyCheck"; // Body Check
+ inline constexpr std::string_view ANALYSIS_INTERFERENCE = "analysis.interference"; // Interference Check
+ inline constexpr std::string_view ANALYSIS_MASS = "analysis.mass"; // Mass Analysis
+
+ // === Category: application ===
+ inline constexpr std::string_view APP_SWITCH_ASSEMBLY = "app.switch.assembly"; // Assembly Design
+ inline constexpr std::string_view APP_SWITCH_BIM = "app.switch.bim"; // BIM
+ inline constexpr std::string_view APP_SWITCH_PARTMODELING = "app.switch.partModeling"; // Part Modeling
+ inline constexpr std::string_view APP_SWITCH_SHEETMETAL = "app.switch.sheetMetal"; // Sheet Metal Design
+ inline constexpr std::string_view APP_SWITCH_SHIP = "app.switch.ship"; // Ship Design
+ inline constexpr std::string_view APP_SWITCH_SKETCH = "app.switch.sketch"; // Sketch Environment
+
+ // === Category: assembly ===
+ inline constexpr std::string_view ASM_ADDCOMPONENT = "asm.addComponent"; // Add Component
+ inline constexpr std::string_view ASM_ALIGN = "asm.align"; // Align
+ inline constexpr std::string_view ASM_ARRANGE = "asm.arrange"; // Arrange Components
+ inline constexpr std::string_view ASM_CONSTRAINT = "asm.constraint"; // Assembly Constraints
+ inline constexpr std::string_view ASM_DISTANCE = "asm.distance"; // Distance
+ inline constexpr std::string_view ASM_EXPLODE = "asm.explode"; // Exploded View
+ inline constexpr std::string_view ASM_MATE = "asm.mate"; // Mate
+ inline constexpr std::string_view ASM_NEWCOMPONENT = "asm.newComponent"; // New Component
+ inline constexpr std::string_view ASM_REPLACECOMPONENT = "asm.replaceComponent"; // Replace Component
+ inline constexpr std::string_view ASM_UNEXPLODE = "asm.unexplode"; // Collapse
+
+ // === Category: boolean ===
+ inline constexpr std::string_view MODEL_BOOLEAN_INTERSECT = "model.boolean.intersect"; // Intersect
+ inline constexpr std::string_view MODEL_BOOLEAN_SUBTRACT = "model.boolean.subtract"; // Subtract
+ inline constexpr std::string_view MODEL_BOOLEAN_UNION = "model.boolean.union"; // Union
+
+ // === Category: curve ===
+ inline constexpr std::string_view CURVE_ARC = "curve.arc"; // Arc
+ inline constexpr std::string_view CURVE_CIRCLE = "curve.circle"; // Circle
+ inline constexpr std::string_view CURVE_EXTEND = "curve.extend"; // Extend Curve
+ inline constexpr std::string_view CURVE_FILLET = "curve.fillet"; // Curve Fillet
+ inline constexpr std::string_view CURVE_FITSPLINE = "curve.fitSpline"; // Fit Spline
+ inline constexpr std::string_view CURVE_JOIN = "curve.join"; // Join Curves
+ inline constexpr std::string_view CURVE_LINE = "curve.line"; // Line
+ inline constexpr std::string_view CURVE_OFFSET = "curve.offset"; // Offset Curve
+ inline constexpr std::string_view CURVE_POINT = "curve.point"; // Point
+ inline constexpr std::string_view CURVE_RECTANGLE = "curve.rectangle"; // Rectangle
+ inline constexpr std::string_view CURVE_SPLINETHROUGH = "curve.splineThrough"; // Spline Through Points
+ inline constexpr std::string_view CURVE_STUDIOSPLINE = "curve.studioSpline"; // Studio Spline
+ inline constexpr std::string_view CURVE_TRIM = "curve.trim"; // Trim Curve
+
+ // === Category: datum ===
+ inline constexpr std::string_view DATUM_AXIS = "datum.axis"; // Datum Axis
+ inline constexpr std::string_view DATUM_CS = "datum.cs"; // Coordinate System
+ inline constexpr std::string_view DATUM_PLANE = "datum.plane"; // Datum Plane
+ inline constexpr std::string_view DATUM_POINT = "datum.point"; // Point
+
+ // === Category: display ===
+ inline constexpr std::string_view DISPLAY_HIDDENLINE = "display.hiddenLine"; // Hidden Line
+ inline constexpr std::string_view DISPLAY_HIDE = "display.hide"; // Hide
+ inline constexpr std::string_view DISPLAY_ISOLATE = "display.isolate"; // Isolate
+ inline constexpr std::string_view DISPLAY_SHADED = "display.shaded"; // Shaded
+ inline constexpr std::string_view DISPLAY_SHADEDWITHEDGES = "display.shadedWithEdges"; // Shaded with Edges
+ inline constexpr std::string_view DISPLAY_SHOW = "display.show"; // Show
+ inline constexpr std::string_view DISPLAY_WIREFRAME = "display.wireframe"; // Wireframe
+
+ // === Category: edit ===
+ inline constexpr std::string_view EDIT_COPY = "edit.copy"; // Copy
+ inline constexpr std::string_view EDIT_CUT = "edit.cut"; // Cut
+ inline constexpr std::string_view EDIT_DELETE = "edit.delete"; // Delete
+ inline constexpr std::string_view EDIT_PASTE = "edit.paste"; // Paste
+ inline constexpr std::string_view EDIT_REDO = "edit.redo"; // Redo
+ inline constexpr std::string_view EDIT_SELECTALL = "edit.selectAll"; // Select All
+ inline constexpr std::string_view EDIT_UNDO = "edit.undo"; // Undo
+
+ // === Category: feature ===
+ inline constexpr std::string_view MODEL_FEATURE_DELETE = "model.feature.delete"; // Delete Feature
+ inline constexpr std::string_view MODEL_FEATURE_SUPPRESS = "model.feature.suppress"; // Suppress Feature
+ inline constexpr std::string_view MODEL_FEATURE_UNSUPPRESS = "model.feature.unsuppress"; // Unsuppress Feature
+
+ // === Category: file ===
+ inline constexpr std::string_view FILE_CLOSE = "file.close"; // Close
+ inline constexpr std::string_view FILE_EXIT = "file.exit"; // Exit
+ inline constexpr std::string_view FILE_NEW = "file.new"; // New
+ inline constexpr std::string_view FILE_OPEN = "file.open"; // Open
+ inline constexpr std::string_view FILE_SAVE = "file.save"; // Save
+ inline constexpr std::string_view FILE_SAVEAS = "file.saveAs"; // Save As
+
+ // === Category: gc ===
+ inline constexpr std::string_view GC_CHECKUPDATE = "gc.checkUpdate"; // Check for Updates
+ inline constexpr std::string_view GC_SETTINGS = "gc.settings"; // GC Settings
+ inline constexpr std::string_view GC_STDPARTLIBRARY = "gc.stdPartLibrary"; // Standard Parts Library
+
+ // === Category: help ===
+ inline constexpr std::string_view HELP_ABOUT = "help.about"; // About
+ inline constexpr std::string_view HELP_CONTENTS = "help.contents"; // Help Contents
+
+ // === Category: measure ===
+ inline constexpr std::string_view MEASURE_ANGLE = "measure.angle"; // Angle
+ inline constexpr std::string_view MEASURE_DIALOG = "measure.dialog"; // Measure Dialog
+ inline constexpr std::string_view MEASURE_DISTANCE = "measure.distance"; // Distance
+ inline constexpr std::string_view MEASURE_DRAFT = "measure.draft"; // Draft Analysis
+ inline constexpr std::string_view MEASURE_MASSPROPS = "measure.massProps"; // Mass Properties
+ inline constexpr std::string_view MEASURE_RADIUS = "measure.radius"; // Radius
+ inline constexpr std::string_view MEASURE_SECTION = "measure.section"; // Section Measurement
+
+ // === Category: modeling ===
+ inline constexpr std::string_view MODEL_CHAMFER = "model.chamfer"; // Chamfer
+ inline constexpr std::string_view MODEL_DRAFT = "model.draft"; // Draft
+ inline constexpr std::string_view MODEL_EXTRUDE = "model.extrude"; // Extrude
+ inline constexpr std::string_view MODEL_FILLET = "model.fillet"; // Fillet
+ inline constexpr std::string_view MODEL_HOLE = "model.hole"; // Hole
+ inline constexpr std::string_view MODEL_REVOLVE = "model.revolve"; // Revolve
+ inline constexpr std::string_view MODEL_SHELL = "model.shell"; // Shell
+ inline constexpr std::string_view MODEL_SLOT = "model.slot"; // Slot
+
+ // === Category: selection ===
+ inline constexpr std::string_view SELECT_FILTER = "select.filter"; // Selection Filter
+ inline constexpr std::string_view SELECT_LASSO = "select.lasso"; // Lasso Select
+ inline constexpr std::string_view SELECT_RECTANGLE = "select.rectangle"; // Rectangle Select
+ inline constexpr std::string_view SELECT_SINGLE = "select.single"; // Single Select
+
+ // === Category: sheet ===
+ inline constexpr std::string_view SHEET_BASEFLANGE = "sheet.baseFlange"; // Base Flange
+ inline constexpr std::string_view SHEET_BEND = "sheet.bend"; // Bend
+ inline constexpr std::string_view SHEET_BREAKCORNER = "sheet.breakCorner"; // Break Corner
+ inline constexpr std::string_view SHEET_CONTOURFLANGE = "sheet.contourFlange"; // Contour Flange
+ inline constexpr std::string_view SHEET_CORNERRELIEF = "sheet.cornerRelief"; // Corner Relief
+ inline constexpr std::string_view SHEET_CUTOUT = "sheet.cutout"; // Cutout
+ inline constexpr std::string_view SHEET_EDGEFLANGE = "sheet.edgeFlange"; // Edge Flange
+ inline constexpr std::string_view SHEET_EXPORTFLAT = "sheet.exportFlat"; // Export Flat
+ inline constexpr std::string_view SHEET_FLATTEN = "sheet.flatten"; // Flat Pattern
+ inline constexpr std::string_view SHEET_HOLE = "sheet.hole"; // Hole
+ inline constexpr std::string_view SHEET_JOG = "sheet.jog"; // Jog
+ inline constexpr std::string_view SHEET_LOFTEDFLANGE = "sheet.loftedFlange"; // Lofted Flange
+ inline constexpr std::string_view SHEET_REBEND = "sheet.rebend"; // Rebend
+ inline constexpr std::string_view SHEET_TAB = "sheet.tab"; // Tab
+ inline constexpr std::string_view SHEET_UNBEND = "sheet.unbend"; // Unbend
+
+ // === Category: sketch ===
+ inline constexpr std::string_view SKETCH_EDIT = "sketch.edit"; // Edit Sketch
+ inline constexpr std::string_view SKETCH_MIRROR = "sketch.mirror"; // Mirror Sketch
+ inline constexpr std::string_view SKETCH_NEW = "sketch.new"; // Sketch
+ inline constexpr std::string_view SKETCH_REUSE = "sketch.reuse"; // Reuse Sketch
+
+ // === Category: sketch.constraint ===
+ inline constexpr std::string_view SKETCH_CONSTRAINT_COINCIDENT = "sketch.constraint.coincident"; // Coincident
+ inline constexpr std::string_view SKETCH_CONSTRAINT_EQUAL = "sketch.constraint.equal"; // Equal
+ inline constexpr std::string_view SKETCH_CONSTRAINT_FIX = "sketch.constraint.fix"; // Fix
+ inline constexpr std::string_view SKETCH_CONSTRAINT_HORIZONTAL = "sketch.constraint.horizontal"; // Horizontal
+ inline constexpr std::string_view SKETCH_CONSTRAINT_PARALLEL = "sketch.constraint.parallel"; // Parallel
+ inline constexpr std::string_view SKETCH_CONSTRAINT_PERPENDICULAR = "sketch.constraint.perpendicular"; // Perpendicular
+ inline constexpr std::string_view SKETCH_CONSTRAINT_SYMMETRIC = "sketch.constraint.symmetric"; // Symmetric
+ inline constexpr std::string_view SKETCH_CONSTRAINT_TANGENT = "sketch.constraint.tangent"; // Tangent
+ inline constexpr std::string_view SKETCH_CONSTRAINT_VERTICAL = "sketch.constraint.vertical"; // Vertical
+
+ // === Category: sketch.dim ===
+ inline constexpr std::string_view SKETCH_DIM_ANGLE = "sketch.dim.angle"; // Angular Dimension
+ inline constexpr std::string_view SKETCH_DIM_DIAMETER = "sketch.dim.diameter"; // Diameter Dimension
+ inline constexpr std::string_view SKETCH_DIM_GENERAL = "sketch.dim.general"; // Smart Dimension
+ inline constexpr std::string_view SKETCH_DIM_HORIZONTAL = "sketch.dim.horizontal"; // Horizontal Dimension
+ inline constexpr std::string_view SKETCH_DIM_RADIUS = "sketch.dim.radius"; // Radius Dimension
+ inline constexpr std::string_view SKETCH_DIM_VERTICAL = "sketch.dim.vertical"; // Vertical Dimension
+
+ // === Category: sketch.modify ===
+ inline constexpr std::string_view SKETCH_MODIFY_EXTEND = "sketch.modify.extend"; // Extend
+ inline constexpr std::string_view SKETCH_MODIFY_FILLET = "sketch.modify.fillet"; // Fillet
+ inline constexpr std::string_view SKETCH_MODIFY_MIRROR = "sketch.modify.mirror"; // Mirror
+ inline constexpr std::string_view SKETCH_MODIFY_OFFSET = "sketch.modify.offset"; // Offset
+ inline constexpr std::string_view SKETCH_MODIFY_PATTERN = "sketch.modify.pattern"; // Pattern
+ inline constexpr std::string_view SKETCH_MODIFY_TRIM = "sketch.modify.trim"; // Trim
+
+ // === Category: synchronous ===
+ inline constexpr std::string_view SMOVE_FACE = "smove.face"; // Move Face
+ inline constexpr std::string_view SYNCHRONOUS_DELETEFACE = "synchronous.deleteFace"; // Delete Face
+ inline constexpr std::string_view SYNCHRONOUS_OFFSETREGION = "synchronous.offsetRegion"; // Offset Region
+ inline constexpr std::string_view SYNCHRONOUS_PULL = "synchronous.pull"; // Pull Face
+
+ // === Category: tools ===
+ inline constexpr std::string_view TOOLS_COMMANDLINE = "tools.commandLine"; // Command Line
+ inline constexpr std::string_view TOOLS_EXPRESSIONS = "tools.expressions"; // Expressions
+ inline constexpr std::string_view TOOLS_JOURNAL_PAUSE = "tools.journal.pause"; // Pause Journal
+ inline constexpr std::string_view TOOLS_JOURNAL_PLAY = "tools.journal.play"; // Play Journal
+ inline constexpr std::string_view TOOLS_JOURNAL_RECORD = "tools.journal.record"; // Record Journal
+ inline constexpr std::string_view TOOLS_PYTHONCONSOLE = "tools.pythonConsole"; // Python Console
+
+ // === Category: ui ===
+ inline constexpr std::string_view UI_RESTORELAYOUT = "ui.restoreLayout"; // Restore Layout
+ inline constexpr std::string_view UI_SAVELAYOUT = "ui.saveLayout"; // Save Layout
+ inline constexpr std::string_view UI_TOGGLEMODE = "ui.toggleMode"; // Toggle Ribbon / Classic
+
+ // === Category: view ===
+ inline constexpr std::string_view VIEW_CLIPPINGPLANE = "view.clippingPlane"; // Clipping Plane
+ inline constexpr std::string_view VIEW_DYNAMICSECTION = "view.dynamicSection"; // Dynamic Section
+ inline constexpr std::string_view VIEW_FRONT = "view.front"; // Front
+ inline constexpr std::string_view VIEW_RIGHT = "view.right"; // Right
+ inline constexpr std::string_view VIEW_TOP = "view.top"; // Top
+ inline constexpr std::string_view VIEW_TRIMETRIC = "view.trimetric"; // Trimetric
+
+ // === Category: window ===
+ inline constexpr std::string_view WINDOW_ARRANGE = "window.arrange"; // Arrange Windows
+ inline constexpr std::string_view WINDOW_NEW = "window.new"; // New Window
+ inline constexpr std::string_view WINDOW_TILEHORIZONTAL = "window.tileHorizontal"; // Tile Horizontally
+
+ } // namespace Cmd
+} // namespace sdr