Compare commits

...

135 Commits

Author SHA1 Message Date
Wayne Stambaugh 567c5bc8db Tag release version 7.0.10. 2023-12-27 16:21:44 -05:00
Seth Hillbrand 1fdf7d0cf4 Update translations 2023-12-19 08:35:23 -08:00
Nguyễn Ngọc Khánh 5ffe28eec2 Translated using Weblate (Vietnamese)
Currently translated at 18.2% (1464 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/vi/
2023-12-19 17:33:17 +01:00
dsa-t 4e855b4cb0 Translated using Weblate (Russian)
Currently translated at 100.0% (8025 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ru/
2023-12-19 17:33:17 +01:00
Nguyễn Ngọc Khánh ae886c824c Translated using Weblate (Vietnamese)
Currently translated at 17.2% (1381 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/vi/
2023-12-19 17:33:17 +01:00
Henrik Kauhanen 46b5442214 Translated using Weblate (Swedish)
Currently translated at 99.9% (8018 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-12-19 17:33:17 +01:00
Nguyễn Ngọc Khánh c3deafd271 Translated using Weblate (Vietnamese)
Currently translated at 16.8% (1352 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/vi/
2023-12-19 17:33:16 +01:00
Ulices de2da52941 Translated using Weblate (Spanish (Mexico))
Currently translated at 99.9% (8021 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/es_MX/
2023-12-19 17:33:16 +01:00
Ulices 8aa3d183ef Translated using Weblate (Spanish)
Currently translated at 99.0% (7950 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/es/
2023-12-19 17:33:16 +01:00
Nguyễn Ngọc Khánh 6623b19b70 Translated using Weblate (Vietnamese)
Currently translated at 16.4% (1318 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/vi/
2023-12-19 17:33:16 +01:00
Henrik Kauhanen 7a40b6e484 Translated using Weblate (Swedish)
Currently translated at 99.9% (8018 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-12-19 17:33:16 +01:00
dsa-t d63dc32e71 Translated using Weblate (Russian)
Currently translated at 99.9% (8024 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ru/
2023-12-19 17:33:16 +01:00
Wellington Terumi Uemura 54aa3bc5d4 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (8025 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/pt_BR/
2023-12-19 17:33:16 +01:00
ZbeeGin 6ebd616049 Translated using Weblate (Polish)
Currently translated at 99.9% (8024 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/pl/
2023-12-19 17:33:16 +01:00
김랑기 c0439feef8 Translated using Weblate (Korean)
Currently translated at 99.9% (8023 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ko/
2023-12-19 17:33:16 +01:00
Tokita, Hiroshi 0e550322db Translated using Weblate (Japanese)
Currently translated at 99.9% (8022 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ja/
2023-12-19 17:33:16 +01:00
Toni Laiho 7398d47728 Translated using Weblate (Finnish)
Currently translated at 99.7% (8007 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/fi/
2023-12-19 17:33:16 +01:00
aris-kimi 9f0f7e8641 Translated using Weblate (Greek)
Currently translated at 99.4% (7982 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/el/
2023-12-19 17:33:16 +01:00
Bas Wijnen f26e36440d Translated using Weblate (Dutch)
Currently translated at 84.0% (6743 of 8025 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/nl/
2023-12-19 17:33:16 +01:00
Wayne Stambaugh 8ff0aca6b4 Tag stable version 7.0.10 release candidate 1. 2023-12-19 07:54:07 -05:00
Marco Ciampa d4b564ee7a Updated Italian translation 2023-12-19 01:12:44 +01:00
Huibean 22a6bf999f Add frame window monitor display index compare with saved dialog and centre it if display changed which caused dialog disapper
(cherry picked from commit 530b72972d)
2023-12-15 16:39:57 +00:00
Jeff Young 09bae9bb14 Fallback to normal undo when wire-drawing not in progress.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16216

(cherry picked from commit 035725cd5d)
2023-12-12 17:15:05 +00:00
Jeff Young 874f7fbdff Prevent copy-elision issues by using smart-pointer.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16335

(cherry picked from commit e801e793dc)
2023-12-11 17:27:16 +00:00
Wayne Stambaugh 6d17d7d7a1 Fix crash when duplicating and editing a hierarchical label.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16264
2023-12-11 10:57:19 -05:00
Wayne Stambaugh 98dc21360a Fix crash on save after pasting symbols in schematic editor.
This was caused by pasting zero length instance paths which are not valid.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16300

(cherry picked from commit 484491aaea)
2023-12-11 08:30:38 -05:00
jean-pierre charras 0d330051ed Pcbnew: draw shadow PCB_SHAPEs for locked items using continuous lines.
Using other shapes gives really strange and ugly results.
From master branch
Fixes #16327
https://gitlab.com/kicad/code/kicad/-/issues/16327
2023-12-10 15:51:14 +01:00
Jeff Young f17c4cceac Back-port bugfix from master.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16315
2023-12-09 14:54:24 +00:00
Jeff Young a3072ffade Revert e99a2fbc56.
The full fix will have to wait for 8.0:
0cf6679bfe
64c692a42e
72c985bc07
2f3c0a608d
2023-12-09 14:10:55 +00:00
Seth Hillbrand f60c544478 Update translations 2023-12-08 09:39:40 -08:00
김랑기 fc320e0ab4 Translated using Weblate (Korean)
Currently translated at 100.0% (8023 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ko/
2023-12-08 18:38:56 +01:00
김랑기 91c861e8d6 Translated using Weblate (Korean)
Currently translated at 100.0% (8023 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ko/
2023-12-08 18:38:56 +01:00
Zhen Sun 2640f4ad41 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.9% (8021 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/zh_Hans/
2023-12-08 18:38:56 +01:00
Henrik Kauhanen 06f5828990 Translated using Weblate (Swedish)
Currently translated at 99.9% (8017 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-12-08 18:38:56 +01:00
Henrik Kauhanen 85604e1707 Translated using Weblate (Swedish)
Currently translated at 99.9% (8017 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-12-08 18:38:56 +01:00
Henrik Kauhanen ad7bc215d0 Translated using Weblate (Swedish)
Currently translated at 99.9% (8016 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-12-08 18:38:56 +01:00
JasonTan f005676c90 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.9% (8016 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/zh_Hans/
2023-12-08 18:38:55 +01:00
Pinpang Liao 17961165cf Translated using Weblate (Chinese (Simplified))
Currently translated at 99.9% (8015 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/zh_Hans/
2023-12-08 18:38:55 +01:00
欠陥電気 6ba2230804 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.9% (8015 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/zh_Hans/
2023-12-08 18:38:55 +01:00
Erkan cacfaac52e Translated using Weblate (Turkish)
Currently translated at 61.4% (4929 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/tr/
2023-12-08 18:38:55 +01:00
Henrik Kauhanen 4f09e18894 Translated using Weblate (Swedish)
Currently translated at 99.9% (8015 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-12-08 18:38:55 +01:00
___davidpr 05f1912d19 Translated using Weblate (Serbian)
Currently translated at 12.3% (993 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sr/
2023-12-08 18:38:55 +01:00
김랑기 e15306464f Translated using Weblate (Korean)
Currently translated at 100.0% (8023 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ko/
2023-12-08 18:38:55 +01:00
欠陥電気 28f75d5ad3 Translated using Weblate (Japanese)
Currently translated at 99.9% (8022 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ja/
2023-12-08 18:38:55 +01:00
Henrik Kauhanen 3021764401 Translated using Weblate (Finnish)
Currently translated at 99.7% (8006 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/fi/
2023-12-08 18:38:55 +01:00
Mark Hämmerling 2766e90fe0 Translated using Weblate (German)
Currently translated at 100.0% (8023 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/de/
2023-12-08 18:38:55 +01:00
Ahmed Elswah 10d5baa862 Translated using Weblate (Arabic)
Currently translated at 1.3% (106 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ar/
2023-12-08 18:38:55 +01:00
Henrik Kauhanen 28a8997603 Translated using Weblate (Swedish)
Currently translated at 99.9% (8015 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-12-08 18:38:55 +01:00
Bas Wijnen 83d4771e6b Translated using Weblate (Dutch)
Currently translated at 83.9% (6736 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/nl/
2023-12-08 18:38:55 +01:00
lê văn lập 0f4cd449b9 Translated using Weblate (Vietnamese)
Currently translated at 15.9% (1283 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/vi/
2023-12-08 18:38:55 +01:00
Henrik Kauhanen 27843728d7 Translated using Weblate (Swedish)
Currently translated at 99.8% (8012 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-12-08 18:38:55 +01:00
김랑기 676ad491fe Translated using Weblate (Korean)
Currently translated at 99.6% (7996 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ko/
2023-12-08 18:38:54 +01:00
Mark Hämmerling 9a91537968 Translated using Weblate (German)
Currently translated at 100.0% (8023 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/de/
2023-12-08 18:38:54 +01:00
Phạm Minh Tấn 3eba0d9bab Translated using Weblate (Vietnamese)
Currently translated at 15.1% (1216 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/vi/
2023-12-08 18:38:54 +01:00
aris-kimi b4995aa711 Translated using Weblate (Greek)
Currently translated at 99.4% (7981 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/el/
2023-12-08 18:38:54 +01:00
dsa-t 55353536e5 Translated using Weblate (Russian)
Currently translated at 100.0% (8023 of 8023 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ru/
2023-12-08 18:38:54 +01:00
jean-pierre charras e3d45fb37b Fix compil issue (change PCB_REFERENCE_IMAGE_T to old name PCB_BITMAP_T) 2023-12-07 17:50:45 +01:00
Jeff Young e3369608fd Add missing case to Selectable().
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16283

(cherry picked from commit aa046345eb)
2023-12-07 14:04:43 +00:00
Alex Shvartzkop 1c6390f829 Don't crash when OCC fails to read a model and didn't open the doc.
(cherry picked from commit 9345b73af5)
2023-12-06 03:18:26 +03:00
Seth Hillbrand df64a6c583 Handle FP polygons in DRC check
Iterator points are relative to the footprint

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16266
2023-12-05 16:07:57 -08:00
Alex Shvartzkop 59c638c64c Fix drawing sheet border random thickness glitch.
(cherry picked from commit 26c8c718eb)
2023-12-05 19:43:31 +03:00
Alex Shvartzkop 9850541433 Gerber plotter: work around CAM350 circle bug.
Some fabs still have issues with circles in 4.6 mm format.

master commit: 9c2c291255
2023-12-05 19:43:31 +03:00
Alex Shvartzkop 5140fd7819 "kicad-cli pcb export drill": hook up --gerber-precision. 2023-12-04 21:59:26 +03:00
jean-pierre charras 5ae1b271e7 Fix crash: Under some circumstances the command "Export symbols to (new) library"
produces a crash when the library links are updated, and a power symbol is not found
in any loaded library.
Add also an option to export all symbols or all not pwer symbols
From master branch
Fixes #16229
https://gitlab.com/kicad/code/kicad/-/issues/
2023-12-04 18:28:06 +01:00
Jon Evans c5cdff6213 Fix crash launching editors with additional command line arguments 2023-12-04 12:22:26 -05:00
jean-pierre charras e05b3955a5 Gerber export: fix incorrect shape of round rect pads on paste layers in some cases.
They can be plotted as rect shape depending on margin value.
From master branch.
Fixes #16257
https://gitlab.com/kicad/code/kicad/-/issues/16257
2023-12-04 13:06:25 +01:00
Wayne Stambaugh e1c0bddff3 Make paste special dialog a bit more user friendly.
Set a default control so that the escape key closes the dialog.

Select the OK button after the user selects an annotation option.  This
allows for keyboard navigation of the dialog and saves an extra mouse
move and click to when choosing an annotation setting.

(cherry picked from commit ef2f72697b)
2023-12-03 13:45:51 -05:00
Wayne Stambaugh 62297e63a2 Fix crash when saving pasted root sheet symbols.
The paste code creates invalid KIID_PATH objects with a zero length.  All
paths must include the root KIID at a minimum.  Code was added to prune
the invalid paths and some defensive code was adding to the formatter to
prevent the crash in case there are other paths where someone generates
a zero length path.

Pruning orphaned instance data does not work when loading schematics prior
to version 7 because the paths did not include the root sheet UUID.  Once
the file is saved to V7 or later, the next load will prune any orphaned or
invalid instance data for the current project.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16245

(cherry picked from commit 764df1d107)
2023-12-03 13:27:34 -05:00
Ian McInerney 54c325a631 Fix broken cherry-pick in 4cb9edd9f0 2023-12-03 18:04:40 +00:00
Jeff Young af99c9da34 Don't use epsilon when calculating pushout force in dp placer.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16210

(cherry picked from commit ff9d834e31)
2023-12-03 17:24:45 +00:00
Jeff Young dbf5455656 Update message panel after switching layers.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16247

(cherry picked from commit a1b514bcba)
2023-12-03 17:10:30 +00:00
Ian McInerney 4cb9edd9f0 Warn when installing PCM local package that is incompatible
Fixes https://gitlab.com/kicad/code/kicad/-/issues/14243

(Cherry-picked from b2cc4b8310)
2023-12-03 11:58:40 +00:00
Ian McInerney 60d23b14e7 Plot footprint edgecuts in PDF drill map file
Fixes https://gitlab.com/kicad/code/kicad/-/issues/15247

(Cherry-picked from e5f688e865)
2023-12-03 11:55:11 +00:00
Seth Hillbrand 12fdeac31c Re-implementation of 8b3ac316
Update GenCAD export to handle arbitrary outline

Fixes https://gitlab.com/kicad/code/kicad/-/issues/15961
2023-12-02 17:15:39 -08:00
Jeff Young 69a1a4611b Fill empty zones when auto-fill is on.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16234

(cherry picked from commit 1618beba2c)
2023-12-02 20:17:41 +00:00
Jeff Young a46501b279 Attempt to fix build. 2023-12-02 19:19:02 +00:00
Jeff Young bc1953dded Collapse drawing tools to a single re-entrancy guard.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16112

(cherry picked from commit c518041f9b)
2023-12-02 16:23:46 +00:00
Jeff Young 789a695737 Remove children from view_group when de-selecting.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16139

(cherry picked from commit 4a25ef164d)
2023-12-02 16:21:50 +00:00
Jeff Young 5f8a0b0728 Import a few more rules from Altium board files.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/15585

(cherry picked from commit 6a2aeeeae2)
2023-12-02 16:20:34 +00:00
Wayne Stambaugh 9fdda223f5 Fix broken symbol reference designators on paste special.
It appears that in our zeal to prevent file changes when saving shared
schematics, we (I) clobbered saving relative symbol instance data paths
to the clipboard.  This has be restored along with setting the correct
symbol unit for relative clipboard paths.

Fixed a serious issue with KIID_PATH::MakeRelativeTo() where the original
path was not restored when the incremental KIID object test fails.  This
also included a minor optimization using the actual KIID object for
comparison instead of converting it to a string and then comparing the
string.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/15981

(cherry picked from commit 6dc25f4775)
2023-12-01 15:30:51 -05:00
Seth Hillbrand 1ff4b2b4eb Upgrade Clipper2 to 1.3.0
Fixes a number of minor inflation issues including slivers when
overlapping points are inflated

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16182

(cherry picked from commit daf178b64f)

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16241
2023-12-01 12:10:28 -08:00
Jon Evans 0751a3ae7f Prevent some issues with recursion on repeat-last-item
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16168

(cherry picked from commit 90a61b8d36)
2023-12-01 13:02:50 -05:00
Marek Roszko e6e08c111b Set PYTHONPATH internally for macOS run from build dir 2023-12-01 12:32:59 -05:00
Marek Roszko 004b96ec21 Make wxPython work under run from build directory on macOS 2023-12-01 12:32:52 -05:00
Seth Hillbrand 7cb98f6856 Check for actual dirty flag
Looking at the address will always return true
2023-12-01 09:31:48 -08:00
Seth Hillbrand fc86de34f8 Add default parameter to GetEffectivePolygon()
Allows legacy plugins to use this function

(cherry picked from commit 6b3ac54a41)
2023-12-01 09:28:13 -08:00
Jon Evans fe69da4cb8 Handle non-IOE exceptions in symbol loader
(cherry picked from commit 35edd84269)
2023-11-30 22:26:14 +00:00
Jon Evans 27434e38f9 Database: handle more possible datatype exceptions
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16090


(cherry picked from commit 44374c661f)
2023-11-30 22:26:02 +00:00
Jon Evans 60ddafa4ff Guard against UNDEFINED_LAYER in GetLayerSet
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16230


(cherry picked from commit 1ff3b5a437)
2023-11-30 22:09:11 +00:00
Seth Hillbrand ef8b6bf9e1 Fix invalid string compare in IBIS parser
strcmp returns 0 if strings are the same but compareIbisWord returns
True (1).

Adds an IBIS simulation QA test case to catch this in the future

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16223
2023-11-30 09:15:01 -08:00
Wayne Stambaugh 59cc7b2d3e Fix unconnected schematic net highlighting issue.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16218

(cherry picked from commit 23175c163f)
2023-11-30 11:41:56 -05:00
Alex Shvartzkop 6245bbff50 IBIS: add stub for Model Spec; support empty strings in line with keywords.
(cherry picked from commit 08e6e0258f)
2023-11-29 22:24:45 +03:00
jean-pierre charras 6331a0ab7a Pcbnew, Excellon export: remove an useless line at end of file
From master branch
2023-11-27 17:30:35 +01:00
jean-pierre charras c43ae314e0 Fix old python examples and a compatibility issue in pcb_shape.i.
Fix simlar to master branch
Fixes #16158
https://gitlab.com/kicad/code/kicad/-/issues/16158
2023-11-26 13:46:33 +01:00
Wayne Stambaugh 250720ca4a Fix broken schematic net highlighting.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16131

(cherry picked from commit 70dad45996)
2023-11-23 18:04:50 -05:00
Alex Shvartzkop a5ac1fc34f 3D OCE plugin: make two-sided faces for non-solid shapes (shells).
Fixes single-face shells display in the 3D viewer.

(cherry picked from commit e9c5b4755b)
2023-11-22 18:57:11 +03:00
jean-pierre charras 1740aeca5e "Kicad PROJECT_ARCHIVER: do not store twice files with extension .gm?"
Better fix than commit 8255e091f0.
It also fixes duplicates for ext like *.g1
From master branch.
2023-11-21 15:51:19 +01:00
Alex Shvartzkop 4f060d9384 STEP export: make use of footprint names instead of "SOLID".
Should help when importing into software that does deduplication
based on label names (e.g. SolidWorks).

(cherry picked from commit 58b9d68084)
2023-11-21 14:12:09 +03:00
Alex Shvartzkop acd244f873 STEP export: Do not set BRepBuilderAPI precision.
This caused issues when loading some STEP models.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/15485

(cherry picked from commit f3fdfa73e6)
2023-11-21 09:20:37 +03:00
jean-pierre charras dfef20658c 3D viewer: fix incorrect display of PCB_TEXTBOX in some cases
From master branch.
2023-11-19 20:37:34 +01:00
jean-pierre charras 8255e091f0 Kicad PROJECT_ARCHIVER: do not store twice files with extension .gm?
Files with extension .g?? and .gm? were stored in zip archive. but
*.gm? files also matches .g?? files so they were stored twice.
2023-11-19 19:58:20 +01:00
jean-pierre charras 96037591c5 fix FOOTPRINT::GetLikelyAttribute() to follow the comments of FOOTPRINT::CheckFootprintAttributes(): at least one through hole pad means most probably a footprint through hole attribute. 2023-11-19 19:57:32 +01:00
jean-pierre charras 692949fd0a Gerbview: fix some issues related to comments and primitives in macros:
- comments on more than one line were not fully skipped, creating read errors
- in macros, some primitives (not all) were incorrectly rotated: they must be
rotated around the aperture macro origin, not the primitive origin.
- a new test file with rotated primitives in macros is added.
From master branch
Fixes #16049
https://gitlab.com/kicad/code/kicad/-/issues/16049
2023-11-19 19:57:32 +01:00
Wayne Stambaugh 4bf75de6fd Don't copy hidden files and folders when creating project from template.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16093

(cherry picked from commit a309e24132)
2023-11-19 11:05:53 -05:00
Wayne Stambaugh 05890480e2 Fix crash when creating an array of footprint fields in board editor.
Attempting to create an array of footprint child objects other than a pad
causes the crash due to the fact that only pads where checked.  The change
now checks if any object has a footprint as a parent.  This should prevent
any future issues when new footprint child objects are added.

There was also another subtle bug fixed when more than one child object of
a footprint were selected, the array feature would make as many copies of
the footprint as selected child items.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16088

(cherry picked from commit 9e1caa0d39)
2023-11-18 11:37:38 -05:00
Wayne Stambaugh 70d7bc2099 Add missing merge conflict fixes from cherry picking 402c139957. 2023-11-18 11:29:13 -05:00
Alex Shvartzkop e2d8d53a10 Fix bad outline font glyphs when ligatures apply.
(cherry picked from commit b108e7058b)
2023-11-18 08:19:48 +03:00
Wayne Stambaugh 402c139957 Change the bus selection behavior of the schematic net highlight tool.
[CHANGED] Bus highlight tool now supports toggling between highlighting
          only the bus objects and highlighting the bus and all of the
          bus member objects.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/15388

(cherry picked from commit f6c99816b2)
2023-11-17 07:56:38 -05:00
Alex Shvartzkop 31e79ef54f PDF plot: match mirror state between hidden and plotted text.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16066
2023-11-12 00:48:18 +03:00
Mark Roszko 39788e7e6c Bump kicad-vcpkg repo for wx 3.2.4 2023-11-10 03:45:21 +00:00
jean-pierre charras 932c908075 3D viewer: Simplify polygons before triangulation.
It reduce the risk to create bad triangulation.
Fixes #15706
https://gitlab.com/kicad/code/kicad/-/issues/15706

(cherry picked from commit b1ed0529d7)
2023-11-10 00:30:31 +03:00
Alex Shvartzkop 443da9943a SVG plotter: fix hidden text orientation when plot is mirrored.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/15422

(cherry picked from commit 556120554e)
2023-11-10 00:27:39 +03:00
Alex Shvartzkop cc1071fe7a Fix a crash in 3D viewer when changing preferences.
It was possible for OnMouseMove to come after ReloadRequest
but before DoRePaint.

Which meant m_3d_render_raytracing->Reload() has't been called yet,
thus the BVH contained invalid data.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16059

(cherry picked from commit 5cd1a4674f)
2023-11-10 00:25:40 +03:00
Alex Shvartzkop 3ac4fd59c5 Use v6 code to read arcs from legacy symbol libraries.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16048

(cherry picked from commit c048635484)
2023-11-07 23:20:56 +03:00
Alex Shvartzkop 5e93814283 Restore clearance cache usage in PNS::NODE::NearestObstacle.
This (and the other commit) restores router performance to pre-7.0.3 levels.
2023-11-07 23:15:23 +03:00
Seneral d29c07a663 Added a temporary item cache to improve router performance
Some items only used within algorithms were never cached
Because they are hard to manually clean up
But caching them does help the algorithms a lot
So this solution is the best I can think of
2023-11-07 23:15:23 +03:00
Simon Richter a558a67fbd Make output conditional 2023-11-07 13:31:54 +00:00
Mark Roszko 153e1190ea Fix build due to previous cli change 2023-11-07 11:20:18 +00:00
Marek Roszko a80a641427 Ensure output directory exists for drill files cli export
(cherry picked from commit 23676eb988)
2023-11-07 02:12:12 +00:00
Jeff Young acd7d5ad2f Don't clamp arc centers quite so aggressively.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16029

(cherry picked from commit 24ca7add42)
2023-11-06 17:00:37 +00:00
Jeff Young 81ba4fa9a6 Make sure to add enough wiggle room when MaxError is very large.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16024

(cherry picked from commit 1df5d9c48c)
2023-11-06 17:00:37 +00:00
Jeff Young 57f007c46e Don't get stuck cycling through invisible layers.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16019

(cherry picked from commit ac172b944a)
2023-11-06 17:00:37 +00:00
Jeff Young d513640572 Behave (or assert) when source or target are null or dirty.
(cherry picked from commit 7f8e397dfb)
2023-11-06 17:00:37 +00:00
Jeff Young 8c695e5044 Clean up references in RN_NETs when garbage collecting CN_ITEMs.
(cherry picked from commit fb59f83683)
2023-11-06 17:00:37 +00:00
Jeff Young 395a966802 When garbage collecting locally we also need to clear global references.
(cherry picked from commit d93bb464bf)
2023-11-06 17:00:37 +00:00
Jeff Young 643894c882 Assign textBox to correct unit & conversion.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/15994

(cherry picked from commit 972308b24b)
2023-11-06 17:00:37 +00:00
Jeff Young c7c28c0471 When presented with empty text we don't want to Normalize() the SIM_VALUE.
But we *do* need to update NUMERICAL_EVALUATOR::m_originalText by
calling NUMERICAL_EVALUATOR::Process().

Fixes https://gitlab.com/kicad/code/kicad/-/issues/15871

(cherry picked from commit 6b29c346b9)
2023-11-06 17:00:37 +00:00
Mark Roszko 20ada81d43 Add the BTI C hint to libcontext arm64
(cherry picked from commit 2b3ad808ea)
2023-11-06 11:30:52 +00:00
jean-pierre charras 07736e59bd Eeschema, plot schematic: fix incorrect rotation of symbol text in textboxes.
Happened with rotated symbols.
From master branch
Fixes #16027
https://gitlab.com/kicad/code/kicad/-/issues/16027
2023-11-05 16:31:38 +01:00
jean-pierre charras 3195ba646f Pcbnew: fix Swap command that improperly rotates footprints when flipping.
Fixes #16025
https://gitlab.com/kicad/code/kicad/-/issues/16025
2023-11-05 16:31:37 +01:00
jean-pierre charras 2deee01592 Eeschema, print schematic: resolve text variables in symbol graphic text.
Variables in graphic text (body item) were resolved in plot, but not in print function.
Fixes #16026
https://gitlab.com/kicad/code/kicad/-/issues/16026
2023-11-05 16:31:37 +01:00
jean-pierre charras 890b09499e legacy library import: fix compatibility with some old symbol libraries (*.lib files). 2023-11-05 16:31:36 +01:00
Jon Evans 01c5fab84b Enforce symbol name not being empty
Fixes https://gitlab.com/kicad/code/kicad/-/issues/15859


(cherry picked from commit e14e7e0bd9)
2023-11-05 15:10:44 +00:00
Jon Evans e9b7737692 Escape net names coming from aliases
Fixes https://gitlab.com/kicad/code/kicad/-/issues/15212


(cherry picked from commit 24e613f60c)
2023-11-05 15:10:17 +00:00
Wayne Stambaugh fe1072a06b Begin version 7.0.10 development. 2023-11-05 08:23:09 -05:00
164 changed files with 27030 additions and 23744 deletions
+4
View File
@@ -49,6 +49,7 @@
#include <dialogs/dialog_color_picker.h>
class COLOR_SETTINGS;
class PCB_TEXTBOX;
/// A type that stores a container of 2d objects for each layer id
typedef std::map<PCB_LAYER_ID, BVH_CONTAINER_2D*> MAP_CONTAINER_2D_BASE;
@@ -356,6 +357,9 @@ private:
void addShape( const PCB_DIMENSION_BASE* aDimension, CONTAINER_2D_BASE* aDstContainer,
const BOARD_ITEM* aOwner );
void addShape( const PCB_TEXTBOX* aTextBox, CONTAINER_2D_BASE* aContainer,
const BOARD_ITEM* aOwner );
void addSolidAreasShapes( const ZONE* aZone, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId );
@@ -44,6 +44,7 @@
#include <pcb_painter.h> // for PCB_RENDER_SETTINGS
#include <zone.h>
#include <fp_text.h>
#include <pcb_textbox.h>
#include <convert_basic_shapes_to_polygon.h>
#include <trigo.h>
#include <geometry/shape_segment.h>
@@ -720,6 +721,11 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
aShape->TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0, ARC_HIGH_DEF,
ERROR_INSIDE );
// Some polygons can be a bit complex (especially when coming from a
// picture ot a text converted to a polygon
// So call Simplify before calling ConvertPolygonToTriangles, just in case.
polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
if( polyList.IsEmpty() ) // Just for caution
break;
@@ -767,6 +773,32 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
}
void BOARD_ADAPTER::addShape( const PCB_TEXTBOX* aTextBox, CONTAINER_2D_BASE* aContainer,
const BOARD_ITEM* aOwner )
{
addText( aTextBox, aContainer, aOwner );
if( !aTextBox->IsBorderEnabled() )
return;
// We cannot use PCB_TEXTBOX::TransformShapeToPolygon because it convert the textbox
// as filled polygon even if there's no background colour.
// So for polygon, we use PCB_SHAPE::TransformShapeToPolygon
if( aTextBox->GetShape() == SHAPE_T::RECT )
addShape( static_cast<const PCB_SHAPE*>( aTextBox ), aContainer, aOwner );
else
{
SHAPE_POLY_SET polyList;
aTextBox->PCB_SHAPE::TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
ConvertPolygonToTriangles( polyList, *aContainer, m_biuTo3Dunits, *aOwner );
}
}
void BOARD_ADAPTER::addSolidAreasShapes( const ZONE* aZone, CONTAINER_2D_BASE* aContainer,
PCB_LAYER_ID aLayerId )
{
+1 -4
View File
@@ -604,9 +604,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
break;
case PCB_TEXTBOX_T:
addText( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
if( static_cast<PCB_TEXTBOX*>( item )->IsBorderEnabled() )
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
break;
case PCB_DIM_ALIGNED_T:
@@ -924,7 +922,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
break;
case PCB_TEXTBOX_T:
addText( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
break;
+3
View File
@@ -637,6 +637,9 @@ void EDA_3D_CANVAS::OnMagnify( wxMouseEvent& event )
void EDA_3D_CANVAS::OnMouseMove( wxMouseEvent& event )
{
if( m_3d_render && m_3d_render->IsReloadRequestPending() )
return; // Prevents using invalid m_3d_render_raytracing data
if( m_camera_is_moving )
return;
+1 -1
View File
@@ -37,7 +37,7 @@
# KiCad.
#
# Note: This version string should follow the semantic versioning system
set( KICAD_SEMANTIC_VERSION "7.0.9" )
set( KICAD_SEMANTIC_VERSION "7.0.10" )
# Default the version to the semantic version.
# This is overridden by the git repository tag though (if using git)
+2
View File
@@ -83,6 +83,8 @@
/// Allows scripts install directory to be referenced by the program code.
#define PYTHON_DEST "@PYTHON_DEST@"
#define PYTHON_SITE_PACKAGE_PATH "@PYTHON_SITE_PACKAGE_PATH@"
/// Allows scripts install directory to be referenced by the program code.
#define KICAD_DATA "@KICAD_DATA@"
+85 -27
View File
@@ -444,7 +444,16 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
case SQL_DECIMAL:
case SQL_NUMERIC:
{
aResult[column] = fmt::format( "{:G}", results.get<double>( i ) );
try
{
aResult[column] = fmt::format( "{:G}", results.get<double>( i ) );
}
catch( nanodbc::null_access_error& e )
{
// Column was empty (null)
aResult[column] = std::string();
}
break;
}
@@ -540,43 +549,92 @@ bool DATABASE_CONNECTION::SelectAll( const std::string& aTable, const std::strin
timer.Stop();
try
{
while( results.next() )
{
ROW result;
for( short j = 0; j < results.columns(); ++j )
auto handleException =
[&]( std::runtime_error& aException, const std::string& aExtraContext = "" )
{
std::string column = toUTF8( results.column_name( j ) );
m_lastError = aException.what();
std::string extra = aExtraContext.empty() ? "" : ": " + aExtraContext;
wxLogTrace( traceDatabase,
wxT( "Exception while parsing result %d from SelectAll: %s%s" ),
aResults.size(), m_lastError, extra );
};
switch( results.column_datatype( j ) )
{
case SQL_DOUBLE:
case SQL_FLOAT:
case SQL_REAL:
case SQL_DECIMAL:
case SQL_NUMERIC:
while( results.next() )
{
short columnCount = 0;
ROW result;
try
{
columnCount = results.columns();
}
catch( nanodbc::database_error& e )
{
handleException( e );
return false;
}
for( short j = 0; j < columnCount; ++j )
{
std::string column;
std::string columnExtraDbgInfo;
int datatype = SQL_UNKNOWN_TYPE;
try
{
column = toUTF8( results.column_name( j ) );
datatype = results.column_datatype( j );
columnExtraDbgInfo = fmt::format( "column index {}, name '{}', type {}", j, column,
datatype );
}
catch( nanodbc::index_range_error& e )
{
handleException( e, columnExtraDbgInfo );
return false;
}
switch( datatype )
{
case SQL_DOUBLE:
case SQL_FLOAT:
case SQL_REAL:
case SQL_DECIMAL:
case SQL_NUMERIC:
{
try
{
result[column] = fmt::format( "{:G}", results.get<double>( j ) );
break;
}
catch( nanodbc::null_access_error& e )
{
// Column was empty (null)
result[column] = std::string();
}
catch( std::runtime_error& e )
{
handleException( e, columnExtraDbgInfo );
return false;
}
break;
}
default:
default:
{
try
{
result[column] = toUTF8( results.get<nanodbc::string>( j,
NANODBC_TEXT( "" ) ) );
}
catch( std::runtime_error& e )
{
handleException( e, columnExtraDbgInfo );
return false;
}
}
}
aResults.emplace_back( std::move( result ) );
}
}
catch( nanodbc::database_error& e )
{
m_lastError = e.what();
wxLogTrace( traceDatabase, wxT( "Exception while parsing results from SelectAll: %s" ),
m_lastError );
return false;
aResults.emplace_back( std::move( result ) );
}
wxLogTrace( traceDatabase, wxT( "SelectAll from %s completed in %0.1f ms" ), aTable,
+8
View File
@@ -288,6 +288,14 @@ bool DIALOG_SHIM::Show( bool show )
std::max( wxDialog::GetSize().y, savedDialogRect.GetSize().y ),
0 );
}
#ifdef __WXMAC__
if( m_parent != nullptr )
{
if( wxDisplay::GetFromPoint( m_parent->GetPosition() )
!= wxDisplay::GetFromPoint( savedDialogRect.GetPosition() ) )
Centre();
}
#endif
}
else if( m_initialSize != wxDefaultSize )
SetSize( m_initialSize );
+10 -2
View File
@@ -29,7 +29,7 @@ static PASTE_MODE g_paste_mode = PASTE_MODE::UNIQUE_ANNOTATIONS;
DIALOG_PASTE_SPECIAL::DIALOG_PASTE_SPECIAL( wxWindow* aParent,
PASTE_MODE* aMode,
wxString aReplacement ) :
const wxString& aReplacement ) :
DIALOG_PASTE_SPECIAL_BASE( aParent ),
m_mode( aMode )
{
@@ -45,7 +45,7 @@ DIALOG_PASTE_SPECIAL::DIALOG_PASTE_SPECIAL( wxWindow* aParent,
"with '%s'." ),
aReplacement ) );
m_sdbSizerOK->SetFocus();
m_pasteOptions->SetFocus();
// Now all widgets have the size fixed, call FinishDialogSettings
finishDialogSettings();
@@ -64,3 +64,11 @@ bool DIALOG_PASTE_SPECIAL::TransferDataFromWindow()
g_paste_mode = *m_mode = static_cast<PASTE_MODE>( m_pasteOptions->GetSelection() );
return true;
}
void DIALOG_PASTE_SPECIAL::onRadioBoxEvent( wxCommandEvent& event )
{
event.Skip();
m_sdbSizerOK->SetFocus();
}
+3 -3
View File
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@@ -45,12 +45,12 @@ DIALOG_PASTE_SPECIAL_BASE::DIALOG_PASTE_SPECIAL_BASE( wxWindow* parent, wxWindow
this->Centre( wxBOTH );
// Connect Events
m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::onOKButton ), NULL, this );
m_pasteOptions->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::onRadioBoxEvent ), NULL, this );
}
DIALOG_PASTE_SPECIAL_BASE::~DIALOG_PASTE_SPECIAL_BASE()
{
// Disconnect Events
m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::onOKButton ), NULL, this );
m_pasteOptions->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::onRadioBoxEvent ), NULL, this );
}
+159 -157
View File
@@ -1,163 +1,165 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="16" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">dialog_paste_special_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">dialog_paste_special</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property>
<object class="Dialog" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="center">wxBOTH</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="extra_style"></property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size">-1,-1</property>
<property name="name">DIALOG_PASTE_SPECIAL_BASE</property>
<property name="pos"></property>
<property name="size">-1,-1</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">Paste Special</property>
<property name="tooltip"></property>
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<object class="wxBoxSizer" expanded="1">
<FileVersion major="1" minor="17"/>
<object class="Project" expanded="true">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">dialog_paste_special_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">dialog_paste_special</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property>
<object class="Dialog" expanded="true">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="center">wxBOTH</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="extra_style"></property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size">-1,-1</property>
<property name="name">DIALOG_PASTE_SPECIAL_BASE</property>
<property name="pos"></property>
<property name="size">-1,-1</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">Paste Special</property>
<property name="tooltip"></property>
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">m_mainSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">10</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">optionsSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxRadioBox" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="choices">&quot;Assign unique reference designators to pasted symbols&quot; &quot;Keep existing reference designators, even if they are duplicated&quot; &quot;Clear reference designators on all pasted symbols&quot;</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Paste Options</property>
<property name="majorDimension">1</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="name">m_mainSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">optionsSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxRadioBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="choices">&quot;Assign unique reference designators to pasted symbols&quot; &quot;Keep existing reference designators, even if they are duplicated&quot; &quot;Clear reference designators on all pasted symbols&quot;</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Paste Options</property>
<property name="majorDimension">1</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_pasteOptions</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="selection">1</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxRA_SPECIFY_COLS</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">6</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxStdDialogButtonSizer" expanded="1">
<property name="Apply">0</property>
<property name="Cancel">1</property>
<property name="ContextHelp">0</property>
<property name="Help">0</property>
<property name="No">0</property>
<property name="OK">1</property>
<property name="Save">0</property>
<property name="Yes">0</property>
<property name="minimum_size"></property>
<property name="name">m_sdbSizer</property>
<property name="permission">protected</property>
<event name="OnOKButtonClick">onOKButton</event>
</object>
</object>
<property name="moveable">1</property>
<property name="name">m_pasteOptions</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="selection">1</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxRA_SPECIFY_COLS</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnRadioBox">onRadioBoxEvent</event>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">6</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxStdDialogButtonSizer" expanded="true">
<property name="Apply">0</property>
<property name="Cancel">1</property>
<property name="ContextHelp">0</property>
<property name="Help">0</property>
<property name="No">0</property>
<property name="OK">1</property>
<property name="Save">0</property>
<property name="Yes">0</property>
<property name="minimum_size"></property>
<property name="name">m_sdbSizer</property>
<property name="permission">protected</property>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>
+2 -2
View File
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@@ -38,7 +38,7 @@ class DIALOG_PASTE_SPECIAL_BASE : public DIALOG_SHIM
wxButton* m_sdbSizerCancel;
// Virtual event handlers, override them in your derived class
virtual void onOKButton( wxCommandEvent& event ) { event.Skip(); }
virtual void onRadioBoxEvent( wxCommandEvent& event ) { event.Skip(); }
public:
+1
View File
@@ -356,5 +356,6 @@ void KIGFX::DS_PAINTER::DrawBorder( const PAGE_INFO* aPageInfo, int aScaleFactor
// Use a gray color for the border color
m_gal->SetStrokeColor( m_renderSettings.m_pageBorderColor );
m_gal->SetIsFill( false );
m_gal->SetLineWidth( m_renderSettings.GetDefaultPenWidth() );
m_gal->DrawRectangle( origin, end );
}
+4 -4
View File
@@ -349,14 +349,14 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
hb_buffer_guess_segment_properties( buf ); // guess direction, script, and language based on
// contents
unsigned int glyphCount;
hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos( buf, &glyphCount );
hb_glyph_position_t* glyphPos = hb_buffer_get_glyph_positions( buf, &glyphCount );
hb_font_t* referencedFont = hb_ft_font_create_referenced( face );
hb_ft_font_set_funcs( referencedFont );
hb_shape( referencedFont, buf, nullptr, 0 );
unsigned int glyphCount;
hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos( buf, &glyphCount );
hb_glyph_position_t* glyphPos = hb_buffer_get_glyph_positions( buf, &glyphCount );
VECTOR2D scaleFactor( glyphSize.x / faceSize(), -glyphSize.y / faceSize() );
scaleFactor = scaleFactor * m_outlineFontSizeCompensation;
+6 -6
View File
@@ -191,22 +191,22 @@ int ExecuteFile( const wxString& aEditorName, const wxString& aFileName, wxProce
if( wxFileExists( fullEditorName ) )
{
int i = 0;
const wchar_t* args[4];
std::vector<const wchar_t*> args;
args[i++] = fullEditorName.wc_str();
args.emplace_back( fullEditorName.wc_str() );
if( !params.empty() )
{
for( const wxString& p : params )
args[i++] = p.wc_str();
args.emplace_back( p.wc_str() );
}
if( !aFileName.IsEmpty() )
args[i++] = aFileName.wc_str();
args.emplace_back( aFileName.wc_str() );
args[i] = nullptr;
args.emplace_back( nullptr );
return wxExecute( const_cast<wchar_t**>( args ), wxEXEC_ASYNC, aCallback );
return wxExecute( const_cast<wchar_t**>( args.data() ), wxEXEC_ASYNC, aCallback );
}
wxString msg;
+5 -2
View File
@@ -3,7 +3,7 @@
*
* Copyright (C) 2020 Ian McInerney <ian.s.mcinerney@ieee.org>
* Copyright (C) 2007-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.TXT for contributors.
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -324,8 +324,11 @@ bool KIID_PATH::MakeRelativeTo( const KIID_PATH& aPath )
for( size_t i = 0; i < aPath.size(); ++i )
{
if( copy.at( i ).AsString() != aPath.at( i ).AsString() )
if( copy.at( i ) != aPath.at( i ) )
{
*this = copy;
return false; // this path is not contained within aPath
}
}
for( size_t i = aPath.size(); i < copy.size(); ++i )
+2
View File
@@ -322,6 +322,8 @@ LIB_TREE_NODE_LIB_ID& LIB_TREE_NODE_LIB::AddItem( LIB_TREE_ITEM* aItem )
void LIB_TREE_NODE_LIB::UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wxString& aLib )
{
m_Score = 0;
// We need to score leaf nodes, which are usually (but not always) children.
if( m_Children.size() )
+2 -1
View File
@@ -821,7 +821,8 @@ void GERBER_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill,
void GERBER_PLOTTER::Circle( const VECTOR2I& aCenter, int aDiameter, FILL_T aFill, int aWidth )
{
Arc( aCenter, ANGLE_0, ANGLE_360, aDiameter / 2, aFill, aWidth );
Arc( aCenter, ANGLE_0, ANGLE_180, aDiameter / 2, aFill, aWidth );
Arc( aCenter, ANGLE_180, ANGLE_360, aDiameter / 2, aFill, aWidth );
}
+15 -6
View File
@@ -1409,10 +1409,11 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
double wideningFactor, heightFactor;
VECTOR2I t_size( std::abs( aSize.x ), std::abs( aSize.y ) );
bool textMirrored = aSize.x < 0;
computeTextParameters( aPos, aText, aOrient, t_size, m_plotMirror, aH_justify,
aV_justify, aWidth, aItalic, aBold, &wideningFactor, &ctm_a,
&ctm_b, &ctm_c, &ctm_d, &ctm_e, &ctm_f, &heightFactor );
computeTextParameters( aPos, aText, aOrient, t_size, textMirrored, aH_justify, aV_justify,
aWidth, aItalic, aBold, &wideningFactor, &ctm_a, &ctm_b, &ctm_c, &ctm_d,
&ctm_e, &ctm_f, &heightFactor );
SetColor( aColor );
SetCurrentLineWidth( aWidth, aData );
@@ -1424,6 +1425,10 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
aFont = KIFONT::FONT::GetFont();
VECTOR2I full_box( aFont->StringBoundaryLimits( aText, t_size, aWidth, aBold, aItalic ) );
if( textMirrored )
full_box.x *= -1;
VECTOR2I box_x( full_box.x, 0 );
VECTOR2I box_y( 0, full_box.y );
@@ -1444,13 +1449,17 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
{
wxString word = str_tok.GetNextToken();
computeTextParameters( pos, word, aOrient, t_size, m_plotMirror, GR_TEXT_H_ALIGN_LEFT,
GR_TEXT_V_ALIGN_BOTTOM, aWidth, aItalic, aBold, &wideningFactor, &ctm_a,
&ctm_b, &ctm_c, &ctm_d, &ctm_e, &ctm_f, &heightFactor );
computeTextParameters( pos, word, aOrient, t_size, textMirrored, GR_TEXT_H_ALIGN_LEFT,
GR_TEXT_V_ALIGN_BOTTOM, aWidth, aItalic, aBold, &wideningFactor,
&ctm_a, &ctm_b, &ctm_c, &ctm_d, &ctm_e, &ctm_f, &heightFactor );
// Extract the changed width and rotate by the orientation to get the offset for the
// next word
VECTOR2I bbox( aFont->StringBoundaryLimits( word, t_size, aWidth, aBold, aItalic ).x, 0 );
if( textMirrored )
bbox.x *= -1;
RotatePoint( bbox, aOrient );
pos += bbox;
+3 -3
View File
@@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -423,7 +423,7 @@ void PSLIKE_PLOTTER::computeTextParameters( const VECTOR2I& aPos,
// This is an approximation of the text bounds (in IUs)
int tw = returnPostscriptTextWidth( aText, aSize.x, aItalic, aWidth );
int th = aSize.y;
int dx, dy;
int dx = 0, dy = 0;
switch( aH_justify )
{
@@ -450,7 +450,7 @@ void PSLIKE_PLOTTER::computeTextParameters( const VECTOR2I& aPos,
*wideningFactor = sz_dev.x / sz_dev.y;
// Mirrored texts must be plotted as mirrored!
if( m_plotMirror )
if( m_plotMirror ^ aMirror )
*wideningFactor = -*wideningFactor;
// The CTM transformation matrix
+4 -4
View File
@@ -825,16 +825,16 @@ void SVG_PLOTTER::Text( const VECTOR2I& aPos,
if( !aOrient.IsZero() )
{
fprintf( m_outputFile,
"<g transform=\"rotate(%f %.*f %.*f)\">\n",
- aOrient.AsDegrees(), m_precision, anchor_pos_dev.x, m_precision, anchor_pos_dev.y );
fprintf( m_outputFile, "<g transform=\"rotate(%f %.*f %.*f)\">\n",
m_plotMirror ? aOrient.AsDegrees() : -aOrient.AsDegrees(), m_precision,
anchor_pos_dev.x, m_precision, anchor_pos_dev.y );
}
fprintf( m_outputFile, "<text x=\"%.*f\" y=\"%.*f\"\n",
m_precision, text_pos_dev.x, m_precision, text_pos_dev.y );
/// If the text is mirrored, we should also mirror the hidden text to match
if( aSize.x < 0 )
if( m_plotMirror != ( aSize.x < 0 ) )
fprintf( m_outputFile, "transform=\"scale(-1 1) translate(%f 0)\"\n", -2 * text_pos_dev.x );
fprintf( m_outputFile,
+8
View File
@@ -177,8 +177,16 @@ bool PROJECT_ARCHIVER::Archive( const wxString& aSrcDir, const wxString& aDestFi
unsigned long uncompressedBytes = 0;
// Our filename collector can store duplicate filenames. for instance *.gm2
// matches both *.g?? and *.gm??.
// So skip duplicate filenames (they are sorted, so it is easy).
wxString lastStoredFile;
for( unsigned ii = 0; ii < files.GetCount(); ii++ )
{
if( lastStoredFile == files[ii] ) // duplicate name: already stored
continue;
wxFileSystem fsfile;
wxFileName curr_fn( files[ii] );
@@ -361,6 +361,12 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataFromWindow()
wxString newName = EscapeString( m_SymbolNameCtrl->GetValue(), CTX_LIBID );
wxString oldName = m_libEntry->GetName();
if( newName.IsEmpty() )
{
wxMessageBox( _( "Symbol must have a name." ) );
return false;
}
if( oldName != newName )
{
wxString libName = m_Parent->GetCurLib();
+2
View File
@@ -465,6 +465,8 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
screen->MigrateSimModels();
}
schematic.PruneOrphanedSymbolInstances( Prj().GetProjectName(), Schematic().GetSheets() );
Schematic().ConnectionGraph()->Reset();
SetScreen( GetCurrentSheet().LastScreen() );
+1 -1
View File
@@ -465,7 +465,7 @@ void LIB_TEXTBOX::Plot( PLOTTER* aPlotter, bool aBackground, const VECTOR2I& aOf
text.GetLinePositions( positions, (int) strings_list.Count() );
TEXT_ATTRIBUTES attrs = GetAttributes();
TEXT_ATTRIBUTES attrs = text.GetAttributes();
attrs.m_StrokeWidth = penWidth;
attrs.m_Multiline = false;
+1 -1
View File
@@ -180,7 +180,7 @@ void SCH_CONNECTION::ConfigureFromLabel( const wxString& aLabel )
auto member = std::make_shared< SCH_CONNECTION >( m_parent, m_sheet );
member->SetPrefix( prefix );
member->SetGraph( m_graph );
member->ConfigureFromLabel( alias_member );
member->ConfigureFromLabel( EscapeString( alias_member, CTX_NETNAME ) );
m_members.push_back( member );
}
}
@@ -499,8 +499,17 @@ LIB_SYMBOL* SCH_DATABASE_PLUGIN::loadSymbolFromRow( const wxString& aSymbolName,
continue;
}
wxString value( std::any_cast<std::string>( aRow.at( mapping.column ) ).c_str(),
wxConvUTF8 );
std:: string strValue;
try
{
strValue = std::any_cast<std::string>( aRow.at( mapping.column ) );
}
catch( std::bad_any_cast& e )
{
}
wxString value( strValue.c_str(), wxConvUTF8 );
if( mapping.name == wxT( "Value" ) )
{
@@ -1694,6 +1694,8 @@ LIB_TEXTBOX* SCH_SEXPR_PARSER::parseTextBox()
FILL_PARAMS fill;
std::unique_ptr<LIB_TEXTBOX> textBox = std::make_unique<LIB_TEXTBOX>( nullptr );
textBox->SetUnit( m_unit );
textBox->SetConvert( m_convert );
token = NextTok();
if( token == T_private )
+30 -41
View File
@@ -550,10 +550,6 @@ void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSelect
m_out->Print( 0, ")\n\n" );
}
// Store the selected sheets instance information
SCH_SHEET_LIST selectedSheets;
SCH_REFERENCE_LIST selectedSymbols;
for( i = 0; i < aSelection->GetSize(); ++i )
{
item = (SCH_ITEM*) aSelection->GetItem( i );
@@ -561,10 +557,8 @@ void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSelect
switch( item->Type() )
{
case SCH_SYMBOL_T:
saveSymbol( static_cast<SCH_SYMBOL*>( item ), aSchematic, 0, aForClipboard );
aSelectionPath->AppendSymbol( selectedSymbols, static_cast<SCH_SYMBOL*>( item ),
true, true );
saveSymbol( static_cast<SCH_SYMBOL*>( item ), aSchematic, 0, aForClipboard,
aSelectionPath );
break;
case SCH_BITMAP_T:
@@ -573,15 +567,6 @@ void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSelect
case SCH_SHEET_T:
saveSheet( static_cast< SCH_SHEET* >( item ), 0 );
{
SCH_SHEET_PATH subSheetPath = *aSelectionPath;
subSheetPath.push_back( static_cast<SCH_SHEET*>( item ) );
fullHierarchy.GetSheetsWithinPath( selectedSheets, subSheetPath );
fullHierarchy.GetSymbolsWithinPath( selectedSymbols, subSheetPath, true, true );
}
break;
case SCH_JUNCTION_T:
@@ -621,33 +606,12 @@ void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSelect
wxASSERT( "Unexpected schematic object type in SCH_SEXPR_PLUGIN::Format()" );
}
}
// Make all instance information relative to the selection path
KIID_PATH selectionPath = aSelectionPath->Path();
selectedSheets.SortByPageNumbers();
std::vector<SCH_SHEET_INSTANCE> sheetinstances = selectedSheets.GetSheetInstances();
for( SCH_SHEET_INSTANCE& sheetInstance : sheetinstances )
{
wxASSERT_MSG( sheetInstance.m_Path.MakeRelativeTo( selectionPath ),
"Sheet is not inside the selection path?" );
}
selectionPath = aSelectionPath->Path();
selectedSymbols.SortByReferenceOnly();
std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = selectedSymbols.GetSymbolInstances();
for( SCH_SYMBOL_INSTANCE& symbolInstance : symbolInstances )
{
wxASSERT_MSG( symbolInstance.m_Path.MakeRelativeTo( selectionPath ),
"Symbol is not inside the selection path?" );
}
}
void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSchematic,
int aNestLevel, bool aForClipboard )
int aNestLevel, bool aForClipboard,
const SCH_SHEET_PATH* aRelativePath )
{
wxCHECK_RET( aSymbol != nullptr && m_out != nullptr, "" );
@@ -717,6 +681,14 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSchema
aSymbol->GetUnit() :
aSymbol->GetInstanceReferences()[0].m_Unit;
if( aForClipboard && aRelativePath )
{
SCH_SYMBOL_INSTANCE unitInstance;
if( aSymbol->GetInstance( unitInstance, aRelativePath->Path() ) )
unit = unitInstance.m_Unit;
}
m_out->Print( 0, " (unit %d)", unit );
if( aSymbol->GetConvert() == LIB_ITEM::LIB_CONVERT::DEMORGAN )
@@ -759,6 +731,14 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSchema
field.SetText( aSymbol->GetField( FOOTPRINT_FIELD )->GetText() );
}
}
else if( aForClipboard && aSymbol->GetInstanceReferences().size() && aRelativePath
&& ( id == REFERENCE_FIELD ) )
{
SCH_SYMBOL_INSTANCE instance;
if( aSymbol->GetInstance( instance, aRelativePath->Path() ) )
field.SetText( instance.m_Reference );
}
try
{
@@ -805,6 +785,9 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSchema
for( size_t i = 0; i < aSymbol->GetInstanceReferences().size(); i++ )
{
// Zero length KIID_PATH objects are not valid and will cause a crash below.
wxCHECK2( aSymbol->GetInstanceReferences()[i].m_Path.size(), continue );
// If the instance data is part of this design but no longer has an associated sheet
// path, don't save it. This prevents large amounts of orphaned instance data for the
// current project from accumulating in the schematic files.
@@ -839,7 +822,13 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSchema
project_open = true;
}
wxString path = aSymbol->GetInstanceReferences()[i].m_Path.AsString();
wxString path;
KIID_PATH tmp = aSymbol->GetInstanceReferences()[i].m_Path;
if( aForClipboard && aRelativePath )
tmp.MakeRelativeTo( aRelativePath->Path() );
path = tmp.AsString();
m_out->Print( aNestLevel + 3, "(path %s\n",
m_out->Quotew( path ).c_str() );
@@ -146,7 +146,7 @@ private:
void loadFile( const wxString& aFileName, SCH_SHEET* aSheet );
void saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSchematic, int aNestLevel,
bool aForClipboard );
bool aForClipboard, const SCH_SHEET_PATH* aRelativePath = nullptr );
void saveField( SCH_FIELD* aField, int aNestLevel );
void saveBitmap( SCH_BITMAP* aBitmap, int aNestLevel );
void saveSheet( SCH_SHEET* aSheet, int aNestLevel );
@@ -95,12 +95,23 @@ void SCH_LEGACY_PLUGIN_CACHE::Load()
m_versionMajor = parseInt( reader, line, &line );
if( *line != '.' )
SCH_PARSE_ERROR( "invalid file version formatting in header", reader, line );
if( *line == '/' )
{
// Some old libraries use a version syntax like
// EESchema-LIBRARY Version 2/10/2006-18:49:15
// use 2.3 version numer to read the file
m_versionMajor = 2;
m_versionMinor = 3;
}
else
{
if( *line != '.' )
SCH_PARSE_ERROR( "invalid file version formatting in header", reader, line );
line++;
line++;
m_versionMinor = parseInt( reader, line, &line );
m_versionMinor = parseInt( reader, line, &line );
}
if( m_versionMajor < 1 || m_versionMinor < 0 || m_versionMinor > 99 )
SCH_PARSE_ERROR( "invalid file version in header", reader, line );
@@ -746,6 +757,68 @@ FILL_T SCH_LEGACY_PLUGIN_CACHE::parseFillMode( LINE_READER& aReader, const char*
}
/**
* This function based on version 6.0 is required for reading legacy arcs.
* Changing it in any way will likely break arcs.
*/
static bool MapAnglesV6( int* aAngle1, int* aAngle2 )
{
auto DECIDEG2RAD = []( double deg ) -> double
{
return deg * M_PI / 1800.0;
};
int angle, delta;
double x, y;
bool swap = false;
delta = *aAngle2 - *aAngle1;
if( delta >= 1800 )
{
*aAngle1 -= 1;
*aAngle2 += 1;
}
x = cos( DECIDEG2RAD( *aAngle1 ) );
y = -sin( DECIDEG2RAD( *aAngle1 ) );
*aAngle1 = KiROUND( RAD2DECIDEG( atan2( y, x ) ) );
x = cos( DECIDEG2RAD( *aAngle2 ) );
y = -sin( DECIDEG2RAD( *aAngle2 ) );
*aAngle2 = KiROUND( RAD2DECIDEG( atan2( y, x ) ) );
NORMALIZE_ANGLE_POS( *aAngle1 );
NORMALIZE_ANGLE_POS( *aAngle2 );
if( *aAngle2 < *aAngle1 )
*aAngle2 += 3600;
if( *aAngle2 - *aAngle1 > 1800 ) // Need to swap the two angles
{
angle = ( *aAngle1 );
*aAngle1 = ( *aAngle2 );
*aAngle2 = angle;
NORMALIZE_ANGLE_POS( *aAngle1 );
NORMALIZE_ANGLE_POS( *aAngle2 );
if( *aAngle2 < *aAngle1 )
*aAngle2 += 3600;
swap = true;
}
if( delta >= 1800 )
{
*aAngle1 += 1;
*aAngle2 -= 1;
}
return swap;
}
LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbol,
LINE_READER& aReader )
{
@@ -762,10 +835,12 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbo
arc->SetPosition( center );
(void) schIUScale.MilsToIU( parseInt( aReader, line, &line ) );
int radius = schIUScale.MilsToIU( parseInt( aReader, line, &line ) );
int angle1 = parseInt( aReader, line, &line );
int angle2 = parseInt( aReader, line, &line );
EDA_ANGLE angle1( parseInt( aReader, line, &line ), TENTHS_OF_A_DEGREE_T );
EDA_ANGLE angle2( parseInt( aReader, line, &line ), TENTHS_OF_A_DEGREE_T );
NORMALIZE_ANGLE_POS( angle1 );
NORMALIZE_ANGLE_POS( angle2 );
arc->SetUnit( parseInt( aReader, line, &line ) );
arc->SetConvert( parseInt( aReader, line, &line ) );
@@ -792,38 +867,33 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbo
arc->SetStart( arcStart );
arc->SetEnd( arcEnd );
}
// Actual Coordinates of arc ends are not read from file (old library), calculate them
else
{
arc->SetArcAngleAndEnd( angle2 - angle1, true );
// Actual Coordinates of arc ends are not read from file
// (old library), calculate them
VECTOR2I arcStart( radius, 0 );
VECTOR2I arcEnd( radius, 0 );
RotatePoint( arcStart, EDA_ANGLE( -angle1, EDA_ANGLE_T::TENTHS_OF_A_DEGREE_T ) );
arcStart += arc->GetCenter();
arc->SetStart( arcStart );
RotatePoint( arcEnd, EDA_ANGLE( -angle2, EDA_ANGLE_T::TENTHS_OF_A_DEGREE_T ) );
arcEnd += arc->GetCenter();
arc->SetEnd( arcEnd );
}
/*
* Current file format stores start-mid-end and so doesn't care about winding. We
* store start-end with an implied winding internally though.
* This issue is only for 180 deg arcs, because 180 deg are a limit to handle arcs in
* legacy libs.
*
* So a workaround is to slightly change the arc angle to
* avoid 180 deg arc after correction
/**
* This accounts for an oddity in the old library format, where the symbol is overdefined.
* The previous draw (based on wxwidgets) used start point and end point and always drew
* counter-clockwise. The new GAL draw takes center, radius and start/end angles. All of
* these points were stored in the file, so we need to mimic the swapping of start/end
* points rather than using the stored angles in order to properly map edge cases.
*/
EDA_ANGLE arc_angle = arc->GetArcAngle();
if( arc_angle == ANGLE_180 )
if( !MapAnglesV6( &angle1, &angle2 ) )
{
VECTOR2I new_center = CalcArcCenter( arc->GetStart(), arc->GetEnd(),
EDA_ANGLE( 179.5, DEGREES_T ) );
arc->SetCenter( new_center );
}
// In legacy libraries, an arc angle is always <= 180.0 degrees
// So if the created arc is > 180 degrees, swap arc ends to have a < 180 deg arc.
if( arc->GetArcAngle() > ANGLE_180 )
{
VECTOR2I new_end = arc->GetStart();
VECTOR2I new_start = arc->GetEnd();
arc->SetStart( new_start );
arc->SetEnd( new_end );
VECTOR2I temp = arc->GetStart();
arc->SetStart( arc->GetEnd() );
arc->SetEnd( temp );
}
return arc;
+59 -1
View File
@@ -34,6 +34,7 @@
#include <project.h>
#include <reporter.h>
#include <sch_draw_panel.h>
#include <trace_helpers.h>
#include <sch_edit_frame.h>
#include <sch_item.h>
@@ -1029,7 +1030,8 @@ void SCH_SCREEN::UpdateSymbolLinks( REPORTER* aReporter )
}
}
symbol->SetLibSymbol( libSymbol.release() );
if( libSymbol.get() ) // Only change the old link if the new link exists
symbol->SetLibSymbol( libSymbol.release() );
}
// Changing the symbol may adjust the bbox of the symbol. This re-inserts the
@@ -1626,6 +1628,51 @@ size_t SCH_SCREEN::getLibSymbolNameMatches( const SCH_SYMBOL& aSymbol,
}
void SCH_SCREEN::PruneOrphanedSymbolInstances( const wxString& aProjectName,
const SCH_SHEET_LIST& aValidSheetPaths )
{
// The project name cannot be empty. Projects older than 7.0 did not save project names
// when saving instance data. Running this algorithm with an empty project name would
// clobber all instance data for projects other than the current one when a schematic
// file is shared across multiple projects.
wxCHECK( !aProjectName.IsEmpty(), /* void */ );
for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
wxCHECK2( symbol, continue );
std::set<KIID_PATH> pathsToPrune;
const std::vector<SCH_SYMBOL_INSTANCE> instances = symbol->GetInstanceReferences();
for( const SCH_SYMBOL_INSTANCE& instance : instances )
{
// Ignore instance paths from other projects.
if( aProjectName != instance.m_ProjectName )
continue;
std::optional<SCH_SHEET_PATH> pathFound =
aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
// Check for paths that do not exist in the current project and paths that do
// not contain the current symbol.
if( !pathFound )
pathsToPrune.emplace( instance.m_Path );
else if( pathFound.value().LastScreen() != this )
pathsToPrune.emplace( pathFound.value().Path() );
}
for( const KIID_PATH& sheetPath : pathsToPrune )
{
wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' symbol instance %s." ),
aProjectName, sheetPath.AsString() );
symbol->RemoveInstance( sheetPath );
}
}
}
#if defined(DEBUG)
void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
{
@@ -2042,3 +2089,14 @@ void SCH_SCREEN::MigrateSimModels()
SIM_MODEL::MigrateSimModel<SCH_SYMBOL, SCH_FIELD>( *symbol, &Schematic()->Prj() );
}
}
void SCH_SCREENS::PruneOrphanedSymbolInstances( const wxString& aProjectName,
const SCH_SHEET_LIST& aValidSheetPaths )
{
wxCHECK( !aProjectName.IsEmpty(), /* void */ );
for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
screen->PruneOrphanedSymbolInstances( aProjectName, aValidSheetPaths );
}
+18
View File
@@ -545,6 +545,21 @@ public:
*/
void MigrateSimModels();
/**
* Remove all invalid symbol instance data in this screen object for the project defined
* by \a aProjectName and the list of \a aValidSheetPaths.
*
* @warning This method will assert and exit on debug builds when \a aProjectName is empty.
*
* @note This method does not affect instance data for any other projects.
*
* @param aProjectName is the name of the current project.
* @param aValidSheetPaths is the list of valid #SCH_SHEET_PATH objects for the current
* project.
*/
void PruneOrphanedSymbolInstances( const wxString& aProjectName,
const SCH_SHEET_LIST& aValidSheetPaths );
private:
friend SCH_EDIT_FRAME; // Only to populate m_symbolInstances.
friend SCH_SEXPR_PARSER; // Only to load instance information from schematic file.
@@ -793,6 +808,9 @@ public:
*/
void SetLegacySymbolInstanceData();
void PruneOrphanedSymbolInstances( const wxString& aProjectName,
const SCH_SHEET_LIST& aValidSheetPaths );
private:
void addScreenToList( SCH_SCREEN* aScreen, SCH_SHEET* aSheet );
void buildScreenList( SCH_SHEET* aSheet);
+33
View File
@@ -1222,6 +1222,39 @@ bool SCH_SHEET::operator <( const SCH_ITEM& aItem ) const
}
void SCH_SHEET::RemoveInstance( const KIID_PATH& aInstancePath )
{
// Search for an existing path and remove it if found (should not occur)
for( unsigned ii = 0; ii < m_instances.size(); ii++ )
{
if( m_instances[ii].m_Path == aInstancePath )
{
wxLogTrace( traceSchSheetPaths, "Removing sheet instance:\n"
" sheet path %s\n"
" page %s, from project %s.",
aInstancePath.AsString(),
m_instances[ii].m_PageNumber,
m_instances[ii].m_ProjectName );
m_instances.erase( m_instances.begin() + ii );
ii--;
}
}
}
void SCH_SHEET::AddInstance( const SCH_SHEET_INSTANCE& aInstance )
{
SCH_SHEET_INSTANCE oldInstance;
if( getInstance( oldInstance, aInstance.m_Path ) )
RemoveInstance( aInstance.m_Path );
m_instances.emplace_back( aInstance );
}
bool SCH_SHEET::addInstance( const SCH_SHEET_PATH& aSheetPath )
{
wxCHECK( aSheetPath.IsFullPath(), false );
+4
View File
@@ -409,6 +409,10 @@ public:
*/
const SCH_SHEET_INSTANCE& GetRootInstance() const;
void RemoveInstance( const KIID_PATH& aInstancePath );
void AddInstance( const SCH_SHEET_INSTANCE& aInstance );
/**
* Compares page numbers of schematic sheets.
*
+5
View File
@@ -698,6 +698,11 @@ void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet, bool aCheckIntegrity )
}
else
{
// If we are not performing a full recursion test, at least check if we are in
// a simple recursion scenario to prevent stack overflow crashes
wxCHECK2_MSG( sheet->GetFileName() != aSheet->GetFileName(), continue,
wxT( "Recursion prevented in SCH_SHEET_LIST::BuildSheetList" ) );
BuildSheetList( sheet, false );
}
}
+21 -3
View File
@@ -547,6 +547,17 @@ void SCH_SYMBOL::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffse
tempPin->SetShape( symbolPin->GetShape() );
}
for( LIB_ITEM& item : tempSymbol.GetDrawItems() )
{
if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( &item ) )
{
// Use SCH_FIELD's text resolver
SCH_FIELD dummy( (SCH_ITEM*) this, -1 );
dummy.SetText( text->GetText() );
text->SetText( dummy.GetShownText( false ) );
}
}
tempSymbol.Print( aSettings, m_pos + aOffset, m_unit, m_convert, opts, GetDNP() );
}
else // Use dummy() part if the actual cannot be found.
@@ -600,16 +611,22 @@ bool SCH_SYMBOL::GetInstance( SCH_SYMBOL_INSTANCE& aInstance,
void SCH_SYMBOL::RemoveInstance( const SCH_SHEET_PATH& aInstancePath )
{
RemoveInstance( aInstancePath.Path() );
}
void SCH_SYMBOL::RemoveInstance( const KIID_PATH& aInstancePath )
{
// Search for an existing path and remove it if found (should not occur)
for( unsigned ii = 0; ii < m_instanceReferences.size(); ii++ )
{
if( m_instanceReferences[ii].m_Path == aInstancePath.Path() )
if( m_instanceReferences[ii].m_Path == aInstancePath )
{
wxLogTrace( traceSchSheetPaths, "Removing symbol instance:\n"
" sheet path %s\n"
" reference %s, unit %d from symbol %s.",
aInstancePath.Path().AsString(),
aInstancePath.AsString(),
m_instanceReferences[ii].m_Reference,
m_instanceReferences[ii].m_Unit,
m_Uuid.AsString() );
@@ -624,7 +641,8 @@ void SCH_SYMBOL::RemoveInstance( const SCH_SHEET_PATH& aInstancePath )
void SCH_SYMBOL::SortInstances( bool (*aSortFunction)( const SCH_SYMBOL_INSTANCE& aLhs,
const SCH_SYMBOL_INSTANCE& aRhs ) )
{
std::sort( m_instanceReferences.begin(), m_instanceReferences.end(), aSortFunction );
if( m_instanceReferences.size() > 1 )
std::sort( m_instanceReferences.begin(), m_instanceReferences.end(), aSortFunction );
}
+1
View File
@@ -146,6 +146,7 @@ public:
const KIID_PATH& aSheetPath, bool aTestFromEnd = false ) const;
void RemoveInstance( const SCH_SHEET_PATH& aInstancePath );
void RemoveInstance( const KIID_PATH& aInstancePath );
void RemoveAllInstances() { m_instanceReferences.clear(); }
+36 -19
View File
@@ -1135,8 +1135,8 @@ bool IbisParser::readString( std::string& aDest )
if( len < 1 )
{
Report( _( "Unable to read string, input is empty." ), RPT_SEVERITY_ERROR );
return false;
// The data is likely on the next line. Skip.
return true;
}
char c = aDest[len - 1];
@@ -1436,6 +1436,20 @@ bool IbisParser::readRamp()
}
bool IbisParser::readModelSpec()
{
bool status = true;
m_continue = IBIS_PARSER_CONTINUE::MODEL_SPEC;
// TODO
// readTypMinMaxValueSubparam( std::string( "Vmeas" ), m_currentModel->... )
// ...
return status;
}
bool IbisParser::parseModel( std::string& aKeyword )
{
bool status = false;
@@ -1458,6 +1472,8 @@ bool IbisParser::parseModel( std::string& aKeyword )
status = readWaveform( nullptr, IBIS_WAVEFORM_TYPE::FALLING );
else if( compareIbisWord( aKeyword.c_str(), "Ramp" ) )
status = readRamp();
else if( compareIbisWord( aKeyword.c_str(), "Model_Spec" ) )
status = readModelSpec();
else if( compareIbisWord( aKeyword.c_str(), "Pullup_Reference" ) )
status = readTypMinMaxValue( m_currentModel->m_pullupReference );
else if( compareIbisWord( aKeyword.c_str(), "Pulldown_Reference" ) )
@@ -1930,39 +1946,39 @@ bool IbisParser::readModel()
{
if( readWord( subparam ) )
{
if( !compareIbisWord( subparam.c_str(), "Input" ) )
if( compareIbisWord( subparam.c_str(), "Input" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::INPUT_STD;
else if( !compareIbisWord( subparam.c_str(), "Output" ) )
else if( compareIbisWord( subparam.c_str(), "Output" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::OUTPUT;
else if( !compareIbisWord( subparam.c_str(), "I/O" ) )
else if( compareIbisWord( subparam.c_str(), "I/O" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::IO;
else if( !compareIbisWord( subparam.c_str(), "3-state" ) )
else if( compareIbisWord( subparam.c_str(), "3-state" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::THREE_STATE;
else if( !compareIbisWord( subparam.c_str(), "Open_drain" ) )
else if( compareIbisWord( subparam.c_str(), "Open_drain" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::OPEN_DRAIN;
else if( !compareIbisWord( subparam.c_str(), "I/O_Open_drain" ) )
else if( compareIbisWord( subparam.c_str(), "I/O_Open_drain" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::IO_OPEN_DRAIN;
else if( !compareIbisWord( subparam.c_str(), "Open_sink" ) )
else if( compareIbisWord( subparam.c_str(), "Open_sink" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::OPEN_SINK;
else if( !compareIbisWord( subparam.c_str(), "I/O_open_sink" ) )
else if( compareIbisWord( subparam.c_str(), "I/O_open_sink" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::IO_OPEN_SINK;
else if( !compareIbisWord( subparam.c_str(), "Open_source" ) )
else if( compareIbisWord( subparam.c_str(), "Open_source" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::OPEN_SOURCE;
else if( !compareIbisWord( subparam.c_str(), "I/O_open_source" ) )
else if( compareIbisWord( subparam.c_str(), "I/O_open_source" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::IO_OPEN_SOURCE;
else if( !compareIbisWord( subparam.c_str(), "Input_ECL" ) )
else if( compareIbisWord( subparam.c_str(), "Input_ECL" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::INPUT_ECL;
else if( !compareIbisWord( subparam.c_str(), "Output_ECL" ) )
else if( compareIbisWord( subparam.c_str(), "Output_ECL" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::OUTPUT_ECL;
else if( !compareIbisWord( subparam.c_str(), "I/O_ECL" ) )
else if( compareIbisWord( subparam.c_str(), "I/O_ECL" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::IO_ECL;
else if( !compareIbisWord( subparam.c_str(), "3-state_ECL" ) )
else if( compareIbisWord( subparam.c_str(), "3-state_ECL" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::THREE_STATE_ECL;
else if( !compareIbisWord( subparam.c_str(), "Terminator" ) )
else if( compareIbisWord( subparam.c_str(), "Terminator" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::TERMINATOR;
else if( !compareIbisWord( subparam.c_str(), "Series" ) )
else if( compareIbisWord( subparam.c_str(), "Series" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::SERIES;
else if( !compareIbisWord( subparam.c_str(), "Series_switch" ) )
else if( compareIbisWord( subparam.c_str(), "Series_switch" ) )
m_currentModel->m_type = IBIS_MODEL_TYPE::SERIES_SWITCH;
else
{
@@ -2577,6 +2593,7 @@ bool IbisParser::onNewLine()
status &= readWaveform( m_currentWaveform, m_currentWaveform->m_type );
break;
case IBIS_PARSER_CONTINUE::RAMP: status &= readRamp(); break;
case IBIS_PARSER_CONTINUE::MODEL_SPEC: status &= readModelSpec(); break;
case IBIS_PARSER_CONTINUE::PACKAGEMODEL_PINS: status &= readPackageModelPins(); break;
case IBIS_PARSER_CONTINUE::MATRIX: status &= readMatrix( m_currentMatrix ); break;
case IBIS_PARSER_CONTINUE::NONE:
+2
View File
@@ -632,6 +632,7 @@ enum class IBIS_PARSER_CONTINUE
MATRIX,
MODELSELECTOR,
MODEL,
MODEL_SPEC,
IV_TABLE,
VT_TABLE,
RAMP,
@@ -772,6 +773,7 @@ private:
bool readMatrixSparse( std::string, IBIS_MATRIX_SPARSE& aDest );
bool readRampdvdt( dvdtTypMinMax& aDest );
bool readRamp();
bool readModelSpec();
bool readWaveform( IbisWaveform* aDest, IBIS_WAVEFORM_TYPE aType );
bool readString( std::string& aDest );
bool storeString( std::string& aDest, bool aMultiline );
+12 -9
View File
@@ -187,17 +187,20 @@ bool SIM_STRING_PROPERTY::StringToValue( wxVariant& aVariant, const wxString& aT
wxString text = aText;
if( !aText.IsEmpty() && allowEval() && m_needsEval && m_eval.Process( aText ) )
if( allowEval() && m_needsEval && m_eval.Process( aText ) )
{
double value = SIM_VALUE::ToDouble( m_eval.Result().ToStdString() );
if( !aText.IsEmpty() )
{
double value = SIM_VALUE::ToDouble( m_eval.Result().ToStdString() );
if( isnan( value ) || SIM_VALUE::Equal( value, aText.ToStdString() ) )
{
// Don't mess up user formatting if eval'ing didn't actually change the value.
}
else
{
text = SIM_VALUE::Normalize( value );
if( std::isnan( value ) || SIM_VALUE::Equal( value, aText.ToStdString() ) )
{
// Don't mess up user formatting if eval'ing didn't actually change the value.
}
else
{
text = SIM_VALUE::Normalize( value );
}
}
}
+8
View File
@@ -125,6 +125,14 @@ std::vector<SYMBOL_ASYNC_LOADER::LOADED_PAIR> SYMBOL_ASYNC_LOADER::worker()
std::lock_guard<std::mutex> lock( m_errorMutex );
m_errors += msg;
}
catch( std::exception& e )
{
wxString msg = wxString::Format( _( "Error loading symbol library %s.\n\n%s\n" ),
nickname, e.what() );
std::lock_guard<std::mutex> lock( m_errorMutex );
m_errors += msg;
}
}
return ret;
+3
View File
@@ -1956,6 +1956,9 @@ void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, SELECTION* aGro
aChild->ClearSelected();
else if( aMode == BRIGHTENED )
aChild->ClearBrightened();
if( aGroup )
aGroup->Remove( aChild );
} );
}
+13 -18
View File
@@ -76,12 +76,7 @@ SCH_DRAWING_TOOLS::SCH_DRAWING_TOOLS() :
m_lastTextboxStroke( 0, PLOT_DASH_TYPE::DEFAULT, COLOR4D::UNSPECIFIED ),
m_mruPath( wxEmptyString ),
m_lastAutoLabelRotateOnPlacement( false ),
m_inPlaceSymbol( false ),
m_inDrawShape( false ),
m_inPlaceImage( false ),
m_inSingleClickPlace( false ),
m_inTwoClickPlace( false ),
m_inDrawSheet( false )
m_inDrawingTool( false )
{
}
@@ -112,10 +107,10 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
EE_GRID_HELPER grid( m_toolMgr );
if( m_inPlaceSymbol )
if( m_inDrawingTool )
return 0;
REENTRANCY_GUARD guard( &m_inPlaceSymbol );
REENTRANCY_GUARD guard( &m_inDrawingTool );
// First we need to get all instances of this sheet so we can annotate
// whatever symbols we place on all copies
@@ -473,10 +468,10 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
bool ignorePrimePosition = false;
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
if( m_inPlaceImage )
if( m_inDrawingTool )
return 0;
REENTRANCY_GUARD guard( &m_inPlaceImage );
REENTRANCY_GUARD guard( &m_inDrawingTool );
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
@@ -709,10 +704,10 @@ int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
SCH_ITEM* previewItem;
bool loggedInfoBarError = false;
if( m_inSingleClickPlace )
if( m_inDrawingTool )
return 0;
REENTRANCY_GUARD guard( &m_inSingleClickPlace );
REENTRANCY_GUARD guard( &m_inDrawingTool );
if( type == SCH_JUNCTION_T && aEvent.HasPosition() )
{
@@ -1129,10 +1124,10 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
SCH_SHEET* sheet = nullptr;
if( m_inTwoClickPlace )
if( m_inDrawingTool )
return 0;
REENTRANCY_GUARD guard( &m_inTwoClickPlace );
REENTRANCY_GUARD guard( &m_inDrawingTool );
bool isText = aEvent.IsAction( &EE_ACTIONS::placeSchematicText );
bool isGlobalLabel = aEvent.IsAction( &EE_ACTIONS::placeGlobalLabel );
@@ -1520,10 +1515,10 @@ int SCH_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
bool isTextBox = aEvent.IsAction( &EE_ACTIONS::drawTextBox );
SHAPE_T type = aEvent.Parameter<SHAPE_T>();
if( m_inDrawShape )
if( m_inDrawingTool )
return 0;
REENTRANCY_GUARD guard( &m_inDrawShape );
REENTRANCY_GUARD guard( &m_inDrawingTool );
// We might be running as the same shape in another co-routine. Make sure that one
// gets whacked.
@@ -1739,10 +1734,10 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
{
SCH_SHEET* sheet = nullptr;
if( m_inDrawSheet )
if( m_inDrawingTool )
return 0;
REENTRANCY_GUARD guard( &m_inDrawSheet );
REENTRANCY_GUARD guard( &m_inDrawingTool );
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
+1 -8
View File
@@ -94,14 +94,7 @@ private:
wxString m_mruPath;
bool m_lastAutoLabelRotateOnPlacement;
///< Re-entrancy guards
bool m_inPlaceSymbol;
bool m_inDrawShape;
bool m_inPlaceImage;
bool m_inSingleClickPlace;
bool m_inTwoClickPlace;
bool m_inDrawSheet;
bool m_inDrawingTool; // Re-entrancy guard
std::unique_ptr<STATUS_TEXT_POPUP> m_statusPopup;
};
+21
View File
@@ -1119,7 +1119,28 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
schIUScale.MilsToIU( cfg->m_Drawing.default_repeat_offset_y ) ) );
}
// If cloning a sheet, check that we aren't going to create recursion
if( newItem->Type() == SCH_SHEET_T )
{
SCH_SHEET_PATH* currentSheet = &m_frame->GetCurrentSheet();
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( newItem );
if( m_frame->CheckSheetForRecursion( sheet, currentSheet ) )
{
// Clear out the filename so that the user can pick a new one
sheet->SetFileName( wxEmptyString );
if( !m_frame->EditSheetProperties( sheet, currentSheet, nullptr ) )
{
// User canceled renaming the sheet; skip it
delete newItem;
continue;
}
}
}
m_toolMgr->RunAction( EE_ACTIONS::addItemToSel, true, newItem );
newItem->SetFlags( IS_NEW );
m_frame->AddToScreen( newItem, m_frame->GetScreen() );
m_frame->SaveCopyInUndoList( m_frame->GetScreen(), newItem, UNDO_REDO::NEWITEM, appendUndo );
+240 -126
View File
@@ -332,10 +332,13 @@ void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aF
int SCH_EDITOR_CONTROL::ExportSymbolsToLibrary( const TOOL_EVENT& aEvent )
{
bool savePowerSymbols = IsOK( m_frame,
_( "Include power symbols in schematic to the library?" ) );
bool createNew = aEvent.IsAction( &EE_ACTIONS::exportSymbolsToNewLibrary );
SCH_REFERENCE_LIST symbols;
m_frame->Schematic().GetSheets().GetSymbols( symbols, false );
m_frame->Schematic().GetSheets().GetSymbols( symbols, savePowerSymbols );
std::map<LIB_ID, LIB_SYMBOL*> libSymbols;
std::map<LIB_ID, std::vector<SCH_SYMBOL*>> symbolMap;
@@ -423,17 +426,29 @@ int SCH_EDITOR_CONTROL::ExportSymbolsToLibrary( const TOOL_EVENT& aEvent )
LIB_SYMBOL* origSym = it.second;
LIB_SYMBOL* newSym = origSym->Flatten().release();
pi->SaveSymbol( dest.GetFullPath(), newSym );
try
{
pi->SaveSymbol( dest.GetFullPath(), newSym );
}
catch( const IO_ERROR& ioe )
{
wxString msg;
msg.Printf( _( "Error saving symbol %s to library '%s'." ),
newSym->GetName(), row->GetNickName() );
msg += wxS( "\n\n" ) + ioe.What();
wxLogWarning( msg );
return 0;
}
if( map )
{
LIB_ID id = it.first;
id.SetLibNickname( targetLib );
for( SCH_SYMBOL* symbol : symbolMap[it.first] )
{
m_frame->SaveCopyInUndoList( m_frame->GetScreen(), symbol, UNDO_REDO::CHANGED, append, false);
m_frame->SaveCopyInUndoList( m_frame->GetScreen(), symbol, UNDO_REDO::CHANGED,
append, false );
symbol->SetLibId( id );
append = true;
}
@@ -487,6 +502,7 @@ int SCH_EDITOR_CONTROL::ExportSymbolsToLibrary( const TOOL_EVENT& aEvent )
for( SCH_SHEET_PATH& sheet : sheets )
{
SCH_SCREEN* screen = sheet.LastScreen();
if( processedScreens.find( ( screen ) ) == processedScreens.end() )
{
processedScreens.insert( screen );
@@ -806,18 +822,27 @@ static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
}
}
wxString connectionName = ( conn ) ? conn->Name() : wxS( "" );
wxString connectionName = ( conn ) ? conn->Name() : wxString( wxS( "" ) );
if( !conn || connectionName == editFrame->GetHighlightedConnection() )
if( !conn )
{
editFrame->SetStatusText( wxT( "" ) );
editFrame->SendCrossProbeClearHighlight();
editFrame->SetHighlightedConnection( wxEmptyString );
editorControl->SetHighlightBusMembers( false );
}
else
{
editFrame->SetCrossProbeConnection( conn );
editFrame->SetHighlightedConnection( connectionName );
if( connectionName != editFrame->GetHighlightedConnection() )
{
editorControl->SetHighlightBusMembers( false );
editFrame->SetCrossProbeConnection( conn );
editFrame->SetHighlightedConnection( connectionName );
}
else
{
editorControl->SetHighlightBusMembers( !editorControl->GetHighlightBusMembers() );
}
}
editFrame->UpdateNetHighlightStatus();
@@ -1014,155 +1039,162 @@ int SCH_EDITOR_CONTROL::AssignNetclass( const TOOL_EVENT& aEvent )
int SCH_EDITOR_CONTROL::UpdateNetHighlighting( const TOOL_EVENT& aEvent )
{
wxCHECK( m_frame, 0 );
const SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
SCH_SCREEN* screen = m_frame->GetCurrentSheet().LastScreen();
CONNECTION_GRAPH* connectionGraph = m_frame->Schematic().ConnectionGraph();
wxString selectedName = m_frame->GetHighlightedConnection();
std::set<wxString> connNames;
std::vector<EDA_ITEM*> itemsToRedraw;
wxCHECK( screen && connectionGraph, 0 );
bool selectedIsBus = false;
wxString selectedName = m_frame->GetHighlightedConnection();
bool selectedIsNoNet = false;
CONNECTION_SUBGRAPH* selectedSubgraph = nullptr;
for( SCH_ITEM* item : screen->Items() )
if( !selectedName.IsEmpty() )
{
bool redraw = item->IsBrightened();
bool highlight = false;
connNames.emplace( selectedName );
if( !selectedName.IsEmpty() )
CONNECTION_SUBGRAPH* sg = connectionGraph->FindSubgraphByName( selectedName, sheetPath );
if( sg && m_highlightBusMembers )
{
SCH_CONNECTION* itemConn = nullptr;
SCH_SYMBOL* symbol = nullptr;
if( item->Type() == SCH_SYMBOL_T )
symbol = static_cast<SCH_SYMBOL*>( item );
if( symbol && symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->IsPower() )
itemConn = symbol->Connection();
else
itemConn = item->Connection();
if( itemConn && ( selectedName == itemConn->Name() ) )
for( const SCH_ITEM* item : sg->GetItems() )
{
selectedIsBus = itemConn->IsBus();
wxCHECK2( item, continue );
if( itemConn->Driver() == nullptr )
{
selectedIsNoNet = true;
selectedSubgraph = connectionGraph->GetSubgraphForItem( itemConn->Parent() );
}
SCH_CONNECTION* connection = item->Connection();
if( selectedIsNoNet && selectedSubgraph )
wxCHECK2( connection, continue );
for( const std::shared_ptr<SCH_CONNECTION>& member : connection->AllMembers() )
{
for( SCH_ITEM* subgraphItem : selectedSubgraph->GetItems() )
{
if( item == subgraphItem )
{
highlight = true;
break;
}
}
}
else if( selectedIsBus && itemConn && itemConn->IsNet() )
{
for( const std::shared_ptr<SCH_CONNECTION>& member : itemConn->Members() )
{
if( member->Name() == itemConn->Name() )
{
highlight = true;
break;
}
else if( member->IsBus() )
{
for( const std::shared_ptr<SCH_CONNECTION>& bus_member :
member->Members() )
{
if( bus_member->Name() == itemConn->Name() )
{
highlight = true;
break;
}
}
}
}
}
else if( !selectedName.IsEmpty() && itemConn
&& ( selectedName == itemConn->Name() ) )
{
highlight = true;
if( member )
connNames.emplace( member->Name() );
}
}
}
}
if( highlight )
item->SetBrightened();
else
item->ClearBrightened();
for( SCH_ITEM* item : screen->Items() )
{
wxCHECK2( item, continue );
redraw |= item->IsBrightened();
if( !item->IsConnectable() )
continue;
SCH_ITEM* redrawItem = nullptr;
if( item->Type() == SCH_SYMBOL_T )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
redraw |= symbol->HasBrightenedPins();
symbol->ClearBrightenedPins();
wxCHECK2( symbol, continue );
for( SCH_PIN* pin : symbol->GetPins() )
{
SCH_CONNECTION* pin_conn = pin->Connection();
if( pin_conn && pin_conn->Name() == selectedName )
wxCHECK2( pin_conn, continue );
if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
{
pin->SetBrightened();
redraw = true;
redrawItem = symbol;
}
else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
{
pin->ClearBrightened();
redrawItem = symbol;
}
}
if( symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->IsPower() )
if( symbol->IsPower() )
{
wxCHECK2( symbol->GetPins().size(), continue );
SCH_CONNECTION* pinConn = symbol->GetPins()[0]->Connection();
wxCHECK2( pinConn, continue );
std::vector<SCH_FIELD>& fields = symbol->GetFields();
for( int id : { REFERENCE_FIELD, VALUE_FIELD } )
{
if( item->IsBrightened() && fields[id].IsVisible() )
if( !fields[id].IsVisible() )
continue;
if( !fields[id].IsBrightened() && connNames.count( pinConn->Name() ) )
{
fields[id].SetBrightened();
else
redrawItem = symbol;
}
else if( fields[id].IsBrightened() && !connNames.count( pinConn->Name() ) )
{
fields[id].ClearBrightened();
redrawItem = symbol;
}
}
}
}
else if( item->Type() == SCH_SHEET_T )
{
for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() )
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
wxCHECK2( sheet, continue );
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
{
wxCHECK2( pin, continue );
SCH_CONNECTION* pin_conn = pin->Connection();
bool redrawPin = pin->IsBrightened();
if( pin_conn && pin_conn->Name() == selectedName )
wxCHECK2( pin_conn, continue );
if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
{
pin->SetBrightened();
else
redrawItem = sheet;
}
else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
{
pin->ClearBrightened();
redrawItem = sheet;
}
}
}
else
{
SCH_CONNECTION* itemConn = item->Connection();
redrawPin ^= pin->IsBrightened();
redraw |= redrawPin;
wxCHECK2( itemConn, continue );
if( !item->IsBrightened() && connNames.count( itemConn->Name() ) )
{
item->SetBrightened();
redrawItem = item;
}
else if( item->IsBrightened() && !connNames.count( itemConn->Name() ) )
{
item->ClearBrightened();
redrawItem = item;
}
}
if( redraw )
itemsToRedraw.push_back( item );
if( redrawItem )
itemsToRedraw.push_back( redrawItem );
}
// Be sure highlight change will be redrawn
KIGFX::VIEW* view = getView();
if( itemsToRedraw.size() )
{
// Be sure highlight change will be redrawn
KIGFX::VIEW* view = getView();
for( EDA_ITEM* redrawItem : itemsToRedraw )
view->Update( (KIGFX::VIEW_ITEM*)redrawItem, KIGFX::VIEW_UPDATE_FLAGS::REPAINT );
for( EDA_ITEM* redrawItem : itemsToRedraw )
view->Update( (KIGFX::VIEW_ITEM*)redrawItem, KIGFX::VIEW_UPDATE_FLAGS::REPAINT );
m_frame->GetCanvas()->Refresh();
m_frame->GetCanvas()->Refresh();
}
return 0;
}
@@ -1374,19 +1406,19 @@ void SCH_EDITOR_CONTROL::updatePastedSymbol( SCH_SYMBOL* aSymbol, SCH_SCREEN* aP
const KIID_PATH& aClipPath,
bool aForceKeepAnnotations )
{
wxCHECK( aSymbol && aPasteScreen, /* void */ );
wxCHECK( m_frame && aSymbol && aPasteScreen, /* void */ );
KIID_PATH clipItemPath = aClipPath;
SCH_SYMBOL_INSTANCE instance;
KIID_PATH pasteLookupPath = aClipPath;
wxString reference, value, footprint;
int unit;
m_pastedSymbols.insert( aSymbol );
if( m_clipboardSymbolInstances.count( clipItemPath ) > 0 )
// The pasted symbol look up paths include the symbol UUID.
pasteLookupPath.push_back( aSymbol->m_Uuid );
if( m_clipboardSymbolInstances.count( pasteLookupPath ) > 0 )
{
SCH_SYMBOL_INSTANCE instance = m_clipboardSymbolInstances.at( clipItemPath );
unit = instance.m_Unit;
reference = instance.m_Reference;
instance = m_clipboardSymbolInstances.at( pasteLookupPath );
}
else
{
@@ -1397,20 +1429,20 @@ void SCH_EDITOR_CONTROL::updatePastedSymbol( SCH_SYMBOL* aSymbol, SCH_SCREEN* aP
// Pasted from notepad or an older instance of eeschema. Use the values in the fields
// instead.
reference = aSymbol->GetField( REFERENCE_FIELD )->GetText();
value = aSymbol->GetField( VALUE_FIELD )->GetText();
footprint = aSymbol->GetField( FOOTPRINT_FIELD )->GetText();
unit = aSymbol->GetUnit();
instance.m_Reference = aSymbol->GetField( REFERENCE_FIELD )->GetText();
instance.m_Unit = aSymbol->GetUnit();
}
if( aForceKeepAnnotations && !reference.IsEmpty() )
aSymbol->SetRef( &aPastePath, reference );
else
instance.m_Path = aPastePath.Path() + aClipPath;
instance.m_ProjectName = m_frame->Prj().GetProjectName();
aSymbol->AddHierarchicalReference( instance );
if( !aForceKeepAnnotations )
aSymbol->ClearAnnotation( &aPastePath, false );
// We might clear annotations but always leave the original unit number from the paste.
aSymbol->SetUnitSelection( &aPastePath, unit );
aSymbol->SetUnit( unit );
aSymbol->SetUnit( instance.m_Unit );
}
@@ -1460,17 +1492,82 @@ SCH_SHEET_PATH SCH_EDITOR_CONTROL::updatePastedSheet( const SCH_SHEET_PATH& aPas
}
void SCH_EDITOR_CONTROL::setClipboardInstances( const SCH_SCREEN* aPastedScreen )
void SCH_EDITOR_CONTROL::setPastedSheetInstances( const SCH_SHEET* aPastedSheet )
{
m_clipboardSheetInstances.clear();
wxCHECK( aPastedSheet, /* void */ );
for( const SCH_SHEET_INSTANCE& sheet : aPastedScreen->GetSheetInstances() )
m_clipboardSheetInstances[sheet.m_Path] = sheet;
for( const SCH_SHEET_INSTANCE& sheetInstance : aPastedSheet->GetInstances() )
{
KIID_PATH pathWithSheet = sheetInstance.m_Path;
m_clipboardSymbolInstances.clear();
pathWithSheet.push_back( aPastedSheet->m_Uuid );
m_clipboardSheetInstances[pathWithSheet] = sheetInstance;
}
for( const SCH_SYMBOL_INSTANCE& symbol : aPastedScreen->GetSymbolInstances() )
m_clipboardSymbolInstances[symbol.m_Path] = symbol;
const SCH_SCREEN* screen = aPastedSheet->GetScreen();
wxCHECK( screen, /* void */ );
for( SCH_ITEM* item : screen->Items() )
{
if( item->Type() == SCH_SHEET_T )
{
const SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
wxCHECK2( sheet, continue );
setPastedSheetInstances( sheet );
}
}
}
void SCH_EDITOR_CONTROL::setPastedSymbolInstances( SCH_SCREENS& aScreenList )
{
for( SCH_SCREEN* screen = aScreenList.GetFirst(); screen; screen = aScreenList.GetNext() )
{
for( SCH_ITEM* item : screen->Items() )
{
if( item->Type() == SCH_SYMBOL_T )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
wxCHECK2( symbol, continue );
for( const SCH_SYMBOL_INSTANCE& symbolInstance : symbol->GetInstanceReferences() )
{
KIID_PATH pathWithSymbol = symbolInstance.m_Path;
pathWithSymbol.push_back( symbol->m_Uuid );
m_clipboardSymbolInstances[pathWithSymbol] = symbolInstance;
}
}
}
}
}
void SCH_EDITOR_CONTROL::prunePastedSymbolInstances()
{
wxCHECK( m_frame, /* void */ );
for( SCH_SYMBOL* symbol : m_pastedSymbols )
{
wxCHECK2( symbol, continue );
std::vector<KIID_PATH> instancePathsToRemove;
for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstanceReferences() )
{
if( ( instance.m_ProjectName != m_frame->Prj().GetProjectName() )
|| instance.m_Path.empty() )
instancePathsToRemove.emplace_back( instance.m_Path );
}
for( const KIID_PATH& path : instancePathsToRemove )
symbol->RemoveInstance( path );
}
}
@@ -1523,8 +1620,15 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
tempScreen->Append( text_item );
}
// Save loaded screen instances to m_clipboardSheetInstances
setClipboardInstances( tempScreen );
SCH_SCREENS tempScreens( tempSheet );
m_pastedSymbols.clear();
m_clipboardSheetInstances.clear();
m_clipboardSymbolInstances.clear();
// Save pasted sheet and symbol instances.
setPastedSheetInstances( &tempSheet );
setPastedSymbolInstances( tempScreens );
tempScreen->MigrateSimModels();
@@ -1870,6 +1974,16 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
m_frame->GetCurrentSheet().UpdateAllScreenReferences();
prunePastedSymbolInstances();
// The copy operation creates instance paths that are not valid for the current project or
// saved as part of another project. Prune them now so they do not accumulate in the saved
// schematic file.
SCH_SCREENS allScreens( m_frame->Schematic().Root() );
allScreens.PruneOrphanedSymbolInstances( m_frame->Prj().GetProjectName(),
m_frame->Schematic().GetSheets() );
// Now clear the previous selection, select the pasted items, and fire up the "move" tool.
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_toolMgr->RunAction( EE_ACTIONS::addItemsToSel, true, &loadedItems );
+25 -2
View File
@@ -42,7 +42,8 @@ public:
EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.EditorControl" ),
m_probingPcbToSch( false ),
m_pickerItem( nullptr ),
m_duplicateIsHoverSelection( false )
m_duplicateIsHoverSelection( false ),
m_highlightBusMembers( false )
{ }
~SCH_EDITOR_CONTROL() { }
@@ -157,6 +158,13 @@ public:
bool aSearchHierarchy, SCH_SEARCH_T aSearchType,
const wxString& aSearchText );
void SetHighlightBusMembers( bool aHighlightBusMembers )
{
m_highlightBusMembers = aHighlightBusMembers;
}
bool GetHighlightBusMembers() const { return m_highlightBusMembers; }
private:
///< copy selection to clipboard or to m_duplicateClipboard
bool doCopy( bool aUseDuplicateClipboard = false );
@@ -176,7 +184,18 @@ private:
SCH_SHEET_LIST* aPastedSheetsSoFar,
SCH_REFERENCE_LIST* aPastedSymbolsSoFar );
void setClipboardInstances( const SCH_SCREEN* aPastedScreen );
void setPastedSheetInstances( const SCH_SHEET* aPastedSheet );
void setPastedSymbolInstances( SCH_SCREENS& aScreenList );
/**
* Remove all pasted symbol instances that do not belong to the current project.
*
* @warning This should **only** be called when cleaning up after a paste. Otherwise it
* could clobber symbol instances for schematics shared across projects. Use
* SCH_SCREENS::PruneOrphanedSymbolInstances() to clean up invalid instance for
* the current project.
*/
void prunePastedSymbolInstances();
/**
* Read the footprint info from each line in the stuff file by reference designator.
@@ -211,6 +230,8 @@ private:
std::string m_duplicateClipboard; // Temporary storage for Duplicate action
bool m_duplicateIsHoverSelection;
bool m_highlightBusMembers;
// A map of sheet filename --> screens for the clipboard contents. We use these to hook up
// cut/paste operations for unsaved sheet content.
std::map<wxString, SCH_SCREEN*> m_supplementaryClipboard;
@@ -220,6 +241,8 @@ private:
// A map of KIID_PATH --> sheet instances for the clipboard contents.
std::map<KIID_PATH, SCH_SHEET_INSTANCE> m_clipboardSheetInstances;
std::set<SCH_SYMBOL*> m_pastedSymbols;
};
@@ -937,6 +937,11 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
m_view->AddToPreview( wire->Clone() );
}
}
else if( evt->IsAction( &ACTIONS::undo ) )
{
// Dispatch as normal undo event
evt->SetPassEvent();
}
else
{
wxBell();
+1 -1
View File
@@ -823,7 +823,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
}
else if( evt->IsAction( &ACTIONS::duplicate ) )
{
if( selection.Front()->IsNew() )
if( selection.Front() && selection.Front()->IsNew() )
{
// This doesn't really make sense; we'll just end up dragging a stack of
// objects so we ignore the duplicate and just carry on.
+16 -9
View File
@@ -92,6 +92,7 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
SHAPE_POLY_SET& aShapeBuffer )
{
// Draw the primitive shape for flashed items.
// Note: rotation of primitives inside a macro must be always done around the macro origin.
// Create a static buffer to avoid a lot of memory reallocation.
static std::vector<VECTOR2I> polybuffer;
polybuffer.clear();
@@ -218,15 +219,17 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
for( int ii = 0; ii < 4; ii++ )
{
polybuffer = subshape_poly;
EDA_ANGLE sub_rotation = rotation + ANGLE_90 * ii;
EDA_ANGLE sub_rotation = ANGLE_90 * ii;
for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
RotatePoint( polybuffer[jj], -sub_rotation );
// Move to center position given by the tool:
// Move to center position given by the tool, and rotate the full shape around
// the center position (origin of the macro):
for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
{
polybuffer[jj] += center;
RotatePoint( polybuffer[jj], -rotation );
}
aShapeBuffer.NewOutline();
@@ -264,6 +267,8 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
VECTOR2I center( mapPt( m_Params[0].GetValueFromMacro( aApertMacro ),
m_Params[1].GetValueFromMacro( aApertMacro ), m_GerbMetric ) );
EDA_ANGLE rotation( m_Params[8].GetValueFromMacro( aApertMacro ), DEGREES_T );
// adjust outerDiam by this on each nested circle
int diamAdjust = ( gap + penThickness ) * 2;
@@ -272,17 +277,21 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
if( outerDiam <= 0 )
break;
// calculate the rotated position of the center:
VECTOR2I circle_center = center;
RotatePoint( circle_center, -rotation );
// Note: outerDiam is the outer diameter of the ring.
// the ring graphic diameter is (outerDiam - penThickness)
if( outerDiam <= penThickness )
{ // No room to draw a ring (no room for the hole):
// draw a circle instead (with no hole), with the right diameter
TransformCircleToPolygon( aShapeBuffer, center, outerDiam / 2, arc_to_seg_error,
TransformCircleToPolygon( aShapeBuffer, circle_center, outerDiam / 2, arc_to_seg_error,
ERROR_INSIDE );
}
else
{
TransformRingToPolygon( aShapeBuffer, center, ( outerDiam - penThickness ) / 2,
TransformRingToPolygon( aShapeBuffer, circle_center, ( outerDiam - penThickness ) / 2,
penThickness, arc_to_seg_error, ERROR_INSIDE );
}
}
@@ -290,13 +299,11 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
// Draw the cross:
ConvertShapeToPolygon( aApertMacro, polybuffer );
EDA_ANGLE rotation( m_Params[8].GetValueFromMacro( aApertMacro ), DEGREES_T );
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
{
// move crossair shape to center and rotate shape:
RotatePoint( polybuffer[ii], -rotation );
polybuffer[ii] += center;
RotatePoint( polybuffer[ii], -rotation );
}
break;
@@ -375,13 +382,13 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
// Creates the shape:
ConvertShapeToPolygon( aApertMacro, polybuffer );
// rotate polygon
// move and rotate polygonal shape
EDA_ANGLE rotation( m_Params[5].GetValueFromMacro( aApertMacro ), DEGREES_T );
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
{
RotatePoint( polybuffer[ii], -rotation );
polybuffer[ii] += curPos;
RotatePoint( polybuffer[ii], -rotation );
}
break;
+7
View File
@@ -99,6 +99,10 @@ public:
// and the actual coordinates calculation must handle this
};
// size of a single line of text from a gerber file.
// warning: some files can have *very long* lines, so the buffer must be large.
#define GERBER_BUFZ 1000000
/**
* Hold the image data and parameters for one gerber file and layer parameters.
*
@@ -455,6 +459,9 @@ public:
GERBER_LAYER m_GBRLayerParams; // hold params for the current gerber layer
GERBER_DRAW_ITEMS m_drawings; // linked list of Gerber Items to draw
// A large buffer to store one line
static char m_LineBuffer[GERBER_BUFZ+1];
private:
wxArrayString m_messagesList; // A list of messages created when reading a file
+6 -8
View File
@@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2007-2016 Jean-Pierre Charras jp.charras at wanadoo.fr
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -223,11 +223,9 @@ bool GERBER_FILE_IMAGE::TestFileIsRS274( const wxString& aFullFileName )
return false;
}
// size of a single line of text from a gerber file.
// warning: some files can have *very long* lines, so the buffer must be large.
#define GERBER_BUFZ 1000000
// A large buffer to store one line
static char lineBuffer[GERBER_BUFZ+1];
char GERBER_FILE_IMAGE::m_LineBuffer[GERBER_BUFZ+1];
bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
{
@@ -252,11 +250,11 @@ bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
while( true )
{
if( fgets( lineBuffer, GERBER_BUFZ, m_Current_File ) == nullptr )
if( fgets( m_LineBuffer, GERBER_BUFZ, m_Current_File ) == nullptr )
break;
m_LineNum++;
text = StrPurge( lineBuffer );
text = StrPurge( m_LineBuffer );
while( text && *text )
{
@@ -313,7 +311,7 @@ bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
if( m_CommandState != ENTER_RS274X_CMD )
{
m_CommandState = ENTER_RS274X_CMD;
ReadRS274XCommand( lineBuffer, GERBER_BUFZ, text );
ReadRS274XCommand( m_LineBuffer, GERBER_BUFZ, text );
}
else //Error
{
+6 -7
View File
@@ -1,8 +1,3 @@
/**
* @file rs274d.cpp
* @brief functions to read the rs274d commands from a rs274d/rs274x file
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
@@ -26,6 +21,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @brief functions to read the rs274d commands from a rs274d/rs274x file
*/
#include <gerbview.h>
#include <gerbview_frame.h>
#include <trigo.h>
@@ -464,8 +464,7 @@ bool GERBER_FILE_IMAGE::Execute_G_Command( char*& text, int G_command )
ExecuteRS274XCommand( code_command, nullptr, 0, cptr );
}
while( *text && (*text != '*') )
text++;
GetEndOfBlock( m_LineBuffer, GERBER_BUFZ, text, m_Current_File );
break;
+2 -6
View File
@@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2007-2018 Jean-Pierre Charras jp.charras at wanadoo.fr
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -22,9 +22,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file rs274x.cpp
*/
#include <base_units.h>
#include <math/util.h> // for KiROUND
@@ -1049,8 +1046,7 @@ bool GERBER_FILE_IMAGE::ReadApertureMacro( char *aBuff, unsigned int aBuffSize,
is_comment = true;
// Skip comment
while( *aText && ( *aText != '*' ) )
aText++;
GetEndOfBlock( m_LineBuffer, GERBER_BUFZ, aText, m_Current_File );
break;
+4 -1
View File
@@ -45,11 +45,14 @@ class DIALOG_PASTE_SPECIAL : public DIALOG_PASTE_SPECIAL_BASE
public:
DIALOG_PASTE_SPECIAL( wxWindow* aParent, PASTE_MODE* aMode,
wxString aReplacement = wxT( "?" ) );
const wxString& aReplacement = wxS( "?" ) );
bool TransferDataToWindow() override;
bool TransferDataFromWindow() override;
protected:
virtual void onRadioBoxEvent( wxCommandEvent& event ) override;
private:
PASTE_MODE* m_mode;
};
+15 -1
View File
@@ -3,7 +3,7 @@
*
* Copyright (C) 2020 Ian McInerney <ian.s.mcinerney@ieee.org>
* Copyright (C) 2007-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.TXT for contributors.
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -190,6 +190,20 @@ public:
return false;
}
KIID_PATH& operator+=( const KIID_PATH& aRhs )
{
for( const KIID& kiid : aRhs )
emplace_back( kiid );
return *this;
}
friend KIID_PATH operator+( KIID_PATH aLhs, const KIID_PATH& aRhs )
{
aLhs += aRhs;
return aLhs;
}
};
/**
+4 -2
View File
@@ -111,11 +111,12 @@ int CLI::EXPORT_PCB_DRILL_COMMAND::doPerform( KIWAY& aKiway )
}
wxString format = FROM_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
if( format == "excellon" )
if( format == wxS( "excellon" ) )
{
drillJob->m_format = JOB_EXPORT_PCB_DRILL::DRILL_FORMAT::EXCELLON;
}
else if( format == "gerber" )
else if( format == wxS( "gerber" ) )
{
drillJob->m_format = JOB_EXPORT_PCB_DRILL::DRILL_FORMAT::GERBER;
}
@@ -229,6 +230,7 @@ int CLI::EXPORT_PCB_DRILL_COMMAND::doPerform( KIWAY& aKiway )
drillJob->m_excellonMinimalHeader = m_argParser.get<bool>( ARG_EXCELLON_MINIMALHEAD );
drillJob->m_excellonCombinePTHNPTH = !m_argParser.get<bool>( ARG_EXCELLON_SEPARATE_TH );
drillJob->m_generateMap = m_argParser.get<bool>( ARG_GENERATE_MAP );
drillJob->m_gerberPrecision = m_argParser.get<int>( ARG_GERBER_PRECISION );
if( drillJob->m_gerberPrecision != 5 && drillJob->m_gerberPrecision != 6 )
{
+4 -4
View File
@@ -215,7 +215,7 @@ PLUGIN_CONTENT_MANAGER::PLUGIN_CONTENT_MANAGER(
std::for_each( m_installed.begin(), m_installed.end(),
[&]( std::pair<const wxString, PCM_INSTALLATION_ENTRY>& entry )
{
preparePackage( entry.second.package );
PreparePackage( entry.second.package );
} );
}
@@ -478,7 +478,7 @@ const bool PLUGIN_CONTENT_MANAGER::CacheRepository( const wxString& aRepositoryI
for( size_t i = 0; i < saved_repo.package_list.size(); i++ )
{
preparePackage( saved_repo.package_list[i] );
PreparePackage( saved_repo.package_list[i] );
saved_repo.package_map[saved_repo.package_list[i].identifier] = i;
}
@@ -508,7 +508,7 @@ const bool PLUGIN_CONTENT_MANAGER::CacheRepository( const wxString& aRepositoryI
for( size_t i = 0; i < current_repo.package_list.size(); i++ )
{
preparePackage( current_repo.package_list[i] );
PreparePackage( current_repo.package_list[i] );
current_repo.package_map[current_repo.package_list[i].identifier] = i;
}
@@ -648,7 +648,7 @@ void PLUGIN_CONTENT_MANAGER::updateInstalledPackagesMetadata( const wxString& aR
}
void PLUGIN_CONTENT_MANAGER::preparePackage( PCM_PACKAGE& aPackage )
void PLUGIN_CONTENT_MANAGER::PreparePackage( PCM_PACKAGE& aPackage )
{
// Parse package version strings
for( PACKAGE_VERSION& ver : aPackage.versions )
+10 -10
View File
@@ -341,6 +341,16 @@ public:
*/
void ReadEnvVar();
/**
* @brief Parses version strings and calculates compatibility
*
* This should be called after loading package metadata from repository or from
* installation entries
*
* @param aPackage package metadata object
*/
static void PreparePackage( PCM_PACKAGE& aPackage );
private:
///< Default download limit of 10 Mb to not use too much memory
static constexpr size_t DEFAULT_DOWNLOAD_MEM_LIMIT = 10 * 1024 * 1024;
@@ -377,16 +387,6 @@ private:
*/
void updateInstalledPackagesMetadata( const wxString& aRepositoryId );
/**
* @brief Parses version strings and calculates compatibility
*
* This should be called after loading package metadata from repository or from
* installation entries
*
* @param aPackage package metadata object
*/
static void preparePackage( PCM_PACKAGE& aPackage );
///< Returns current UTC timestamp
time_t getCurrentTimestamp() const;
+10
View File
@@ -371,6 +371,7 @@ void PCM_TASK_MANAGER::InstallFromFile( wxWindow* aParent, const wxString& aFile
}
PCM_PACKAGE package = metadata.get<PCM_PACKAGE>();
PLUGIN_CONTENT_MANAGER::PreparePackage( package );
if( package.versions.size() != 1 )
{
@@ -378,6 +379,15 @@ void PCM_TASK_MANAGER::InstallFromFile( wxWindow* aParent, const wxString& aFile
return;
}
if( !package.versions[0].compatible
&& wxMessageBox( _( "This package version is incompatible with your kicad version or "
"platform. Are you sure you want to install it anyway?" ),
_( "Install package" ), wxICON_EXCLAMATION | wxYES_NO, aParent )
== wxNO )
{
return;
}
bool isUpdate = false;
// wxRegEx is not CopyConstructible hence the weird choice of forward_list
std::forward_list<wxRegEx> keep_on_update;
+12 -3
View File
@@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Brian Sidebotham <brian.sidebotham@gmail.com>
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -81,7 +81,11 @@ public:
virtual wxDirTraverseResult OnFile( const wxString& filename ) override
{
if( !filename.StartsWith( m_exclude ) )
wxFileName fn( filename );
bool exclude = filename.StartsWith( m_exclude ) || fn.GetName().StartsWith( wxS( "." ) );
if( !exclude )
m_files.emplace_back( wxFileName( filename ) );
return wxDIR_CONTINUE;
@@ -89,7 +93,12 @@ public:
virtual wxDirTraverseResult OnDir( const wxString& dirname ) override
{
if( !dirname.StartsWith( m_exclude ) )
wxFileName fn( dirname, wxEmptyString );
wxArrayString dirs = fn.GetDirs();
wxString lastDir = dirs[ fn.GetDirCount() - 1 ];
bool exclude = dirname.StartsWith( m_exclude ) || lastDir.StartsWith( wxS( "." ) );
if( !exclude )
m_files.emplace_back( wxFileName::DirName( dirname ) );
return wxDIR_CONTINUE;
+9 -10
View File
@@ -499,7 +499,7 @@ bool SHAPE_POLY_SET::IsPolygonSelfIntersecting( int aPolygonIndex ) const
break;
int index_diff = std::abs( firstSegment.Index() - secondSegment.Index() );
bool adjacent = ( index_diff == 1) || (index_diff == (segments.size() - 1) );
bool adjacent = ( index_diff == 1) || (index_diff == ((int)segments.size() - 1) );
// Check whether the two segments built collide, only when they are not adjacent.
if( !adjacent && firstSegment.Collide( secondSegment, 0 ) )
@@ -1009,28 +1009,27 @@ void SHAPE_POLY_SET::inflate2( int aAmount, int aCircleSegCount, CORNER_STRATEGY
// http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/JoinType.htm
JoinType joinType = JoinType::Round; // The way corners are offsetted
double miterLimit = 2.0; // Smaller value when using jtMiter for joinType
JoinType miterFallback = JoinType::Square;
switch( aCornerStrategy )
{
case ALLOW_ACUTE_CORNERS:
case CORNER_STRATEGY::ALLOW_ACUTE_CORNERS:
joinType = JoinType::Miter;
miterLimit = 10; // Allows large spikes
break;
case CHAMFER_ACUTE_CORNERS: // Acute angles are chamfered
case CORNER_STRATEGY::CHAMFER_ACUTE_CORNERS: // Acute angles are chamfered
joinType = JoinType::Miter;
break;
case ROUND_ACUTE_CORNERS: // Acute angles are rounded
case CORNER_STRATEGY::ROUND_ACUTE_CORNERS: // Acute angles are rounded
joinType = JoinType::Miter;
break;
case CHAMFER_ALL_CORNERS: // All angles are chamfered.
case CORNER_STRATEGY::CHAMFER_ALL_CORNERS: // All angles are chamfered.
joinType = JoinType::Square;
break;
case ROUND_ALL_CORNERS: // All angles are rounded.
case CORNER_STRATEGY::ROUND_ALL_CORNERS: // All angles are rounded.
joinType = JoinType::Round;
break;
}
@@ -1079,11 +1078,11 @@ void SHAPE_POLY_SET::inflate2( int aAmount, int aCircleSegCount, CORNER_STRATEGY
Paths64 paths;
c.Execute( aAmount, paths );
Clipper2Lib::SimplifyPaths( paths, std::abs( aAmount ) * coeff, false );
Clipper2Lib::SimplifyPaths( paths, std::abs( aAmount ) * coeff, true );
Clipper64 c2;
c2.PreserveCollinear = false;
c2.ReverseSolution = false;
c2.PreserveCollinear( false );
c2.ReverseSolution( false );
c2.AddSubject( paths );
c2.Execute(ClipType::Union, FillRule::Positive, tree);
}
+4 -4
View File
@@ -478,13 +478,13 @@ const VECTOR2I CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aMid, cons
VECTOR2I iCenter;
iCenter.x = KiROUND( Clamp<double>( double( std::numeric_limits<int>::min() / 2.0 ),
iCenter.x = KiROUND( Clamp<double>( double( std::numeric_limits<int>::min() + 100 ),
dCenter.x,
double( std::numeric_limits<int>::max() / 2.0 ) ) );
double( std::numeric_limits<int>::max() - 100 ) ) );
iCenter.y = KiROUND( Clamp<double>( double( std::numeric_limits<int>::min() / 2.0 ),
iCenter.y = KiROUND( Clamp<double>( double( std::numeric_limits<int>::min() + 100 ),
dCenter.y,
double( std::numeric_limits<int>::max() / 2.0 ) ) );
double( std::numeric_limits<int>::max() - 100 ) ) );
return iCenter;
}
+18 -3
View File
@@ -79,15 +79,30 @@ void ARRAY_CREATOR::Invoke()
for( int ptN = 0; ptN < array_opts->GetArraySize(); ptN++ )
{
PCB_SELECTION items_for_this_block;
std::set<FOOTPRINT*> fpDeDupe;
for ( int i = 0; i < m_selection.Size(); ++i )
{
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( m_selection[ i ] );
if( item->Type() == PCB_PAD_T && !m_isFootprintEditor )
FOOTPRINT* parentFootprint = dynamic_cast<FOOTPRINT*>( item->GetParentFootprint() );
// If it is not the footprint editor, then duplicate the parent footprint instead.
// This check assumes that the footprint child objects are correctly parented, if
// they are not, this will segfault.
if( !m_isFootprintEditor && parentFootprint )
{
// If it is not the footprint editor, then duplicate the parent footprint instead
item = static_cast<FOOTPRINT*>( item )->GetParent();
// It is possible to select multiple footprint child objects in the board editor.
// Do not create multiple copies of the same footprint when this occurs.
if( fpDeDupe.count( parentFootprint ) == 0 )
{
fpDeDupe.emplace( parentFootprint );
item = parentFootprint;
}
else
{
continue;
}
}
BOARD_ITEM* this_item = nullptr;
+18 -2
View File
@@ -216,6 +216,13 @@ bool CN_CONNECTIVITY_ALGO::Add( BOARD_ITEM* aItem )
}
void CN_CONNECTIVITY_ALGO::RemoveInvalidRefs()
{
for( CN_ITEM* item : m_itemList )
item->RemoveInvalidRefs();
}
void CN_CONNECTIVITY_ALGO::searchConnections()
{
#ifdef PROFILE
@@ -224,6 +231,11 @@ void CN_CONNECTIVITY_ALGO::searchConnections()
std::vector<CN_ITEM*> garbage;
garbage.reserve( 1024 );
m_parentConnectivityData->RemoveInvalidRefs();
if( m_isLocal )
m_globalConnectivityData->RemoveInvalidRefs();
m_itemList.RemoveInvalidItems( garbage );
for( CN_ITEM* item : garbage )
@@ -542,9 +554,13 @@ void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
}
void CN_CONNECTIVITY_ALGO::LocalBuild( const std::vector<BOARD_ITEM*>& aItems )
void CN_CONNECTIVITY_ALGO::LocalBuild( std::shared_ptr<CONNECTIVITY_DATA> aGlobalConnectivity,
const std::vector<BOARD_ITEM*>& aLocalItems )
{
for( BOARD_ITEM* item : aItems )
m_isLocal = true;
m_globalConnectivityData = aGlobalConnectivity;
for( BOARD_ITEM* item : aLocalItems )
{
switch( item->Type() )
{
+27 -4
View File
@@ -93,6 +93,15 @@ public:
void SetSourceNode( const std::shared_ptr<const CN_ANCHOR>& aNode ) { m_source = aNode; }
void SetTargetNode( const std::shared_ptr<const CN_ANCHOR>& aNode ) { m_target = aNode; }
void RemoveInvalidRefs()
{
if( m_source && !m_source->Valid() )
m_source.reset();
if( m_target && !m_target->Valid() )
m_target.reset();
}
void SetWeight( unsigned weight ) { m_weight = weight; }
unsigned GetWeight() const { return m_weight; }
@@ -154,8 +163,15 @@ public:
std::list<CN_ITEM*> m_items;
};
CN_CONNECTIVITY_ALGO() {}
~CN_CONNECTIVITY_ALGO() { Clear(); }
CN_CONNECTIVITY_ALGO( CONNECTIVITY_DATA* aParentConnectivityData ) :
m_parentConnectivityData( aParentConnectivityData ),
m_isLocal( false )
{}
~CN_CONNECTIVITY_ALGO()
{
Clear();
}
bool ItemExists( const BOARD_CONNECTED_ITEM* aItem ) const
{
@@ -197,8 +213,9 @@ public:
return m_dirtyNets.size();
}
void Build( BOARD* aZoneLayer, PROGRESS_REPORTER* aReporter = nullptr );
void LocalBuild( const std::vector<BOARD_ITEM*>& aItems );
void Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter = nullptr );
void LocalBuild( std::shared_ptr<CONNECTIVITY_DATA> aGlobalConnectivity,
const std::vector<BOARD_ITEM*>& aLocalItems );
void Clear();
@@ -247,6 +264,8 @@ public:
}
void MarkNetAsDirty( int aNet );
void RemoveInvalidRefs();
void SetProgressReporter( PROGRESS_REPORTER* aReporter );
private:
@@ -265,6 +284,7 @@ private:
void markItemNetAsDirty( const BOARD_ITEM* aItem );
private:
CONNECTIVITY_DATA* m_parentConnectivityData;
CN_LIST m_itemList;
std::unordered_map<const BOARD_ITEM*, ITEM_MAP_ENTRY> m_itemMap;
@@ -272,6 +292,9 @@ private:
std::vector<std::shared_ptr<CN_CLUSTER>> m_ratsnestClusters;
std::vector<bool> m_dirtyNets;
bool m_isLocal;
std::shared_ptr<CONNECTIVITY_DATA> m_globalConnectivityData;
PROGRESS_REPORTER* m_progressReporter = nullptr;
};
+39 -10
View File
@@ -44,18 +44,21 @@
#include <trigo.h>
#include <drc/drc_rtree.h>
CONNECTIVITY_DATA::CONNECTIVITY_DATA()
CONNECTIVITY_DATA::CONNECTIVITY_DATA() :
m_skipRatsnestUpdate( false )
{
m_connAlgo.reset( new CN_CONNECTIVITY_ALGO );
m_connAlgo.reset( new CN_CONNECTIVITY_ALGO( this ) );
m_progressReporter = nullptr;
m_fromToCache.reset( new FROM_TO_CACHE );
}
CONNECTIVITY_DATA::CONNECTIVITY_DATA( const std::vector<BOARD_ITEM*>& aItems, bool aSkipRatsnest )
: m_skipRatsnest( aSkipRatsnest )
CONNECTIVITY_DATA::CONNECTIVITY_DATA( std::shared_ptr<CONNECTIVITY_DATA> aGlobalConnectivity,
const std::vector<BOARD_ITEM*>& aLocalItems,
bool aSkipRatsnestUpdate ) :
m_skipRatsnestUpdate( aSkipRatsnestUpdate )
{
Build( aItems );
Build( aGlobalConnectivity, aLocalItems );
m_progressReporter = nullptr;
m_fromToCache.reset( new FROM_TO_CACHE );
}
@@ -109,7 +112,7 @@ bool CONNECTIVITY_DATA::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
std::shared_ptr<NET_SETTINGS>& netSettings = aBoard->GetDesignSettings().m_NetSettings;
m_connAlgo.reset( new CN_CONNECTIVITY_ALGO );
m_connAlgo.reset( new CN_CONNECTIVITY_ALGO( this ) );
m_connAlgo->Build( aBoard, aReporter );
m_netclassMap.clear();
@@ -140,15 +143,16 @@ bool CONNECTIVITY_DATA::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
}
void CONNECTIVITY_DATA::Build( const std::vector<BOARD_ITEM*>& aItems )
void CONNECTIVITY_DATA::Build( std::shared_ptr<CONNECTIVITY_DATA>& aGlobalConnectivity,
const std::vector<BOARD_ITEM*>& aLocalItems )
{
std::unique_lock<KISPINLOCK> lock( m_lock, std::try_to_lock );
if( !lock )
return;
m_connAlgo.reset( new CN_CONNECTIVITY_ALGO );
m_connAlgo->LocalBuild( aItems );
m_connAlgo.reset( new CN_CONNECTIVITY_ALGO( this ) );
m_connAlgo->LocalBuild( aGlobalConnectivity, aLocalItems );
internalRecalculateRatsnest();
}
@@ -272,7 +276,7 @@ void CONNECTIVITY_DATA::internalRecalculateRatsnest( BOARD_COMMIT* aCommit )
m_connAlgo->ClearDirtyFlags();
if( !m_skipRatsnest )
if( !m_skipRatsnestUpdate )
updateRatsnest();
}
@@ -381,6 +385,10 @@ void CONNECTIVITY_DATA::ComputeLocalRatsnest( const std::vector<BOARD_ITEM*>& aI
{
const std::shared_ptr<const CN_ANCHOR>& nodeA = edge.GetSourceNode();
const std::shared_ptr<const CN_ANCHOR>& nodeB = edge.GetTargetNode();
if( !nodeA || nodeA->Dirty() || !nodeB || nodeB->Dirty() )
continue;
RN_DYNAMIC_LINE l;
// Use the parents' positions
@@ -910,6 +918,15 @@ void CONNECTIVITY_DATA::MarkItemNetAsDirty( BOARD_ITEM *aItem )
}
void CONNECTIVITY_DATA::RemoveInvalidRefs()
{
m_connAlgo->RemoveInvalidRefs();
for( RN_NET* rnNet : m_nets )
rnNet->RemoveInvalidRefs();
}
void CONNECTIVITY_DATA::SetProgressReporter( PROGRESS_REPORTER* aReporter )
{
m_progressReporter = aReporter;
@@ -951,6 +968,9 @@ const std::vector<CN_EDGE> CONNECTIVITY_DATA::GetRatsnestForItems( std::vector<B
std::shared_ptr<const CN_ANCHOR> srcNode = edge.GetSourceNode();
std::shared_ptr<const CN_ANCHOR> dstNode = edge.GetTargetNode();
if( !srcNode || srcNode->Dirty() || !dstNode || dstNode->Dirty() )
continue;
BOARD_CONNECTED_ITEM* srcParent = srcNode->Parent();
BOARD_CONNECTED_ITEM* dstParent = dstNode->Parent();
@@ -973,6 +993,12 @@ const std::vector<CN_EDGE> CONNECTIVITY_DATA::GetRatsnestForPad( const PAD* aPad
for( const CN_EDGE& edge : net->GetEdges() )
{
if( !edge.GetSourceNode() || edge.GetSourceNode()->Dirty() )
continue;
if( !edge.GetTargetNode() || edge.GetTargetNode()->Dirty() )
continue;
if( edge.GetSourceNode()->Parent() == aPad || edge.GetTargetNode()->Parent() == aPad )
edges.push_back( edge );
}
@@ -1002,6 +1028,9 @@ const std::vector<CN_EDGE> CONNECTIVITY_DATA::GetRatsnestForComponent( FOOTPRINT
auto srcNode = edge.GetSourceNode();
auto dstNode = edge.GetTargetNode();
if( !srcNode || srcNode->Dirty() || !dstNode || dstNode->Dirty() )
continue;
const PAD* srcParent = static_cast<const PAD*>( srcNode->Parent() );
const PAD* dstParent = static_cast<const PAD*>( dstNode->Parent() );
+7 -3
View File
@@ -88,7 +88,8 @@ public:
CONNECTIVITY_DATA();
~CONNECTIVITY_DATA();
CONNECTIVITY_DATA( const std::vector<BOARD_ITEM*>& aItems, bool aSkipItems = false );
CONNECTIVITY_DATA( std::shared_ptr<CONNECTIVITY_DATA> aGlobalConnectivity,
const std::vector<BOARD_ITEM*>& aLocalItems, bool aSkipRatsnestUpdate = false );
/**
* Function Build()
@@ -100,7 +101,8 @@ public:
* Function Build()
* Builds the connectivity database for a set of items aItems.
*/
void Build( const std::vector<BOARD_ITEM*>& aItems );
void Build( std::shared_ptr<CONNECTIVITY_DATA>& aGlobalConnectivity,
const std::vector<BOARD_ITEM*>& aLocalItems );
/**
* Function Add()
@@ -263,6 +265,8 @@ public:
KISPINLOCK& GetLock() { return m_lock; }
void MarkItemNetAsDirty( BOARD_ITEM* aItem );
void RemoveInvalidRefs();
void SetProgressReporter( PROGRESS_REPORTER* aReporter );
const std::map<int, wxString>& GetNetclassMap() const { return m_netclassMap; }
@@ -297,7 +301,7 @@ private:
std::vector<RN_NET*> m_nets;
/// Used to suppress ratsnest calculations on dynamic ratsnests
bool m_skipRatsnest = false;
bool m_skipRatsnestUpdate;
KISPINLOCK m_lock;
@@ -266,9 +266,6 @@ void CN_LIST::RemoveInvalidItems( std::vector<CN_ITEM*>& aGarbage )
m_items.resize( lastItem - m_items.begin() );
for( CN_ITEM* item : m_items )
item->RemoveInvalidRefs();
for( CN_ITEM* item : aGarbage )
m_index.Remove( item );
+8
View File
@@ -479,6 +479,14 @@ void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent )
m_frame->GetBoard()->GetConnectivity()->RunOnUnconnectedEdges(
[&]( CN_EDGE& edge )
{
// Connectivity was valid when DRC was run, but this is a modeless dialog
// so it might not be now.
if( !edge.GetSourceNode() || edge.GetSourceNode()->Dirty() )
return true;
if( !edge.GetTargetNode() || edge.GetTargetNode()->Dirty() )
return true;
if( edge.GetSourceNode()->Parent() == a
&& edge.GetTargetNode()->Parent() == b )
{
@@ -151,6 +151,9 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
if( !reportProgress( ii++, count, progressDelta ) )
return false; // DRC cancelled
wxCHECK( edge.GetSourceNode() && !edge.GetSourceNode()->Dirty(), true );
wxCHECK( edge.GetTargetNode() && !edge.GetTargetNode()->Dirty(), true );
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS );
drcItem->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() );
reportViolation( drcItem, edge.GetSourceNode()->Pos(), UNDEFINED_LAYER );
@@ -218,6 +218,14 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
for( size_t ii = 0; ii < poly.GetSegmentCount(); ++ii )
{
SEG seg = poly.CSegment( ii );
// The polygon iterator returns coordinates relative to the parent
if( FOOTPRINT* fp = shape->GetParentFootprint() )
{
seg.A += fp->GetPosition();
seg.B += fp->GetPosition();
}
edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
edges.back()->SetShape( SHAPE_T::SEGMENT );
edges.back()->SetStart( seg.A );
+9 -14
View File
@@ -47,6 +47,7 @@
#include <pcbnew_settings.h>
#include <pgm_base.h>
#include <project/project_file.h> // LAST_PATH_TYPE
#include <geometry/shape_poly_set.h>
#include <wx/app.h>
#include <wx/filedlg.h>
@@ -1140,21 +1141,15 @@ static void CreateBoardSection( FILE* aFile, BOARD* aPcb )
{
fputs( "$BOARD\n", aFile );
// Extract the board edges
for( BOARD_ITEM* drawing : aPcb->Drawings() )
{
if( drawing->Type() == PCB_SHAPE_T )
{
PCB_SHAPE* drawseg = static_cast<PCB_SHAPE*>( drawing );
SHAPE_POLY_SET outline;
aPcb->GetBoardPolygonOutlines( outline );
if( drawseg->GetLayer() == Edge_Cuts )
{
// XXX GenCAD supports arc boundaries but I've seen nothing that reads them
fprintf( aFile, "LINE %g %g %g %g\n",
MapXTo( drawseg->GetStart().x ), MapYTo( drawseg->GetStart().y ),
MapXTo( drawseg->GetEnd().x ), MapYTo( drawseg->GetEnd().y ) );
}
}
for( auto seg1 = outline.IterateSegmentsWithHoles(); seg1; seg1++ )
{
SEG seg = *seg1;
fprintf( aFile, "LINE %g %g %g %g\n",
MapXTo( seg.A.x ), MapYTo( seg.A.y ),
MapXTo( seg.B.x ), MapYTo( seg.B.y ) );
}
fputs( "$ENDBOARD\n\n", aFile );
@@ -33,6 +33,7 @@
#include <math/util.h> // for KiROUND
#include <board.h>
#include <footprint.h>
#include <pcbnew.h>
#include <pcbplot.h>
@@ -258,6 +259,31 @@ bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName, PLOT_
}
}
// Plot edge cuts in footprints
for( const FOOTPRINT* footprint : m_pcb->Footprints() )
{
for( BOARD_ITEM* item : footprint->GraphicalItems() )
{
if( item-> GetLayer() != Edge_Cuts )
continue;
switch( item->Type() )
{
case PCB_FP_SHAPE_T:
{
PCB_SHAPE dummy_shape( *static_cast<PCB_SHAPE*>( item ) );
dummy_shape.SetLayer( Dwgs_User );
dummy_shape.SetParentGroup( nullptr ); // Remove group association, not needed for plotting
itemplotter.PlotPcbShape( &dummy_shape );
}
break;
default:
break;
}
}
}
int plotX, plotY, TextWidth;
int intervalle = 0;
char line[1024];
@@ -575,6 +575,6 @@ void EXCELLON_WRITER::writeEXCELLONHeader( DRILL_LAYER_PAIR aLayerPair, TYPE_FIL
void EXCELLON_WRITER::writeEXCELLONEndOfFile()
{
// add if minimal here
fputs( "T0\nM30\n", m_file );
fputs( "M30\n", m_file );
fclose( m_file );
}
+30 -10
View File
@@ -189,14 +189,14 @@ STEP_PCB_MODEL::STEP_PCB_MODEL( const wxString& aPcbName )
m_mergeOCCMaxDist = OCC_MAX_DISTANCE_TO_MERGE_POINTS;
m_minx = 1.0e10; // absurdly large number; any valid PCB X value will be smaller
m_pcbName = aPcbName;
BRepBuilderAPI::Precision( m_mergeOCCMaxDist );
m_maxError = pcbIUScale.mmToIU( ARC_TO_SEGMENT_MAX_ERROR_MM );
}
STEP_PCB_MODEL::~STEP_PCB_MODEL()
{
m_doc->Close();
if( m_doc->CanClose() == CDM_CCS_OK )
m_doc->Close();
}
@@ -328,7 +328,6 @@ void STEP_PCB_MODEL::OCCSetMergeMaxDistance( double aDistance )
{
// Ensure a minimal value (in mm)
m_mergeOCCMaxDist = aDistance;
BRepBuilderAPI::Precision( m_mergeOCCMaxDist );
}
@@ -1048,14 +1047,18 @@ bool STEP_PCB_MODEL::readIGES( Handle( TDocStd_Document )& doc, const char* fnam
if( !reader.Transfer( doc ) )
{
doc->Close();
if( doc->CanClose() == CDM_CCS_OK )
doc->Close();
return false;
}
// are there any shapes to translate?
if( reader.NbShapes() < 1 )
{
doc->Close();
if( doc->CanClose() == CDM_CCS_OK )
doc->Close();
return false;
}
@@ -1081,19 +1084,23 @@ bool STEP_PCB_MODEL::readSTEP( Handle( TDocStd_Document )& doc, const char* fnam
// set other translation options
reader.SetColorMode( true ); // use model colors
reader.SetNameMode( false ); // don't use label names
reader.SetNameMode( true ); // use label names
reader.SetLayerMode( false ); // ignore LAYER data
if( !reader.Transfer( doc ) )
{
doc->Close();
if( doc->CanClose() == CDM_CCS_OK )
doc->Close();
return false;
}
// are there any shapes to translate?
if( reader.NbRootsForTransfer() < 1 )
{
doc->Close();
if( doc->CanClose() == CDM_CCS_OK )
doc->Close();
return false;
}
@@ -1133,10 +1140,17 @@ TDF_Label STEP_PCB_MODEL::transferModel( Handle( TDocStd_Document )& source,
while( id <= nshapes )
{
TopoDS_Shape shape = s_assy->GetShape( frshapes.Value( id ) );
const TDF_Label& s_shapeLabel = frshapes.Value( id );
TopoDS_Shape shape = s_assy->GetShape( s_shapeLabel );
if( !shape.IsNull() )
{
Handle( TDataStd_Name ) s_nameAttr;
s_shapeLabel.FindAttribute( TDataStd_Name::GetID(), s_nameAttr );
TCollection_ExtendedString s_labelName =
s_nameAttr ? s_nameAttr->Get() : TCollection_ExtendedString();
TopoDS_Shape scaled_shape( shape );
if( aScale.x != 1.0 || aScale.y != 1.0 || aScale.z != 1.0 )
@@ -1155,7 +1169,13 @@ TDF_Label STEP_PCB_MODEL::transferModel( Handle( TDocStd_Document )& source,
}
}
TDF_Label niulab = d_assy->AddComponent( component, scaled_shape, Standard_False );
TDF_Label d_shapeLabel = d_assy->AddShape( scaled_shape, Standard_False );
if( s_labelName.Length() > 0 )
TDataStd_Name::Set( d_shapeLabel, s_labelName );
TDF_Label niulab =
d_assy->AddComponent( component, d_shapeLabel, scaled_shape.Location() );
// check for per-surface colors
stop.Init( shape, TopAbs_FACE );
+5 -3
View File
@@ -762,12 +762,14 @@ int FOOTPRINT::GetLikelyAttribute() const
}
}
if( smd_count > 0 )
return FP_SMD;
// Footprints with plated through-hole pads should usually be marked through hole even if they
// also have SMD because they might not be auto-placed. Exceptions to this might be shielded
if( tht_count > 0 )
return FP_THROUGH_HOLE;
if( smd_count > 0 )
return FP_SMD;
return 0;
}
+1 -1
View File
@@ -415,7 +415,7 @@ std::shared_ptr<SHAPE_SEGMENT> PAD::GetEffectiveHoleShape() const
int PAD::GetBoundingRadius() const
{
if( m_polyDirty )
if( m_polyDirty[ERROR_OUTSIDE] )
BuildEffectivePolygon( ERROR_OUTSIDE );
return m_effectiveBoundingRadius;
+5 -4
View File
@@ -33,6 +33,7 @@
#include <geometry/shape_compound.h>
#include <pad_shapes.h>
#include <geometry/eda_angle.h>
#include <geometry/geometry_utils.h>
#include <core/arraydim.h>
class PCB_SHAPE;
@@ -436,7 +437,7 @@ public:
* @param ignoreLineWidth used for edge cuts where the line width is only for visualization.
*/
void TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
int aMaxError, ERROR_LOC aErrorLoc,
int aMaxError, ERROR_LOC aErrorLoc = ERROR_INSIDE,
bool ignoreLineWidth = false ) const override;
/**
@@ -449,7 +450,7 @@ public:
* @return false if the pad has no hole, true otherwise.
*/
bool TransformHoleToPolygon( SHAPE_POLY_SET& aBuffer, int aClearance, int aError,
ERROR_LOC aErrorLoc ) const;
ERROR_LOC aErrorLoc = ERROR_INSIDE ) const;
/**
* Some pad shapes can be complex (rounded/chamfered rectangle), even without considering
@@ -470,7 +471,7 @@ public:
GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING flashPTHPads = FLASHING::DEFAULT ) const override;
const std::shared_ptr<SHAPE_POLY_SET>& GetEffectivePolygon( ERROR_LOC aErrorLoc ) const;
const std::shared_ptr<SHAPE_POLY_SET>& GetEffectivePolygon( ERROR_LOC aErrorLoc = ERROR_INSIDE ) const;
/**
* Return a SHAPE_SEGMENT object representing the pad's hole.
@@ -730,7 +731,7 @@ public:
* the dirty bit.
*/
void BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const;
void BuildEffectivePolygon( ERROR_LOC aErrorLoc ) const;
void BuildEffectivePolygon( ERROR_LOC aErrorLoc = ERROR_INSIDE ) const;
virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
+3 -1
View File
@@ -1655,7 +1655,9 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
m_gal->SetFillColor( color );
m_gal->SetStrokeColor( color );
if( lineStyle <= PLOT_DASH_TYPE::FIRST_TYPE )
// Note: on LAYER_LOCKED_ITEM_SHADOW always draw shadow shapes as continuous lines
// otherwise the look is very strange and ugly
if( lineStyle <= PLOT_DASH_TYPE::FIRST_TYPE || aLayer == LAYER_LOCKED_ITEM_SHADOW )
{
switch( aShape->GetShape() )
{
+3
View File
@@ -506,6 +506,9 @@ LSET PCB_VIA::GetLayerSet() const
{
LSET layermask;
if( m_layer < PCBNEW_LAYER_ID_START )
return layermask;
if( GetViaType() == VIATYPE::THROUGH )
layermask = LSET::AllCuMask();
else
+9
View File
@@ -461,6 +461,15 @@ int PCBNEW_JOBS_HANDLER::JobExportDrill( JOB* aJob )
BOARD* brd = LoadBoard( aDrillJob->m_filename );
// ensure output dir exists
wxFileName fn( aDrillJob->m_outputDir + wxT( "/" ) );
if( !fn.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
{
if( aJob->IsCli() )
wxFprintf( stderr, _( "Failed to create output directory\n" ) );
return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
}
std::unique_ptr<GENDRILL_WRITER_BASE> drillWriter;
if( aDrillJob->m_format == JOB_EXPORT_PCB_DRILL::DRILL_FORMAT::EXCELLON )
+11 -11
View File
@@ -1,10 +1,3 @@
/**
* @file plot_board_layers.cpp
* @brief Functions to plot one board layer (silkscreen layers or other layers).
* Silkscreen layers have specific requirement for pads (not filled) and texts
* (with option to remove them from some copper areas (pads...)
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
@@ -28,6 +21,12 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @brief Functions to plot one board layer (silkscreen layers or other layers).
* Silkscreen layers have specific requirement for pads (not filled) and texts
* (with option to remove them from some copper areas (pads...)
*/
#include <eda_item.h>
#include <layer_ids.h>
@@ -448,11 +447,12 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
case PAD_SHAPE::ROUNDRECT:
{
// rounding is stored as a percent, but we have to change the new radius
// to initial_radius + clearance to have a inflated/deflated similar shape
int initial_radius = pad->GetRoundRectCornerRadius();
// rounding is stored as a percent, but we have to update this ratio
// to force recalculation of other values after size changing (we do not
// really change the rounding percent value)
double radius_ratio = pad->GetRoundRectRadiusRatio();
pad->SetSize( padPlotsSize );
pad->SetRoundRectCornerRadius( std::max( initial_radius + mask_clearance, 0 ) );
pad->SetRoundRectRadiusRatio( radius_ratio );
itemplotter.PlotPad( pad, color, padPlotMode );
break;
+18 -3
View File
@@ -531,15 +531,31 @@ ARULE6::ARULE6( ALTIUM_PARSER& aReader )
else if( rulekind == wxT( "HoleSize" ) )
{
kind = ALTIUM_RULE_KIND::HOLE_SIZE;
minLimit = ALTIUM_PARSER::ReadKicadUnit( props, wxT( "MINLIMIT" ), wxT( "1mil" ) );
maxLimit = ALTIUM_PARSER::ReadKicadUnit( props, wxT( "MAXLIMIT" ), wxT( "150mil" ) );
}
else if( rulekind == wxT( "HoleToHoleClearance" ) )
{
kind = ALTIUM_RULE_KIND::HOLE_TO_HOLE_CLEARANCE;
clearanceGap = ALTIUM_PARSER::ReadKicadUnit( props, wxT( "GAP" ), wxT( "10mil" ) );
}
else if( rulekind == wxT( "RoutingVias" ) )
{
kind = ALTIUM_RULE_KIND::ROUTING_VIAS;
width = ALTIUM_PARSER::ReadKicadUnit( props, wxT( "WIDTH" ), wxT( "20mil" ) );
minWidth = ALTIUM_PARSER::ReadKicadUnit( props, wxT( "MINWIDTH" ), wxT( "20mil" ) );
maxWidth = ALTIUM_PARSER::ReadKicadUnit( props, wxT( "MAXWIDTH" ), wxT( "50mil" ) );
holeWidth = ALTIUM_PARSER::ReadKicadUnit( props, wxT( "HOLEWIDTH" ), wxT( "10mil" ) );
minHoleWidth = ALTIUM_PARSER::ReadKicadUnit( props, wxT( "MINHOLEWIDTH" ), wxT( "10mil" ) );
maxHoleWidth = ALTIUM_PARSER::ReadKicadUnit( props, wxT( "MAXHOLEWIDTH" ), wxT( "28mil" ) );
}
else if( rulekind == wxT( "Width" ) )
{
kind = ALTIUM_RULE_KIND::WIDTH;
}
minLimit = ALTIUM_PARSER::ReadKicadUnit( props, wxT( "MINLIMIT" ), wxT( "6mil" ) );
maxLimit = ALTIUM_PARSER::ReadKicadUnit( props, wxT( "MAXLIMIT" ), wxT( "40mil" ) );
preferredWidth = ALTIUM_PARSER::ReadKicadUnit( props, wxT( "PREFERREDWIDTH" ), wxT( "6mil" ) );
}
else if( rulekind == wxT( "PasteMaskExpansion" ) )
{
kind = ALTIUM_RULE_KIND::PASTE_MASK_EXPANSION;
@@ -548,8 +564,7 @@ ARULE6::ARULE6( ALTIUM_PARSER& aReader )
else if( rulekind == wxT( "SolderMaskExpansion" ) )
{
kind = ALTIUM_RULE_KIND::SOLDER_MASK_EXPANSION;
soldermaskExpansion =
ALTIUM_PARSER::ReadKicadUnit( props, wxT( "EXPANSION" ), wxT( "4mil" ) );
soldermaskExpansion = ALTIUM_PARSER::ReadKicadUnit( props, wxT( "EXPANSION" ), wxT( "4mil" ) );
}
else if( rulekind == wxT( "PlaneClearance" ) )
{
+18
View File
@@ -108,6 +108,7 @@ enum class ALTIUM_RULE_KIND
SOLDER_MASK_EXPANSION = 8,
PLANE_CLEARANCE = 9,
POLYGON_CONNECT = 10,
ROUTING_VIAS = 11
};
enum class ALTIUM_CONNECT_STYLE
@@ -499,8 +500,25 @@ struct ARULE6
wxString scope2expr;
// ALTIUM_RULE_KIND::CLEARANCE
// ALTIUM_RULE_KIND::HOLE_TO_HOLE_CLEARANCE
int clearanceGap;
// ALTIUM_RULE_KIND::WIDTH
// ALTIUM_RULE_KIND::HOLE_SIZE
int minLimit;
int maxLimit;
// ALTIUM_RULE_KIND::WIDTH
int preferredWidth;
// ALTIUM_RULE_KIND::ROUTING_VIAS
int width;
int minWidth;
int maxWidth;
int holeWidth;
int minHoleWidth;
int maxHoleWidth;
// ALTIUM_RULE_KIND::PLANE_CLEARANCE
int planeclearanceClearance;
+29
View File
@@ -1901,6 +1901,35 @@ void ALTIUM_PCB::ParseRules6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile
} );
}
const ARULE6* clearanceRule = GetRuleDefault( ALTIUM_RULE_KIND::CLEARANCE );
const ARULE6* trackWidthRule = GetRuleDefault( ALTIUM_RULE_KIND::WIDTH );
const ARULE6* routingViasRule = GetRuleDefault( ALTIUM_RULE_KIND::ROUTING_VIAS );
const ARULE6* holeSizeRule = GetRuleDefault( ALTIUM_RULE_KIND::HOLE_SIZE );
const ARULE6* holeToHoleRule = GetRuleDefault( ALTIUM_RULE_KIND::HOLE_TO_HOLE_CLEARANCE );
if( clearanceRule )
m_board->GetDesignSettings().m_MinClearance = clearanceRule->clearanceGap;
if( trackWidthRule )
{
m_board->GetDesignSettings().m_TrackMinWidth = trackWidthRule->minLimit;
// TODO: construct a custom rule for preferredWidth and maxLimit values
}
if( routingViasRule )
{
m_board->GetDesignSettings().m_ViasMinSize = routingViasRule->minWidth;
m_board->GetDesignSettings().m_MinThroughDrill = routingViasRule->minHoleWidth;
}
if( holeSizeRule )
{
// TODO: construct a custom rule for minLimit / maxLimit values
}
if( holeToHoleRule )
m_board->GetDesignSettings().m_HoleToHoleMin = holeToHoleRule->clearanceGap;
const ARULE6* soldermaskRule = GetRuleDefault( ALTIUM_RULE_KIND::SOLDER_MASK_EXPANSION );
const ARULE6* pastemaskRule = GetRuleDefault( ALTIUM_RULE_KIND::PASTE_MASK_EXPANSION );
+9 -9
View File
@@ -2,8 +2,8 @@
import os.path
from pcbnew import *
size_025_160mm = wxSizeMM(0.25,1.6)
size_150_200mm = wxSizeMM(1.50,2.0)
size_025_160mm = VECTOR2I_MM(0.25,1.6)
size_150_200mm = VECTOR2I_MM(1.50,2.0)
pads = 40
# create a blank board
@@ -12,9 +12,9 @@ pcb = BOARD()
# create a new module, it's parent is our previously created pcb
module = FOOTPRINT(pcb)
module.SetReference("FPC"+str(pads)) # give it a reference name
module.Reference().SetPos0(wxPointMM(-1,-1))
module.Reference().SetPos0(VECTOR2I_MM(-1,-1))
pcb.Add(module) # add it to our pcb
m_pos = wxPointMM(50,50)
m_pos = VECTOR2I_MM(50,50)
module.SetPosition(m_pos)
# create a pad array and add it to the module
@@ -31,18 +31,18 @@ def smdRectPad(module,size,pos,name):
return pad
for n in range (0,pads):
pad = smdRectPad(module,size_025_160mm,wxPointMM(0.5*n,0),str(n+1))
pad = smdRectPad(module,size_025_160mm,VECTOR2I_MM(0.5*n,0),str(n+1))
module.Add(pad)
pad_s0 = smdRectPad(module,size_150_200mm,wxPointMM(-1.6,1.3),"0")
pad_s1 = smdRectPad(module,size_150_200mm,wxPointMM((pads-1)*0.5+1.6,1.3),"0")
pad_s0 = smdRectPad(module,size_150_200mm,VECTOR2I_MM(-1.6,1.3),"0")
pad_s1 = smdRectPad(module,size_150_200mm,VECTOR2I_MM((pads-1)*0.5+1.6,1.3),"0")
module.Add(pad_s0)
module.Add(pad_s1)
e = FP_SHAPE(module)
e.SetStart0(wxPointMM(-1,0))
e.SetEnd0(wxPointMM(0,0))
e.SetStart0(VECTOR2I_MM(-1,0))
e.SetEnd0(VECTOR2I_MM(0,0))
e.SetWidth(FromMM(0.2))
e.SetLayer(F_SilkS)
e.SetShape(S_SEGMENT)
+6 -6
View File
@@ -12,8 +12,8 @@ def fromUTF8Text( aText ):
return aText
def GenerateBoard():
size_0_6mm = wxSizeMM(0.6,0.6)
size_1_0mm = wxSizeMM(1.0,1.0)
size_0_6mm = VECTOR2I_MM(0.6,0.6)
size_1_0mm = VECTOR2I_MM(1.0,1.0)
# create a blank board
pcb = CreateEmptyBoard()
@@ -21,11 +21,11 @@ def GenerateBoard():
# create a new footprint, it's parent is our previously created pcb
footprint = FOOTPRINT(pcb)
footprint.SetReference("M1") # give it a reference name
footprint.Reference().SetPos0(wxPointMM(6,-2))
footprint.Reference().SetPos0(VECTOR2I_MM(3,-2))
footprint.Reference().SetDrawCoord()
pcb.Add(footprint) # add it to our pcb
m_pos = wxPointMM(50,50)
footprint.SetPosition(m_pos)
mod_pos = VECTOR2I_MM(50,50)
footprint.SetPosition(mod_pos)
# create a pad array and add it to the footprint
n = 1
@@ -34,7 +34,7 @@ def GenerateBoard():
pad = PAD(footprint)
pad.SetDrillSize(size_0_6mm)
pad.SetSize(size_1_0mm)
pt = wxPointMM(1.27*x,1.27*y)
pt = VECTOR2I_MM(1.27*x,1.27*y)
pad.SetPos0(pt);
pad.SetDrawCoord()
pad.SetName(str(n))
+7 -4
View File
@@ -25,20 +25,23 @@ print("List vias:")
for item in pcb.GetTracks():
if type(item) is PCB_VIA:
pos = item.GetPosition()
drill = item.GetDrillValue()
width = item.GetWidth()
print(" * Via: %s - %f/%f " % (ToUnits(pos), ToUnits(drill), ToUnits(width)))
elif type(item) is PCB_TRACK:
start = item.GetStart()
end = item.GetEnd()
width = item.GetWidth()
print(" * Track: %s to %s, width %f" % (ToUnits(start), ToUnits(end), ToUnits(width)))
elif type(item) is PCB_ARC:
start = item.GetStart()
end = item.GetEnd()
width = item.GetWidth()
print(" * Track arc: %s to %s, width %f" % (ToUnits(start), ToUnits(end), ToUnits(width)))
else:
print("Unknown type %s" % type(item))
@@ -69,4 +72,4 @@ print("List zones:", pcb.GetAreaCount())
for idx in range(0, pcb.GetAreaCount()):
zone=pcb.GetArea(idx)
print("zone:", idx, "priority:", zone.GetPriority(), "netname", fromUTF8Text( zone.GetNetname() ) )
print("zone:", idx, "priority:", zone.GetAssignedPriority(), "netname", fromUTF8Text( zone.GetNetname() ) )
+1 -1
View File
@@ -50,7 +50,7 @@
%pythoncode
%{
def GetShapeStr(self):
return self.ShowShape(self.GetShape())
return self.ShowShape()
%}
}
+14
View File
@@ -123,6 +123,8 @@ void RN_NET::kruskalMST( const std::vector<CN_EDGE> &aEdges )
const std::shared_ptr<const CN_ANCHOR>& source = tmp.GetSourceNode();
const std::shared_ptr<const CN_ANCHOR>& target = tmp.GetTargetNode();
wxCHECK2( source && !source->Dirty() && target && !target->Dirty(), continue );
if( dset.unite( source->GetTag(), target->GetTag() ) )
{
if( tmp.GetWeight() > 0 )
@@ -416,6 +418,8 @@ void RN_NET::OptimizeRNEdges()
const std::shared_ptr<const CN_ANCHOR>& source = edge.GetSourceNode();
const std::shared_ptr<const CN_ANCHOR>& target = edge.GetTargetNode();
wxCHECK2( source && !source->Dirty() && target && !target->Dirty(), continue );
if( source->ConnectedItemsCount() == 0 )
{
optimizeZoneAnchor( source->Pos(), source->Parent()->GetLayerSet(), target,
@@ -456,6 +460,16 @@ void RN_NET::UpdateNet()
}
void RN_NET::RemoveInvalidRefs()
{
for( CN_EDGE& edge : m_rnEdges )
edge.RemoveInvalidRefs();
for( CN_EDGE& edge : m_boardEdges )
edge.RemoveInvalidRefs();
}
void RN_NET::Clear()
{
m_rnEdges.clear();
+2
View File
@@ -77,6 +77,8 @@ public:
*/
void UpdateNet();
void RemoveInvalidRefs();
/**
* Find optimal ends of RNEdges. The MST will have found the closest anchors, but when
* zones are involved we might have points closer than the anchors.
+4 -3
View File
@@ -196,12 +196,13 @@ void RATSNEST_VIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
const std::shared_ptr<const CN_ANCHOR>& sourceNode = edge.GetSourceNode();
const std::shared_ptr<const CN_ANCHOR>& targetNode = edge.GetTargetNode();
const VECTOR2I source( sourceNode->Pos() );
const VECTOR2I target( targetNode->Pos() );
if( !sourceNode->Valid() || !targetNode->Valid() )
if( !sourceNode || sourceNode->Dirty() || !targetNode || targetNode->Dirty() )
continue;
const VECTOR2I source( sourceNode->Pos() );
const VECTOR2I target( targetNode->Pos() );
bool enable = !sourceNode->GetNoLine() && !targetNode->GetNoLine();
bool show;
+1 -1
View File
@@ -159,7 +159,7 @@ bool DIFF_PAIR_PLACER::propagateDpHeadForces ( const VECTOR2I& aP, VECTOR2I& aNe
if( !obs || handled.count( obs->m_item ) )
break;
int clearance = m_currentNode->GetClearance( obs->m_item, &m_currentTrace.PLine() );
int clearance = m_currentNode->GetClearance( obs->m_item, &m_currentTrace.PLine(), false );
if( obs->m_item->Shape()->Collide( virtHead.Shape(), clearance, &force ) )
{
+26 -4
View File
@@ -126,6 +126,7 @@ public:
void ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems ) override;
void ClearCaches() override;
void ClearTemporaryCaches() override;
private:
/**
@@ -148,6 +149,7 @@ private:
int m_clearanceEpsilon;
std::unordered_map<CLEARANCE_CACHE_KEY, int> m_clearanceCache;
std::unordered_map<CLEARANCE_CACHE_KEY, int> m_tempClearanceCache;
};
@@ -447,6 +449,13 @@ void PNS_PCBNEW_RULE_RESOLVER::ClearCacheForItems( std::vector<const PNS::ITEM*>
void PNS_PCBNEW_RULE_RESOLVER::ClearCaches()
{
m_clearanceCache.clear();
m_tempClearanceCache.clear();
}
void PNS_PCBNEW_RULE_RESOLVER::ClearTemporaryCaches()
{
m_tempClearanceCache.clear();
}
@@ -454,11 +463,17 @@ int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS::ITEM* aA, const PNS::ITEM* a
bool aUseClearanceEpsilon )
{
CLEARANCE_CACHE_KEY key = { aA, aB, aUseClearanceEpsilon };
auto it = m_clearanceCache.find( key );
// Search cache (used for actual board items)
auto it = m_clearanceCache.find( key );
if( it != m_clearanceCache.end() )
return it->second;
// Search cache (used for temporary items within an algorithm)
it = m_tempClearanceCache.find( key );
if( it != m_tempClearanceCache.end() )
return it->second;
PNS::CONSTRAINT constraint;
int rv = 0;
LAYER_RANGE layers;
@@ -519,10 +534,17 @@ int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS::ITEM* aA, const PNS::ITEM* a
/* It makes no sense to put items that have no owning NODE in the cache - they can be allocated on stack
and we can't really invalidate them in the cache when they are destroyed. Probably a better idea would be
to use a static unique counter in PNS::ITEM constructor to generate the cache keys. */
if( aA && aB && aA->Owner() && aB->Owner() )
to use a static unique counter in PNS::ITEM constructor to generate the cache keys. */
/* However, algorithms DO greatly benefit from using the cache, so ownerless items need to be cached.
In order to easily clear those only, a temporary cache is created. If this doesn't seem nice, an alternative
is clearing the full cache once it reaches a certain size. Also not pretty, but VERY effective
to keep things interactive. */
if( aA && aB )
{
m_clearanceCache[ key ] = rv;
if ( aA->Owner() && aB->Owner() )
m_clearanceCache[ key ] = rv;
else
m_tempClearanceCache[ key ] = rv;
}
return rv;
+6 -10
View File
@@ -281,21 +281,17 @@ int NODE::QueryColliding( const ITEM* aItem, NODE::OBSTACLES& aObstacles,
NODE::OPT_OBSTACLE NODE::NearestObstacle( const LINE* aLine,
const COLLISION_SEARCH_OPTIONS& aOpts )
{
const int clearanceEpsilon = GetRuleResolver()->ClearanceEpsilon();
OBSTACLES obstacleList;
std::vector<SEGMENT> tmpSegs;
tmpSegs.reserve( aLine->CLine().SegmentCount() );
const int clearanceEpsilon = GetRuleResolver()->ClearanceEpsilon();
OBSTACLES obstacleList;
for( int i = 0; i < aLine->CLine().SegmentCount(); i++ )
{
// Note: Clearances between tmpSegs.back() and other items are cached,
// Note: Clearances between &s and other items are cached,
// which means they'll be the same for all segments in the line.
// Disabling the cache will lead to slowness.
tmpSegs.emplace_back( *aLine, aLine->CLine().CSegment( i ) );
QueryColliding( &tmpSegs.back(), obstacleList, aOpts );
const SEGMENT s( *aLine, aLine->CLine().CSegment( i ) );
QueryColliding( &s, obstacleList, aOpts );
}
if( aLine->EndsWithVia() )
@@ -703,7 +699,7 @@ void NODE::doRemove( ITEM* aItem )
if( aItem->BelongsTo( m_root ) && !isRoot() )
{
m_override.insert( aItem );
if( aItem->HasHole() )
m_override.insert( aItem->Hole() );
}
+1
View File
@@ -156,6 +156,7 @@ public:
virtual void ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems ) {}
virtual void ClearCaches() {}
virtual void ClearTemporaryCaches() {}
virtual int ClearanceEpsilon() const { return 0; }
};
+2
View File
@@ -494,6 +494,8 @@ bool ROUTER::Move( const VECTOR2I& aP, ITEM* endItem )
break;
}
GetRuleResolver()->ClearTemporaryCaches();
return false;
}
+1 -1
View File
@@ -32,7 +32,7 @@ namespace PNS {
bool VIA::PushoutForce( NODE* aNode, const ITEM* aOther, VECTOR2I& aForce )
{
int clearance = aNode->GetClearance( this, aOther );
int clearance = aNode->GetClearance( this, aOther, false );
VECTOR2I elementForces[4], force;
size_t nf = 0;

Some files were not shown because too many files have changed in this diff Show More