You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

519 lines
20 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you may find one here:
  18. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  19. * or you may search the http://www.gnu.org website for the version 2 license,
  20. * or you may write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  22. */
  23. #include <advanced_config.h>
  24. #include <config_params.h>
  25. #include <settings/settings_manager.h>
  26. #include <wx/app.h>
  27. #include <wx/config.h>
  28. #include <wx/filename.h>
  29. #include <wx/log.h>
  30. #include <wx/tokenzr.h>
  31. /*
  32. * Flag to enable advanced config debugging
  33. *
  34. * Use "KICAD_ADVANCED_CONFIG" to enable.
  35. *
  36. * @ingroup trace_env_vars
  37. */
  38. static const wxChar AdvancedConfigMask[] = wxT( "KICAD_ADVANCED_CONFIG" );
  39. /**
  40. * Limits and default settings for the coroutine stack size allowed.
  41. * Warning! Setting the stack size below the default may lead to unexplained crashes
  42. * This configuration setting is intended for developers only.
  43. */
  44. namespace AC_STACK
  45. {
  46. static constexpr int min_stack = 32 * 4096;
  47. static constexpr int default_stack = 256 * 4096;
  48. static constexpr int max_stack = 4096 * 4096;
  49. }
  50. /**
  51. * List of known keys for advanced configuration options.
  52. *
  53. * Set these options in the file `kicad_advanced` in the
  54. * KiCad config directory.
  55. */
  56. namespace AC_KEYS
  57. {
  58. /**
  59. * Should the schematic use the new incremental connectivity algorithm
  60. */
  61. static const wxChar IncrementalConnectivity[] = wxT( "IncrementalConnectivity" );
  62. /**
  63. * Decide whether to attempt usage of the 3DConnexion mouse
  64. */
  65. static const wxChar Use3DConnexionDriver[] = wxT( "3DConnexionDriver" );
  66. /**
  67. * When filling zones, we add an extra amount of clearance to each zone to ensure that rounding
  68. * errors do not overrun minimum clearance distances. This is the extra in mm.
  69. */
  70. static const wxChar ExtraFillMargin[] = wxT( "ExtraFillMargin" );
  71. /**
  72. * A fudge factor for DRC. Required to prevent false positives due to rounding errors, errors
  73. * in polygonalization, etc.
  74. * Previous versions hard-coded various values from 0.000005mm to 0.002mm.
  75. */
  76. static const wxChar DRCEpsilon[] = wxT( "DRCEpsilon" );
  77. /**
  78. * Angle and width tolerances for copper and solder mask sliver detection.
  79. */
  80. static const wxChar DRCSliverWidthTolerance[] = wxT( "DRCSliverWidthTolerance" );
  81. static const wxChar DRCSliverMinimumLength[] = wxT( "DRCSliverMinimumLength" );
  82. static const wxChar DRCSliverAngleTolerance[] = wxT( "DRCSliverAngleTolerance" );
  83. /**
  84. * Used to calculate the actual hole size from the finish hole size.
  85. * IPC-6012 says 0.015-0.018mm; Cadence says at least 0.020mm for a Class 2 board and at least
  86. * 0.025mm for Class 3.
  87. */
  88. static const wxChar HoleWallThickness[] = wxT( "HoleWallPlatingThickness" );
  89. /**
  90. * Configure the coroutine stack size in bytes. This should be allocated in multiples of
  91. * the system page size (n*4096 is generally safe)
  92. */
  93. static const wxChar CoroutineStackSize[] = wxT( "CoroutineStackSize" );
  94. /**
  95. * Show PNS router debug graphics while routing
  96. */
  97. static const wxChar ShowRouterDebugGraphics[] = wxT( "ShowRouterDebugGraphics" );
  98. /**
  99. * When set to true, this will wrap polygon point sets at 4 points per line rather
  100. * than a single point per line. Single point per line helps with version control systems
  101. */
  102. static const wxChar CompactFileSave[] = wxT( "CompactSave" );
  103. /**
  104. * For drawsegments - arcs.
  105. * Distance from an arc end point and the estimated end point,
  106. * when rotating from the start point to the end point.
  107. * 0 will not allow any approximate result, and the arc will not show.
  108. * Squared value for performances, in system unit.
  109. */
  110. static const wxChar DrawArcAccuracy[] = wxT( "DrawArcAccuracy" );
  111. /**
  112. * For drawsegments - arcs.
  113. * When drawing an arc, the angle ( center - start ) - ( start - end ),
  114. * can be limited to avoid extremely high radii.
  115. * The value is the tan( angle )
  116. */
  117. static const wxChar DrawArcCenterStartEndMaxAngle[] = wxT( "DrawArcCenterStartEndMaxAngle" );
  118. /**
  119. * For arc track interactive drag-resizing
  120. * Maximum angle between the tangent line of an arc track and a connected straight track
  121. * in order to commence arc dragging. Units are degrees.
  122. */
  123. static const wxChar MaxTangentTrackAngleDeviation[] = wxT( "MaxTangentTrackAngleDeviation" );
  124. /**
  125. * For arc track interactive drag-resizing
  126. * Maximum track length to keep after doing an arc track resizing operation. Units are mm.
  127. */
  128. static const wxChar MaxTrackLengthToKeep[] = wxT( "MaxTrackLengthToKeep" );
  129. /**
  130. * When true, GAL will stroke the triangulations (only used in OpenGL) with a visible color
  131. */
  132. static const wxChar StrokeTriangulation[] = wxT( "StrokeTriangulation" );
  133. /**
  134. * When true, a third zone-display-mode is included which strokes the filled areas and fracture
  135. * boundaries.
  136. */
  137. static const wxChar ExtraZoneDisplayModes[] = wxT( "ExtraZoneDisplayModes" );
  138. /**
  139. * Absolute minimum pen width to send to the plotter. PDF seems happy enough with 0.0212mm
  140. * (which equates to 1px @ 1200dpi).
  141. */
  142. static const wxChar MinPlotPenWidth[] = wxT( "MinPlotPenWidth" );
  143. static const wxChar DebugZoneFiller[] = wxT( "DebugZoneFiller" );
  144. static const wxChar DebugPDFWriter[] = wxT( "DebugPDFWriter" );
  145. /**
  146. * The diameter of the drill marks on print and plot outputs (in mm),
  147. * when the "Drill marks" option is set to "Small mark"
  148. */
  149. static const wxChar SmallDrillMarkSize[] = wxT( "SmallDrillMarkSize" );
  150. static const wxChar HotkeysDumper[] = wxT( "HotkeysDumper" );
  151. static const wxChar DrawBoundingBoxes[] = wxT( "DrawBoundingBoxes" );
  152. static const wxChar ShowPcbnewExportNetlist[] = wxT( "ShowPcbnewExportNetlist" );
  153. static const wxChar Skip3DModelFileCache[] = wxT( "Skip3DModelFileCache" );
  154. static const wxChar Skip3DModelMemoryCache[] = wxT( "Skip3DModelMemoryCache" );
  155. static const wxChar HideVersionFromTitle[] = wxT( "HideVersionFromTitle" );
  156. static const wxChar TraceMasks[] = wxT( "TraceMasks" );
  157. static const wxChar ShowRepairSchematic[] = wxT( "ShowRepairSchematic" );
  158. static const wxChar ShowEventCounters[] = wxT( "ShowEventCounters" );
  159. static const wxChar AllowManualCanvasScale[] = wxT( "AllowManualCanvasScale" );
  160. static const wxChar UpdateUIEventInterval[] = wxT( "UpdateUIEventInterval" );
  161. static const wxChar ShowPropertiesPanel[] = wxT( "ShowPropertiesPanel" );
  162. static const wxChar V3DRT_BevelHeight_um[] = wxT( "V3DRT_BevelHeight_um" );
  163. static const wxChar V3DRT_BevelExtentFactor[] = wxT( "V3DRT_BevelExtentFactor" );
  164. static const wxChar UseClipper2[] = wxT( "UseClipper2" );
  165. } // namespace KEYS
  166. /**
  167. * List of known groups for advanced configuration options.
  168. *
  169. */
  170. namespace AC_GROUPS
  171. {
  172. static const wxChar V3D_RayTracing[] = wxT( "G_3DV_RayTracing" );
  173. }
  174. /*
  175. * Get a simple string for common parameters.
  176. *
  177. * This isn't exhaustive, but it covers most common types that might be
  178. * used in the advance config
  179. */
  180. wxString dumpParamCfg( const PARAM_CFG& aParam )
  181. {
  182. wxString s = aParam.m_Ident + wxS( ": " );
  183. /*
  184. * This implementation is rather simplistic, but it is
  185. * effective enough for simple uses. A better implementation would be
  186. * some kind of visitor, but that's somewhat more work.
  187. */
  188. switch( aParam.m_Type )
  189. {
  190. case paramcfg_id::PARAM_INT:
  191. case paramcfg_id::PARAM_INT_WITH_SCALE:
  192. s << *static_cast<const PARAM_CFG_INT&>( aParam ).m_Pt_param;
  193. break;
  194. case paramcfg_id::PARAM_DOUBLE:
  195. s << *static_cast<const PARAM_CFG_DOUBLE&>( aParam ).m_Pt_param;
  196. break;
  197. case paramcfg_id::PARAM_WXSTRING:
  198. s << *static_cast<const PARAM_CFG_WXSTRING&>( aParam ).m_Pt_param;
  199. break;
  200. case paramcfg_id::PARAM_FILENAME:
  201. s << *static_cast<const PARAM_CFG_FILENAME&>( aParam ).m_Pt_param;
  202. break;
  203. case paramcfg_id::PARAM_BOOL:
  204. s << ( *static_cast<const PARAM_CFG_BOOL&>( aParam ).m_Pt_param ? wxS( "true" ) : wxS( "false" ) );
  205. break;
  206. default: s << wxS( "Unsupported PARAM_CFG variant: " ) << aParam.m_Type;
  207. }
  208. return s;
  209. }
  210. /**
  211. * Dump the configs in the given array to trace.
  212. */
  213. static void dumpCfg( const std::vector<PARAM_CFG*>& aArray )
  214. {
  215. // only dump if we need to
  216. if( !wxLog::IsAllowedTraceMask( AdvancedConfigMask ) )
  217. return;
  218. for( const PARAM_CFG* param : aArray )
  219. {
  220. wxLogTrace( AdvancedConfigMask, dumpParamCfg( *param ) );
  221. }
  222. }
  223. /**
  224. * Get the filename for the advanced config file
  225. *
  226. * The user must check the file exists if they care.
  227. */
  228. static wxFileName getAdvancedCfgFilename()
  229. {
  230. const static wxString cfg_filename{ wxS( "kicad_advanced" ) };
  231. return wxFileName( SETTINGS_MANAGER::GetUserSettingsPath(), cfg_filename );
  232. }
  233. ADVANCED_CFG::ADVANCED_CFG()
  234. {
  235. wxLogTrace( AdvancedConfigMask, wxS( "Init advanced config" ) );
  236. // Init defaults - this is done in case the config doesn't exist,
  237. // then the values will remain as set here.
  238. m_CoroutineStackSize = AC_STACK::default_stack;
  239. m_ShowRouterDebugGraphics = false;
  240. m_DrawArcAccuracy = 10.0;
  241. m_DrawArcCenterMaxAngle = 50.0;
  242. m_MaxTangentAngleDeviation = 1.0;
  243. m_MaxTrackLengthToKeep = 0.0005;
  244. m_ExtraZoneDisplayModes = false;
  245. m_DrawTriangulationOutlines = false;
  246. m_ExtraClearance = 0.0005;
  247. m_DRCEpsilon = 0.0005; // 0.5um is small enough not to materially violate
  248. // any constraints.
  249. m_SliverWidthTolerance = 0.08;
  250. m_SliverMinimumLength = 0.0008;
  251. m_SliverAngleTolerance = 20.0;
  252. m_HoleWallThickness = 0.020; // IPC-6012 says 15-18um; Cadence says at least
  253. // 0.020 for a Class 2 board and at least 0.025
  254. // for Class 3.
  255. m_MinPlotPenWidth = 0.0212; // 1 pixel at 1200dpi.
  256. m_DebugZoneFiller = false;
  257. m_DebugPDFWriter = false;
  258. m_SmallDrillMarkSize = 0.35;
  259. m_HotkeysDumper = false;
  260. m_DrawBoundingBoxes = false;
  261. m_ShowPcbnewExportNetlist = false;
  262. m_Skip3DModelFileCache = false;
  263. m_Skip3DModelMemoryCache = false;
  264. m_HideVersionFromTitle = false;
  265. m_ShowEventCounters = false;
  266. m_AllowManualCanvasScale = false;
  267. m_CompactSave = false;
  268. m_UpdateUIEventInterval = 0;
  269. m_ShowRepairSchematic = false;
  270. m_ShowPropertiesPanel = false;
  271. m_3DRT_BevelHeight_um = 30;
  272. m_3DRT_BevelExtentFactor = 1.0 / 16.0;
  273. m_UseClipper2 = true;
  274. #ifdef _WIN32
  275. // spacemouse is largely stable on Windows
  276. m_Use3DConnexionDriver = true;
  277. #else
  278. m_Use3DConnexionDriver = false;
  279. #endif
  280. m_IncrementalConnectivity = false;
  281. loadFromConfigFile();
  282. }
  283. const ADVANCED_CFG& ADVANCED_CFG::GetCfg()
  284. {
  285. static ADVANCED_CFG instance;
  286. return instance;
  287. }
  288. void ADVANCED_CFG::loadFromConfigFile()
  289. {
  290. const wxFileName k_advanced = getAdvancedCfgFilename();
  291. // If we are running headless, use the class defaults because we cannot instantiate wxConfig
  292. if( !wxTheApp )
  293. return;
  294. if( !k_advanced.FileExists() )
  295. {
  296. wxLogTrace( AdvancedConfigMask, wxS( "File does not exist %s" ), k_advanced.GetFullPath() );
  297. // load the defaults
  298. wxConfig emptyConfig;
  299. loadSettings( emptyConfig );
  300. return;
  301. }
  302. wxLogTrace( AdvancedConfigMask, wxS( "Loading advanced config from: %s" ), k_advanced.GetFullPath() );
  303. wxFileConfig file_cfg( wxS( "" ), wxS( "" ), k_advanced.GetFullPath() );
  304. loadSettings( file_cfg );
  305. }
  306. void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
  307. {
  308. std::vector<PARAM_CFG*> configParams;
  309. configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::ExtraFillMargin,
  310. &m_ExtraClearance, m_ExtraClearance, 0.0, 1.0 ) );
  311. configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DRCEpsilon,
  312. &m_DRCEpsilon, m_DRCEpsilon, 0.0, 1.0 ) );
  313. configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DRCSliverWidthTolerance,
  314. &m_SliverWidthTolerance, m_SliverWidthTolerance, 0.01, 0.25 ) );
  315. configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DRCSliverMinimumLength,
  316. &m_SliverMinimumLength, m_SliverMinimumLength, 1e-9, 10 ) );
  317. configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DRCSliverAngleTolerance,
  318. &m_SliverAngleTolerance, m_SliverAngleTolerance, 1.0, 90.0 ) );
  319. configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::HoleWallThickness,
  320. &m_HoleWallThickness, m_HoleWallThickness, 0.0, 1.0 ) );
  321. configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::CoroutineStackSize,
  322. &m_CoroutineStackSize, AC_STACK::default_stack,
  323. AC_STACK::min_stack, AC_STACK::max_stack ) );
  324. configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::UpdateUIEventInterval,
  325. &m_UpdateUIEventInterval, m_UpdateUIEventInterval, -1, 100000 ) );
  326. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowRouterDebugGraphics,
  327. &m_ShowRouterDebugGraphics, m_ShowRouterDebugGraphics ) );
  328. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::CompactFileSave,
  329. &m_CompactSave, m_CompactSave ) );
  330. configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DrawArcAccuracy,
  331. &m_DrawArcAccuracy, m_DrawArcAccuracy, 0.0, 100000.0 ) );
  332. configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DrawArcCenterStartEndMaxAngle,
  333. &m_DrawArcCenterMaxAngle, m_DrawArcCenterMaxAngle, 0.0, 100000.0 ) );
  334. configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MaxTangentTrackAngleDeviation,
  335. &m_MaxTangentAngleDeviation, m_MaxTangentAngleDeviation, 0.0, 90.0 ) );
  336. configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MaxTrackLengthToKeep,
  337. &m_MaxTrackLengthToKeep, m_MaxTrackLengthToKeep, 0.0, 1.0 ) );
  338. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ExtraZoneDisplayModes,
  339. &m_ExtraZoneDisplayModes, m_ExtraZoneDisplayModes ) );
  340. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::StrokeTriangulation,
  341. &m_DrawTriangulationOutlines, m_DrawTriangulationOutlines ) );
  342. configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MinPlotPenWidth,
  343. &m_MinPlotPenWidth, m_MinPlotPenWidth, 0.0, 1.0 ) );
  344. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DebugZoneFiller,
  345. &m_DebugZoneFiller, m_DebugZoneFiller ) );
  346. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DebugPDFWriter,
  347. &m_DebugPDFWriter, m_DebugPDFWriter ) );
  348. configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::SmallDrillMarkSize,
  349. &m_SmallDrillMarkSize, m_SmallDrillMarkSize, 0.0, 3.0 ) );
  350. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::HotkeysDumper,
  351. &m_HotkeysDumper, m_HotkeysDumper ) );
  352. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DrawBoundingBoxes,
  353. &m_DrawBoundingBoxes, m_DrawBoundingBoxes ) );
  354. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowPcbnewExportNetlist,
  355. &m_ShowPcbnewExportNetlist, m_ShowPcbnewExportNetlist ) );
  356. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::Skip3DModelFileCache,
  357. &m_Skip3DModelFileCache, m_Skip3DModelFileCache ) );
  358. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::Skip3DModelMemoryCache,
  359. &m_Skip3DModelMemoryCache, m_Skip3DModelMemoryCache ) );
  360. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::HideVersionFromTitle,
  361. &m_HideVersionFromTitle, m_HideVersionFromTitle ) );
  362. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowRepairSchematic,
  363. &m_ShowRepairSchematic, m_ShowRepairSchematic ) );
  364. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowEventCounters,
  365. &m_ShowEventCounters, m_ShowEventCounters ) );
  366. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::AllowManualCanvasScale,
  367. &m_AllowManualCanvasScale, m_AllowManualCanvasScale ) );
  368. configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::V3DRT_BevelHeight_um,
  369. &m_3DRT_BevelHeight_um, m_3DRT_BevelHeight_um,
  370. 0, std::numeric_limits<int>::max(),
  371. AC_GROUPS::V3D_RayTracing ) );
  372. configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::V3DRT_BevelExtentFactor,
  373. &m_3DRT_BevelExtentFactor, m_3DRT_BevelExtentFactor,
  374. 0.0, 100.0,
  375. AC_GROUPS::V3D_RayTracing ) );
  376. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::UseClipper2,
  377. &m_UseClipper2, m_UseClipper2 ) );
  378. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::Use3DConnexionDriver,
  379. &m_Use3DConnexionDriver, m_Use3DConnexionDriver ) );
  380. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::IncrementalConnectivity,
  381. &m_IncrementalConnectivity, m_IncrementalConnectivity ) );
  382. // Special case for trace mask setting...we just grab them and set them immediately
  383. // Because we even use wxLogTrace inside of advanced config
  384. wxString traceMasks;
  385. configParams.push_back( new PARAM_CFG_WXSTRING( true, AC_KEYS::TraceMasks, &traceMasks, wxS( "" ) ) );
  386. configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowPropertiesPanel,
  387. &m_ShowPropertiesPanel, false ) );
  388. // Load the config from file
  389. wxConfigLoadSetups( &aCfg, configParams );
  390. // Now actually set the trace masks
  391. wxStringTokenizer traceMaskTokenizer( traceMasks, wxS( "," ) );
  392. while( traceMaskTokenizer.HasMoreTokens() )
  393. {
  394. wxString mask = traceMaskTokenizer.GetNextToken();
  395. wxLog::AddTraceMask( mask );
  396. }
  397. dumpCfg( configParams );
  398. for( PARAM_CFG* param : configParams )
  399. delete param;
  400. }