From 35b37bf4625ff8c07ee0900d0e87f18a58901956 Mon Sep 17 00:00:00 2001 From: SAM-BIM-AI Date: Mon, 28 Sep 2026 17:50:57 +0200 Subject: [PATCH 1/8] feat(gh-icons): apply SAM GH icon design system to all 38 SAM_Systems Grasshopper objects Propagates the SAM Grasshopper icon redesign (SAM-BIM/SAM#166) to SAM_Systems: - design/grasshopper-icons: shared SAM-BIM icon kit (icons.py/render.py/ sam_classify.py vendored verbatim from SAM#166 @ cf4d924a, hash-checked; SAM-BIM extension glyphs v1; repo_rules.py), manifest (source of truth), SVG sources, 24x24 PNGs, contact sheet, Rhino 8 icon load test. - 38/38 objects wired through the existing resx/Bitmap mechanism; only the icon token in each Icon getter changes. No GUID/API/behaviour change. Co-Authored-By: Claude Opus 5.5 (cherry picked from commit bad9d316af9e6b6e4a8a7da57fac83b802331ef4) --- .../Classes/GooSystemComponent.cs | 2 +- .../Classes/GooSystemEnergyCentre.cs | 2 +- .../Classes/GooSystemGroup.cs | 2 +- .../Classes/GooSystemObject.cs | 2 +- .../Classes/GooSystemPlantRoom.cs | 2 +- .../Classes/GooSystemSpace.cs | 2 +- ...AMAnalyticalSystemAddSystemEnergyCentre.cs | 2 +- .../SAMAnalyticalSystemComponentType.cs | 2 +- .../SAMAnalyticalSystemConnectedSensor.cs | 2 +- ...alyticalSystemConnectedSystemComponents.cs | 2 +- ...AMAnalyticalSystemConnectedSystemGroups.cs | 2 +- ...MAnalyticalSystemConnectedSystemObjects.cs | 2 +- .../Component/SAMAnalyticalSystemConnector.cs | 2 +- ...stemCreateDisplaySystemConnectorManager.cs | 2 +- ...lyticalSystemCreateDisplaySystemManager.cs | 2 +- ...nalyticalSystemCreateSystemEnergyCentre.cs | 2 +- ...teSystemEnergyCentreByMechanicalSystems.cs | 2 +- ...lyticalSystemCreateSystemGeometrySymbol.cs | 2 +- ...ticalSystemEnergyCentreModifyByAirflows.cs | 2 +- ...alSystemEnergyCentreModifyFanByAirflows.cs | 2 +- .../SAMAnalyticalSystemModifyAirSystem.cs | 2 +- ...AnalyticalSystemOrderedSystemComponents.cs | 2 +- ...AnalyticalSystemPlantRoomRelatedObjects.cs | 2 +- ...AnalyticalSystemResultValueByHourOfYear.cs | 2 +- .../Component/SAMAnalyticalSystemResults.cs | 2 +- .../Component/SAMAnalyticalSystemToAHU.cs | 2 +- .../Component/SAMAnalyticalSystemType.cs | 2 +- .../SAMAnalyticalSystemUpdateAirSystem.cs | 2 +- ...nalyticalSystemVentilationUnitCatalogue.cs | 2 +- ...MSystemsCreateComponentByMollierProcess.cs | 2 +- ...MSystemsCreateDisplaySystemEnergyCentre.cs | 2 +- .../SAMSystemsCreateEnergyCentreByMollier.cs | 2 +- .../SAMSystemsCreatePlantRoomByMollier.cs | 2 +- .../SAMSystemsMergeEnergyCentreByECs.cs | 2 +- .../SAMSystemsMollierTwinWheelExample.cs | 2 +- .../SAMSystemsSystemEnergyCentreDataType.cs | 2 +- .../Properties/Resources.Designer.cs | 340 ++++++ .../Properties/Resources.resx | 102 ++ .../Resources/Icons/SAM_GH_Ahu.png | Bin 0 -> 765 bytes .../Resources/Icons/SAM_GH_AhuConvert.png | Bin 0 -> 1041 bytes .../Resources/Icons/SAM_GH_AhuCreate.png | Bin 0 -> 1026 bytes .../Resources/Icons/SAM_GH_AhuPluralGet.png | Bin 0 -> 1308 bytes .../Resources/Icons/SAM_GH_AhuPluralSort.png | Bin 0 -> 1249 bytes .../Resources/Icons/SAM_GH_AhuValue.png | Bin 0 -> 1023 bytes .../Resources/Icons/SAM_GH_AirflowSet.png | Bin 0 -> 601 bytes .../Icons/SAM_GH_ConnectorCreate.png | Bin 0 -> 641 bytes .../Icons/SAM_GH_ConnectorPluralCreate.png | Bin 0 -> 944 bytes .../Resources/Icons/SAM_GH_EnergyCentre.png | Bin 0 -> 916 bytes .../Icons/SAM_GH_EnergyCentreAdd.png | Bin 0 -> 1330 bytes .../Icons/SAM_GH_EnergyCentreCreate.png | Bin 0 -> 1110 bytes .../Icons/SAM_GH_EnergyCentreDisplay.png | Bin 0 -> 1107 bytes .../Icons/SAM_GH_EnergyCentreMerge.png | Bin 0 -> 1101 bytes .../Icons/SAM_GH_EnergyCentreValue.png | Bin 0 -> 1087 bytes .../Icons/SAM_GH_FanLibraryImport.png | Bin 0 -> 1132 bytes .../Resources/Icons/SAM_GH_FanModify.png | Bin 0 -> 1185 bytes .../Resources/Icons/SAM_GH_FanUpdate.png | Bin 0 -> 1169 bytes .../Icons/SAM_GH_Geometry2DCreate.png | Bin 0 -> 707 bytes .../Resources/Icons/SAM_GH_Object.png | Bin 0 -> 364 bytes .../Icons/SAM_GH_ObjectPluralGet.png | Bin 0 -> 925 bytes .../Resources/Icons/SAM_GH_PlantRoom.png | Bin 0 -> 920 bytes .../Icons/SAM_GH_PlantRoomCreate.png | Bin 0 -> 1200 bytes .../SAM_GH_ProcessHeatRecoveryCreate.png | Bin 0 -> 796 bytes .../Icons/SAM_GH_RelationPluralGet.png | Bin 0 -> 1186 bytes .../Resources/Icons/SAM_GH_ResultGet.png | Bin 0 -> 641 bytes .../Icons/SAM_GH_ResultPluralGet.png | Bin 0 -> 845 bytes .../Resources/Icons/SAM_GH_SettingsCreate.png | Bin 0 -> 657 bytes .../Resources/Icons/SAM_GH_Space.png | Bin 0 -> 663 bytes .../Resources/Icons/SAM_GH_SystemModify.png | Bin 0 -> 816 bytes .../Resources/Icons/SAM_GH_SystemPlural.png | Bin 0 -> 800 bytes .../Icons/SAM_GH_SystemPluralGet.png | Bin 0 -> 1095 bytes .../Resources/Icons/SAM_GH_SystemValue.png | Bin 0 -> 785 bytes .../Resources/Icons/SAM_GH_ThermometerGet.png | Bin 0 -> 830 bytes .../Classes/GooSystem.cs | 2 +- .../Classes/GooSystemResult.cs | 2 +- .../Properties/Resources.Designer.cs | 20 + .../Properties/Resources.resx | 6 + .../Resources/Icons/SAM_GH_Result.png | Bin 0 -> 334 bytes .../Resources/Icons/SAM_GH_System.png | Bin 0 -> 513 bytes design/grasshopper-icons/.gitignore | 3 + .../grasshopper-icons/ICON_DESIGN_SYSTEM.md | 163 +++ .../ICON_DESIGN_SYSTEM_EXT.md | 80 ++ design/grasshopper-icons/manifest.csv | 39 + design/grasshopper-icons/manifest.json | 1066 +++++++++++++++++ design/grasshopper-icons/manifest_raw.json | 648 ++++++++++ design/grasshopper-icons/png/24/ahu.png | Bin 0 -> 765 bytes .../grasshopper-icons/png/24/ahu_convert.png | Bin 0 -> 1041 bytes .../grasshopper-icons/png/24/ahu_create.png | Bin 0 -> 1026 bytes .../png/24/ahu_plural_get.png | Bin 0 -> 1308 bytes .../png/24/ahu_plural_sort.png | Bin 0 -> 1249 bytes design/grasshopper-icons/png/24/ahu_value.png | Bin 0 -> 1023 bytes .../grasshopper-icons/png/24/airflow_set.png | Bin 0 -> 601 bytes .../png/24/connector_create.png | Bin 0 -> 641 bytes .../png/24/connector_plural_create.png | Bin 0 -> 944 bytes .../grasshopper-icons/png/24/energyCentre.png | Bin 0 -> 916 bytes .../png/24/energyCentre_add.png | Bin 0 -> 1330 bytes .../png/24/energyCentre_create.png | Bin 0 -> 1110 bytes .../png/24/energyCentre_display.png | Bin 0 -> 1107 bytes .../png/24/energyCentre_merge.png | Bin 0 -> 1101 bytes .../png/24/energyCentre_value.png | Bin 0 -> 1087 bytes .../png/24/fan_library_import.png | Bin 0 -> 1132 bytes .../grasshopper-icons/png/24/fan_modify.png | Bin 0 -> 1185 bytes .../grasshopper-icons/png/24/fan_update.png | Bin 0 -> 1169 bytes .../png/24/geometry2D_create.png | Bin 0 -> 707 bytes design/grasshopper-icons/png/24/object.png | Bin 0 -> 364 bytes .../png/24/object_plural_get.png | Bin 0 -> 925 bytes design/grasshopper-icons/png/24/plantRoom.png | Bin 0 -> 920 bytes .../png/24/plantRoom_create.png | Bin 0 -> 1200 bytes .../png/24/processHeatRecovery_create.png | Bin 0 -> 796 bytes .../png/24/relation_plural_get.png | Bin 0 -> 1186 bytes design/grasshopper-icons/png/24/result.png | Bin 0 -> 334 bytes .../grasshopper-icons/png/24/result_get.png | Bin 0 -> 641 bytes .../png/24/result_plural_get.png | Bin 0 -> 845 bytes .../png/24/settings_create.png | Bin 0 -> 657 bytes design/grasshopper-icons/png/24/space.png | Bin 0 -> 663 bytes design/grasshopper-icons/png/24/system.png | Bin 0 -> 513 bytes .../png/24/system_modify.png | Bin 0 -> 816 bytes .../png/24/system_plural.png | Bin 0 -> 800 bytes .../png/24/system_plural_get.png | Bin 0 -> 1095 bytes .../grasshopper-icons/png/24/system_value.png | Bin 0 -> 785 bytes .../png/24/thermometer_get.png | Bin 0 -> 830 bytes design/grasshopper-icons/review/REVIEW.md | 8 + .../review/contact_sheet.html | 12 + .../review/contact_sheet.png | Bin 0 -> 258669 bytes design/grasshopper-icons/svg/ahu.svg | 1 + design/grasshopper-icons/svg/ahu_convert.svg | 1 + design/grasshopper-icons/svg/ahu_create.svg | 1 + .../grasshopper-icons/svg/ahu_plural_get.svg | 1 + .../grasshopper-icons/svg/ahu_plural_sort.svg | 1 + design/grasshopper-icons/svg/ahu_value.svg | 1 + design/grasshopper-icons/svg/airflow_set.svg | 1 + .../svg/connector_create.svg | 1 + .../svg/connector_plural_create.svg | 1 + design/grasshopper-icons/svg/energyCentre.svg | 1 + .../svg/energyCentre_add.svg | 1 + .../svg/energyCentre_create.svg | 1 + .../svg/energyCentre_display.svg | 1 + .../svg/energyCentre_merge.svg | 1 + .../svg/energyCentre_value.svg | 1 + .../svg/fan_library_import.svg | 1 + design/grasshopper-icons/svg/fan_modify.svg | 1 + design/grasshopper-icons/svg/fan_update.svg | 1 + .../svg/geometry2D_create.svg | 1 + design/grasshopper-icons/svg/object.svg | 1 + .../svg/object_plural_get.svg | 1 + design/grasshopper-icons/svg/plantRoom.svg | 1 + .../svg/plantRoom_create.svg | 1 + .../svg/processHeatRecovery_create.svg | 1 + .../svg/relation_plural_get.svg | 1 + design/grasshopper-icons/svg/result.svg | 1 + design/grasshopper-icons/svg/result_get.svg | 1 + .../svg/result_plural_get.svg | 1 + .../grasshopper-icons/svg/settings_create.svg | 1 + design/grasshopper-icons/svg/space.svg | 1 + design/grasshopper-icons/svg/system.svg | 1 + .../grasshopper-icons/svg/system_modify.svg | 1 + .../grasshopper-icons/svg/system_plural.svg | 1 + .../svg/system_plural_get.svg | 1 + design/grasshopper-icons/svg/system_value.svg | 1 + .../grasshopper-icons/svg/thermometer_get.svg | 1 + .../tests/GhIconTest/GhIconTest.csproj | 21 + .../tests/GhIconTest/IconTests.cs | 65 + .../tests/GhIconTest/README.md | 16 + .../GhIconTest/Rhino.Testing.Configs.xml | 5 + design/grasshopper-icons/tools/build.py | 145 +++ .../tools/check_assemblies.py | 73 ++ .../grasshopper-icons/tools/check_source.py | 91 ++ design/grasshopper-icons/tools/classify.py | 176 +++ design/grasshopper-icons/tools/icons.py | 782 ++++++++++++ design/grasshopper-icons/tools/icons_ext.py | 223 ++++ design/grasshopper-icons/tools/integrate.py | 206 ++++ design/grasshopper-icons/tools/inventory.py | 129 ++ design/grasshopper-icons/tools/render.py | 132 ++ design/grasshopper-icons/tools/repo_rules.py | 41 + .../grasshopper-icons/tools/sam_classify.py | 422 +++++++ 174 files changed, 5088 insertions(+), 38 deletions(-) create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_Ahu.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AhuConvert.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AhuCreate.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AhuPluralGet.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AhuPluralSort.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AhuValue.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AirflowSet.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ConnectorCreate.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ConnectorPluralCreate.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_EnergyCentre.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_EnergyCentreAdd.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_EnergyCentreCreate.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_EnergyCentreDisplay.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_EnergyCentreMerge.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_EnergyCentreValue.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_FanLibraryImport.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_FanModify.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_FanUpdate.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_Geometry2DCreate.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_Object.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ObjectPluralGet.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_PlantRoom.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_PlantRoomCreate.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ProcessHeatRecoveryCreate.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_RelationPluralGet.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ResultGet.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ResultPluralGet.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_SettingsCreate.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_Space.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_SystemModify.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_SystemPlural.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_SystemPluralGet.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_SystemValue.png create mode 100644 Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ThermometerGet.png create mode 100644 Grasshopper/SAM.Core.Grasshopper.Systems/Resources/Icons/SAM_GH_Result.png create mode 100644 Grasshopper/SAM.Core.Grasshopper.Systems/Resources/Icons/SAM_GH_System.png create mode 100644 design/grasshopper-icons/.gitignore create mode 100644 design/grasshopper-icons/ICON_DESIGN_SYSTEM.md create mode 100644 design/grasshopper-icons/ICON_DESIGN_SYSTEM_EXT.md create mode 100644 design/grasshopper-icons/manifest.csv create mode 100644 design/grasshopper-icons/manifest.json create mode 100644 design/grasshopper-icons/manifest_raw.json create mode 100644 design/grasshopper-icons/png/24/ahu.png create mode 100644 design/grasshopper-icons/png/24/ahu_convert.png create mode 100644 design/grasshopper-icons/png/24/ahu_create.png create mode 100644 design/grasshopper-icons/png/24/ahu_plural_get.png create mode 100644 design/grasshopper-icons/png/24/ahu_plural_sort.png create mode 100644 design/grasshopper-icons/png/24/ahu_value.png create mode 100644 design/grasshopper-icons/png/24/airflow_set.png create mode 100644 design/grasshopper-icons/png/24/connector_create.png create mode 100644 design/grasshopper-icons/png/24/connector_plural_create.png create mode 100644 design/grasshopper-icons/png/24/energyCentre.png create mode 100644 design/grasshopper-icons/png/24/energyCentre_add.png create mode 100644 design/grasshopper-icons/png/24/energyCentre_create.png create mode 100644 design/grasshopper-icons/png/24/energyCentre_display.png create mode 100644 design/grasshopper-icons/png/24/energyCentre_merge.png create mode 100644 design/grasshopper-icons/png/24/energyCentre_value.png create mode 100644 design/grasshopper-icons/png/24/fan_library_import.png create mode 100644 design/grasshopper-icons/png/24/fan_modify.png create mode 100644 design/grasshopper-icons/png/24/fan_update.png create mode 100644 design/grasshopper-icons/png/24/geometry2D_create.png create mode 100644 design/grasshopper-icons/png/24/object.png create mode 100644 design/grasshopper-icons/png/24/object_plural_get.png create mode 100644 design/grasshopper-icons/png/24/plantRoom.png create mode 100644 design/grasshopper-icons/png/24/plantRoom_create.png create mode 100644 design/grasshopper-icons/png/24/processHeatRecovery_create.png create mode 100644 design/grasshopper-icons/png/24/relation_plural_get.png create mode 100644 design/grasshopper-icons/png/24/result.png create mode 100644 design/grasshopper-icons/png/24/result_get.png create mode 100644 design/grasshopper-icons/png/24/result_plural_get.png create mode 100644 design/grasshopper-icons/png/24/settings_create.png create mode 100644 design/grasshopper-icons/png/24/space.png create mode 100644 design/grasshopper-icons/png/24/system.png create mode 100644 design/grasshopper-icons/png/24/system_modify.png create mode 100644 design/grasshopper-icons/png/24/system_plural.png create mode 100644 design/grasshopper-icons/png/24/system_plural_get.png create mode 100644 design/grasshopper-icons/png/24/system_value.png create mode 100644 design/grasshopper-icons/png/24/thermometer_get.png create mode 100644 design/grasshopper-icons/review/REVIEW.md create mode 100644 design/grasshopper-icons/review/contact_sheet.html create mode 100644 design/grasshopper-icons/review/contact_sheet.png create mode 100644 design/grasshopper-icons/svg/ahu.svg create mode 100644 design/grasshopper-icons/svg/ahu_convert.svg create mode 100644 design/grasshopper-icons/svg/ahu_create.svg create mode 100644 design/grasshopper-icons/svg/ahu_plural_get.svg create mode 100644 design/grasshopper-icons/svg/ahu_plural_sort.svg create mode 100644 design/grasshopper-icons/svg/ahu_value.svg create mode 100644 design/grasshopper-icons/svg/airflow_set.svg create mode 100644 design/grasshopper-icons/svg/connector_create.svg create mode 100644 design/grasshopper-icons/svg/connector_plural_create.svg create mode 100644 design/grasshopper-icons/svg/energyCentre.svg create mode 100644 design/grasshopper-icons/svg/energyCentre_add.svg create mode 100644 design/grasshopper-icons/svg/energyCentre_create.svg create mode 100644 design/grasshopper-icons/svg/energyCentre_display.svg create mode 100644 design/grasshopper-icons/svg/energyCentre_merge.svg create mode 100644 design/grasshopper-icons/svg/energyCentre_value.svg create mode 100644 design/grasshopper-icons/svg/fan_library_import.svg create mode 100644 design/grasshopper-icons/svg/fan_modify.svg create mode 100644 design/grasshopper-icons/svg/fan_update.svg create mode 100644 design/grasshopper-icons/svg/geometry2D_create.svg create mode 100644 design/grasshopper-icons/svg/object.svg create mode 100644 design/grasshopper-icons/svg/object_plural_get.svg create mode 100644 design/grasshopper-icons/svg/plantRoom.svg create mode 100644 design/grasshopper-icons/svg/plantRoom_create.svg create mode 100644 design/grasshopper-icons/svg/processHeatRecovery_create.svg create mode 100644 design/grasshopper-icons/svg/relation_plural_get.svg create mode 100644 design/grasshopper-icons/svg/result.svg create mode 100644 design/grasshopper-icons/svg/result_get.svg create mode 100644 design/grasshopper-icons/svg/result_plural_get.svg create mode 100644 design/grasshopper-icons/svg/settings_create.svg create mode 100644 design/grasshopper-icons/svg/space.svg create mode 100644 design/grasshopper-icons/svg/system.svg create mode 100644 design/grasshopper-icons/svg/system_modify.svg create mode 100644 design/grasshopper-icons/svg/system_plural.svg create mode 100644 design/grasshopper-icons/svg/system_plural_get.svg create mode 100644 design/grasshopper-icons/svg/system_value.svg create mode 100644 design/grasshopper-icons/svg/thermometer_get.svg create mode 100644 design/grasshopper-icons/tests/GhIconTest/GhIconTest.csproj create mode 100644 design/grasshopper-icons/tests/GhIconTest/IconTests.cs create mode 100644 design/grasshopper-icons/tests/GhIconTest/README.md create mode 100644 design/grasshopper-icons/tests/GhIconTest/Rhino.Testing.Configs.xml create mode 100644 design/grasshopper-icons/tools/build.py create mode 100644 design/grasshopper-icons/tools/check_assemblies.py create mode 100644 design/grasshopper-icons/tools/check_source.py create mode 100644 design/grasshopper-icons/tools/classify.py create mode 100644 design/grasshopper-icons/tools/icons.py create mode 100644 design/grasshopper-icons/tools/icons_ext.py create mode 100644 design/grasshopper-icons/tools/integrate.py create mode 100644 design/grasshopper-icons/tools/inventory.py create mode 100644 design/grasshopper-icons/tools/render.py create mode 100644 design/grasshopper-icons/tools/repo_rules.py create mode 100644 design/grasshopper-icons/tools/sam_classify.py diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemComponent.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemComponent.cs index bf03e3e7..2b3cf27e 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemComponent.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemComponent.cs @@ -41,7 +41,7 @@ public class GooSystemComponentParam : GH_PersistentParam { public override Guid ComponentGuid => new Guid("2d34ab26-ac12-4ba4-984c-50cdfd7ae237"); - protected override System.Drawing.Bitmap Icon => Resources.SAM3_0; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_Ahu; public GooSystemComponentParam() : base(typeof(ISystemComponent).Name, typeof(ISystemComponent).Name, typeof(ISystemComponent).FullName.Replace(".", " "), "Params", "SAM") diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemEnergyCentre.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemEnergyCentre.cs index d5b46fae..402a7ad4 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemEnergyCentre.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemEnergyCentre.cs @@ -41,7 +41,7 @@ public class GooSystemEnergyCentreParam : GH_PersistentParam new Guid("3f01a7cf-8268-496a-8247-602d1b4f109b"); - protected override System.Drawing.Bitmap Icon => Resources.SAM3_0; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_EnergyCentre; public GooSystemEnergyCentreParam() : base(typeof(SystemEnergyCentre).Name, typeof(SystemEnergyCentre).Name, typeof(SystemEnergyCentre).FullName.Replace(".", " "), "Params", "SAM") diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemGroup.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemGroup.cs index 82e137e6..17f8d337 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemGroup.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemGroup.cs @@ -124,7 +124,7 @@ public class GooSystemGroupParam : GH_PersistentParam, IGH_Previ { public override Guid ComponentGuid => new Guid("3243e174-d434-45bf-bc75-0854c3bb7735"); - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_SystemPlural; public bool Hidden { get; set; } diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemObject.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemObject.cs index 78687061..4e79af04 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemObject.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemObject.cs @@ -127,7 +127,7 @@ public class GooSystemObjectParam : GH_PersistentParam, IGH_Pre { public override Guid ComponentGuid => new Guid("55d4a95d-124b-4e7d-b415-f77e12b6f2dc"); - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_Object; public bool Hidden { get; set; } diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemPlantRoom.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemPlantRoom.cs index 9e010a42..3b61e768 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemPlantRoom.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemPlantRoom.cs @@ -51,7 +51,7 @@ public class GooSystemPlantRoomParam : GH_PersistentParam { public override Guid ComponentGuid => new Guid("cc593874-611a-4378-92a0-85d88ed82b9a"); - protected override System.Drawing.Bitmap Icon => Resources.SAM3_0; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_PlantRoom; public GooSystemPlantRoomParam() : base(typeof(SystemPlantRoom).Name, typeof(SystemPlantRoom).Name, typeof(SystemPlantRoom).FullName.Replace(".", " "), "Params", "SAM") diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemSpace.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemSpace.cs index cba496a2..f93e1bf9 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemSpace.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemSpace.cs @@ -51,7 +51,7 @@ public class GooSystemSpaceParam : GH_PersistentParam { public override Guid ComponentGuid => new Guid("1ea2ed4a-1fd0-44ff-a4cb-a910aefe2fc9"); - protected override System.Drawing.Bitmap Icon => Resources.SAM3_0; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_Space; public override GH_Exposure Exposure => GH_Exposure.hidden; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemAddSystemEnergyCentre.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemAddSystemEnergyCentre.cs index c988ec82..decc4818 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemAddSystemEnergyCentre.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemAddSystemEnergyCentre.cs @@ -26,7 +26,7 @@ public class SAMAnalyticalSystemAddSystemEnergyCentre : GH_SAMVariableOutputPara /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_EnergyCentreAdd; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemComponentType.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemComponentType.cs index 0d8001c3..c7f57e5b 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemComponentType.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemComponentType.cs @@ -23,7 +23,7 @@ public class SAMAnalyticalSystemComponentType : GH_SAMEnumComponent /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_AhuValue; /// /// About SAM Enum Component diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSensor.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSensor.cs index 7faf54ec..4f5a5b33 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSensor.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSensor.cs @@ -26,7 +26,7 @@ public class SAMAnalyticalSystemConnectedSensor : GH_SAMVariableOutputParameterC /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_ThermometerGet; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemComponents.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemComponents.cs index 50871d6b..53413082 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemComponents.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemComponents.cs @@ -26,7 +26,7 @@ public class SAMAnalyticalSystemConnectedSystemComponents : GH_SAMVariableOutput /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_AhuPluralGet; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemGroups.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemGroups.cs index 3c72d791..4b78795f 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemGroups.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemGroups.cs @@ -25,7 +25,7 @@ public class SAMAnalyticalSystemConnectedSystemGroups : GH_SAMVariableOutputPara /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_SystemPluralGet; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemObjects.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemObjects.cs index a6877211..30a074b1 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemObjects.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemObjects.cs @@ -25,7 +25,7 @@ public class SAMAnalyticalSystemConnectedSystemObjects : GH_SAMVariableOutputPar /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_ObjectPluralGet; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnector.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnector.cs index 1259f651..fae006d0 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnector.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnector.cs @@ -31,7 +31,7 @@ public class SAMAnalyticalSystemConnector : GH_SAMVariableOutputParameterCompone /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_ConnectorCreate; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemConnectorManager.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemConnectorManager.cs index 18d43d71..e67ab031 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemConnectorManager.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemConnectorManager.cs @@ -26,7 +26,7 @@ public class SAMAnalyticalSystemCreateDisplaySystemConnectorManager : GH_SAMVari /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_ConnectorPluralCreate; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemManager.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemManager.cs index f1e6ee89..33035af8 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemManager.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemManager.cs @@ -27,7 +27,7 @@ public class SAMAnalyticalSystemCreateDisplaySystemManager : GH_SAMVariableOutpu /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_SettingsCreate; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentre.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentre.cs index 9d220df8..52e3f2d0 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentre.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentre.cs @@ -29,7 +29,7 @@ public class SAMAnalyticalSystemCreateSystemEnergyCentre : GH_SAMVariableOutputP /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_EnergyCentreCreate; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentreByMechanicalSystems.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentreByMechanicalSystems.cs index 8556bbdb..56ae2e69 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentreByMechanicalSystems.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentreByMechanicalSystems.cs @@ -27,7 +27,7 @@ public class SAMAnalyticalSystemCreateSystemEnergyCentreByMechanicalSystems : GH /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_EnergyCentreCreate; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemGeometrySymbol.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemGeometrySymbol.cs index 2f677d56..76e69626 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemGeometrySymbol.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemGeometrySymbol.cs @@ -31,7 +31,7 @@ public class SAMAnalyticalSystemCreateSystemGeometrySymbol : GH_SAMVariableOutpu /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_Geometry2DCreate; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyByAirflows.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyByAirflows.cs index ce0baaef..4aeac813 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyByAirflows.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyByAirflows.cs @@ -27,7 +27,7 @@ public class SAMAnalyticalSystemEnergyCentreModifyByAirflows : GH_SAMVariableOut /// /// Provides an icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_AirflowSet; /// /// Initialises a new instance of the SystemEnergyCentre.ModifyByAirflows component. diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyFanByAirflows.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyFanByAirflows.cs index 81115744..130bc456 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyFanByAirflows.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyFanByAirflows.cs @@ -38,7 +38,7 @@ public SAMAnalyticalSystemEnergyCentreModifyFanByAirflows() /// /// Provides an icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_FanModify; /// /// Registers all the input parameters for this component. diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemModifyAirSystem.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemModifyAirSystem.cs index e8e3629f..aff276ea 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemModifyAirSystem.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemModifyAirSystem.cs @@ -29,7 +29,7 @@ public class SAMAnalyticalSystemModifyAirSystem : GH_SAMVariableOutputParameterC /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_SystemModify; /// /// Initializes a new instance of the SAM_point3D class. diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemOrderedSystemComponents.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemOrderedSystemComponents.cs index 7e492cf5..1532ea8d 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemOrderedSystemComponents.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemOrderedSystemComponents.cs @@ -27,7 +27,7 @@ public class SAMAnalyticalSystemOrderedSystemComponents : GH_SAMVariableOutputPa /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_AhuPluralSort; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemPlantRoomRelatedObjects.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemPlantRoomRelatedObjects.cs index f14be6f8..18d2c7bb 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemPlantRoomRelatedObjects.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemPlantRoomRelatedObjects.cs @@ -27,7 +27,7 @@ public class SAMAnalyticalSystemPlantRoomRelatedObjects : GH_SAMVariableOutputPa /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_RelationPluralGet; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResultValueByHourOfYear.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResultValueByHourOfYear.cs index 26b05283..b20004e8 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResultValueByHourOfYear.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResultValueByHourOfYear.cs @@ -25,7 +25,7 @@ public class SAMAnalyticalSystemResultValueByHourOfYear : GH_SAMVariableOutputPa /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_ResultGet; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResults.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResults.cs index bb0fc187..fafdbecd 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResults.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResults.cs @@ -33,7 +33,7 @@ public class SAMAnalyticalSystemResults : GH_Component, IGH_VariableParameterCom /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_ResultPluralGet; public override bool Obsolete { diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemToAHU.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemToAHU.cs index 5e1b7f32..a2d44b96 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemToAHU.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemToAHU.cs @@ -27,7 +27,7 @@ public class SAMAnalyticalSystemToAHU : GH_SAMVariableOutputParameterComponent /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_AhuConvert; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemType.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemType.cs index ccd0923e..d06f5d77 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemType.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemType.cs @@ -23,7 +23,7 @@ public class SAMAnalyticalSystemType : GH_SAMEnumComponent /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_SystemValue; /// /// About SAM Enum Component diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemUpdateAirSystem.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemUpdateAirSystem.cs index 4cd088de..a807c3f0 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemUpdateAirSystem.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemUpdateAirSystem.cs @@ -28,7 +28,7 @@ public class SAMAnalyticalSystemUpdateAirSystem : GH_SAMVariableOutputParameterC /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_FanUpdate; /// /// Initializes a new instance of the SAM_point3D class. diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemVentilationUnitCatalogue.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemVentilationUnitCatalogue.cs index a7f41c6b..199a4d40 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemVentilationUnitCatalogue.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemVentilationUnitCatalogue.cs @@ -34,7 +34,7 @@ public class SAMAnalyticalSystemVentilationUnitCatalogue : GH_SAMVariableOutputP /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_FanLibraryImport; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateComponentByMollierProcess.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateComponentByMollierProcess.cs index 6d206810..52e46c31 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateComponentByMollierProcess.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateComponentByMollierProcess.cs @@ -27,7 +27,7 @@ public class SAMSystemsCreateComponentByMollierProcess : GH_SAMVariableOutputPar /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_AhuCreate; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateDisplaySystemEnergyCentre.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateDisplaySystemEnergyCentre.cs index 35a014f7..2520f2e4 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateDisplaySystemEnergyCentre.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateDisplaySystemEnergyCentre.cs @@ -26,7 +26,7 @@ public class SAMSystemsCreateDisplaySystemEnergyCentre : GH_SAMVariableOutputPar /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_EnergyCentreDisplay; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateEnergyCentreByMollier.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateEnergyCentreByMollier.cs index 99175f8d..a46b7695 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateEnergyCentreByMollier.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateEnergyCentreByMollier.cs @@ -27,7 +27,7 @@ public class SAMSystemsCreateEnergyCentreByMollier : GH_SAMVariableOutputParamet /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_EnergyCentreCreate; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreatePlantRoomByMollier.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreatePlantRoomByMollier.cs index 5972428a..d01e4901 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreatePlantRoomByMollier.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreatePlantRoomByMollier.cs @@ -27,7 +27,7 @@ public class SAMSystemsCreatePlantRoomByMollier : GH_SAMVariableOutputParameterC /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_PlantRoomCreate; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMergeEnergyCentreByECs.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMergeEnergyCentreByECs.cs index 6326091c..8cdf7255 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMergeEnergyCentreByECs.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMergeEnergyCentreByECs.cs @@ -26,7 +26,7 @@ public class SAMSystemsMergeEnergyCentreByECs : GH_SAMVariableOutputParameterCom /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM3_0; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_EnergyCentreMerge; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMollierTwinWheelExample.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMollierTwinWheelExample.cs index c1461555..868f055f 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMollierTwinWheelExample.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMollierTwinWheelExample.cs @@ -26,7 +26,7 @@ public class SAMSystemsMollierTwinWheelExample : GH_SAMVariableOutputParameterCo /// /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_ProcessHeatRecoveryCreate; public override GH_Exposure Exposure => GH_Exposure.primary; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsSystemEnergyCentreDataType.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsSystemEnergyCentreDataType.cs index 535f5171..5c638079 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsSystemEnergyCentreDataType.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsSystemEnergyCentreDataType.cs @@ -20,7 +20,7 @@ public class SAMSystemsSystemEnergyCentreDataType : GH_SAMEnumComponent /// Provides an Icon for the component. /// - protected override System.Drawing.Bitmap Icon => Resources.SAM_Small; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_EnergyCentreValue; /// /// Panel Type diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Properties/Resources.Designer.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Properties/Resources.Designer.cs index df320bad..83216d8d 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Properties/Resources.Designer.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Properties/Resources.Designer.cs @@ -81,5 +81,345 @@ internal static System.Drawing.Bitmap SAM3_0 return ((System.Drawing.Bitmap)(obj)); } } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_Ahu { + get { + object obj = ResourceManager.GetObject("SAM_GH_Ahu", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_AhuConvert { + get { + object obj = ResourceManager.GetObject("SAM_GH_AhuConvert", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_AhuCreate { + get { + object obj = ResourceManager.GetObject("SAM_GH_AhuCreate", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_AhuPluralGet { + get { + object obj = ResourceManager.GetObject("SAM_GH_AhuPluralGet", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_AhuPluralSort { + get { + object obj = ResourceManager.GetObject("SAM_GH_AhuPluralSort", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_AhuValue { + get { + object obj = ResourceManager.GetObject("SAM_GH_AhuValue", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_AirflowSet { + get { + object obj = ResourceManager.GetObject("SAM_GH_AirflowSet", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_ConnectorCreate { + get { + object obj = ResourceManager.GetObject("SAM_GH_ConnectorCreate", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_ConnectorPluralCreate { + get { + object obj = ResourceManager.GetObject("SAM_GH_ConnectorPluralCreate", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_EnergyCentre { + get { + object obj = ResourceManager.GetObject("SAM_GH_EnergyCentre", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_EnergyCentreAdd { + get { + object obj = ResourceManager.GetObject("SAM_GH_EnergyCentreAdd", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_EnergyCentreCreate { + get { + object obj = ResourceManager.GetObject("SAM_GH_EnergyCentreCreate", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_EnergyCentreDisplay { + get { + object obj = ResourceManager.GetObject("SAM_GH_EnergyCentreDisplay", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_EnergyCentreMerge { + get { + object obj = ResourceManager.GetObject("SAM_GH_EnergyCentreMerge", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_EnergyCentreValue { + get { + object obj = ResourceManager.GetObject("SAM_GH_EnergyCentreValue", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_FanLibraryImport { + get { + object obj = ResourceManager.GetObject("SAM_GH_FanLibraryImport", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_FanModify { + get { + object obj = ResourceManager.GetObject("SAM_GH_FanModify", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_FanUpdate { + get { + object obj = ResourceManager.GetObject("SAM_GH_FanUpdate", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_Geometry2DCreate { + get { + object obj = ResourceManager.GetObject("SAM_GH_Geometry2DCreate", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_Object { + get { + object obj = ResourceManager.GetObject("SAM_GH_Object", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_ObjectPluralGet { + get { + object obj = ResourceManager.GetObject("SAM_GH_ObjectPluralGet", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_PlantRoom { + get { + object obj = ResourceManager.GetObject("SAM_GH_PlantRoom", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_PlantRoomCreate { + get { + object obj = ResourceManager.GetObject("SAM_GH_PlantRoomCreate", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_ProcessHeatRecoveryCreate { + get { + object obj = ResourceManager.GetObject("SAM_GH_ProcessHeatRecoveryCreate", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_RelationPluralGet { + get { + object obj = ResourceManager.GetObject("SAM_GH_RelationPluralGet", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_ResultGet { + get { + object obj = ResourceManager.GetObject("SAM_GH_ResultGet", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_ResultPluralGet { + get { + object obj = ResourceManager.GetObject("SAM_GH_ResultPluralGet", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_SettingsCreate { + get { + object obj = ResourceManager.GetObject("SAM_GH_SettingsCreate", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_Space { + get { + object obj = ResourceManager.GetObject("SAM_GH_Space", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_SystemModify { + get { + object obj = ResourceManager.GetObject("SAM_GH_SystemModify", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_SystemPlural { + get { + object obj = ResourceManager.GetObject("SAM_GH_SystemPlural", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_SystemPluralGet { + get { + object obj = ResourceManager.GetObject("SAM_GH_SystemPluralGet", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_SystemValue { + get { + object obj = ResourceManager.GetObject("SAM_GH_SystemValue", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_ThermometerGet { + get { + object obj = ResourceManager.GetObject("SAM_GH_ThermometerGet", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } } } diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Properties/Resources.resx b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Properties/Resources.resx index 29d1f283..3869376a 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Properties/Resources.resx +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Properties/Resources.resx @@ -130,4 +130,106 @@ ..\Resources\SAM_TasTPD3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\Icons\SAM_GH_Ahu.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_AhuConvert.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_AhuCreate.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_AhuPluralGet.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_AhuPluralSort.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_AhuValue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_AirflowSet.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_ConnectorCreate.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_ConnectorPluralCreate.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_EnergyCentre.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_EnergyCentreAdd.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_EnergyCentreCreate.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_EnergyCentreDisplay.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_EnergyCentreMerge.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_EnergyCentreValue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_FanLibraryImport.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_FanModify.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_FanUpdate.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_Geometry2DCreate.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_Object.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_ObjectPluralGet.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_PlantRoom.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_PlantRoomCreate.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_ProcessHeatRecoveryCreate.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_RelationPluralGet.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_ResultGet.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_ResultPluralGet.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_SettingsCreate.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_Space.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_SystemModify.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_SystemPlural.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_SystemPluralGet.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_SystemValue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_ThermometerGet.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_Ahu.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_Ahu.png new file mode 100644 index 0000000000000000000000000000000000000000..619f510e32a30d3f93b1b3df0b4baa4246630369 GIT binary patch literal 765 zcmVK%qakT)_QENb5|Y-uB_cvn ztZYehYa1h5*s;vw_XU4Td_U8ks0`4B@7tlT9Z4s(-!#qYfq>EghGAS$G->(xywTVhT@6K*(~=ousJ+#Q zOQ-KUUo1PGa8vvG>nLppx~|X3o{%-SBWB@RRUJOIbz*8k7=j>tuZ9qen>Yf6YiCJ; zY{S?3qJ6O>E87%F`IKo#X#h>riYCnq&RtQO3tv#i!y7I9>iJrH`e2bM`RSmX+z}{T zGfVP^d`3&ths7chOJrGj@4D{OUpxzJ^pP z^)uN^F}!}>hOgbW$`~jiWNFV1q)fA`scysDdKU*u4}o)z^73-j*EHkNqL(~>VIBd1 zx;qVAQUy$35+Y{I#jD!Rcl`l=&M?;K;P|lI9G%?Cjsc+%bh&N=B1U^U%~yP=#cm2(C~Q6P#U7-P_N9gHzdUJ%6N8|@f2Qbl-% z(N}Gm0j6n|0krkbnbtCZkJ`PbL_AVai9{lSJ$p+qW{UpZY7qC_vjb+DW)*;H!!WkT zVzJ6CTQ+COs)(G~S(sNmw$JlqjKk^n`UD6Wz|69&lb_?J&vg?U9mjq5_Gy>%=20gY z<7vh%^%kxlZL!}sbhmk)cX6PGu^VrJMW#Y6XY;ElTNz0es~D`q%Xhf>;`Xk9Kr&00000NkvXXu0mjfB!g@E literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AhuConvert.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AhuConvert.png new file mode 100644 index 0000000000000000000000000000000000000000..0cfc6531f8c0a5de889665f734c416a469631fe4 GIT binary patch literal 1041 zcmV+s1n&EZP)s{vfXRFFg=QdcvT!H@~oOzDVF?wDJ9OS#8~#YJ=sa3;QZUe7P*bI$kV ze1E|I@m~kOQeM-v12&s&dpeyS20&{Cu;mJ?s(L_@g(FI?>||i<%H>pYA+uO-7{&(x ztbYpNRaJdll7;5m9EvmaR8T3~T@1#6FFzhd=dpqG<@waiLOR=E7)HlxKuZ7)hoeif z2@l;-l#ds~k3f>eC66u3!q6w@@ZtMkq_51Uk{L7m>PizW*@2=crRxiG%4ZVuIN2V> zuTz(>waf>O3O`c?>!uQ<0P`#?DfZsSql?qr*QSRlx$g08DkIpbpl~I?FKrg zaN&%J*A6v-h|t{Jj57o0@%5f@+I3$M1Au7XCs-D?|6EBZK^~xyO|eH@jrc;cz_1 z3tX!tN;#s;qhMza?tSuhD0UGiUKxcmUqR#H28{I2ptG|Re!m|85Rb9>pB2nVq)UfKN2E36$}O`5{WF4N7FR& zdc9OxS-B>OZWM2YLZSPIhlkP9(t^3UIq15MWHO1at}c|6ln{Vcc8gQI9S(<|@9yqK zet!Nn2S_9k3WZQxTl+d=tm)s7s+fq5N2AfHXf!%SM8}D!_>cVW0%(dxL+Z;Q00000 LNkvXXu0mjfeN^u! literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AhuCreate.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AhuCreate.png new file mode 100644 index 0000000000000000000000000000000000000000..f60c6981b6a196574e37b19fddd89a50a07bfad2 GIT binary patch literal 1026 zcmV+d1pWJoP)LeUHaerzlE=Wm(4ou&DybLSPsV^*~kCC3!cymPZCn?Em;M zeh-hLys`)!$Bo~H5ZqXti|R)f3En)-{afGAN}*cq8?=d6h&Dv_jcd%RShL@ z`$Tkio@M)Xc47FUN#-rf1{Id%qI&fr!Q*#pXHQ*R$rJt+QIsy&wtejHXL46c#=vm| zMHM+HD)$mamPz+F{iv_qjvcS>M>?I(Bs*z}Grxo}_D4dd6gnZ~zJFFAOr%|KR~YAd zZES3424f5@EiLE`_Txy+uWZ>pr33&De;ZY#e<9CWM?L7ydKL5&~t=2W3}$yyAX9`Kx)EHCn&kVVo!2I)nG%%X~^REd$Cg#A3S|4tF7?20BGhW z08rC3-yew@Zre_-u`K)ixnnVF;K(Q_9haiwwxuxa8obcnhq&!vZ~c7iez6>J+rgUc zC&(Awml^=vO|J1v$w;TV1%D!zQuglo4A1XV5Q(J#09|h^1p`pE@h1R4UXFz0Z&e+f z>gUMmy8e{MtDB)SVR}n_kR9lautR+Y8?zlYW;^UqpTQ3FMp*H>AR8R9E^$)?P{S~G zjzkU3lkwcE_%2CR32~hs(iEzC}lCR4>Gi3hWRojkcNpv}$Ti`;zF86TLFsp5w zA1%%Vi4;X5>15)qkCjjWtzpS`}+b4rD;6l{Kn{_2vU77b9A*6ZQ wp34|3i`!0n&wv^388E|f+i7Qvm0jNd6F#VZAe*UQ0000007*qoM6N<$g4he*hyVZp literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AhuPluralGet.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AhuPluralGet.png new file mode 100644 index 0000000000000000000000000000000000000000..c2d1f0abc89fb80d84a69e60bce453405ab22808 GIT binary patch literal 1308 zcmV+%1>^dOP)| zn#xeuO5GB}4X0!hri)_y)DjtlNWcyc?zn@y_ulvJ{q_g5MAXdI*7M)9&%U3}^Zh=b z@AG|t|Jl+3F#H$9Mo|G5j&@%53`|L}VM)QG+PEaE zVW8WYO(9ln(Ce9AZ)lSwDe#X3^m=_NW9(_!A7nqBYsaP2m(_%nXlApUU{AClXJv*q zX{J4Fpl9fDugm|YP8XIeNm3nvz=H~8CC@i4+EA9J6>K^Tc1gJK%`fbHWurQMb{va} z5fB|OLTAuwuQlJ`lt3tx=Xt*@%XPOn_&Z4r219&=VB8f{)E6}xt~n$V3;2RKf1nqI zuN5+#PKSN_KIZnk`W38pL6s#1qazZRG+zMwE#&tMQukd;WHcJ>CUfLIp68EbE=)~( zeoMA4q^Pm&4Fftymk)84Lf)JFvN`{hx|?+H~) zlGHXS14DRN4}rA#>la|fOHc3skd~FCS>Ce%l?N`ONJ82WAv`c!y+_Lf}XRG(0+k3T=10-Bov*=C%?s0t1FRgDBco zgp(&vqNu1C7Q28sc^1}vbpYx4R<^uk8Zz>2U|@qmCG;r~ZFk;urQVHvfZDk>^aR8)lW@^Vz)yKtuq*JRZ+Bm&^5QKnXNn>Fe-Z>Fe+W zlt2>^EuG||{vPLMqtUoCq^O5^PR=bUDPh()0gG~DCY?(1hQM(gi0J)OE#JLWT2;n; zvNUdYoj&8kRVCF#v>QO_ghuoEd;>n8FVAc?Pv!O4?;7$hzTT|Y#HNO80AR!sK-*cT zegBo2+Hp)o0C&_-=|a%gp_D|RHZ12 zWHy`093?7I7O^ZcGSW&!XBO;UMKgBf(z=7iRNvJ?a!?^6qWZ38TDWI55z!g$egYnk zr*m*%_}Q_su?$sJPX{D<>hO?ztJmvwIy}zI;W0M=;OFi(wDw+wRx@4@#yAXmhvD!z zGx-M@8j7N{jEsydyBA)Zw-KA4T8;g6M=>{H<^+s?*bx^aSeufp33<7*pZt^jlbS+gR)C0>{LsROa$| zww6|v{WZLGdX%o%imc?h?=i+||MhQxh-Ud^e??nwdw*MRd%s`yR}j&xTlgPur6Tu1 SQ4|dT0000=-M~-`ntAb-GHrZ88Qdy1_aR<29Y3f1kpu^7$F9X5oTmyrZK^V1PuZP zV$=xB#F*$vbco3e5QEM@fQ&I1QGpD%fvj${w(H94YhT~}{9_U~hKQhvH~Id!`Et*> z_q*r2=K}w;VFTd!FMt(I(`s^Zz5O}kz5Pz7^92AIce0TEP2Qtv+BQiRm-z~^v1r9? z2j_$XA010X2jYgAO1}|}MjHSm{t7_69lEAzTNz`|kJB=wXXI4(Z#9}WVsh%O{ z`8|$ccc_vqw!vYyGrQft@Pk8<#49#i#$>}VS^*^QlwkJcS^nofqAo z$Fj$($jR4WbI9_Aj?03Xv??S?N~BV$)*Beo&7cm4BY&K#Y)+f}Sy2=^tQ4`Np2m^g zS5ULAhS_X3?AY;+@Yai;!sAnU$}kZhGz9-F73^m#5gVZHTb4*s6ra5L) zgELnG6KRyj(@KI0Zh>(424siEC|E_Q9@VRq>a&N^uW!c8BroeU_iJljoS6K z*uQ^2YHK&Z?Nc#*p__I86hxrP!xq;SqP)rr1~!m3t(`=)F?20bax3sr1R09Z^!cWX z363-x8yituTZ@K<2Dm3GCSr7yPMD(T=-uG&%dp!fc{>PRx z%WXxwTZm{2fcjC5rt5l8*Y$-imur$_$A^*d(EOebyO>*&DFVP?e-fRCLPq~3U0l6- z&4EaF!)t46HX=GS@;Y^7tIx0x-hc1)tcfdHZ~K(0s#=`m%Wl>*ja)7lxw17g+pX=& z%F6N((ZOF^3n@_Q9L|l1nbR~1A1fvzIw;+aAQp>t#bS6umgRt=C|gX^T&?SRaJXxN z6|lmX>KEYi@L`!SVBIo8y1QIdL#ckI&}(zlDX?C00000 LNkvXXu0mjfECW;J literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AhuValue.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_AhuValue.png new file mode 100644 index 0000000000000000000000000000000000000000..15a20043a1790f3919d0f5ef28d295d3aaba0a3e GIT binary patch literal 1023 zcmVaL(>_+Y-BFt&M@S($XbeSQKMOug3Hk^`&YP9=t$;ia{|&ibm3s zn2ps3V_MS?>}#`P6SM|NlpseiRa>@TH7=>LCDQFFwcQKL86TQ9uF9q5!51g_o@O$? zZ)P(80sgoD+W5u%x~}haI2@Z(sni(&bh`jHUt&$u_DZsFP$`gI42)g7noP`Q=2|Sv z`Urr1rvP5lv?nE5=*U+Um+?%s65Lh_#(=Lsiz0GlAa!*nIX#=owpy0ey%bOmKvmU` zC5Q0H-6chMDf}2DSYNy#+9`YL+qIjc=Ib@j)e|{b>?s^|b-aLtHHhU|0E^FiGvy-^~M^d(JXpFJlf3HB8uXh98 zlelm?jo0_LgNV@4(Sg$g=ke{1A8G4DB@6(}z9bo znaGADN#J=NwrxXE6xg*=l7|PLz6**|#PL_7a1|+NJJ5>J{%J%a5%~Rn06;7jgJBrd)YQ}g zpnX0qqI5d_O)8l>B#PoMHraveR#tMlCBf}eaJFw6RlyLlQ-z4dVyLUDLnstNAP_)B zMFmXLWaH!G_g7X{4lGqtI8D>`dAzO*Yu0&_9ZaZ+0?F1i2!002ovPDHLkV1gmOBDNo5Tp5BK!Ktx3W<|qVigT>Ff0zFlY@hC@e##Vqz)C(4mvnUOcMtb zjd8-Lq()72z+xim+tx3BfS z0PWWMl8(Z{hAJT5W(^{erD989)>1206V`Tmju}c_7Kjt%fZ<3UjtAmdOAuKjON9jD z(B$y@o`|>XB(K>~Gb{O-Tp$NVy6@dwH8(Vz{dn}J zkJiNLs|v5i1urAlXdLP zs5SxpsY?KyvV4o63mp(;PV_!`1OUiQHzS`yVp4$=c+V-kc%!g$o5qbU4dy-rx#?!h z1t$8QjsY0^CH!c=i_MIQv+kFpxeVaHR!k`?HUl;@w)6r( z$X?xxriR5S6CD@C-WI#J*Mu~HzJFQ-NM6aO2APSP%#5rqYSd&tHAs?yvTPe98(Bz) n_55g3&yOZqNQX%_{;+=o-7x$jk#4oD00000NkvXXu0mjf7{?K# literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ConnectorCreate.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ConnectorCreate.png new file mode 100644 index 0000000000000000000000000000000000000000..e3f150a99799b6d02233715ea2bb89c5fddaf35f GIT binary patch literal 641 zcmV-{0)G98P)dw0NFp@l*G3K zZ~{zldmV+tO^Oo$6RKMqkC2vgv-dyl0Ve3+mQLnzCXz2c7v<-3tt{|YNEOns{w9jP z2Ymp5vllxC#S`0+EWv(ZH3AdZZ+^0p=lf3u>G||=rD2EC-r3O$0P>-o7v^HgIRL|@ z6wnD|W;8<(rF^|~VgUe|Q=#zdsl2EC0D$ob061kX7v&fE5P8ksO8&&iQuE@V07iz* z!3Jlev6f<8mCCmSB5KNHO?7la(?%yWEt54>B5L}t8LX1n1|T>Tj$Y{=7-OO%FGkOq z2ky7-c|}Aw0R*gce)#d*@8oM6Az#}Fjebp#8qo^z^LJ5`h>i*t+_@Zl_N5TGMH@Ct z%Z6NiI?e!et=XcPxL$9Vgh%cB;Bncpm5Ts?mtFhuGqr$o4?kfhuGd>p0MQ}9<67CH z$7RQc#hI*GfnOHYjiT+?$(|1YfN-z@1YjxNUFCvb7F8<>dTyNBwY>E?6X~o`h;N;) zH38ga7I&a`C>%ZCJurr9MFbJ>ZC=NnmRdA7R$gO_1(TMFi_X7+uDxHrGIaK$A@k;3=>ED>UsO}JLi1A z^PNAy|5k};cp_C`d)K^yPtHcLR9# zKM4Rxl0!tixPl4w+65l0y+lPDd%gNnpXWJdxvWq^q9?g73VK z9f3!Y|I=Ji%!&zYGkYn$Uiswt{V%4@UApjF%~~zEk~q>d?E@lujfmuu{`|ddi;vxg zGQ4@G*9`!ZW66BtuPhTtDTQ&OP_VldmvgM6r%83XBuCaN6eB+*67#dk=GzFG{0*_d z9>34KrVhdu7(Ft{`CPu$>2y8`AV5TaFmu=H&02TY(|#8Kod0S%8@+732_OWZdr^s^ z5aK)2G%wuVWMoNh0B7&62L#x0YwPyFBkIYK(Hg`u_c>hhY9df2J9Q@kgQdp0f$&7+YUjgUR{cib zsGZE5V?b0wAOo0*oStvI9$p$d7S{&H-o6GL08oo?B%|y4OEFeE$A+T{0L)xT3ucb4 zXo@@@&o))7IZ6zTiS6`_LceL6$CsTBLs8`cNumb z0NPvJzbj69i-^8mRJ<}{W(h#w$awsXL&qjbS={JcLEzKp)^pE8jX?m1Q3b({p&w)H z-FJq)`_6Fq`b`c^nPohBF)o<-F-H|g_w~N7ua<#Zk>IKQ=d`^$e1!lUlq=0Xvyj_T z6pSzSZ-S=E@EfHiKXI@FH_|p<{`@j#7IIsvsQ`-80ZqO0kD4mOwb+x2EAZ(`s7{e~ zKGpvV0ARdtD;U5MZf{ZH)0I#)74#q3v#ty>1%XVySjHbd(w literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_EnergyCentre.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_EnergyCentre.png new file mode 100644 index 0000000000000000000000000000000000000000..406012bd66f91b780703f203fb18bd9b7b15eef9 GIT binary patch literal 916 zcmV;F18e+=P)bY?CHUzo(n? zbH8)WmvaFA$A2F5`y_cho>j6eUtk!f&ExUNG)?zojP-w{B1w|YDT-n>H8mOGaG2E9 z)nQqdbAljjv5R*smw*t$3xa^!+uNCNI81b1XBmbe7-P{cp0cs!Ns@HL>-9F+B_M=m z8XFs-xw#oI#;CQm6+)rVEJ8?sR|m8xieIptV4*heG-KmGcfK&qDpa8nkg+B^&;Ea81v5{nt3BKaMlTM1w-! ze*JNPY}#Fo>i5<_IynnppXnwKhn^u(;h=VR5Mnoy;Pd&GCWv-U=A43qE?y(f6V+@l zq$(Q%Fx))_otGof`Avja7C~;ACF^$5a&ReYkry`Cvl`mqnzZ3`l|%+4qOHlV^l-*C<}&2y<#>LLIv zAfe}G^;_CprUm5~5|5;+#s*dJ_!(LXz9EWUov@0^1SAGH001y?4&r?&^7{jgn1;DW zRn-=|&)>eLhBl|)(lq@%WF6L{-ao3wqAKzDSy~D@A$oO!1Xl9M<#j+jk|upWJU0_h zGxxKG_4&-qOvh3hphfI%pDZ0i2%V5u@O0vt<`jGk%%x2O2*gZmz1LRT!Ihsco$|@v qtnBxWEp`C^HdvM|UF7oq`*;BWHcayK^~I|I00009*wn literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_EnergyCentreAdd.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_EnergyCentreAdd.png new file mode 100644 index 0000000000000000000000000000000000000000..39f83a7e63a775d0f4f11bb5694e5beb5e568a8b GIT binary patch literal 1330 zcmV-21+JZU@*KUieiz~YE^iiXHKVchuiI5<8(Sd z`cDd|sv0PYB3DyW!vla;t0j-e6L>F<`#TbyP8Vi2n~RM`qt|RUe{L`sB1RKA?uONB zyQjV#p)oQa9MG;$DTgB4SQuus6EMB}ANl8gKckUdjtE>GI5)$~-)YRE6EiC~9 z0|Rio-4EV8i^X!rX0wsaW}~R6D6&{AYIt}!Ns>e+lZk?ZgUMpC5D`&+emH^tJLRdzOhx;OurhZ!IyyR#m6ZjZP6wXn z!59N$3|_An>FMbxE-pq!Mg|l`L0elJ2f#k2$%01saZW}erRUDzq|iV=0LXrQ4!%8f z7AsaPN7R%^cs!oFk~A6(mMvSx0O0D?t58*yTrSs3vMiU6DZugY>**d)2z19up@GO< zw*XnIp2X?W3+U?Z#?IY^x2*^OXliOgMMZ_Hv$K-}uvwPnvhgHht3I4TH6>SQ@Un|V zCr?sWZA$0#!MeLZ_G{N+%PYsg6+7n7OGR~cH2_>!6lG6CLql8m#L4fp_x>>j0HVVK zJ4FrK#27mX0K%mBAS~Y%%P##SqwYu#%g_DhZ&YD~Ou#IGUTAodW{{S*2(Ds`3uC0{|*Fr$A8& z3wJaD06u*+mX=O4E#R6?^tBYP{@GXm_3v=Ie27eukh?dYO|k|d$mBe*QktvA`iXxj$Pj^zsLZr6Z(6Gk_-mJ{Dx!wdoCRBi<`c5 zg64^*P4ElgA^0(39AjM#GFrbM9PxS-S@F?qr_c>$u!sc@&>zvLPj_FeON)U~oK ze+AsJo2cPn2pD_G3;_cCZ}nu{VI@gYCdacP0HLH}joohl41n*i7$Q0~YfJsYi~TMD z!1?XdK>%iLsmDz>1)yf@wA15`Ylp*ed}z>a85*>UcDsGwz2vu+tsrO0XyEdyaCwx` zc;^dKRRFu#!#v1D^uf{d{dwz;{Dz4kB8Y&VAvbofn2Kj-hHYbvZGGrp0};gyyOo1Y o-Ok>oZfEbXTRBKXakuyX1WT(9_<*7%pUD#j)8 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 TLuCmN00000NkvXXu0mjf@M{cO literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_EnergyCentreValue.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_EnergyCentreValue.png new file mode 100644 index 0000000000000000000000000000000000000000..cd0e1619295fb34b966d9f6a21c258215cb5a44a GIT binary patch literal 1087 zcmV-F1i<@=P)K8I4A{p`k%?I-RtlqC(_( zKBm=bpNwapuw4L3sYa{S5}VD&I-O1$3Wby`%TiGk_3`W#ab#+a<6brx3`gQQ5JHw~ zYHHBh+6qw=Nk>NqGBYz*2qB@r%7D@9_0K6)2_K~H(5w9OD+;4BZ7LiRUtd~U8oU+b zW*^o|wn-irfaAEMYK`g>V-}Zk?8QftEG0V;4odju+-1x8Zdbo1N#za&rRG2&;M{IW z6Vfw`UZY8$Dx4_O7CxM}p-9vyQGI+LIrvnu()s0h(S^@P2ULk^Q({<}+zx<33P*C5 z{6WpNA7|qlBx;nXdG;alq3xuy>UgO|ouoQ?-eJeY#KfKL!I36&OR|xXFZOyA7rq#! zpdj}aW^GNCWnkWwO%5I_RzzbFoa?qD5{Y2Xp1l|w8c)eZ-flpwot~h4t=vOlYGN>$5 zlFTdR2OdjRWSEm+&fE?9a~`~2FRH4lHpVs(2*7T)BR@Z%TCLVflAe)zIu?^p@pq}2 z(x*)cckkx50Ck@H0p|S%m=72>AF=Pknto+-^69hldB5)s@gt za5dacVl17yw7B<|@c?vbEW_}mE$)87Yf;h?p^o{K&@ z@cvba#t^$n9e+Bex6>x4@Z2kekT>`o4KqI-Ow^{ZSoKFFP`D$a-0b)JUn?ssJ7lp~ z(A(R)$+@<+79NiWLqkJ@w`0>~-@N}cfHuhVRZ2+9sxR_uEQ-d(#l?a3qy#}YG%+!O zuC6W^3~T-I`Fyb1Y!C#20(g(y$u=sL%KIfrngk&Kfx16#Yin!j@9&4nWC8%p%*;R# z1T;1_zD)>e`Ntm+rL=%j+Uat+uDe{W>y*+?N@>Bm{&x;Jv4rtw>)-$Y002ovPDHLk FV1hWb0@eTk literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_FanLibraryImport.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_FanLibraryImport.png new file mode 100644 index 0000000000000000000000000000000000000000..4c1cadd358df508f08d5f9fa29aed6abba47e42f GIT binary patch literal 1132 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 KMNUMnLSTY!F`n@N literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ObjectPluralGet.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ObjectPluralGet.png new file mode 100644 index 0000000000000000000000000000000000000000..4c62d4495c707c34c7f0984229e341d649ffe655 GIT binary patch literal 925 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 O00001uEi3u4dbdi-6VHc@g^rMzWI+K1c0uj3~ zFD4P)^s97XAz>p(B+>Mu5(Q1umiwCfo-S(T-*9vGTs<%Ec{%Sn&*1_7a|O5?old6< z3=9+<4u`ao1j4NT8Z*~<`>?yaTh-Rq7P%Bo;ckdX4S>BR7#SI<1`rM)-zx%Ns-vT0 zwIoSJvMgu&V$qUy_*Oy~05}|u6U^M3k&*GzYl{Ft)CkHWmD@@|&@2XK=A6QtNf?{{ zWHbbBJm$@(<`9I(2Za(*ttT)Oftc~?bMwrND#T@$I6mz@p8T^3K^M^9VRH46Rvv9Ym>-p*~&6dk&qY*4XWZkPB{OUc_&0BCP- zFO_9E*5z_-&dbYlc}qa`6;Y`?wr}IWvfeh|pNA)-obWXXaf*^h^}R zg4ER1DUZ=*HcL*f?j8Cb1pqN&LH(kV&Joe$`3jnIb91weM&ndpU*BX;PtWAQz`zfW zYd9bP7K>$*#$-00z26T}`P*&DDdWyz6K5r?tp-r>mmoMeIA0KiB5$Re&1T)+Q}tU; zH}wJlUYt*YOJ-zVu>k*4&41g9v8e%U21t1<}~QBczguD*Rpr%p7NzT#dHD$sya| ziSpt{Vjz&9i3TDXEEct)B$N~+6sgo=Fr~H9W!s(I+0WUTdwhVBP)WO1&*T5*oZmh7 z{7)_+&nPM?TICNEoT_=$m=?cnXZyS3IX5RNVzF3sqC6>IfY0yUvvfm9UGqY@XTzJ- zexF}fnE8>(^6~~SSk7ey1Aq_=*AbE=N%CZQa=rj3%ine#`>SzeAdN_W26jeBj^lJr z84w5r)=837<2X)RB9Z9HX0u%d1qHZ%KKcoO=>RqYm+=N4BW`!9NdB$!)V8NwAh_A+q1Ar{c z3q4**ZroC)HorVKP@u}s>$<*m(iz0#@vGBk81W;o_86tLMd&>{ia^jSS+}uL*Y!O_ zG>e%-%=}PEjYGp4*fb$rz8ni@VMVg=`XtP%QsFvWCWL5W<`5Cx zV&pvIh#i&ok1WFSnBb3xXphuzb50@+kIfL8#7}H0C9J- zi@l1shXn@#fCw2Oc!g=2-4ga>cyxX~3o09iu^PnRRj)8oL@4a*G{J&jG7Q6F=GjCPBGAf}&z4ZILPgoa zBIWAoNR8j`FL}_7{{dj;=DCZs%=#VkGyupX`q1AU-^R=~5e)+vWM*fuC!qu@R1E!= z005*?sl;7dud^L{@AYth6#!HR%YRp7<*wRSdLJj_!3POz|2i& z`!1aB=(~VIpNfy$kKT8Fc*{Pqyt2M&${i5V56pZZnu>34IdR~g?pJ(hd3rmRSJuBn zMD73i{h7HoZKn@j8R#9lGSEAew$lfhxpwUQZ^x1mhLG+$qW}N^07*qoM6N<$f)FV* A7XSbN literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ResultGet.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ResultGet.png new file mode 100644 index 0000000000000000000000000000000000000000..9814c7827b140c2306b000c3ae134190a516feea GIT binary patch literal 641 zcmV-{0)G98P)g$Hk_UVw@xu-R-!iKwqsY@&@?Kc*spi258m%%e_^1sm%*#3MhXoJ#j=0aPuK z(_=yJ**5Gw?$FexT(j>%(*b-V1+55ZgrHSRRIi}_r^tc85l&L1=;CrBy||o6ONtaF zqJg@+DDRRS27Tv|*|S~PKX$^Gk@G!a(i?r_Cojzq(HMXrUvNk(5jk@zLCUI7B?1w+ zO0iax8*8!ySD%k#Uq>f~51j#Hd2gEe7-o_xUmNT^IL8WrdjN)u2}L8PO+vX?C=|kt z`AMXHi6uaHy9a`f$NZ-cxcKZABA2IM6-#toQIr=%B>eGtMgY`uv0Yv6C#koh6#(9U zj-e;H1i#B$$m8&BErqY?@7+8Ah@vP0n5{(vK@gPU_(J~>&h?(cLDzNtjy&dS-TSTep6OU75Sa(0S{ b+{O9d)h7c@AmidB00000NkvXXu0mjfiEbit literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ResultPluralGet.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ResultPluralGet.png new file mode 100644 index 0000000000000000000000000000000000000000..3dc417c49ebe18b8ca8c69eb8191ee0ea4172a4d GIT binary patch literal 845 zcmV-T1G4;yP)N3$;a)$PL^~%7TbADD9uv{jAr3wRY~!N?pMohM>i$JQ_`SB; zXiQg?h(bh`?_Mp?c(WIz6EVhe0IUZvm4N3Mw{l0Cn6p|Iuk3A|{A54{5CI^K$^Aa> zaOQuj0TFG{BATbYuS;p~>r%9c<{_djN&iK09PfgPnsC-z%g5l850X3TP&+k6| zh=|Sts1&SLt4k-{`R%I;gNesje&oT=K?HnZfXDy_uCFtINJs|}B!|OsI1~!CK7QYH z;^c#Btjfy6!Qwp=gZQYmfoak3sjYcMje;Nuo1$Ue+40hcj+Z`gJfKHNep^2<5hdvm zUf=Em0K}psF~-gS@Kis!J}IjFMJ^b40Yo~E-8;v&<`o?k{C@u>0GE-kcUX6Qq;Rnb~yUF1~Z`Irp4%zwZM7yGdI) zEQIiRJf4H9s{S-h({d8ya+urAIUfLENRl)Hz~G$sIVn(bSouX+VOJVk_sI1ZcB3?) zBC36_^0<|0(=^}xE0zHO=R61?n6*ubRqsDqTz>pgWybgXVH6);eVqaDan1F}FpS4J zjflAz+wfxfPdsCcvUaeUan8@Vi(K6emn-Fp171wOPvS+_l>N)1pswpr3PQJ%G9D5_ zPopmJuzpr0pPZ6*Xg?M`x4WyXPM5` z&S#%8V22{XyG_pE8-0@uKwHlIj_Kxnb!(UgM-vnoH)zqaY0EG^p^eD_RM3cx*<&xnZVLH}^PrM-6o6~zjOfSGR=?w_r~sk+jejIoZqe^?@_ rS+MLLEt;IwqRH6>%kCkfn)Lo}7)KDU#_@@800000NkvXXu0mjf^V>Oe literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_Space.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_Space.png new file mode 100644 index 0000000000000000000000000000000000000000..63caf6700d4a88713972cde77e1c74bd2cb0ff28 GIT binary patch literal 663 zcmV;I0%-k-P)K{OCNpo-s?b`Sm-|zSd8C#&-s4me)r}8hb(HLMz<_00sxsz zW*UGvD1gp6zvcF@$L0}_9{}t^DeaWX53{lu+Yvf#(!%s-6`hTvZ{Qr=yn7WcH>+yccFLG~GKc7FTrrP^p1~kxzm|}Q{!Z2f z003!(?khobg#+|uegnHf0IH08heFhO-Um%1EPY>xQi>V^0JW2uz8AFcCPqXAm!YZN z!4P%!>=?K5+gZJXzd@7t#)@%e#Cos1LkC&moxoQeHG*tjH34nWfzXDy||>QWw`<~D4{78xPL%bE)f z0363zD{k6PHRW1cS;Qb{m8b88cZkNNu}C(RG9f8bb$8@$6)nK&)B)%bq4YQ1$m8f^EcIOoc; xEENb@DbD$5<>m(^opb((bN=w4jsNQ((H}`I7F>f<4l4iv002ovPDHLkV1fX~C#e7c literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_SystemModify.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_SystemModify.png new file mode 100644 index 0000000000000000000000000000000000000000..64fa3b37a513d7267c539b635f24a353cb4f31e1 GIT binary patch literal 816 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 P00000NkvXXu0mjf`n`M$ literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ThermometerGet.png b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Resources/Icons/SAM_GH_ThermometerGet.png new file mode 100644 index 0000000000000000000000000000000000000000..9b05aa0c69a152dff68a8a12bbc49f5bdbd6a3c9 GIT binary patch literal 830 zcmV-E1Ht@>P)0Bnuaz{~7Q33!oHa3n5A+m$P;NX9u$2mV-Qc_~jcoY{G z2U1c}_Wer@ON_kJ<#O344p~`QHpW;g=e&w@ew1^*H(r201`)Awd1Ll4aV7;lJuOqt zx~`v{>1SdBj3$`4c>e$ZU_Q&A=uH&>8vsKHaV|cIh|Rr3zsJ8wWSMIxTc+^~{O@+}zxZ(w*C3btJ;-NW`w)rEt658H%FZh-+0OCnqnm zTCD?qzu$7F?>PEJ7XToQXQOcOez;sNGEH-tX`1h6#ULpuDO1z5VP*|Y76*WS(FNN) z3F+zS-z7=P7@w%kp>W94{lRZ^fAAZjaL7YMn`2Fp2m}HNPU}LX@f`FE?>K`T*ra*T zbv;2*lp!I+$=h$99IU=o!-69}#@I{p>eE{f+#{kB0IL5gou+B;>gwt!6bVw-$7bsK z*i4~FkZNmdNz=4GBHD1{^#jT{w2^jPuA#sf;U#<@g3jn~&J}=e|yhWbo9;44J_#7C*C*w=* zv`#h*qunr!tXPv$Rak~S`P*>mSv}lKR>r?703g+&deYS;g&SRKCySqZconObjsdJ# zkcL!;>S415Afkd7{`N=D{q3;H3NEx*+y%2{z!-Z>L^a=nMn(0lnqMZB zWKPk|&_w)VaW8UO$Q07*qo IM6N<$f;#ws@Bjb+ literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystem.cs b/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystem.cs index ae0c26e6..ab771175 100644 --- a/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystem.cs +++ b/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystem.cs @@ -48,7 +48,7 @@ public class GooSystemParam : GH_PersistentParam { public override Guid ComponentGuid => new Guid("bceb3ae6-4542-42c3-8930-46982b2ab3c4"); - protected override System.Drawing.Bitmap Icon => Resources.SAM3_0; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_System; public override GH_Exposure Exposure => GH_Exposure.hidden; diff --git a/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystemResult.cs b/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystemResult.cs index 0310d3f0..f3d758b9 100644 --- a/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystemResult.cs +++ b/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystemResult.cs @@ -49,7 +49,7 @@ public class GooSystemResultParam : GH_PersistentParam { public override Guid ComponentGuid => new Guid("ab9deb98-f591-469b-8b47-aa69df35000f"); - protected override System.Drawing.Bitmap Icon => Resources.SAM3_0; + protected override System.Drawing.Bitmap Icon => Resources.SAM_GH_Result; public override GH_Exposure Exposure => GH_Exposure.hidden; diff --git a/Grasshopper/SAM.Core.Grasshopper.Systems/Properties/Resources.Designer.cs b/Grasshopper/SAM.Core.Grasshopper.Systems/Properties/Resources.Designer.cs index 778dde4c..5ed58816 100644 --- a/Grasshopper/SAM.Core.Grasshopper.Systems/Properties/Resources.Designer.cs +++ b/Grasshopper/SAM.Core.Grasshopper.Systems/Properties/Resources.Designer.cs @@ -99,5 +99,25 @@ internal static System.Drawing.Bitmap SAM3_0 { return ((System.Drawing.Bitmap)(obj)); } } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_Result { + get { + object obj = ResourceManager.GetObject("SAM_GH_Result", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SAM_GH_System { + get { + object obj = ResourceManager.GetObject("SAM_GH_System", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } } } diff --git a/Grasshopper/SAM.Core.Grasshopper.Systems/Properties/Resources.resx b/Grasshopper/SAM.Core.Grasshopper.Systems/Properties/Resources.resx index fa52a2ec..4d24d2c8 100644 --- a/Grasshopper/SAM.Core.Grasshopper.Systems/Properties/Resources.resx +++ b/Grasshopper/SAM.Core.Grasshopper.Systems/Properties/Resources.resx @@ -130,4 +130,10 @@ ..\Resources\SAM_Small.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\Icons\SAM_GH_Result.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\SAM_GH_System.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/Grasshopper/SAM.Core.Grasshopper.Systems/Resources/Icons/SAM_GH_Result.png b/Grasshopper/SAM.Core.Grasshopper.Systems/Resources/Icons/SAM_GH_Result.png new file mode 100644 index 0000000000000000000000000000000000000000..5ecc83b93ab145ae5c33962eb59e2963beff333c GIT binary patch literal 334 zcmV-U0kQsxP)LDcpf`Z~{6w0u5o2BCzqA zM;D;*PmE0gOt-VM`|Z59yFkYw4b}tzHa?9BVA&c#RnJ9aw%S1OyjVQ;i|S32ws#M< zuy?$Tr~6l2o!$1zYP}|ao)H9_1}3N$ptOT93=c`hE3wIB-NTduNXEmR{wx{~kSufD zT|cC`+BCEj(1xLv5`EXu-)ZvC08~{;M!6%> z7YCOTB)qygRgG0u3%_esodY-(kuNiRBkJTpfaHa>c3K3`EXyV&{f~cM2*B0J`M#e3 gxUtq+{KwymcPD?1N+rS{(EtDd07*qoM6N<$g1P98)Bpeg literal 0 HcmV?d00001 diff --git a/Grasshopper/SAM.Core.Grasshopper.Systems/Resources/Icons/SAM_GH_System.png b/Grasshopper/SAM.Core.Grasshopper.Systems/Resources/Icons/SAM_GH_System.png new file mode 100644 index 0000000000000000000000000000000000000000..129f5cedf577ff74381c7d82d9a635ac3cfe328d GIT binary patch literal 513 zcmV+c0{;DpP)HV{6vcnfc2w1|L!OaiJ}OixMO1X^K#`yeQjr)bdpBTXIA>T1|n7Oh_nadV1&Ro_pTaeK5v<4{>;~EURJ|#tLAMSfi69 z$&)CGwuTvq$|?8T{NhZ-J16y{f-KAE?Ct?zmrXQH3>0X7*-78N{M2eSx6l60z&H$W zu%Db>xqqEWb0R0#p1xuA@heQz1R##P+`N5-Yq#ce&0cq3zjx!o8NdRf;|AKFa(BZX z&mXSS?Zj->Kl1)vojB_8?9n>Cxc}Ghr%5TlODRL86dSchPJFKapja&8`#z52;CUYH zcAJ7xpz)!Z>o#f)lu}43J5tK8KZ7)({&TsOBcjSzw$2<(w&AYGf~JBui#n7w#` zne$bI5G>!lO8KNU`W{p~x4p15d&2Q-2d+zct1f{|G+;`_iEg!AUJ700000NkvXXu0mjf D9GvZD literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/.gitignore b/design/grasshopper-icons/.gitignore new file mode 100644 index 00000000..990b07d4 --- /dev/null +++ b/design/grasshopper-icons/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +tests/GhIconTest/bin/ +tests/GhIconTest/obj/ diff --git a/design/grasshopper-icons/ICON_DESIGN_SYSTEM.md b/design/grasshopper-icons/ICON_DESIGN_SYSTEM.md new file mode 100644 index 00000000..83b5ea5c --- /dev/null +++ b/design/grasshopper-icons/ICON_DESIGN_SYSTEM.md @@ -0,0 +1,163 @@ +# SAM Grasshopper Icon Design System + +Status: **frozen v1** (2026-09-28). It builds on the approved exploratory direction ("Opus 5.5 proposal", 5 icons), +refined toward the SAM-BIM identity and scaled to the whole library. +`tools/icons.py` implements this file. If they disagree, fix whichever one is wrong. Don't hand-edit generated SVG/PNG. + +## 1. Grammar + +``` +icon = object glyph + SAM-green subject + operation badge + (what) (what is produced (what the component does) + or affected) +``` + +* **Object glyph**: one per SAM object family (§3). It sits in the top-left ~18×18 px and has a strong silhouette. +* **Subject**: the part the component produces, returns or changes is drawn in SAM green. Context is neutral grey/white. +* **Operation badge**: a 10 px disc, always at the bottom-right (centre 19,19). Its colour gives the operation *family*, its glyph the *verb* (§4). +* **Parameters** (`GH_PersistentParam`): the object glyph alone, all green, with no badge. A missing badge means "this is data, not an operation". + +A user learns roughly 40 object shapes and 7 badge colours, and can then read any SAM component. + +## 2. Palette (from https://sambim.xyz, inspected 2026-09-28) + +| Role | Hex | Source | +|---|---|---| +| Ink (outlines, dark glyphs) | `#111111` | site `--text` / `--line` | +| **SAM emblem green** (subject) | `#81BC44` | `assets/SAM_BIM_logo.png`, averaged tile pixels | +| Subject light / shade faces | `#ADD485` / `#659335` | derived from emblem green (35 % tint / 22 % shade) | +| SAM deep green | `#277A45` | site `--green` | +| Blue | `#1565C0` | site `--blue` | +| Yellow | `#F6C90E` | site `--yellow` | +| Red | `#D32F2F` | site `--red` | +| Muted | `#424242` | site `--muted` | +| Neutral faces | `#FFFFFF` / `#E3E3E3` / `#BDBDBD` | site `--bg` / derived / site border grey | + +Rules: +- Flat fills only: no gradients, glows or text. +- Every icon uses the emblem green for its subject. This is the SAM identity. +- The site's primary accents (blue, yellow, red, deep green, black) are used **only** in operation badges, plus two semantic exceptions: the sun is yellow, and the colour glyph uses the site's red/yellow/blue stripe. +- 3D glyphs use 3-tone flat shading (top / left / right), in green when the part is the subject and neutral when it's context. + +## 3. Object families + +| Family | Glyph | Motif | +|---|---|---| +| AnalyticalModel / BuildingModel | `model` | isometric house block (gable roof) | +| AdjacencyCluster | `cluster` | two joined rooms with a green shared-wall seam (the adjacency) | +| Case / scenario | `case` | two models (variants) | +| Space | `space` | isometric room cube | +| ExternalSpace | `externalSpace` | dashed ghost cube | +| Floor (area) | `floor` | cutaway room corner with a green floor (approved exploratory icon) | +| Zone | `zone` | green floor plate carrying two rooms | +| IZAM (inter-zone air) | `izam` | two rooms with an air arc between them | +| Panel | `panel` | upright wall plane | +| Aperture / opening | `aperture` | wall plane with a green window | +| OpeningProperties | `openingProperties` | window with an open green sash | +| Shade | `shade` | overhang plate on a wall | +| Normal | `normal` | wall with a normal arrow | +| Construction (+ Wall/Floor/Roof/HostPartitionType) | `construction` | layered wall block: neutral, green core, neutral | +| ConstructionLayer / MaterialLayer | `constructionLayer` / `materialLayer` | single layer slab (material layer is hatched) | +| ApertureConstruction / OpeningType | `apertureConstruction` | double-glazing unit, green glass | +| ConstructionManager | `constructionManager` | construction + glazing unit together | +| Material (opaque / transparent / gas) | `material` / `transparentMaterial` / `gasMaterial` | sample sphere: solid / clear / dotted | +| Profile | `profile` | step schedule on axes | +| InternalCondition, occupancy, NCM | `internalCondition` | person | +| DegreeOfActivity | `degreeOfActivity` | person with motion ticks | +| Lighting / equipment / infiltration / pollutant gains | `lighting` / `equipment` / `infiltration` / `pollutant` | bulb / monitor / wind / cloud with particles | +| Set-point, comfort, TM52, adaptive | `thermometer` | thermometer | +| Ventilation system | `fan` | fan | +| Airflow | `airflow` | three air arrows | +| AirHandlingUnit, equipment object | `ahu` | box with fan port | +| System / SystemType | `system` | duct unit | +| Heat transfer | `heat` | arrow through a wall | +| Daylight | `daylight` | sun rays onto a floor | +| Level | `level` | datum line with a level marker | +| Shell | `shell` | hexagonal prism (closed solid) | +| Face3D / PlanarBoundary3D | `face` | flat polygon plate | +| Geometry (generic) / Geometry2D | `geometry` / `geometry2D` | hexagon with vertices / flat L-polygon | +| Plane, Transform3D, Mesh, Polyloop, Segment, Points, Vector, Grid | same names | plane + normal, axis triad, fan mesh, loop, segment, 3 points, arrow, dotted floor | +| Section | `sectionBox` | solid split open, green cut face (approved exploratory icon) | +| Weather / WeatherData / WeatherYear / DesignDay | `weather` / `weatherData` / `weatherYear` / `designDay` | sun + cloud / sun + bars / calendar + sun / sun on day arc | +| Location / Address / direction | `location` / `address` / `compass` | map pin / pin + card / compass | +| Time / day | `clock` / `calendar` | clock / calendar | +| Result, DesignExplorer | `result` | bar chart | +| SAM object (generic) | `object` | the SAM emblem tile (green rounded square), no lettering | +| RelationCluster / Group / IndexedObjects / Type | `relation` / `group` / `indexed` / `type` | node graph / dashed group / indexed tiles / shape trio | +| Value / parameter, Name, Text, Number | `value` / `name` / `text` / `number` | tag / label / quotes / ruler | +| Table (DelimitedFileTable, Csv, TableModifier), TextMap | `table` / `textMap` | grid with a green header / two mapped columns | +| JSON, File, Folder, Log, List, DataTree | `json` / `file` / `folder` / `log` / `list` / `tree` | braces / page / folder / log page / bullets / tree | +| Colour | `colour` | the site's red/yellow/blue squares | +| Settings (merge settings, combine type) | `settings` | sliders | +| Matrix | `matrix` | bracketed dot grid | +| About / Version | `info` | emblem tile with "i" (identity exception) | + +## 4. Operation families (badges) + +| Family | Disc | Verbs → glyph | +|---|---|---| +| **Construct** | blue `#1565C0`, white glyph | Create `+` · Add `+` · Copy/Duplicate ⧉ | +| **Query** | deep green `#277A45`, white glyph | Get ↗ (out) · Filter/Select funnel · Inspect magnifier · Report/List ≡ · Display/Label eye | +| **Change** | yellow `#F6C90E`, ink glyph | Set ↙ (in) · Modify/Fix/Adjust/Rename Δ · Update/Map/Replace ↻ · Merge/Join/Combine ⋎ · Split/Cut/Trim ⋏ · Section ⊟ · Union ∪ · Intersect ∩ · Difference ⌐ · Offset ⧈ · Transform/Move ↔ · Snap •\| · Align · Extend →\| · Flip ⇅ · Triangulate · Sort | +| **Remove** | red `#D32F2F`, white glyph | Remove − · Error ! | +| **Evaluate** | ink `#111111`, white glyph | Calculate `=` · Sum `+` · Multiply × · Divide ÷ · Analyse bars · Validate/Check/Is ✓ | +| **Transfer** | white, ink ring and glyph | Convert/To ⇄ · Import/Read/Load/From ↓ · Export/Write/Save/Bake/To-file ↑ | +| **Value** | white, ink ring and glyph | enum value lists (`GH_SAMEnumComponent`) ≡ | + +The badge carries shape **and** colour, so it stays readable with colour-blindness and in greyscale. Mirrored pairs are intentional: Get ↗ out / Set ↙ in, Merge ⋎ / Split ⋏, Union ∪ / Intersect ∩, Import ↓ / Export ↑. + +## 5. Modifiers (object-layer composition) + +| Modifier | Drawing | Used for | +|---|---|---| +| plural | two instances (0.78 scale, fixed offsets) | `GetSpaces` vs `GetSpaceByName`, `…Panels` vs `…Panel` | +| library | two cards behind the object (0.74) | `*Library` objects, default libraries | +| add | neutral existing instance + green new instance | every `Add…` (plurality not drawn) | +| library + add | green item going into a neutral library | `AddMaterials`, `AddMissingProfiles` | +| split effect | glyph cut diagonally and pulled apart | Split/Cut/Trim | +| intersect effect | two neutral instances, overlap in green | Intersection | +| difference effect | green instance with a dashed white cutter | Difference | + +Outline weight stays 1.1 px under every scale: `scaled()` compensates the stroke width. + +## 6. Construction rules + +1. Canvas 24×24, one outline weight (1.1 px ink), round joins. +2. Isometric glyphs use 2:1 pixel isometry, so every solid shares one camera. +3. The bottom-right quadrant (the badge disc, r = 5 with a white ring) is reserved. Glyphs may pass under it, but can't rely on anything there. +4. Minimal detail: no element under ~1.5 px, and no text inside icons. +5. On light Grasshopper bodies the ink outline carries the silhouette. On dark bodies the light/green fills carry it. The white badge ring separates the badge on both. +6. Qualifiers (`…By`) are not drawn. Variants that differ only by qualifier share one icon **intentionally**. +7. **Badge glyph weight** (from the live Rhino review): line glyphs use a stroke of at least 1.6 px (outline shapes at least 1.3 px). Arrows use filled heads. Transfer badges use one bold solid arrow (↓ import, ↑ export, ⇄ convert) and no base line. Thinner glyphs collapsed to a dot at native size. +8. Review every icon on all three Grasshopper body states: normal grey, **orange warning** (the default for a freshly placed component with unconnected inputs) and a dark skin. The yellow Change disc keeps its white ring, so it still reads on the orange warning body. + +## 7. Collision rules + +* Singular vs plural of the same query/change always differ (the plural modifier). +* Create vs Add always differ (single green object vs neutral + green). +* Get vs Set always differ (colour family **and** mirrored arrow). +* `tools/build.py` fails the review if two different icon ids rasterise to identical pixels. The current result is 0 identical groups. + +## 8. Exceptions + +* `SAM.About` / `SAM.Version`: SAM emblem tile + info mark (identity, not an analytical object). +* `SAM.Test` (`A_SAMAnalytical`): it had no Icon override. It gets `object + validate`. This is the only class that gains a new `Icon` line. +* `AssemblyInfo.Icon` / `AssemblyIcon` (the Grasshopper tab/plugin identity) are **not** component icons and keep the SAM logo. +* Hidden/obsolete components get the same grammar icon as their live equivalent. They appear only in old definitions. + +## 9. Pipeline (deterministic) + +``` +tools/inventory.py -> manifest_raw.json (parse C#: every class with ComponentGuid) +tools/classify.py -> manifest.json / .csv (rules + explicit OVERRIDES table) +tools/build.py -> svg/ png/24/ review/batch_*.png SAM_GH_ICON_LIBRARY.png (+ identical-pixel check) +tools/integrate.py -> Grasshopper//Resources/Icons/*.png, Resources.resx, Resources.Designer.cs, Icon getters +tools/catalogue.py -> review/_catalogue/ (all glyphs, badges and modifiers) +tools/check_assemblies.py (every required icon embedded at 24x24 in the built DLLs) +tools/live_review_rhino.py (real Rhino 8 / GH canvas capture, light + dark; see file header) +``` + +The rasteriser renders each SVG alone at a fixed page position, so an icon's PNG depends only on its own SVG. Adding icons never changes existing PNGs. + +Requirements: Python 3 with Pillow, and Microsoft Edge (headless) as the SVG rasteriser. +`svg/` is the canonical editable source. The PNGs are generated, never hand-edited. diff --git a/design/grasshopper-icons/ICON_DESIGN_SYSTEM_EXT.md b/design/grasshopper-icons/ICON_DESIGN_SYSTEM_EXT.md new file mode 100644 index 00000000..f6739e62 --- /dev/null +++ b/design/grasshopper-icons/ICON_DESIGN_SYSTEM_EXT.md @@ -0,0 +1,80 @@ +# SAM-BIM icon design system: extension v1 + +Status: **frozen v1** (2026-09-28). It extends the SAM Grasshopper icon design system (`ICON_DESIGN_SYSTEM.md`, +vendored verbatim from SAM-BIM/SAM#166 @ `cf4d924a`) to the SAM-BIM plugin repositories. +`tools/icons_ext.py` implements this file and is **byte-identical in every SAM-BIM repository**. + +## What the extension may and may not do + +* It **adds** object glyphs for domains where SAM has no noun. It also adds **one** verb, `run`. +* It does **not** change the grammar (object glyph + SAM-green subject + operation badge), the palette, the 7 badge + families and their colours, any SAM glyph, badge or modifier, or the construction rules (24×24, one 1.1 px outline, + flat fills, no text, bottom-right badge quadrant reserved). +* SAM glyphs are reused wherever the noun already exists: space, panel, construction, shell, model, system, fan, + weather, file, table, result and so on. An object that SAM already draws is never redrawn. +* An icon id that also exists in SAM (e.g. `model_import`, `shell_union_plural`) renders **pixel-identically** to + SAM's icon, because `icons.py` and `render.py` are the same bytes. + +## New object glyphs (v1) + +| Glyph | Motif | Used for | +|---|---|---| +| `mollierChart` | psychrometric chart axes + saturation curve, green area | Mollier/psychrometric chart, diagram, generic Mollier object | +| `mollierPoint` | chart (thin) + green state point | MollierPoint | +| `mollierProcess` | chart (thin) + two green states joined | MollierProcess (generic, undefined, by two points), MollierGroup (plural param) | +| `processHeating` / `processCooling` | chart + bold green arrow → / ← (mirrored pair) | heating / cooling processes | +| `processHumidification` | chart + arrow ↑ | isothermal and steam humidification | +| `processAdiabatic` | chart + arrow ↖ | adiabatic humidification | +| `processRoom` | chart + arrow ↗ | room (load) process | +| `processMixing` | chart + two arrows converging on a state | mixing process | +| `processHeatRecovery` | chart + ⇄ arrows | heat recovery process | +| `processFan` | chart + fan disc + short arrow → | fan process | +| `cellComplex` | isometric solid divided into 2×2×2 cells | Topologic/OCCT CellComplex, Topology | +| `algorithm` | objective curve with the green optimum | GenOpt / solver algorithms | +| `objective` | target | optimisation objective | +| `script` | terminal `>_` (dark body, green prompt) | Python / GenOpt / Excel macro scripts | +| `tasks` | three green lanes running in parallel | Multitasker | +| `sound` | speaker + sound waves | acoustic band values and absorption | +| `view` | drawing sheet: green plan + title block | Revit views and sheets | +| `element` | green cube on a neutral base plate | Revit/BIM element instances and ids | +| `energyCentre` | plant block with a stack | SystemEnergyCentre | +| `plantRoom` | SAM `floor` cutaway room with a green plant unit | SystemPlantRoom | +| `connector` | two green units joined by a pipe | system connectors, connected objects | +| `sunPath` | sun + green direction arrow to the ground | sun direction / sun position | +| `solar` | sun + parallel rays onto a green surface | irradiance, sun exposure, solar simulation | + +Process arrows use the mid subject green `#659335` (SAM's `G_RIGHT`) at 2.2 px. It stays readable on the normal, +orange-warning and dark Grasshopper bodies, where the deep green `#277A45` disappears on dark. +Chart glyphs never take the plural modifier (`classify.py` `NO_PLURAL`): stacked charts do not read at 24 px. + +## New verb (v1) + +| Verb | Family | Glyph | Leading words | +|---|---|---|---| +| `run` | **Evaluate** (existing ink disc, white glyph) | ▶ filled play triangle | Run, Simulate, Execute, Solve, Workflow | + +## Classification (tools/classify.py) + +Rules, in order: `repo_rules.OVERRIDES` → SAM `OVERRIDES` → verbs (repo, SAM, extension) → nouns +(repo, extension, SAM) → params (repo, extension, SAM). Plugin name prefixes (`SAMMollier.`, `Tas.`, `SAMOCCT.`, `Revit.` …) +are stripped the way SAM strips `SAMAnalytical.`. Two conventions apply to interop components: + +* external → SAM (`X.SAMAnalytical`, `FromX`, `Open…`) = **import ↓**; SAM → external (`SAMAnalytical.X`, `ToX`, `Save…`) = **export ↑**. +* The object glyph is the SAM object that is read or written (model, geometry, result…), never a vendor logo. + +`repo_rules.py` holds a repository's explicit decisions (overrides, param nouns). Each entry is one line with a reason when +it is not obvious. + +## Tooling (identical in every repo, except `repo_rules.py`) + +``` +tools/inventory.py -> manifest_raw.json (every non-abstract class declaring ComponentGuid, any project layout) +tools/classify.py -> manifest.json/.csv (source of truth: object, op, modifiers, icon id, resource, origin) +tools/build.py -> svg/ png/24/ review/contact_sheet.png review/REVIEW.md (+ identical-pixel check) +tools/integrate.py -> Resources/Icons/*.png, resx + Designer (or the project's icon holder class), Icon getters +tools/check_source.py -> vendored-file hashes, icon-token-only C# diff, ComponentGuid set unchanged +tools/check_assemblies.py -> built .gha/.dll embed every required 24x24 icon +tests/GhIconTest/ -> real Rhino 8 / Grasshopper: every object loads by GUID with its redesigned icon +``` +Vendored verbatim from SAM#166 (hash-checked by `check_source.py`): `icons.py`, `render.py`, `sam_classify.py` +(SAM's `classify.py`), and `ICON_DESIGN_SYSTEM.md`. Requirements: Python 3 + Pillow, Microsoft Edge (headless rasteriser). diff --git a/design/grasshopper-icons/manifest.csv b/design/grasshopper-icons/manifest.csv new file mode 100644 index 00000000..e7dda890 --- /dev/null +++ b/design/grasshopper-icons/manifest.csv @@ -0,0 +1,39 @@ +class,name,nickname,category,subcategory,project,project_dir,source,guid,kind,exposure,obsolete,current_icon,icon_holder,object,op,plural,container,glyph_origin,badge_origin,rule,note,icon_id,resource,icon_file,status +GooSystemComponentParam,{typeof(ISystemComponent).Name},{typeof(ISystemComponent).Name},Params,SAM,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemComponent.cs,2d34ab26-ac12-4ba4-984c-50cdfd7ae237,param,,False,SAM3_0,Resources,ahu,,False,,SAM,,param:SystemComponent,,ahu,SAM_GH_Ahu,svg/ahu.svg,integrated +SAMAnalyticalSystemToAHU,SAMAnalytical.SystemToAHU,SAMAnalytical.SystemToAHU,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemToAHU.cs,6df8ab41-f2bf-4a2a-84ab-427c072c655c,component,GH_Exposure.primary,False,SAM_Small,Resources,ahu,convert,False,,SAM,SAM,override,,ahu_convert,SAM_GH_AhuConvert,svg/ahu_convert.svg,integrated +SAMSystemsCreateComponentByMollierProcess,SAMSystems.CreateComponentByMollierProcess,SAMSystems.CreateComponentByMollierProcess,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateComponentByMollierProcess.cs,d9a5e4c3-6f8b-4cad-9e32-7a4b2c5d8f01,component,GH_Exposure.primary,False,SAM_Small,Resources,ahu,create,False,,SAM,SAM,override,produces a SystemComponent from a Mollier process,ahu_create,SAM_GH_AhuCreate,svg/ahu_create.svg,integrated +SAMAnalyticalSystemConnectedSystemComponents,SAMAnalytical.ConnectedSystemComponents,SAMAnalytical.ConnectedSystemComponents,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemComponents.cs,11f8fdbc-0270-44bf-a2d5-aca2e10a39f7,component,GH_Exposure.primary,False,SAM_Small,Resources,ahu,get,True,,SAM,SAM,override,,ahu_plural_get,SAM_GH_AhuPluralGet,svg/ahu_plural_get.svg,integrated +SAMAnalyticalSystemOrderedSystemComponents,SAMAnalytical.OrderedSystemComponents,SAMAnalytical.OrderedSystemComponents,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemOrderedSystemComponents.cs,32b7d078-f950-4e41-8b19-b93de65c6b01,component,GH_Exposure.primary,False,SAM_Small,Resources,ahu,sort,True,,SAM,SAM,override,,ahu_plural_sort,SAM_GH_AhuPluralSort,svg/ahu_plural_sort.svg,integrated +SAMAnalyticalSystemComponentType,SAM.AnalyticalSystemComponentType,SAM.AnalyticalSystemComponentType,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemComponentType.cs,fd4670c1-70e6-4008-a469-1e8565085293,component,,False,SAM_Small,Resources,ahu,value,False,,SAM,SAM,override,,ahu_value,SAM_GH_AhuValue,svg/ahu_value.svg,integrated +SAMAnalyticalSystemEnergyCentreModifyByAirflows,SystemEnergyCentre.ModifyByAirflows,SystemEnergyCentre.ModifyByAirflows,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyByAirflows.cs,31a4c1d3-6cef-4c5b-a9b1-46684c947ea9,component,,False,SAM_Small,Resources,airflow,set,False,,SAM,SAM,override,,airflow_set,SAM_GH_AirflowSet,svg/airflow_set.svg,integrated +SAMAnalyticalSystemCreateDisplaySystemConnectorManager,SAMAnalytical.CreateDisplaySystemConnectorManager,SAMAnalytical.CreateDisplaySystemConnectorManager,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemConnectorManager.cs,1c03806e-54d8-4136-923c-81c263aeee20,component,GH_Exposure.primary,False,SAM_Small,Resources,connector,create,True,,SAM-BIM ext v1,SAM,override,,connector_plural_create,SAM_GH_ConnectorPluralCreate,svg/connector_plural_create.svg,integrated +SAMAnalyticalSystemConnector,SAMAnalytical.SystemConnector,SAMAnalytical.SystemConnector,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnector.cs,81ad840f-1382-4091-9f6e-7c15affc2384,component,GH_Exposure.primary,False,SAM_Small,Resources,connector,create,False,,SAM-BIM ext v1,SAM,override,,connector_create,SAM_GH_ConnectorCreate,svg/connector_create.svg,integrated +GooSystemEnergyCentreParam,{typeof(SystemEnergyCentre).Name},{typeof(SystemEnergyCentre).Name},Params,SAM,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemEnergyCentre.cs,3f01a7cf-8268-496a-8247-602d1b4f109b,param,,False,SAM3_0,Resources,energyCentre,,False,,SAM-BIM ext v1,,param:SystemEnergyCentre,,energyCentre,SAM_GH_EnergyCentre,svg/energyCentre.svg,integrated +SAMAnalyticalSystemAddSystemEnergyCentre,SAMAnalytical.AddSystemEnergyCentre,SAMAnalytical.AddSystemEnergyCentre,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemAddSystemEnergyCentre.cs,271e61dd-abc3-496e-b4d5-ca7be989c3ed,component,GH_Exposure.primary,False,SAM_Small,Resources,energyCentre,add,False,,SAM-BIM ext v1,SAM,rule,,energyCentre_add,SAM_GH_EnergyCentreAdd,svg/energyCentre_add.svg,integrated +SAMAnalyticalSystemCreateSystemEnergyCentre,SAMAnalytical.CreateSystemEnergyCentre,SAMAnalytical.CreateSystemEnergyCentre,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentre.cs,980a8d42-ad72-49fa-b6fc-1ad98fa234bc,component,GH_Exposure.primary,False,SAM_Small,Resources,energyCentre,create,False,,SAM-BIM ext v1,SAM,rule,,energyCentre_create,SAM_GH_EnergyCentreCreate,svg/energyCentre_create.svg,integrated +SAMAnalyticalSystemCreateSystemEnergyCentreByMechanicalSystems,SAMAnalytical.CreateSystemEnergyCentreByMechanicalSystems,SAMAnalytical.CreateSystemEnergyCentreByMechanicalSystems,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentreByMechanicalSystems.cs,168d4a90-00c3-424e-b4ec-d97437bac56b,component,GH_Exposure.primary,False,SAM_Small,Resources,energyCentre,create,False,,SAM-BIM ext v1,SAM,rule,,energyCentre_create,SAM_GH_EnergyCentreCreate,svg/energyCentre_create.svg,integrated +SAMSystemsCreateEnergyCentreByMollier,SAMSystems.CreateEnergyCentreByMollier,SAMSystems.CreateEnergyCentreByMollier,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateEnergyCentreByMollier.cs,b7e3c2a1-4d6f-4a8b-9c12-7e5f0a3b6d24,component,GH_Exposure.primary,False,SAM_Small,Resources,energyCentre,create,False,,SAM-BIM ext v1,SAM,rule,,energyCentre_create,SAM_GH_EnergyCentreCreate,svg/energyCentre_create.svg,integrated +SAMSystemsCreateDisplaySystemEnergyCentre,SAMSystems.CreateDisplaySystemEnergyCentre,SAMSystems.CreateDisplaySystemEnergyCentre,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateDisplaySystemEnergyCentre.cs,a3d8c1f6-4e57-49b2-9c0a-7d2e5f8b41c9,component,GH_Exposure.primary,False,SAM_Small,Resources,energyCentre,display,False,,SAM-BIM ext v1,SAM,override,previewable schematic,energyCentre_display,SAM_GH_EnergyCentreDisplay,svg/energyCentre_display.svg,integrated +SAMSystemsMergeEnergyCentreByECs,SAMSystems.MergeEnergyCentreByECs,SAMSystems.MergeEnergyCentreByECs,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMergeEnergyCentreByECs.cs,3e1534f7-3ff4-40a0-8b29-1633699eeab5,component,GH_Exposure.primary,False,SAM3_0,Resources,energyCentre,merge,False,,SAM-BIM ext v1,SAM,rule,,energyCentre_merge,SAM_GH_EnergyCentreMerge,svg/energyCentre_merge.svg,integrated +SAMSystemsSystemEnergyCentreDataType,SAMSystems.SystemEnergyCentreDataType,SAMSystems.SystemEnergyCentreDataType,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsSystemEnergyCentreDataType.cs,2ce0997f-a5e2-457d-9baa-39fbc2a5ebb6,component,,False,SAM_Small,Resources,energyCentre,value,False,,SAM-BIM ext v1,SAM,rule,,energyCentre_value,SAM_GH_EnergyCentreValue,svg/energyCentre_value.svg,integrated +SAMAnalyticalSystemVentilationUnitCatalogue,SAMAnalytical.SystemVentilationUnitCatalogue,SAMAnalytical.SystemVentilationUnitCatalogue,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemVentilationUnitCatalogue.cs,8b6e1f3a-4d2c-4a91-9e7b-2c5f6a8d1e30,component,GH_Exposure.primary,False,SAM_Small,Resources,fan,import,False,library,SAM,SAM,override,,fan_library_import,SAM_GH_FanLibraryImport,svg/fan_library_import.svg,integrated +SAMAnalyticalSystemEnergyCentreModifyFanByAirflows,SystemEnergyCentre.ModifyFanByAirflows,SystemEnergyCentre.ModifyFanByAirflows,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyFanByAirflows.cs,53ff901d-4a76-4b3e-b9e1-6ca0c9d4b04d,component,,False,SAM_Small,Resources,fan,modify,False,,SAM,SAM,override,,fan_modify,SAM_GH_FanModify,svg/fan_modify.svg,integrated +SAMAnalyticalSystemUpdateAirSystem,SAMAnalytical.UpdateVentilationSystem,SAMAnalytical.UpdateVentilationSystem,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemUpdateAirSystem.cs,76c087b1-93ed-4a20-873a-cabf2e176f0c,component,,False,SAM_Small,Resources,fan,update,False,,SAM,SAM,rule,,fan_update,SAM_GH_FanUpdate,svg/fan_update.svg,integrated +SAMAnalyticalSystemCreateSystemGeometrySymbol,SAMAnalytical.CreateSystemGeometrySymbol,SAMAnalytical.CreateSystemGeometrySymbol,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemGeometrySymbol.cs,9f1933d2-d443-4caf-9e7d-8d61023d7360,component,GH_Exposure.primary,False,SAM_Small,Resources,geometry2D,create,False,,SAM,SAM,override,2D schematic symbol,geometry2D_create,SAM_GH_Geometry2DCreate,svg/geometry2D_create.svg,integrated +GooSystemObjectParam,{typeof(ISystemObject).Name},{typeof(ISystemObject).Name},Params,SAM,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemObject.cs,55d4a95d-124b-4e7d-b415-f77e12b6f2dc,param,,False,SAM_Small,Resources,object,,False,,SAM,,param:SystemObject,,object,SAM_GH_Object,svg/object.svg,integrated +SAMAnalyticalSystemConnectedSystemObjects,SAMAnalytical.ConnectedSystemObjects,SAMAnalytical.ConnectedSystemObjects,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemObjects.cs,162c87ab-0bd8-493f-bebb-4b04b93ee498,component,GH_Exposure.primary,False,SAM_Small,Resources,object,get,True,,SAM,SAM,override,,object_plural_get,SAM_GH_ObjectPluralGet,svg/object_plural_get.svg,integrated +GooSystemPlantRoomParam,{typeof(SystemPlantRoom).Name},{typeof(SystemPlantRoom).Name},Params,SAM,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemPlantRoom.cs,cc593874-611a-4378-92a0-85d88ed82b9a,param,,False,SAM3_0,Resources,plantRoom,,False,,SAM-BIM ext v1,,param:SystemPlantRoom,,plantRoom,SAM_GH_PlantRoom,svg/plantRoom.svg,integrated +SAMSystemsCreatePlantRoomByMollier,SAMSystems.CreatePlantRoomByMollier,SAMSystems.CreatePlantRoomByMollier,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreatePlantRoomByMollier.cs,c8f4d3b2-5e7a-4b9c-8d21-6f3a1b4c7e90,component,GH_Exposure.primary,False,SAM_Small,Resources,plantRoom,create,False,,SAM-BIM ext v1,SAM,rule,,plantRoom_create,SAM_GH_PlantRoomCreate,svg/plantRoom_create.svg,integrated +SAMSystemsMollierTwinWheelExample,SAMSystems.MollierTwinWheelExample,SAMSystems.MollierTwinWheelExample,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMollierTwinWheelExample.cs,e1b6f5d4-7a9c-4dbe-af43-8b5c3d6e9f12,component,GH_Exposure.primary,False,SAM_Small,Resources,processHeatRecovery,create,False,,SAM-BIM ext v1,SAM,override,worked twin-wheel heat-recovery example,processHeatRecovery_create,SAM_GH_ProcessHeatRecoveryCreate,svg/processHeatRecovery_create.svg,integrated +SAMAnalyticalSystemPlantRoomRelatedObjects,SystemPlantRoom.RelatedObjects,SystemPlantRoom.RelatedObjects,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemPlantRoomRelatedObjects.cs,7e6476fa-9fcc-448a-82ee-9f08fbdc03de,component,GH_Exposure.primary,False,SAM_Small,Resources,relation,get,True,,SAM,SAM,rule,,relation_plural_get,SAM_GH_RelationPluralGet,svg/relation_plural_get.svg,integrated +SAMAnalyticalSystemResultValueByHourOfYear,SAMAnalytical.SystemResultValueByHourOfYear,SAMAnalytical.SystemResultValueByHourOfYear,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResultValueByHourOfYear.cs,8e927e8f-58d2-4d07-8952-86f09cdfb6a6,component,GH_Exposure.primary,False,SAM_Small,Resources,result,get,False,,SAM,SAM,override,,result_get,SAM_GH_ResultGet,svg/result_get.svg,integrated +SAMAnalyticalSystemResults,SAMAnalytical.SystemResults,SAMAnalytical.SystemResults,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResults.cs,b095f799-82ce-4a41-9c56-f9ccfa921065,component,GH_Exposure.tertiary,False,SAM_Small,Resources,result,get,True,,SAM,SAM,override,,result_plural_get,SAM_GH_ResultPluralGet,svg/result_plural_get.svg,integrated +SAMAnalyticalSystemCreateDisplaySystemManager,SAMAnalytical.CreateDisplaySystemManager,SAMAnalytical.CreateDisplaySystemManager,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemManager.cs,8b67bdca-b7f6-4707-b90a-d15959f08316,component,GH_Exposure.primary,False,SAM_Small,Resources,settings,create,False,,SAM,SAM,override,component-type -> symbol display settings,settings_create,SAM_GH_SettingsCreate,svg/settings_create.svg,integrated +GooSystemSpaceParam,{typeof(ISystemSpace).Name},{typeof(ISystemSpace).Name},Params,SAM,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemSpace.cs,1ea2ed4a-1fd0-44ff-a4cb-a910aefe2fc9,param,GH_Exposure.hidden,False,SAM3_0,Resources,space,,False,,SAM,,param:SystemSpace,,space,SAM_GH_Space,svg/space.svg,integrated +GooSystemGroupParam,{typeof(ISystemGroup).Name},{typeof(ISystemGroup).Name},Params,SAM,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemGroup.cs,3243e174-d434-45bf-bc75-0854c3bb7735,param,,False,SAM_Small,Resources,system,,True,,SAM,,param:SystemGroup,,system_plural,SAM_GH_SystemPlural,svg/system_plural.svg,integrated +SAMAnalyticalSystemConnectedSystemGroups,SAMAnalytical.ConnectedSystemGroups,SAMAnalytical.ConnectedSystemGroups,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemGroups.cs,761a15c3-a6da-491f-b959-7d991a46bb52,component,GH_Exposure.primary,False,SAM_Small,Resources,system,get,True,,SAM,SAM,override,,system_plural_get,SAM_GH_SystemPluralGet,svg/system_plural_get.svg,integrated +SAMAnalyticalSystemModifyAirSystem,SAMAnalytical.ModifyAirSystem,SAMAnalytical.ModifyAirSystem,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemModifyAirSystem.cs,6f57c6d7-8669-45a0-8af6-9595572921c2,component,,False,SAM_Small,Resources,system,modify,False,,SAM,SAM,rule,,system_modify,SAM_GH_SystemModify,svg/system_modify.svg,integrated +SAMAnalyticalSystemType,SAM.AnalyticalSystemType,SAM.AnalyticalSystemType,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemType.cs,75997483-9ed7-4404-afd8-627144405160,component,,False,SAM_Small,Resources,system,value,False,,SAM,SAM,rule,,system_value,SAM_GH_SystemValue,svg/system_value.svg,integrated +SAMAnalyticalSystemConnectedSensor,SAMAnalytical.ConnectedSensor,SAMAnalytical.ConnectedSensor,SAM,Systems,SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems,Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSensor.cs,8341425d-783f-49ad-a8db-d5269d128800,component,GH_Exposure.primary,False,SAM_Small,Resources,thermometer,get,False,,SAM,SAM,override,the sensor a controller reads,thermometer_get,SAM_GH_ThermometerGet,svg/thermometer_get.svg,integrated +GooSystemResultParam,{typeof(ISystemResult).Name},{typeof(ISystemResult).Name},Params,SAM,SAM.Core.Grasshopper.Systems,Grasshopper/SAM.Core.Grasshopper.Systems,Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystemResult.cs,ab9deb98-f591-469b-8b47-aa69df35000f,param,GH_Exposure.hidden,False,SAM3_0,Resources,result,,False,,SAM,,param:SystemResult,,result,SAM_GH_Result,svg/result.svg,integrated +GooSystemParam,{typeof(Core.Systems.ISystem).Name},{typeof(Core.Systems.ISystem).Name},Params,SAM,SAM.Core.Grasshopper.Systems,Grasshopper/SAM.Core.Grasshopper.Systems,Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystem.cs,bceb3ae6-4542-42c3-8930-46982b2ab3c4,param,GH_Exposure.hidden,False,SAM3_0,Resources,system,,False,,SAM,,param:System,,system,SAM_GH_System,svg/system.svg,integrated diff --git a/design/grasshopper-icons/manifest.json b/design/grasshopper-icons/manifest.json new file mode 100644 index 00000000..4d151582 --- /dev/null +++ b/design/grasshopper-icons/manifest.json @@ -0,0 +1,1066 @@ +[ + { + "class": "GooSystemComponentParam", + "name": "{typeof(ISystemComponent).Name}", + "nickname": "{typeof(ISystemComponent).Name}", + "category": "Params", + "subcategory": "SAM", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemComponent.cs", + "guid": "2d34ab26-ac12-4ba4-984c-50cdfd7ae237", + "kind": "param", + "exposure": null, + "obsolete": false, + "current_icon": "SAM3_0", + "icon_holder": "Resources", + "object": "ahu", + "op": null, + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": null, + "rule": "param:SystemComponent", + "note": null, + "icon_id": "ahu", + "resource": "SAM_GH_Ahu", + "icon_file": "svg/ahu.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemToAHU", + "name": "SAMAnalytical.SystemToAHU", + "nickname": "SAMAnalytical.SystemToAHU", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemToAHU.cs", + "guid": "6df8ab41-f2bf-4a2a-84ab-427c072c655c", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "ahu", + "op": "convert", + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": null, + "icon_id": "ahu_convert", + "resource": "SAM_GH_AhuConvert", + "icon_file": "svg/ahu_convert.svg", + "status": "integrated" + }, + { + "class": "SAMSystemsCreateComponentByMollierProcess", + "name": "SAMSystems.CreateComponentByMollierProcess", + "nickname": "SAMSystems.CreateComponentByMollierProcess", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateComponentByMollierProcess.cs", + "guid": "d9a5e4c3-6f8b-4cad-9e32-7a4b2c5d8f01", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "ahu", + "op": "create", + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": "produces a SystemComponent from a Mollier process", + "icon_id": "ahu_create", + "resource": "SAM_GH_AhuCreate", + "icon_file": "svg/ahu_create.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemConnectedSystemComponents", + "name": "SAMAnalytical.ConnectedSystemComponents", + "nickname": "SAMAnalytical.ConnectedSystemComponents", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemComponents.cs", + "guid": "11f8fdbc-0270-44bf-a2d5-aca2e10a39f7", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "ahu", + "op": "get", + "plural": true, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": null, + "icon_id": "ahu_plural_get", + "resource": "SAM_GH_AhuPluralGet", + "icon_file": "svg/ahu_plural_get.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemOrderedSystemComponents", + "name": "SAMAnalytical.OrderedSystemComponents", + "nickname": "SAMAnalytical.OrderedSystemComponents", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemOrderedSystemComponents.cs", + "guid": "32b7d078-f950-4e41-8b19-b93de65c6b01", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "ahu", + "op": "sort", + "plural": true, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": null, + "icon_id": "ahu_plural_sort", + "resource": "SAM_GH_AhuPluralSort", + "icon_file": "svg/ahu_plural_sort.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemComponentType", + "name": "SAM.AnalyticalSystemComponentType", + "nickname": "SAM.AnalyticalSystemComponentType", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemComponentType.cs", + "guid": "fd4670c1-70e6-4008-a469-1e8565085293", + "kind": "component", + "exposure": null, + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "ahu", + "op": "value", + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": null, + "icon_id": "ahu_value", + "resource": "SAM_GH_AhuValue", + "icon_file": "svg/ahu_value.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemEnergyCentreModifyByAirflows", + "name": "SystemEnergyCentre.ModifyByAirflows", + "nickname": "SystemEnergyCentre.ModifyByAirflows", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyByAirflows.cs", + "guid": "31a4c1d3-6cef-4c5b-a9b1-46684c947ea9", + "kind": "component", + "exposure": null, + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "airflow", + "op": "set", + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": null, + "icon_id": "airflow_set", + "resource": "SAM_GH_AirflowSet", + "icon_file": "svg/airflow_set.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemCreateDisplaySystemConnectorManager", + "name": "SAMAnalytical.CreateDisplaySystemConnectorManager", + "nickname": "SAMAnalytical.CreateDisplaySystemConnectorManager", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemConnectorManager.cs", + "guid": "1c03806e-54d8-4136-923c-81c263aeee20", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "connector", + "op": "create", + "plural": true, + "container": null, + "glyph_origin": "SAM-BIM ext v1", + "badge_origin": "SAM", + "rule": "override", + "note": null, + "icon_id": "connector_plural_create", + "resource": "SAM_GH_ConnectorPluralCreate", + "icon_file": "svg/connector_plural_create.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemConnector", + "name": "SAMAnalytical.SystemConnector", + "nickname": "SAMAnalytical.SystemConnector", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnector.cs", + "guid": "81ad840f-1382-4091-9f6e-7c15affc2384", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "connector", + "op": "create", + "plural": false, + "container": null, + "glyph_origin": "SAM-BIM ext v1", + "badge_origin": "SAM", + "rule": "override", + "note": null, + "icon_id": "connector_create", + "resource": "SAM_GH_ConnectorCreate", + "icon_file": "svg/connector_create.svg", + "status": "integrated" + }, + { + "class": "GooSystemEnergyCentreParam", + "name": "{typeof(SystemEnergyCentre).Name}", + "nickname": "{typeof(SystemEnergyCentre).Name}", + "category": "Params", + "subcategory": "SAM", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemEnergyCentre.cs", + "guid": "3f01a7cf-8268-496a-8247-602d1b4f109b", + "kind": "param", + "exposure": null, + "obsolete": false, + "current_icon": "SAM3_0", + "icon_holder": "Resources", + "object": "energyCentre", + "op": null, + "plural": false, + "container": null, + "glyph_origin": "SAM-BIM ext v1", + "badge_origin": null, + "rule": "param:SystemEnergyCentre", + "note": null, + "icon_id": "energyCentre", + "resource": "SAM_GH_EnergyCentre", + "icon_file": "svg/energyCentre.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemAddSystemEnergyCentre", + "name": "SAMAnalytical.AddSystemEnergyCentre", + "nickname": "SAMAnalytical.AddSystemEnergyCentre", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemAddSystemEnergyCentre.cs", + "guid": "271e61dd-abc3-496e-b4d5-ca7be989c3ed", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "energyCentre", + "op": "add", + "plural": false, + "container": null, + "glyph_origin": "SAM-BIM ext v1", + "badge_origin": "SAM", + "rule": "rule", + "note": null, + "icon_id": "energyCentre_add", + "resource": "SAM_GH_EnergyCentreAdd", + "icon_file": "svg/energyCentre_add.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemCreateSystemEnergyCentre", + "name": "SAMAnalytical.CreateSystemEnergyCentre", + "nickname": "SAMAnalytical.CreateSystemEnergyCentre", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentre.cs", + "guid": "980a8d42-ad72-49fa-b6fc-1ad98fa234bc", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "energyCentre", + "op": "create", + "plural": false, + "container": null, + "glyph_origin": "SAM-BIM ext v1", + "badge_origin": "SAM", + "rule": "rule", + "note": null, + "icon_id": "energyCentre_create", + "resource": "SAM_GH_EnergyCentreCreate", + "icon_file": "svg/energyCentre_create.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemCreateSystemEnergyCentreByMechanicalSystems", + "name": "SAMAnalytical.CreateSystemEnergyCentreByMechanicalSystems", + "nickname": "SAMAnalytical.CreateSystemEnergyCentreByMechanicalSystems", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentreByMechanicalSystems.cs", + "guid": "168d4a90-00c3-424e-b4ec-d97437bac56b", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "energyCentre", + "op": "create", + "plural": false, + "container": null, + "glyph_origin": "SAM-BIM ext v1", + "badge_origin": "SAM", + "rule": "rule", + "note": null, + "icon_id": "energyCentre_create", + "resource": "SAM_GH_EnergyCentreCreate", + "icon_file": "svg/energyCentre_create.svg", + "status": "integrated" + }, + { + "class": "SAMSystemsCreateEnergyCentreByMollier", + "name": "SAMSystems.CreateEnergyCentreByMollier", + "nickname": "SAMSystems.CreateEnergyCentreByMollier", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateEnergyCentreByMollier.cs", + "guid": "b7e3c2a1-4d6f-4a8b-9c12-7e5f0a3b6d24", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "energyCentre", + "op": "create", + "plural": false, + "container": null, + "glyph_origin": "SAM-BIM ext v1", + "badge_origin": "SAM", + "rule": "rule", + "note": null, + "icon_id": "energyCentre_create", + "resource": "SAM_GH_EnergyCentreCreate", + "icon_file": "svg/energyCentre_create.svg", + "status": "integrated" + }, + { + "class": "SAMSystemsCreateDisplaySystemEnergyCentre", + "name": "SAMSystems.CreateDisplaySystemEnergyCentre", + "nickname": "SAMSystems.CreateDisplaySystemEnergyCentre", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateDisplaySystemEnergyCentre.cs", + "guid": "a3d8c1f6-4e57-49b2-9c0a-7d2e5f8b41c9", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "energyCentre", + "op": "display", + "plural": false, + "container": null, + "glyph_origin": "SAM-BIM ext v1", + "badge_origin": "SAM", + "rule": "override", + "note": "previewable schematic", + "icon_id": "energyCentre_display", + "resource": "SAM_GH_EnergyCentreDisplay", + "icon_file": "svg/energyCentre_display.svg", + "status": "integrated" + }, + { + "class": "SAMSystemsMergeEnergyCentreByECs", + "name": "SAMSystems.MergeEnergyCentreByECs", + "nickname": "SAMSystems.MergeEnergyCentreByECs", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMergeEnergyCentreByECs.cs", + "guid": "3e1534f7-3ff4-40a0-8b29-1633699eeab5", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM3_0", + "icon_holder": "Resources", + "object": "energyCentre", + "op": "merge", + "plural": false, + "container": null, + "glyph_origin": "SAM-BIM ext v1", + "badge_origin": "SAM", + "rule": "rule", + "note": null, + "icon_id": "energyCentre_merge", + "resource": "SAM_GH_EnergyCentreMerge", + "icon_file": "svg/energyCentre_merge.svg", + "status": "integrated" + }, + { + "class": "SAMSystemsSystemEnergyCentreDataType", + "name": "SAMSystems.SystemEnergyCentreDataType", + "nickname": "SAMSystems.SystemEnergyCentreDataType", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsSystemEnergyCentreDataType.cs", + "guid": "2ce0997f-a5e2-457d-9baa-39fbc2a5ebb6", + "kind": "component", + "exposure": null, + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "energyCentre", + "op": "value", + "plural": false, + "container": null, + "glyph_origin": "SAM-BIM ext v1", + "badge_origin": "SAM", + "rule": "rule", + "note": null, + "icon_id": "energyCentre_value", + "resource": "SAM_GH_EnergyCentreValue", + "icon_file": "svg/energyCentre_value.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemVentilationUnitCatalogue", + "name": "SAMAnalytical.SystemVentilationUnitCatalogue", + "nickname": "SAMAnalytical.SystemVentilationUnitCatalogue", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemVentilationUnitCatalogue.cs", + "guid": "8b6e1f3a-4d2c-4a91-9e7b-2c5f6a8d1e30", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "fan", + "op": "import", + "plural": false, + "container": "library", + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": null, + "icon_id": "fan_library_import", + "resource": "SAM_GH_FanLibraryImport", + "icon_file": "svg/fan_library_import.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemEnergyCentreModifyFanByAirflows", + "name": "SystemEnergyCentre.ModifyFanByAirflows", + "nickname": "SystemEnergyCentre.ModifyFanByAirflows", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyFanByAirflows.cs", + "guid": "53ff901d-4a76-4b3e-b9e1-6ca0c9d4b04d", + "kind": "component", + "exposure": null, + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "fan", + "op": "modify", + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": null, + "icon_id": "fan_modify", + "resource": "SAM_GH_FanModify", + "icon_file": "svg/fan_modify.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemUpdateAirSystem", + "name": "SAMAnalytical.UpdateVentilationSystem", + "nickname": "SAMAnalytical.UpdateVentilationSystem", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemUpdateAirSystem.cs", + "guid": "76c087b1-93ed-4a20-873a-cabf2e176f0c", + "kind": "component", + "exposure": null, + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "fan", + "op": "update", + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "rule", + "note": null, + "icon_id": "fan_update", + "resource": "SAM_GH_FanUpdate", + "icon_file": "svg/fan_update.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemCreateSystemGeometrySymbol", + "name": "SAMAnalytical.CreateSystemGeometrySymbol", + "nickname": "SAMAnalytical.CreateSystemGeometrySymbol", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemGeometrySymbol.cs", + "guid": "9f1933d2-d443-4caf-9e7d-8d61023d7360", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "geometry2D", + "op": "create", + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": "2D schematic symbol", + "icon_id": "geometry2D_create", + "resource": "SAM_GH_Geometry2DCreate", + "icon_file": "svg/geometry2D_create.svg", + "status": "integrated" + }, + { + "class": "GooSystemObjectParam", + "name": "{typeof(ISystemObject).Name}", + "nickname": "{typeof(ISystemObject).Name}", + "category": "Params", + "subcategory": "SAM", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemObject.cs", + "guid": "55d4a95d-124b-4e7d-b415-f77e12b6f2dc", + "kind": "param", + "exposure": null, + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "object", + "op": null, + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": null, + "rule": "param:SystemObject", + "note": null, + "icon_id": "object", + "resource": "SAM_GH_Object", + "icon_file": "svg/object.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemConnectedSystemObjects", + "name": "SAMAnalytical.ConnectedSystemObjects", + "nickname": "SAMAnalytical.ConnectedSystemObjects", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemObjects.cs", + "guid": "162c87ab-0bd8-493f-bebb-4b04b93ee498", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "object", + "op": "get", + "plural": true, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": null, + "icon_id": "object_plural_get", + "resource": "SAM_GH_ObjectPluralGet", + "icon_file": "svg/object_plural_get.svg", + "status": "integrated" + }, + { + "class": "GooSystemPlantRoomParam", + "name": "{typeof(SystemPlantRoom).Name}", + "nickname": "{typeof(SystemPlantRoom).Name}", + "category": "Params", + "subcategory": "SAM", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemPlantRoom.cs", + "guid": "cc593874-611a-4378-92a0-85d88ed82b9a", + "kind": "param", + "exposure": null, + "obsolete": false, + "current_icon": "SAM3_0", + "icon_holder": "Resources", + "object": "plantRoom", + "op": null, + "plural": false, + "container": null, + "glyph_origin": "SAM-BIM ext v1", + "badge_origin": null, + "rule": "param:SystemPlantRoom", + "note": null, + "icon_id": "plantRoom", + "resource": "SAM_GH_PlantRoom", + "icon_file": "svg/plantRoom.svg", + "status": "integrated" + }, + { + "class": "SAMSystemsCreatePlantRoomByMollier", + "name": "SAMSystems.CreatePlantRoomByMollier", + "nickname": "SAMSystems.CreatePlantRoomByMollier", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreatePlantRoomByMollier.cs", + "guid": "c8f4d3b2-5e7a-4b9c-8d21-6f3a1b4c7e90", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "plantRoom", + "op": "create", + "plural": false, + "container": null, + "glyph_origin": "SAM-BIM ext v1", + "badge_origin": "SAM", + "rule": "rule", + "note": null, + "icon_id": "plantRoom_create", + "resource": "SAM_GH_PlantRoomCreate", + "icon_file": "svg/plantRoom_create.svg", + "status": "integrated" + }, + { + "class": "SAMSystemsMollierTwinWheelExample", + "name": "SAMSystems.MollierTwinWheelExample", + "nickname": "SAMSystems.MollierTwinWheelExample", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMollierTwinWheelExample.cs", + "guid": "e1b6f5d4-7a9c-4dbe-af43-8b5c3d6e9f12", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "processHeatRecovery", + "op": "create", + "plural": false, + "container": null, + "glyph_origin": "SAM-BIM ext v1", + "badge_origin": "SAM", + "rule": "override", + "note": "worked twin-wheel heat-recovery example", + "icon_id": "processHeatRecovery_create", + "resource": "SAM_GH_ProcessHeatRecoveryCreate", + "icon_file": "svg/processHeatRecovery_create.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemPlantRoomRelatedObjects", + "name": "SystemPlantRoom.RelatedObjects", + "nickname": "SystemPlantRoom.RelatedObjects", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemPlantRoomRelatedObjects.cs", + "guid": "7e6476fa-9fcc-448a-82ee-9f08fbdc03de", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "relation", + "op": "get", + "plural": true, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "rule", + "note": null, + "icon_id": "relation_plural_get", + "resource": "SAM_GH_RelationPluralGet", + "icon_file": "svg/relation_plural_get.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemResultValueByHourOfYear", + "name": "SAMAnalytical.SystemResultValueByHourOfYear", + "nickname": "SAMAnalytical.SystemResultValueByHourOfYear", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResultValueByHourOfYear.cs", + "guid": "8e927e8f-58d2-4d07-8952-86f09cdfb6a6", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "result", + "op": "get", + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": null, + "icon_id": "result_get", + "resource": "SAM_GH_ResultGet", + "icon_file": "svg/result_get.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemResults", + "name": "SAMAnalytical.SystemResults", + "nickname": "SAMAnalytical.SystemResults", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResults.cs", + "guid": "b095f799-82ce-4a41-9c56-f9ccfa921065", + "kind": "component", + "exposure": "GH_Exposure.tertiary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "result", + "op": "get", + "plural": true, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": null, + "icon_id": "result_plural_get", + "resource": "SAM_GH_ResultPluralGet", + "icon_file": "svg/result_plural_get.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemCreateDisplaySystemManager", + "name": "SAMAnalytical.CreateDisplaySystemManager", + "nickname": "SAMAnalytical.CreateDisplaySystemManager", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemManager.cs", + "guid": "8b67bdca-b7f6-4707-b90a-d15959f08316", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "settings", + "op": "create", + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": "component-type -> symbol display settings", + "icon_id": "settings_create", + "resource": "SAM_GH_SettingsCreate", + "icon_file": "svg/settings_create.svg", + "status": "integrated" + }, + { + "class": "GooSystemSpaceParam", + "name": "{typeof(ISystemSpace).Name}", + "nickname": "{typeof(ISystemSpace).Name}", + "category": "Params", + "subcategory": "SAM", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemSpace.cs", + "guid": "1ea2ed4a-1fd0-44ff-a4cb-a910aefe2fc9", + "kind": "param", + "exposure": "GH_Exposure.hidden", + "obsolete": false, + "current_icon": "SAM3_0", + "icon_holder": "Resources", + "object": "space", + "op": null, + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": null, + "rule": "param:SystemSpace", + "note": null, + "icon_id": "space", + "resource": "SAM_GH_Space", + "icon_file": "svg/space.svg", + "status": "integrated" + }, + { + "class": "GooSystemGroupParam", + "name": "{typeof(ISystemGroup).Name}", + "nickname": "{typeof(ISystemGroup).Name}", + "category": "Params", + "subcategory": "SAM", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemGroup.cs", + "guid": "3243e174-d434-45bf-bc75-0854c3bb7735", + "kind": "param", + "exposure": null, + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "system", + "op": null, + "plural": true, + "container": null, + "glyph_origin": "SAM", + "badge_origin": null, + "rule": "param:SystemGroup", + "note": null, + "icon_id": "system_plural", + "resource": "SAM_GH_SystemPlural", + "icon_file": "svg/system_plural.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemConnectedSystemGroups", + "name": "SAMAnalytical.ConnectedSystemGroups", + "nickname": "SAMAnalytical.ConnectedSystemGroups", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemGroups.cs", + "guid": "761a15c3-a6da-491f-b959-7d991a46bb52", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "system", + "op": "get", + "plural": true, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": null, + "icon_id": "system_plural_get", + "resource": "SAM_GH_SystemPluralGet", + "icon_file": "svg/system_plural_get.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemModifyAirSystem", + "name": "SAMAnalytical.ModifyAirSystem", + "nickname": "SAMAnalytical.ModifyAirSystem", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemModifyAirSystem.cs", + "guid": "6f57c6d7-8669-45a0-8af6-9595572921c2", + "kind": "component", + "exposure": null, + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "system", + "op": "modify", + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "rule", + "note": null, + "icon_id": "system_modify", + "resource": "SAM_GH_SystemModify", + "icon_file": "svg/system_modify.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemType", + "name": "SAM.AnalyticalSystemType", + "nickname": "SAM.AnalyticalSystemType", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemType.cs", + "guid": "75997483-9ed7-4404-afd8-627144405160", + "kind": "component", + "exposure": null, + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "system", + "op": "value", + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "rule", + "note": null, + "icon_id": "system_value", + "resource": "SAM_GH_SystemValue", + "icon_file": "svg/system_value.svg", + "status": "integrated" + }, + { + "class": "SAMAnalyticalSystemConnectedSensor", + "name": "SAMAnalytical.ConnectedSensor", + "nickname": "SAMAnalytical.ConnectedSensor", + "category": "SAM", + "subcategory": "Systems", + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSensor.cs", + "guid": "8341425d-783f-49ad-a8db-d5269d128800", + "kind": "component", + "exposure": "GH_Exposure.primary", + "obsolete": false, + "current_icon": "SAM_Small", + "icon_holder": "Resources", + "object": "thermometer", + "op": "get", + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": "SAM", + "rule": "override", + "note": "the sensor a controller reads", + "icon_id": "thermometer_get", + "resource": "SAM_GH_ThermometerGet", + "icon_file": "svg/thermometer_get.svg", + "status": "integrated" + }, + { + "class": "GooSystemResultParam", + "name": "{typeof(ISystemResult).Name}", + "nickname": "{typeof(ISystemResult).Name}", + "category": "Params", + "subcategory": "SAM", + "project": "SAM.Core.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Core.Grasshopper.Systems", + "source": "Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystemResult.cs", + "guid": "ab9deb98-f591-469b-8b47-aa69df35000f", + "kind": "param", + "exposure": "GH_Exposure.hidden", + "obsolete": false, + "current_icon": "SAM3_0", + "icon_holder": "Resources", + "object": "result", + "op": null, + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": null, + "rule": "param:SystemResult", + "note": null, + "icon_id": "result", + "resource": "SAM_GH_Result", + "icon_file": "svg/result.svg", + "status": "integrated" + }, + { + "class": "GooSystemParam", + "name": "{typeof(Core.Systems.ISystem).Name}", + "nickname": "{typeof(Core.Systems.ISystem).Name}", + "category": "Params", + "subcategory": "SAM", + "project": "SAM.Core.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Core.Grasshopper.Systems", + "source": "Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystem.cs", + "guid": "bceb3ae6-4542-42c3-8930-46982b2ab3c4", + "kind": "param", + "exposure": "GH_Exposure.hidden", + "obsolete": false, + "current_icon": "SAM3_0", + "icon_holder": "Resources", + "object": "system", + "op": null, + "plural": false, + "container": null, + "glyph_origin": "SAM", + "badge_origin": null, + "rule": "param:System", + "note": null, + "icon_id": "system", + "resource": "SAM_GH_System", + "icon_file": "svg/system.svg", + "status": "integrated" + } +] \ No newline at end of file diff --git a/design/grasshopper-icons/manifest_raw.json b/design/grasshopper-icons/manifest_raw.json new file mode 100644 index 00000000..5aa04628 --- /dev/null +++ b/design/grasshopper-icons/manifest_raw.json @@ -0,0 +1,648 @@ +[ + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "GooSystemComponentParam", + "base_type": "GH_PersistentParam", + "guid": "2d34ab26-ac12-4ba4-984c-50cdfd7ae237", + "name": "{typeof(ISystemComponent).Name}", + "nickname": "{typeof(ISystemComponent).Name}", + "category": "Params", + "subcategory": "SAM", + "icon_expr": "SAM3_0", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": null, + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemComponent.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "GooSystemEnergyCentreParam", + "base_type": "GH_PersistentParam", + "guid": "3f01a7cf-8268-496a-8247-602d1b4f109b", + "name": "{typeof(SystemEnergyCentre).Name}", + "nickname": "{typeof(SystemEnergyCentre).Name}", + "category": "Params", + "subcategory": "SAM", + "icon_expr": "SAM3_0", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": null, + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemEnergyCentre.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "GooSystemGroupParam", + "base_type": "GH_PersistentParam, IGH_PreviewObject, IGH_BakeAwareObject", + "guid": "3243e174-d434-45bf-bc75-0854c3bb7735", + "name": "{typeof(ISystemGroup).Name}", + "nickname": "{typeof(ISystemGroup).Name}", + "category": "Params", + "subcategory": "SAM", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": null, + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemGroup.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "GooSystemObjectParam", + "base_type": "GH_PersistentParam, IGH_PreviewObject, IGH_BakeAwareObject", + "guid": "55d4a95d-124b-4e7d-b415-f77e12b6f2dc", + "name": "{typeof(ISystemObject).Name}", + "nickname": "{typeof(ISystemObject).Name}", + "category": "Params", + "subcategory": "SAM", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": null, + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemObject.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "GooSystemPlantRoomParam", + "base_type": "GH_PersistentParam", + "guid": "cc593874-611a-4378-92a0-85d88ed82b9a", + "name": "{typeof(SystemPlantRoom).Name}", + "nickname": "{typeof(SystemPlantRoom).Name}", + "category": "Params", + "subcategory": "SAM", + "icon_expr": "SAM3_0", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": null, + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemPlantRoom.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "GooSystemSpaceParam", + "base_type": "GH_PersistentParam", + "guid": "1ea2ed4a-1fd0-44ff-a4cb-a910aefe2fc9", + "name": "{typeof(ISystemSpace).Name}", + "nickname": "{typeof(ISystemSpace).Name}", + "category": "Params", + "subcategory": "SAM", + "icon_expr": "SAM3_0", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.hidden", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemSpace.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemAddSystemEnergyCentre", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "271e61dd-abc3-496e-b4d5-ca7be989c3ed", + "name": "SAMAnalytical.AddSystemEnergyCentre", + "nickname": "SAMAnalytical.AddSystemEnergyCentre", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemAddSystemEnergyCentre.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemComponentType", + "base_type": "GH_SAMEnumComponent", + "guid": "fd4670c1-70e6-4008-a469-1e8565085293", + "name": "SAM.AnalyticalSystemComponentType", + "nickname": "SAM.AnalyticalSystemComponentType", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": null, + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemComponentType.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemConnectedSensor", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "8341425d-783f-49ad-a8db-d5269d128800", + "name": "SAMAnalytical.ConnectedSensor", + "nickname": "SAMAnalytical.ConnectedSensor", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSensor.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemConnectedSystemComponents", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "11f8fdbc-0270-44bf-a2d5-aca2e10a39f7", + "name": "SAMAnalytical.ConnectedSystemComponents", + "nickname": "SAMAnalytical.ConnectedSystemComponents", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemComponents.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemConnectedSystemGroups", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "761a15c3-a6da-491f-b959-7d991a46bb52", + "name": "SAMAnalytical.ConnectedSystemGroups", + "nickname": "SAMAnalytical.ConnectedSystemGroups", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemGroups.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemConnectedSystemObjects", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "162c87ab-0bd8-493f-bebb-4b04b93ee498", + "name": "SAMAnalytical.ConnectedSystemObjects", + "nickname": "SAMAnalytical.ConnectedSystemObjects", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnectedSystemObjects.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemConnector", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "81ad840f-1382-4091-9f6e-7c15affc2384", + "name": "SAMAnalytical.SystemConnector", + "nickname": "SAMAnalytical.SystemConnector", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemConnector.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemCreateDisplaySystemConnectorManager", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "1c03806e-54d8-4136-923c-81c263aeee20", + "name": "SAMAnalytical.CreateDisplaySystemConnectorManager", + "nickname": "SAMAnalytical.CreateDisplaySystemConnectorManager", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemConnectorManager.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemCreateDisplaySystemManager", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "8b67bdca-b7f6-4707-b90a-d15959f08316", + "name": "SAMAnalytical.CreateDisplaySystemManager", + "nickname": "SAMAnalytical.CreateDisplaySystemManager", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateDisplaySystemManager.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemCreateSystemEnergyCentre", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "980a8d42-ad72-49fa-b6fc-1ad98fa234bc", + "name": "SAMAnalytical.CreateSystemEnergyCentre", + "nickname": "SAMAnalytical.CreateSystemEnergyCentre", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentre.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemCreateSystemEnergyCentreByMechanicalSystems", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "168d4a90-00c3-424e-b4ec-d97437bac56b", + "name": "SAMAnalytical.CreateSystemEnergyCentreByMechanicalSystems", + "nickname": "SAMAnalytical.CreateSystemEnergyCentreByMechanicalSystems", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemEnergyCentreByMechanicalSystems.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemCreateSystemGeometrySymbol", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "9f1933d2-d443-4caf-9e7d-8d61023d7360", + "name": "SAMAnalytical.CreateSystemGeometrySymbol", + "nickname": "SAMAnalytical.CreateSystemGeometrySymbol", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemCreateSystemGeometrySymbol.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemEnergyCentreModifyByAirflows", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "31a4c1d3-6cef-4c5b-a9b1-46684c947ea9", + "name": "SystemEnergyCentre.ModifyByAirflows", + "nickname": "SystemEnergyCentre.ModifyByAirflows", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": null, + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyByAirflows.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemEnergyCentreModifyFanByAirflows", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "53ff901d-4a76-4b3e-b9e1-6ca0c9d4b04d", + "name": "SystemEnergyCentre.ModifyFanByAirflows", + "nickname": "SystemEnergyCentre.ModifyFanByAirflows", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": null, + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemEnergyCentreModifyFanByAirflows.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemModifyAirSystem", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "6f57c6d7-8669-45a0-8af6-9595572921c2", + "name": "SAMAnalytical.ModifyAirSystem", + "nickname": "SAMAnalytical.ModifyAirSystem", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": null, + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemModifyAirSystem.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemOrderedSystemComponents", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "32b7d078-f950-4e41-8b19-b93de65c6b01", + "name": "SAMAnalytical.OrderedSystemComponents", + "nickname": "SAMAnalytical.OrderedSystemComponents", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemOrderedSystemComponents.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemPlantRoomRelatedObjects", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "7e6476fa-9fcc-448a-82ee-9f08fbdc03de", + "name": "SystemPlantRoom.RelatedObjects", + "nickname": "SystemPlantRoom.RelatedObjects", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemPlantRoomRelatedObjects.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemResultValueByHourOfYear", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "8e927e8f-58d2-4d07-8952-86f09cdfb6a6", + "name": "SAMAnalytical.SystemResultValueByHourOfYear", + "nickname": "SAMAnalytical.SystemResultValueByHourOfYear", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResultValueByHourOfYear.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemResults", + "base_type": "GH_Component, IGH_VariableParameterComponent, IGH_SAMComponent", + "guid": "b095f799-82ce-4a41-9c56-f9ccfa921065", + "name": "SAMAnalytical.SystemResults", + "nickname": "SAMAnalytical.SystemResults", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.tertiary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemResults.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemToAHU", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "6df8ab41-f2bf-4a2a-84ab-427c072c655c", + "name": "SAMAnalytical.SystemToAHU", + "nickname": "SAMAnalytical.SystemToAHU", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemToAHU.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemType", + "base_type": "GH_SAMEnumComponent", + "guid": "75997483-9ed7-4404-afd8-627144405160", + "name": "SAM.AnalyticalSystemType", + "nickname": "SAM.AnalyticalSystemType", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": null, + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemType.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemUpdateAirSystem", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "76c087b1-93ed-4a20-873a-cabf2e176f0c", + "name": "SAMAnalytical.UpdateVentilationSystem", + "nickname": "SAMAnalytical.UpdateVentilationSystem", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": null, + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemUpdateAirSystem.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMAnalyticalSystemVentilationUnitCatalogue", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "8b6e1f3a-4d2c-4a91-9e7b-2c5f6a8d1e30", + "name": "SAMAnalytical.SystemVentilationUnitCatalogue", + "nickname": "SAMAnalytical.SystemVentilationUnitCatalogue", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMAnalyticalSystemVentilationUnitCatalogue.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMSystemsCreateComponentByMollierProcess", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "d9a5e4c3-6f8b-4cad-9e32-7a4b2c5d8f01", + "name": "SAMSystems.CreateComponentByMollierProcess", + "nickname": "SAMSystems.CreateComponentByMollierProcess", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateComponentByMollierProcess.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMSystemsCreateDisplaySystemEnergyCentre", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "a3d8c1f6-4e57-49b2-9c0a-7d2e5f8b41c9", + "name": "SAMSystems.CreateDisplaySystemEnergyCentre", + "nickname": "SAMSystems.CreateDisplaySystemEnergyCentre", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateDisplaySystemEnergyCentre.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMSystemsCreateEnergyCentreByMollier", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "b7e3c2a1-4d6f-4a8b-9c12-7e5f0a3b6d24", + "name": "SAMSystems.CreateEnergyCentreByMollier", + "nickname": "SAMSystems.CreateEnergyCentreByMollier", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreateEnergyCentreByMollier.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMSystemsCreatePlantRoomByMollier", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "c8f4d3b2-5e7a-4b9c-8d21-6f3a1b4c7e90", + "name": "SAMSystems.CreatePlantRoomByMollier", + "nickname": "SAMSystems.CreatePlantRoomByMollier", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsCreatePlantRoomByMollier.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMSystemsMergeEnergyCentreByECs", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "3e1534f7-3ff4-40a0-8b29-1633699eeab5", + "name": "SAMSystems.MergeEnergyCentreByECs", + "nickname": "SAMSystems.MergeEnergyCentreByECs", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM3_0", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMergeEnergyCentreByECs.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMSystemsMollierTwinWheelExample", + "base_type": "GH_SAMVariableOutputParameterComponent", + "guid": "e1b6f5d4-7a9c-4dbe-af43-8b5c3d6e9f12", + "name": "SAMSystems.MollierTwinWheelExample", + "nickname": "SAMSystems.MollierTwinWheelExample", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.primary", + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsMollierTwinWheelExample.cs" + }, + { + "project": "SAM.Analytical.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Analytical.Grasshopper.Systems", + "class": "SAMSystemsSystemEnergyCentreDataType", + "base_type": "GH_SAMEnumComponent", + "guid": "2ce0997f-a5e2-457d-9baa-39fbc2a5ebb6", + "name": "SAMSystems.SystemEnergyCentreDataType", + "nickname": "SAMSystems.SystemEnergyCentreDataType", + "category": "SAM", + "subcategory": "Systems", + "icon_expr": "SAM_Small", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": null, + "obsolete": false, + "source": "Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsSystemEnergyCentreDataType.cs" + }, + { + "project": "SAM.Core.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Core.Grasshopper.Systems", + "class": "GooSystemParam", + "base_type": "GH_PersistentParam", + "guid": "bceb3ae6-4542-42c3-8930-46982b2ab3c4", + "name": "{typeof(Core.Systems.ISystem).Name}", + "nickname": "{typeof(Core.Systems.ISystem).Name}", + "category": "Params", + "subcategory": "SAM", + "icon_expr": "SAM3_0", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.hidden", + "obsolete": false, + "source": "Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystem.cs" + }, + { + "project": "SAM.Core.Grasshopper.Systems", + "project_dir": "Grasshopper/SAM.Core.Grasshopper.Systems", + "class": "GooSystemResultParam", + "base_type": "GH_PersistentParam", + "guid": "ab9deb98-f591-469b-8b47-aa69df35000f", + "name": "{typeof(ISystemResult).Name}", + "nickname": "{typeof(ISystemResult).Name}", + "category": "Params", + "subcategory": "SAM", + "icon_expr": "SAM3_0", + "icon_holder": "Resources", + "icon_via_bytes": false, + "exposure": "GH_Exposure.hidden", + "obsolete": false, + "source": "Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystemResult.cs" + } +] \ No newline at end of file diff --git a/design/grasshopper-icons/png/24/ahu.png b/design/grasshopper-icons/png/24/ahu.png new file mode 100644 index 0000000000000000000000000000000000000000..619f510e32a30d3f93b1b3df0b4baa4246630369 GIT binary patch literal 765 zcmVK%qakT)_QENb5|Y-uB_cvn ztZYehYa1h5*s;vw_XU4Td_U8ks0`4B@7tlT9Z4s(-!#qYfq>EghGAS$G->(xywTVhT@6K*(~=ousJ+#Q zOQ-KUUo1PGa8vvG>nLppx~|X3o{%-SBWB@RRUJOIbz*8k7=j>tuZ9qen>Yf6YiCJ; zY{S?3qJ6O>E87%F`IKo#X#h>riYCnq&RtQO3tv#i!y7I9>iJrH`e2bM`RSmX+z}{T zGfVP^d`3&ths7chOJrGj@4D{OUpxzJ^pP z^)uN^F}!}>hOgbW$`~jiWNFV1q)fA`scysDdKU*u4}o)z^73-j*EHkNqL(~>VIBd1 zx;qVAQUy$35+Y{I#jD!Rcl`l=&M?;K;P|lI9G%?Cjsc+%bh&N=B1U^U%~yP=#cm2(C~Q6P#U7-P_N9gHzdUJ%6N8|@f2Qbl-% z(N}Gm0j6n|0krkbnbtCZkJ`PbL_AVai9{lSJ$p+qW{UpZY7qC_vjb+DW)*;H!!WkT zVzJ6CTQ+COs)(G~S(sNmw$JlqjKk^n`UD6Wz|69&lb_?J&vg?U9mjq5_Gy>%=20gY z<7vh%^%kxlZL!}sbhmk)cX6PGu^VrJMW#Y6XY;ElTNz0es~D`q%Xhf>;`Xk9Kr&00000NkvXXu0mjfB!g@E literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/ahu_convert.png b/design/grasshopper-icons/png/24/ahu_convert.png new file mode 100644 index 0000000000000000000000000000000000000000..0cfc6531f8c0a5de889665f734c416a469631fe4 GIT binary patch literal 1041 zcmV+s1n&EZP)s{vfXRFFg=QdcvT!H@~oOzDVF?wDJ9OS#8~#YJ=sa3;QZUe7P*bI$kV ze1E|I@m~kOQeM-v12&s&dpeyS20&{Cu;mJ?s(L_@g(FI?>||i<%H>pYA+uO-7{&(x ztbYpNRaJdll7;5m9EvmaR8T3~T@1#6FFzhd=dpqG<@waiLOR=E7)HlxKuZ7)hoeif z2@l;-l#ds~k3f>eC66u3!q6w@@ZtMkq_51Uk{L7m>PizW*@2=crRxiG%4ZVuIN2V> zuTz(>waf>O3O`c?>!uQ<0P`#?DfZsSql?qr*QSRlx$g08DkIpbpl~I?FKrg zaN&%J*A6v-h|t{Jj57o0@%5f@+I3$M1Au7XCs-D?|6EBZK^~xyO|eH@jrc;cz_1 z3tX!tN;#s;qhMza?tSuhD0UGiUKxcmUqR#H28{I2ptG|Re!m|85Rb9>pB2nVq)UfKN2E36$}O`5{WF4N7FR& zdc9OxS-B>OZWM2YLZSPIhlkP9(t^3UIq15MWHO1at}c|6ln{Vcc8gQI9S(<|@9yqK zet!Nn2S_9k3WZQxTl+d=tm)s7s+fq5N2AfHXf!%SM8}D!_>cVW0%(dxL+Z;Q00000 LNkvXXu0mjfeN^u! literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/ahu_create.png b/design/grasshopper-icons/png/24/ahu_create.png new file mode 100644 index 0000000000000000000000000000000000000000..f60c6981b6a196574e37b19fddd89a50a07bfad2 GIT binary patch literal 1026 zcmV+d1pWJoP)LeUHaerzlE=Wm(4ou&DybLSPsV^*~kCC3!cymPZCn?Em;M zeh-hLys`)!$Bo~H5ZqXti|R)f3En)-{afGAN}*cq8?=d6h&Dv_jcd%RShL@ z`$Tkio@M)Xc47FUN#-rf1{Id%qI&fr!Q*#pXHQ*R$rJt+QIsy&wtejHXL46c#=vm| zMHM+HD)$mamPz+F{iv_qjvcS>M>?I(Bs*z}Grxo}_D4dd6gnZ~zJFFAOr%|KR~YAd zZES3424f5@EiLE`_Txy+uWZ>pr33&De;ZY#e<9CWM?L7ydKL5&~t=2W3}$yyAX9`Kx)EHCn&kVVo!2I)nG%%X~^REd$Cg#A3S|4tF7?20BGhW z08rC3-yew@Zre_-u`K)ixnnVF;K(Q_9haiwwxuxa8obcnhq&!vZ~c7iez6>J+rgUc zC&(Awml^=vO|J1v$w;TV1%D!zQuglo4A1XV5Q(J#09|h^1p`pE@h1R4UXFz0Z&e+f z>gUMmy8e{MtDB)SVR}n_kR9lautR+Y8?zlYW;^UqpTQ3FMp*H>AR8R9E^$)?P{S~G zjzkU3lkwcE_%2CR32~hs(iEzC}lCR4>Gi3hWRojkcNpv}$Ti`;zF86TLFsp5w zA1%%Vi4;X5>15)qkCjjWtzpS`}+b4rD;6l{Kn{_2vU77b9A*6ZQ wp34|3i`!0n&wv^388E|f+i7Qvm0jNd6F#VZAe*UQ0000007*qoM6N<$g4he*hyVZp literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/ahu_plural_get.png b/design/grasshopper-icons/png/24/ahu_plural_get.png new file mode 100644 index 0000000000000000000000000000000000000000..c2d1f0abc89fb80d84a69e60bce453405ab22808 GIT binary patch literal 1308 zcmV+%1>^dOP)| zn#xeuO5GB}4X0!hri)_y)DjtlNWcyc?zn@y_ulvJ{q_g5MAXdI*7M)9&%U3}^Zh=b z@AG|t|Jl+3F#H$9Mo|G5j&@%53`|L}VM)QG+PEaE zVW8WYO(9ln(Ce9AZ)lSwDe#X3^m=_NW9(_!A7nqBYsaP2m(_%nXlApUU{AClXJv*q zX{J4Fpl9fDugm|YP8XIeNm3nvz=H~8CC@i4+EA9J6>K^Tc1gJK%`fbHWurQMb{va} z5fB|OLTAuwuQlJ`lt3tx=Xt*@%XPOn_&Z4r219&=VB8f{)E6}xt~n$V3;2RKf1nqI zuN5+#PKSN_KIZnk`W38pL6s#1qazZRG+zMwE#&tMQukd;WHcJ>CUfLIp68EbE=)~( zeoMA4q^Pm&4Fftymk)84Lf)JFvN`{hx|?+H~) zlGHXS14DRN4}rA#>la|fOHc3skd~FCS>Ce%l?N`ONJ82WAv`c!y+_Lf}XRG(0+k3T=10-Bov*=C%?s0t1FRgDBco zgp(&vqNu1C7Q28sc^1}vbpYx4R<^uk8Zz>2U|@qmCG;r~ZFk;urQVHvfZDk>^aR8)lW@^Vz)yKtuq*JRZ+Bm&^5QKnXNn>Fe-Z>Fe+W zlt2>^EuG||{vPLMqtUoCq^O5^PR=bUDPh()0gG~DCY?(1hQM(gi0J)OE#JLWT2;n; zvNUdYoj&8kRVCF#v>QO_ghuoEd;>n8FVAc?Pv!O4?;7$hzTT|Y#HNO80AR!sK-*cT zegBo2+Hp)o0C&_-=|a%gp_D|RHZ12 zWHy`093?7I7O^ZcGSW&!XBO;UMKgBf(z=7iRNvJ?a!?^6qWZ38TDWI55z!g$egYnk zr*m*%_}Q_su?$sJPX{D<>hO?ztJmvwIy}zI;W0M=;OFi(wDw+wRx@4@#yAXmhvD!z zGx-M@8j7N{jEsydyBA)Zw-KA4T8;g6M=>{H<^+s?*bx^aSeufp33<7*pZt^jlbS+gR)C0>{LsROa$| zww6|v{WZLGdX%o%imc?h?=i+||MhQxh-Ud^e??nwdw*MRd%s`yR}j&xTlgPur6Tu1 SQ4|dT0000=-M~-`ntAb-GHrZ88Qdy1_aR<29Y3f1kpu^7$F9X5oTmyrZK^V1PuZP zV$=xB#F*$vbco3e5QEM@fQ&I1QGpD%fvj${w(H94YhT~}{9_U~hKQhvH~Id!`Et*> z_q*r2=K}w;VFTd!FMt(I(`s^Zz5O}kz5Pz7^92AIce0TEP2Qtv+BQiRm-z~^v1r9? z2j_$XA010X2jYgAO1}|}MjHSm{t7_69lEAzTNz`|kJB=wXXI4(Z#9}WVsh%O{ z`8|$ccc_vqw!vYyGrQft@Pk8<#49#i#$>}VS^*^QlwkJcS^nofqAo z$Fj$($jR4WbI9_Aj?03Xv??S?N~BV$)*Beo&7cm4BY&K#Y)+f}Sy2=^tQ4`Np2m^g zS5ULAhS_X3?AY;+@Yai;!sAnU$}kZhGz9-F73^m#5gVZHTb4*s6ra5L) zgELnG6KRyj(@KI0Zh>(424siEC|E_Q9@VRq>a&N^uW!c8BroeU_iJljoS6K z*uQ^2YHK&Z?Nc#*p__I86hxrP!xq;SqP)rr1~!m3t(`=)F?20bax3sr1R09Z^!cWX z363-x8yituTZ@K<2Dm3GCSr7yPMD(T=-uG&%dp!fc{>PRx z%WXxwTZm{2fcjC5rt5l8*Y$-imur$_$A^*d(EOebyO>*&DFVP?e-fRCLPq~3U0l6- z&4EaF!)t46HX=GS@;Y^7tIx0x-hc1)tcfdHZ~K(0s#=`m%Wl>*ja)7lxw17g+pX=& z%F6N((ZOF^3n@_Q9L|l1nbR~1A1fvzIw;+aAQp>t#bS6umgRt=C|gX^T&?SRaJXxN z6|lmX>KEYi@L`!SVBIo8y1QIdL#ckI&}(zlDX?C00000 LNkvXXu0mjfECW;J literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/ahu_value.png b/design/grasshopper-icons/png/24/ahu_value.png new file mode 100644 index 0000000000000000000000000000000000000000..15a20043a1790f3919d0f5ef28d295d3aaba0a3e GIT binary patch literal 1023 zcmVaL(>_+Y-BFt&M@S($XbeSQKMOug3Hk^`&YP9=t$;ia{|&ibm3s zn2ps3V_MS?>}#`P6SM|NlpseiRa>@TH7=>LCDQFFwcQKL86TQ9uF9q5!51g_o@O$? zZ)P(80sgoD+W5u%x~}haI2@Z(sni(&bh`jHUt&$u_DZsFP$`gI42)g7noP`Q=2|Sv z`Urr1rvP5lv?nE5=*U+Um+?%s65Lh_#(=Lsiz0GlAa!*nIX#=owpy0ey%bOmKvmU` zC5Q0H-6chMDf}2DSYNy#+9`YL+qIjc=Ib@j)e|{b>?s^|b-aLtHHhU|0E^FiGvy-^~M^d(JXpFJlf3HB8uXh98 zlelm?jo0_LgNV@4(Sg$g=ke{1A8G4DB@6(}z9bo znaGADN#J=NwrxXE6xg*=l7|PLz6**|#PL_7a1|+NJJ5>J{%J%a5%~Rn06;7jgJBrd)YQ}g zpnX0qqI5d_O)8l>B#PoMHraveR#tMlCBf}eaJFw6RlyLlQ-z4dVyLUDLnstNAP_)B zMFmXLWaH!G_g7X{4lGqtI8D>`dAzO*Yu0&_9ZaZ+0?F1i2!002ovPDHLkV1gmOBDNo5Tp5BK!Ktx3W<|qVigT>Ff0zFlY@hC@e##Vqz)C(4mvnUOcMtb zjd8-Lq()72z+xim+tx3BfS z0PWWMl8(Z{hAJT5W(^{erD989)>1206V`Tmju}c_7Kjt%fZ<3UjtAmdOAuKjON9jD z(B$y@o`|>XB(K>~Gb{O-Tp$NVy6@dwH8(Vz{dn}J zkJiNLs|v5i1urAlXdLP zs5SxpsY?KyvV4o63mp(;PV_!`1OUiQHzS`yVp4$=c+V-kc%!g$o5qbU4dy-rx#?!h z1t$8QjsY0^CH!c=i_MIQv+kFpxeVaHR!k`?HUl;@w)6r( z$X?xxriR5S6CD@C-WI#J*Mu~HzJFQ-NM6aO2APSP%#5rqYSd&tHAs?yvTPe98(Bz) n_55g3&yOZqNQX%_{;+=o-7x$jk#4oD00000NkvXXu0mjf7{?K# literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/connector_create.png b/design/grasshopper-icons/png/24/connector_create.png new file mode 100644 index 0000000000000000000000000000000000000000..e3f150a99799b6d02233715ea2bb89c5fddaf35f GIT binary patch literal 641 zcmV-{0)G98P)dw0NFp@l*G3K zZ~{zldmV+tO^Oo$6RKMqkC2vgv-dyl0Ve3+mQLnzCXz2c7v<-3tt{|YNEOns{w9jP z2Ymp5vllxC#S`0+EWv(ZH3AdZZ+^0p=lf3u>G||=rD2EC-r3O$0P>-o7v^HgIRL|@ z6wnD|W;8<(rF^|~VgUe|Q=#zdsl2EC0D$ob061kX7v&fE5P8ksO8&&iQuE@V07iz* z!3Jlev6f<8mCCmSB5KNHO?7la(?%yWEt54>B5L}t8LX1n1|T>Tj$Y{=7-OO%FGkOq z2ky7-c|}Aw0R*gce)#d*@8oM6Az#}Fjebp#8qo^z^LJ5`h>i*t+_@Zl_N5TGMH@Ct z%Z6NiI?e!et=XcPxL$9Vgh%cB;Bncpm5Ts?mtFhuGqr$o4?kfhuGd>p0MQ}9<67CH z$7RQc#hI*GfnOHYjiT+?$(|1YfN-z@1YjxNUFCvb7F8<>dTyNBwY>E?6X~o`h;N;) zH38ga7I&a`C>%ZCJurr9MFbJ>ZC=NnmRdA7R$gO_1(TMFi_X7+uDxHrGIaK$A@k;3=>ED>UsO}JLi1A z^PNAy|5k};cp_C`d)K^yPtHcLR9# zKM4Rxl0!tixPl4w+65l0y+lPDd%gNnpXWJdxvWq^q9?g73VK z9f3!Y|I=Ji%!&zYGkYn$Uiswt{V%4@UApjF%~~zEk~q>d?E@lujfmuu{`|ddi;vxg zGQ4@G*9`!ZW66BtuPhTtDTQ&OP_VldmvgM6r%83XBuCaN6eB+*67#dk=GzFG{0*_d z9>34KrVhdu7(Ft{`CPu$>2y8`AV5TaFmu=H&02TY(|#8Kod0S%8@+732_OWZdr^s^ z5aK)2G%wuVWMoNh0B7&62L#x0YwPyFBkIYK(Hg`u_c>hhY9df2J9Q@kgQdp0f$&7+YUjgUR{cib zsGZE5V?b0wAOo0*oStvI9$p$d7S{&H-o6GL08oo?B%|y4OEFeE$A+T{0L)xT3ucb4 zXo@@@&o))7IZ6zTiS6`_LceL6$CsTBLs8`cNumb z0NPvJzbj69i-^8mRJ<}{W(h#w$awsXL&qjbS={JcLEzKp)^pE8jX?m1Q3b({p&w)H z-FJq)`_6Fq`b`c^nPohBF)o<-F-H|g_w~N7ua<#Zk>IKQ=d`^$e1!lUlq=0Xvyj_T z6pSzSZ-S=E@EfHiKXI@FH_|p<{`@j#7IIsvsQ`-80ZqO0kD4mOwb+x2EAZ(`s7{e~ zKGpvV0ARdtD;U5MZf{ZH)0I#)74#q3v#ty>1%XVySjHbd(w literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/energyCentre.png b/design/grasshopper-icons/png/24/energyCentre.png new file mode 100644 index 0000000000000000000000000000000000000000..406012bd66f91b780703f203fb18bd9b7b15eef9 GIT binary patch literal 916 zcmV;F18e+=P)bY?CHUzo(n? zbH8)WmvaFA$A2F5`y_cho>j6eUtk!f&ExUNG)?zojP-w{B1w|YDT-n>H8mOGaG2E9 z)nQqdbAljjv5R*smw*t$3xa^!+uNCNI81b1XBmbe7-P{cp0cs!Ns@HL>-9F+B_M=m z8XFs-xw#oI#;CQm6+)rVEJ8?sR|m8xieIptV4*heG-KmGcfK&qDpa8nkg+B^&;Ea81v5{nt3BKaMlTM1w-! ze*JNPY}#Fo>i5<_IynnppXnwKhn^u(;h=VR5Mnoy;Pd&GCWv-U=A43qE?y(f6V+@l zq$(Q%Fx))_otGof`Avja7C~;ACF^$5a&ReYkry`Cvl`mqnzZ3`l|%+4qOHlV^l-*C<}&2y<#>LLIv zAfe}G^;_CprUm5~5|5;+#s*dJ_!(LXz9EWUov@0^1SAGH001y?4&r?&^7{jgn1;DW zRn-=|&)>eLhBl|)(lq@%WF6L{-ao3wqAKzDSy~D@A$oO!1Xl9M<#j+jk|upWJU0_h zGxxKG_4&-qOvh3hphfI%pDZ0i2%V5u@O0vt<`jGk%%x2O2*gZmz1LRT!Ihsco$|@v qtnBxWEp`C^HdvM|UF7oq`*;BWHcayK^~I|I00009*wn literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/energyCentre_add.png b/design/grasshopper-icons/png/24/energyCentre_add.png new file mode 100644 index 0000000000000000000000000000000000000000..39f83a7e63a775d0f4f11bb5694e5beb5e568a8b GIT binary patch literal 1330 zcmV-21+JZU@*KUieiz~YE^iiXHKVchuiI5<8(Sd z`cDd|sv0PYB3DyW!vla;t0j-e6L>F<`#TbyP8Vi2n~RM`qt|RUe{L`sB1RKA?uONB zyQjV#p)oQa9MG;$DTgB4SQuus6EMB}ANl8gKckUdjtE>GI5)$~-)YRE6EiC~9 z0|Rio-4EV8i^X!rX0wsaW}~R6D6&{AYIt}!Ns>e+lZk?ZgUMpC5D`&+emH^tJLRdzOhx;OurhZ!IyyR#m6ZjZP6wXn z!59N$3|_An>FMbxE-pq!Mg|l`L0elJ2f#k2$%01saZW}erRUDzq|iV=0LXrQ4!%8f z7AsaPN7R%^cs!oFk~A6(mMvSx0O0D?t58*yTrSs3vMiU6DZugY>**d)2z19up@GO< zw*XnIp2X?W3+U?Z#?IY^x2*^OXliOgMMZ_Hv$K-}uvwPnvhgHht3I4TH6>SQ@Un|V zCr?sWZA$0#!MeLZ_G{N+%PYsg6+7n7OGR~cH2_>!6lG6CLql8m#L4fp_x>>j0HVVK zJ4FrK#27mX0K%mBAS~Y%%P##SqwYu#%g_DhZ&YD~Ou#IGUTAodW{{S*2(Ds`3uC0{|*Fr$A8& z3wJaD06u*+mX=O4E#R6?^tBYP{@GXm_3v=Ie27eukh?dYO|k|d$mBe*QktvA`iXxj$Pj^zsLZr6Z(6Gk_-mJ{Dx!wdoCRBi<`c5 zg64^*P4ElgA^0(39AjM#GFrbM9PxS-S@F?qr_c>$u!sc@&>zvLPj_FeON)U~oK ze+AsJo2cPn2pD_G3;_cCZ}nu{VI@gYCdacP0HLH}joohl41n*i7$Q0~YfJsYi~TMD z!1?XdK>%iLsmDz>1)yf@wA15`Ylp*ed}z>a85*>UcDsGwz2vu+tsrO0XyEdyaCwx` zc;^dKRRFu#!#v1D^uf{d{dwz;{Dz4kB8Y&VAvbofn2Kj-hHYbvZGGrp0};gyyOo1Y o-Ok>oZfEbXTRBKXakuyX1WT(9_<*7%pUD#j)8 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 TLuCmN00000NkvXXu0mjf@M{cO literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/energyCentre_value.png b/design/grasshopper-icons/png/24/energyCentre_value.png new file mode 100644 index 0000000000000000000000000000000000000000..cd0e1619295fb34b966d9f6a21c258215cb5a44a GIT binary patch literal 1087 zcmV-F1i<@=P)K8I4A{p`k%?I-RtlqC(_( zKBm=bpNwapuw4L3sYa{S5}VD&I-O1$3Wby`%TiGk_3`W#ab#+a<6brx3`gQQ5JHw~ zYHHBh+6qw=Nk>NqGBYz*2qB@r%7D@9_0K6)2_K~H(5w9OD+;4BZ7LiRUtd~U8oU+b zW*^o|wn-irfaAEMYK`g>V-}Zk?8QftEG0V;4odju+-1x8Zdbo1N#za&rRG2&;M{IW z6Vfw`UZY8$Dx4_O7CxM}p-9vyQGI+LIrvnu()s0h(S^@P2ULk^Q({<}+zx<33P*C5 z{6WpNA7|qlBx;nXdG;alq3xuy>UgO|ouoQ?-eJeY#KfKL!I36&OR|xXFZOyA7rq#! zpdj}aW^GNCWnkWwO%5I_RzzbFoa?qD5{Y2Xp1l|w8c)eZ-flpwot~h4t=vOlYGN>$5 zlFTdR2OdjRWSEm+&fE?9a~`~2FRH4lHpVs(2*7T)BR@Z%TCLVflAe)zIu?^p@pq}2 z(x*)cckkx50Ck@H0p|S%m=72>AF=Pknto+-^69hldB5)s@gt za5dacVl17yw7B<|@c?vbEW_}mE$)87Yf;h?p^o{K&@ z@cvba#t^$n9e+Bex6>x4@Z2kekT>`o4KqI-Ow^{ZSoKFFP`D$a-0b)JUn?ssJ7lp~ z(A(R)$+@<+79NiWLqkJ@w`0>~-@N}cfHuhVRZ2+9sxR_uEQ-d(#l?a3qy#}YG%+!O zuC6W^3~T-I`Fyb1Y!C#20(g(y$u=sL%KIfrngk&Kfx16#Yin!j@9&4nWC8%p%*;R# z1T;1_zD)>e`Ntm+rL=%j+Uat+uDe{W>y*+?N@>Bm{&x;Jv4rtw>)-$Y002ovPDHLk FV1hWb0@eTk literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/fan_library_import.png b/design/grasshopper-icons/png/24/fan_library_import.png new file mode 100644 index 0000000000000000000000000000000000000000..4c1cadd358df508f08d5f9fa29aed6abba47e42f GIT binary patch literal 1132 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 KMNUMnLSTY!F`n@N literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/object_plural_get.png b/design/grasshopper-icons/png/24/object_plural_get.png new file mode 100644 index 0000000000000000000000000000000000000000..4c62d4495c707c34c7f0984229e341d649ffe655 GIT binary patch literal 925 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 O00001uEi3u4dbdi-6VHc@g^rMzWI+K1c0uj3~ zFD4P)^s97XAz>p(B+>Mu5(Q1umiwCfo-S(T-*9vGTs<%Ec{%Sn&*1_7a|O5?old6< z3=9+<4u`ao1j4NT8Z*~<`>?yaTh-Rq7P%Bo;ckdX4S>BR7#SI<1`rM)-zx%Ns-vT0 zwIoSJvMgu&V$qUy_*Oy~05}|u6U^M3k&*GzYl{Ft)CkHWmD@@|&@2XK=A6QtNf?{{ zWHbbBJm$@(<`9I(2Za(*ttT)Oftc~?bMwrND#T@$I6mz@p8T^3K^M^9VRH46Rvv9Ym>-p*~&6dk&qY*4XWZkPB{OUc_&0BCP- zFO_9E*5z_-&dbYlc}qa`6;Y`?wr}IWvfeh|pNA)-obWXXaf*^h^}R zg4ER1DUZ=*HcL*f?j8Cb1pqN&LH(kV&Joe$`3jnIb91weM&ndpU*BX;PtWAQz`zfW zYd9bP7K>$*#$-00z26T}`P*&DDdWyz6K5r?tp-r>mmoMeIA0KiB5$Re&1T)+Q}tU; zH}wJlUYt*YOJ-zVu>k*4&41g9v8e%U21t1<}~QBczguD*Rpr%p7NzT#dHD$sya| ziSpt{Vjz&9i3TDXEEct)B$N~+6sgo=Fr~H9W!s(I+0WUTdwhVBP)WO1&*T5*oZmh7 z{7)_+&nPM?TICNEoT_=$m=?cnXZyS3IX5RNVzF3sqC6>IfY0yUvvfm9UGqY@XTzJ- zexF}fnE8>(^6~~SSk7ey1Aq_=*AbE=N%CZQa=rj3%ine#`>SzeAdN_W26jeBj^lJr z84w5r)=837<2X)RB9Z9HX0u%d1qHZ%KKcoO=>RqYm+=N4BW`!9NdB$!)V8NwAh_A+q1Ar{c z3q4**ZroC)HorVKP@u}s>$<*m(iz0#@vGBk81W;o_86tLMd&>{ia^jSS+}uL*Y!O_ zG>e%-%=}PEjYGp4*fb$rz8ni@VMVg=`XtP%QsFvWCWL5W<`5Cx zV&pvIh#i&ok1WFSnBb3xXphuzb50@+kIfL8#7}H0C9J- zi@l1shXn@#fCw2Oc!g=2-4ga>cyxX~3o09iu^PnRRj)8oL@4a*G{J&jG7Q6F=GjCPBGAf}&z4ZILPgoa zBIWAoNR8j`FL}_7{{dj;=DCZs%=#VkGyupX`q1AU-^R=~5e)+vWM*fuC!qu@R1E!= z005*?sl;7dud^L{@AYth6#!HR%YRp7<*wRSdLJj_!3POz|2i& z`!1aB=(~VIpNfy$kKT8Fc*{Pqyt2M&${i5V56pZZnu>34IdR~g?pJ(hd3rmRSJuBn zMD73i{h7HoZKn@j8R#9lGSEAew$lfhxpwUQZ^x1mhLG+$qW}N^07*qoM6N<$f)FV* A7XSbN literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/result.png b/design/grasshopper-icons/png/24/result.png new file mode 100644 index 0000000000000000000000000000000000000000..5ecc83b93ab145ae5c33962eb59e2963beff333c GIT binary patch literal 334 zcmV-U0kQsxP)LDcpf`Z~{6w0u5o2BCzqA zM;D;*PmE0gOt-VM`|Z59yFkYw4b}tzHa?9BVA&c#RnJ9aw%S1OyjVQ;i|S32ws#M< zuy?$Tr~6l2o!$1zYP}|ao)H9_1}3N$ptOT93=c`hE3wIB-NTduNXEmR{wx{~kSufD zT|cC`+BCEj(1xLv5`EXu-)ZvC08~{;M!6%> z7YCOTB)qygRgG0u3%_esodY-(kuNiRBkJTpfaHa>c3K3`EXyV&{f~cM2*B0J`M#e3 gxUtq+{KwymcPD?1N+rS{(EtDd07*qoM6N<$g1P98)Bpeg literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/result_get.png b/design/grasshopper-icons/png/24/result_get.png new file mode 100644 index 0000000000000000000000000000000000000000..9814c7827b140c2306b000c3ae134190a516feea GIT binary patch literal 641 zcmV-{0)G98P)g$Hk_UVw@xu-R-!iKwqsY@&@?Kc*spi258m%%e_^1sm%*#3MhXoJ#j=0aPuK z(_=yJ**5Gw?$FexT(j>%(*b-V1+55ZgrHSRRIi}_r^tc85l&L1=;CrBy||o6ONtaF zqJg@+DDRRS27Tv|*|S~PKX$^Gk@G!a(i?r_Cojzq(HMXrUvNk(5jk@zLCUI7B?1w+ zO0iax8*8!ySD%k#Uq>f~51j#Hd2gEe7-o_xUmNT^IL8WrdjN)u2}L8PO+vX?C=|kt z`AMXHi6uaHy9a`f$NZ-cxcKZABA2IM6-#toQIr=%B>eGtMgY`uv0Yv6C#koh6#(9U zj-e;H1i#B$$m8&BErqY?@7+8Ah@vP0n5{(vK@gPU_(J~>&h?(cLDzNtjy&dS-TSTep6OU75Sa(0S{ b+{O9d)h7c@AmidB00000NkvXXu0mjfiEbit literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/result_plural_get.png b/design/grasshopper-icons/png/24/result_plural_get.png new file mode 100644 index 0000000000000000000000000000000000000000..3dc417c49ebe18b8ca8c69eb8191ee0ea4172a4d GIT binary patch literal 845 zcmV-T1G4;yP)N3$;a)$PL^~%7TbADD9uv{jAr3wRY~!N?pMohM>i$JQ_`SB; zXiQg?h(bh`?_Mp?c(WIz6EVhe0IUZvm4N3Mw{l0Cn6p|Iuk3A|{A54{5CI^K$^Aa> zaOQuj0TFG{BATbYuS;p~>r%9c<{_djN&iK09PfgPnsC-z%g5l850X3TP&+k6| zh=|Sts1&SLt4k-{`R%I;gNesje&oT=K?HnZfXDy_uCFtINJs|}B!|OsI1~!CK7QYH z;^c#Btjfy6!Qwp=gZQYmfoak3sjYcMje;Nuo1$Ue+40hcj+Z`gJfKHNep^2<5hdvm zUf=Em0K}psF~-gS@Kis!J}IjFMJ^b40Yo~E-8;v&<`o?k{C@u>0GE-kcUX6Qq;Rnb~yUF1~Z`Irp4%zwZM7yGdI) zEQIiRJf4H9s{S-h({d8ya+urAIUfLENRl)Hz~G$sIVn(bSouX+VOJVk_sI1ZcB3?) zBC36_^0<|0(=^}xE0zHO=R61?n6*ubRqsDqTz>pgWybgXVH6);eVqaDan1F}FpS4J zjflAz+wfxfPdsCcvUaeUan8@Vi(K6emn-Fp171wOPvS+_l>N)1pswpr3PQJ%G9D5_ zPopmJuzpr0pPZ6*Xg?M`x4WyXPM5` z&S#%8V22{XyG_pE8-0@uKwHlIj_Kxnb!(UgM-vnoH)zqaY0EG^p^eD_RM3cx*<&xnZVLH}^PrM-6o6~zjOfSGR=?w_r~sk+jejIoZqe^?@_ rS+MLLEt;IwqRH6>%kCkfn)Lo}7)KDU#_@@800000NkvXXu0mjf^V>Oe literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/space.png b/design/grasshopper-icons/png/24/space.png new file mode 100644 index 0000000000000000000000000000000000000000..63caf6700d4a88713972cde77e1c74bd2cb0ff28 GIT binary patch literal 663 zcmV;I0%-k-P)K{OCNpo-s?b`Sm-|zSd8C#&-s4me)r}8hb(HLMz<_00sxsz zW*UGvD1gp6zvcF@$L0}_9{}t^DeaWX53{lu+Yvf#(!%s-6`hTvZ{Qr=yn7WcH>+yccFLG~GKc7FTrrP^p1~kxzm|}Q{!Z2f z003!(?khobg#+|uegnHf0IH08heFhO-Um%1EPY>xQi>V^0JW2uz8AFcCPqXAm!YZN z!4P%!>=?K5+gZJXzd@7t#)@%e#Cos1LkC&moxoQeHG*tjH34nWfzXDy||>QWw`<~D4{78xPL%bE)f z0363zD{k6PHRW1cS;Qb{m8b88cZkNNu}C(RG9f8bb$8@$6)nK&)B)%bq4YQ1$m8f^EcIOoc; xEENb@DbD$5<>m(^opb((bN=w4jsNQ((H}`I7F>f<4l4iv002ovPDHLkV1fX~C#e7c literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/system.png b/design/grasshopper-icons/png/24/system.png new file mode 100644 index 0000000000000000000000000000000000000000..129f5cedf577ff74381c7d82d9a635ac3cfe328d GIT binary patch literal 513 zcmV+c0{;DpP)HV{6vcnfc2w1|L!OaiJ}OixMO1X^K#`yeQjr)bdpBTXIA>T1|n7Oh_nadV1&Ro_pTaeK5v<4{>;~EURJ|#tLAMSfi69 z$&)CGwuTvq$|?8T{NhZ-J16y{f-KAE?Ct?zmrXQH3>0X7*-78N{M2eSx6l60z&H$W zu%Db>xqqEWb0R0#p1xuA@heQz1R##P+`N5-Yq#ce&0cq3zjx!o8NdRf;|AKFa(BZX z&mXSS?Zj->Kl1)vojB_8?9n>Cxc}Ghr%5TlODRL86dSchPJFKapja&8`#z52;CUYH zcAJ7xpz)!Z>o#f)lu}43J5tK8KZ7)({&TsOBcjSzw$2<(w&AYGf~JBui#n7w#` zne$bI5G>!lO8KNU`W{p~x4p15d&2Q-2d+zct1f{|G+;`_iEg!AUJ700000NkvXXu0mjf D9GvZD literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/system_modify.png b/design/grasshopper-icons/png/24/system_modify.png new file mode 100644 index 0000000000000000000000000000000000000000..64fa3b37a513d7267c539b635f24a353cb4f31e1 GIT binary patch literal 816 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 P00000NkvXXu0mjf`n`M$ literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/png/24/thermometer_get.png b/design/grasshopper-icons/png/24/thermometer_get.png new file mode 100644 index 0000000000000000000000000000000000000000..9b05aa0c69a152dff68a8a12bbc49f5bdbd6a3c9 GIT binary patch literal 830 zcmV-E1Ht@>P)0Bnuaz{~7Q33!oHa3n5A+m$P;NX9u$2mV-Qc_~jcoY{G z2U1c}_Wer@ON_kJ<#O344p~`QHpW;g=e&w@ew1^*H(r201`)Awd1Ll4aV7;lJuOqt zx~`v{>1SdBj3$`4c>e$ZU_Q&A=uH&>8vsKHaV|cIh|Rr3zsJ8wWSMIxTc+^~{O@+}zxZ(w*C3btJ;-NW`w)rEt658H%FZh-+0OCnqnm zTCD?qzu$7F?>PEJ7XToQXQOcOez;sNGEH-tX`1h6#ULpuDO1z5VP*|Y76*WS(FNN) z3F+zS-z7=P7@w%kp>W94{lRZ^fAAZjaL7YMn`2Fp2m}HNPU}LX@f`FE?>K`T*ra*T zbv;2*lp!I+$=h$99IU=o!-69}#@I{p>eE{f+#{kB0IL5gou+B;>gwt!6bVw-$7bsK z*i4~FkZNmdNz=4GBHD1{^#jT{w2^jPuA#sf;U#<@g3jn~&J}=e|yhWbo9;44J_#7C*C*w=* zv`#h*qunr!tXPv$Rak~S`P*>mSv}lKR>r?703g+&deYS;g&SRKCySqZconObjsdJ# zkcL!;>S415Afkd7{`N=D{q3;H3NEx*+y%2{z!-Z>L^a=nMn(0lnqMZB zWKPk|&_w)VaW8UO$Q07*qo IM6N<$f;#ws@Bjb+ literal 0 HcmV?d00001 diff --git a/design/grasshopper-icons/review/REVIEW.md b/design/grasshopper-icons/review/REVIEW.md new file mode 100644 index 00000000..1ec165ce --- /dev/null +++ b/design/grasshopper-icons/review/REVIEW.md @@ -0,0 +1,8 @@ +# SAM_Systems - icon review + +- Objects: **38** (30 components, 8 params) +- Distinct icons: **36** (25 on SAM glyphs, 11 on SAM-BIM extension glyphs) +- Identical-pixel groups (different icon ids): **0** +- Icons shared by several objects (intentional: qualifier variants / same noun+verb): **1** + + - `energyCentre_create`: SAMAnalytical.CreateSystemEnergyCentre, SAMAnalytical.CreateSystemEnergyCentreByMechanicalSystems, SAMSystems.CreateEnergyCentreByMollier diff --git a/design/grasshopper-icons/review/contact_sheet.html b/design/grasshopper-icons/review/contact_sheet.html new file mode 100644 index 00000000..9d116498 --- /dev/null +++ b/design/grasshopper-icons/review/contact_sheet.html @@ -0,0 +1,12 @@ +SAM_Systems - SAM GH icons

SAM_Systems - SAM GH icons

38 Grasshopper objects · 36 distinct icons (11 on new SAM-BIM glyphs, green frame). Native 24 px on GH normal / orange-warning / dark bodies, plus 3x nearest-neighbour for inspection.

ahu (5)

SAMAnalytical.SystemToAHU
ahu_convert · ahu · convert
SAMSystems.CreateComponentByMollierProcess
ahu_create · ahu · create
SAMAnalytical.ConnectedSystemComponents
ahu_plural_get · ahu · get · plural
SAMAnalytical.OrderedSystemComponents
ahu_plural_sort · ahu · sort · plural
SAM.AnalyticalSystemComponentType
ahu_value · ahu · value

airflow (1)

SystemEnergyCentre.ModifyByAirflows
airflow_set · airflow · set

connector (2)

SAMAnalytical.SystemConnector
connector_create · connector · create · new glyph
SAMAnalytical.CreateDisplaySystemConnectorManager
connector_plural_create · connector · create · plural · new glyph

energyCentre (5)

SAMAnalytical.AddSystemEnergyCentre
energyCentre_add · energyCentre · add · new glyph
SAMAnalytical.CreateSystemEnergyCentre
SAMAnalytical.CreateSystemEnergyCentreByMechanicalSystems
SAMSystems.CreateEnergyCentreByMollier
energyCentre_create · energyCentre · create · new glyph
SAMSystems.CreateDisplaySystemEnergyCentre
energyCentre_display · energyCentre · display · new glyph
SAMSystems.MergeEnergyCentreByECs
energyCentre_merge · energyCentre · merge · new glyph
SAMSystems.SystemEnergyCentreDataType
energyCentre_value · energyCentre · value · new glyph

fan (3)

SAMAnalytical.SystemVentilationUnitCatalogue
fan_library_import · fan · import · library
SystemEnergyCentre.ModifyFanByAirflows
fan_modify · fan · modify
SAMAnalytical.UpdateVentilationSystem
fan_update · fan · update

geometry2D (1)

SAMAnalytical.CreateSystemGeometrySymbol
geometry2D_create · geometry2D · create

object (1)

SAMAnalytical.ConnectedSystemObjects
object_plural_get · object · get · plural

plantRoom (1)

SAMSystems.CreatePlantRoomByMollier
plantRoom_create · plantRoom · create · new glyph

processHeatRecovery (1)

SAMSystems.MollierTwinWheelExample
processHeatRecovery_create · processHeatRecovery · create · new glyph

relation (1)

SystemPlantRoom.RelatedObjects
relation_plural_get · relation · get · plural

result (2)

SAMAnalytical.SystemResultValueByHourOfYear
result_get · result · get
SAMAnalytical.SystemResults
result_plural_get · result · get · plural

settings (1)

SAMAnalytical.CreateDisplaySystemManager
settings_create · settings · create

system (3)

SAMAnalytical.ConnectedSystemGroups
system_plural_get · system · get · plural
SAMAnalytical.ModifyAirSystem
system_modify · system · modify
SAM.AnalyticalSystemType
system_value · system · value

thermometer (1)

SAMAnalytical.ConnectedSensor
thermometer_get · thermometer · get

Parameters: object glyph only, no badge (8)

ISystemComponent (param)
ahu · ahu · param
SystemEnergyCentre (param)
energyCentre · energyCentre · param · new glyph
ISystemObject (param)
object · object · param
SystemPlantRoom (param)
plantRoom · plantRoom · param · new glyph
ISystemResult (param) (hidden/obsolete)
result · result · param
ISystemSpace (param) (hidden/obsolete)
space · space · param
ISystem (param) (hidden/obsolete)
system · system · param
ISystemGroup (param)
system_plural · system · param · plural
\ No newline at end of file diff --git a/design/grasshopper-icons/review/contact_sheet.png b/design/grasshopper-icons/review/contact_sheet.png new file mode 100644 index 0000000000000000000000000000000000000000..c228b669fc5ec4ccfd67307fcd7415968fab82fe GIT binary patch literal 258669 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 z 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ò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
  • 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
  • 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 diff --git a/design/grasshopper-icons/svg/ahu_convert.svg b/design/grasshopper-icons/svg/ahu_convert.svg new file mode 100644 index 00000000..c30487e6 --- /dev/null +++ b/design/grasshopper-icons/svg/ahu_convert.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/ahu_create.svg b/design/grasshopper-icons/svg/ahu_create.svg new file mode 100644 index 00000000..4f367972 --- /dev/null +++ b/design/grasshopper-icons/svg/ahu_create.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/ahu_plural_get.svg b/design/grasshopper-icons/svg/ahu_plural_get.svg new file mode 100644 index 00000000..d48033a0 --- /dev/null +++ b/design/grasshopper-icons/svg/ahu_plural_get.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/ahu_plural_sort.svg b/design/grasshopper-icons/svg/ahu_plural_sort.svg new file mode 100644 index 00000000..c5dd5824 --- /dev/null +++ b/design/grasshopper-icons/svg/ahu_plural_sort.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/ahu_value.svg b/design/grasshopper-icons/svg/ahu_value.svg new file mode 100644 index 00000000..1da05c25 --- /dev/null +++ b/design/grasshopper-icons/svg/ahu_value.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/airflow_set.svg b/design/grasshopper-icons/svg/airflow_set.svg new file mode 100644 index 00000000..c86190aa --- /dev/null +++ b/design/grasshopper-icons/svg/airflow_set.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/connector_create.svg b/design/grasshopper-icons/svg/connector_create.svg new file mode 100644 index 00000000..3926f24c --- /dev/null +++ b/design/grasshopper-icons/svg/connector_create.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/connector_plural_create.svg b/design/grasshopper-icons/svg/connector_plural_create.svg new file mode 100644 index 00000000..3b03e547 --- /dev/null +++ b/design/grasshopper-icons/svg/connector_plural_create.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/energyCentre.svg b/design/grasshopper-icons/svg/energyCentre.svg new file mode 100644 index 00000000..c2742c08 --- /dev/null +++ b/design/grasshopper-icons/svg/energyCentre.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/energyCentre_add.svg b/design/grasshopper-icons/svg/energyCentre_add.svg new file mode 100644 index 00000000..96e1ed13 --- /dev/null +++ b/design/grasshopper-icons/svg/energyCentre_add.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/energyCentre_create.svg b/design/grasshopper-icons/svg/energyCentre_create.svg new file mode 100644 index 00000000..7cba93d3 --- /dev/null +++ b/design/grasshopper-icons/svg/energyCentre_create.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/energyCentre_display.svg b/design/grasshopper-icons/svg/energyCentre_display.svg new file mode 100644 index 00000000..71dc1b21 --- /dev/null +++ b/design/grasshopper-icons/svg/energyCentre_display.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/energyCentre_merge.svg b/design/grasshopper-icons/svg/energyCentre_merge.svg new file mode 100644 index 00000000..15e07c59 --- /dev/null +++ b/design/grasshopper-icons/svg/energyCentre_merge.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/energyCentre_value.svg b/design/grasshopper-icons/svg/energyCentre_value.svg new file mode 100644 index 00000000..7a63b6c7 --- /dev/null +++ b/design/grasshopper-icons/svg/energyCentre_value.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/fan_library_import.svg b/design/grasshopper-icons/svg/fan_library_import.svg new file mode 100644 index 00000000..8bd80d08 --- /dev/null +++ b/design/grasshopper-icons/svg/fan_library_import.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/fan_modify.svg b/design/grasshopper-icons/svg/fan_modify.svg new file mode 100644 index 00000000..ce7f9eb5 --- /dev/null +++ b/design/grasshopper-icons/svg/fan_modify.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/fan_update.svg b/design/grasshopper-icons/svg/fan_update.svg new file mode 100644 index 00000000..8b20fcde --- /dev/null +++ b/design/grasshopper-icons/svg/fan_update.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/geometry2D_create.svg b/design/grasshopper-icons/svg/geometry2D_create.svg new file mode 100644 index 00000000..c5c16937 --- /dev/null +++ b/design/grasshopper-icons/svg/geometry2D_create.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/object.svg b/design/grasshopper-icons/svg/object.svg new file mode 100644 index 00000000..f6587ef5 --- /dev/null +++ b/design/grasshopper-icons/svg/object.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/object_plural_get.svg b/design/grasshopper-icons/svg/object_plural_get.svg new file mode 100644 index 00000000..3bcdd737 --- /dev/null +++ b/design/grasshopper-icons/svg/object_plural_get.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/plantRoom.svg b/design/grasshopper-icons/svg/plantRoom.svg new file mode 100644 index 00000000..ec95f83d --- /dev/null +++ b/design/grasshopper-icons/svg/plantRoom.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/plantRoom_create.svg b/design/grasshopper-icons/svg/plantRoom_create.svg new file mode 100644 index 00000000..4427bffe --- /dev/null +++ b/design/grasshopper-icons/svg/plantRoom_create.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/processHeatRecovery_create.svg b/design/grasshopper-icons/svg/processHeatRecovery_create.svg new file mode 100644 index 00000000..583017c7 --- /dev/null +++ b/design/grasshopper-icons/svg/processHeatRecovery_create.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/relation_plural_get.svg b/design/grasshopper-icons/svg/relation_plural_get.svg new file mode 100644 index 00000000..61f82bd8 --- /dev/null +++ b/design/grasshopper-icons/svg/relation_plural_get.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/result.svg b/design/grasshopper-icons/svg/result.svg new file mode 100644 index 00000000..d978a6dc --- /dev/null +++ b/design/grasshopper-icons/svg/result.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/result_get.svg b/design/grasshopper-icons/svg/result_get.svg new file mode 100644 index 00000000..2c806e54 --- /dev/null +++ b/design/grasshopper-icons/svg/result_get.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/result_plural_get.svg b/design/grasshopper-icons/svg/result_plural_get.svg new file mode 100644 index 00000000..dc1526bb --- /dev/null +++ b/design/grasshopper-icons/svg/result_plural_get.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/settings_create.svg b/design/grasshopper-icons/svg/settings_create.svg new file mode 100644 index 00000000..c23cf4a7 --- /dev/null +++ b/design/grasshopper-icons/svg/settings_create.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/space.svg b/design/grasshopper-icons/svg/space.svg new file mode 100644 index 00000000..de5c0e80 --- /dev/null +++ b/design/grasshopper-icons/svg/space.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/system.svg b/design/grasshopper-icons/svg/system.svg new file mode 100644 index 00000000..267cc66e --- /dev/null +++ b/design/grasshopper-icons/svg/system.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/system_modify.svg b/design/grasshopper-icons/svg/system_modify.svg new file mode 100644 index 00000000..9d624dfd --- /dev/null +++ b/design/grasshopper-icons/svg/system_modify.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/system_plural.svg b/design/grasshopper-icons/svg/system_plural.svg new file mode 100644 index 00000000..df8c5b5a --- /dev/null +++ b/design/grasshopper-icons/svg/system_plural.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/system_plural_get.svg b/design/grasshopper-icons/svg/system_plural_get.svg new file mode 100644 index 00000000..1b30ec4c --- /dev/null +++ b/design/grasshopper-icons/svg/system_plural_get.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/system_value.svg b/design/grasshopper-icons/svg/system_value.svg new file mode 100644 index 00000000..52dd99bd --- /dev/null +++ b/design/grasshopper-icons/svg/system_value.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/svg/thermometer_get.svg b/design/grasshopper-icons/svg/thermometer_get.svg new file mode 100644 index 00000000..af39417c --- /dev/null +++ b/design/grasshopper-icons/svg/thermometer_get.svg @@ -0,0 +1 @@ + diff --git a/design/grasshopper-icons/tests/GhIconTest/GhIconTest.csproj b/design/grasshopper-icons/tests/GhIconTest/GhIconTest.csproj new file mode 100644 index 00000000..4dbac6fd --- /dev/null +++ b/design/grasshopper-icons/tests/GhIconTest/GhIconTest.csproj @@ -0,0 +1,21 @@ + + + net8.0-windows + true + true + disable + True + + + + + + + + + + + + + + diff --git a/design/grasshopper-icons/tests/GhIconTest/IconTests.cs b/design/grasshopper-icons/tests/GhIconTest/IconTests.cs new file mode 100644 index 00000000..782a0555 --- /dev/null +++ b/design/grasshopper-icons/tests/GhIconTest/IconTests.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text.Json; +using NUnit.Framework; + +[SetUpFixture] +public sealed class Setup : Rhino.Testing.Fixtures.RhinoSetupFixture { } + +[TestFixture] +public class IconTests +{ + // SAM_ICON_MANIFESTS = ';'-separated paths to /design/grasshopper-icons/manifest.json + [Test] + public void EveryManifestObject_LoadsInGrasshopper_WithItsRedesignedIcon() + { + var server = Grasshopper.Instances.ComponentServer; + Assert.That(server, Is.Not.Null); + var failures = new List(); + var report = new List(); + foreach (string manifest in (Environment.GetEnvironmentVariable("SAM_ICON_MANIFESTS") ?? "").Split(';', StringSplitOptions.RemoveEmptyEntries)) + { + string repo = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(manifest), "..", "..")); + var rows = JsonDocument.Parse(File.ReadAllText(manifest)).RootElement.EnumerateArray().ToList(); + int ok = 0; int globalMax = 0; + foreach (var r in rows) + { + string guid = r.GetProperty("guid").GetString(), cls = r.GetProperty("class").GetString(); + string png = Path.Combine(repo, r.GetProperty("project_dir").GetString(), "Resources", "Icons", r.GetProperty("resource").GetString() + ".png"); + var obj = server.EmitObject(new Guid(guid)); + if (obj == null) { failures.Add($"{Path.GetFileName(repo)} {cls} {guid}: not loaded by Grasshopper"); continue; } + string name = r.GetProperty("name").GetString() ?? ""; + if (!name.StartsWith("{") && obj.Name != name) failures.Add($"{cls}: name '{obj.Name}' != source '{name}'"); + string cat = r.GetProperty("category").ValueKind == JsonValueKind.String ? r.GetProperty("category").GetString() : null; + if (cat != null && !cat.StartsWith("{") && obj.Category != cat) failures.Add($"{cls}: category '{obj.Category}' != source '{cat}'"); + Bitmap icon = obj.Icon_24x24 as Bitmap; + if (icon == null) { failures.Add($"{cls}: Icon_24x24 null"); continue; } + if (icon.Width != 24 || icon.Height != 24) { failures.Add($"{cls}: icon {icon.Width}x{icon.Height}"); continue; } + using var expected = new Bitmap(png); + int maxd = 0; + for (int y = 0; y < 24; y++) + for (int x = 0; x < 24; x++) + { + Color a = icon.GetPixel(x, y), b = expected.GetPixel(x, y); + int d = Math.Abs(a.A - b.A); + if (a.A > 0 && b.A > 0) d = Math.Max(d, Math.Max(Math.Abs(a.R - b.R), Math.Max(Math.Abs(a.G - b.G), Math.Abs(a.B - b.B)))); + maxd = Math.Max(maxd, d); + } + string dump = Environment.GetEnvironmentVariable("SAM_ICON_DUMP"); + if (!string.IsNullOrEmpty(dump)) { Directory.CreateDirectory(dump); icon.Save(Path.Combine(dump, cls + ".png")); } + globalMax = Math.Max(globalMax, maxd); + if (maxd > 2) { failures.Add($"{cls}: icon differs from {Path.GetFileName(png)} (max channel diff {maxd})"); continue; } + ok++; + } + report.Add($"{Path.GetFileName(repo)}: {ok}/{rows.Count} objects load in Grasshopper with their redesigned 24x24 icon (max channel diff vs manifest PNG: {globalMax}, premultiplied-alpha rounding; tolerance 2)"); + } + foreach (var l in report) TestContext.Progress.WriteLine(l); + foreach (var f in failures) TestContext.Progress.WriteLine("FAIL " + f); + File.WriteAllLines(Path.Combine(TestContext.CurrentContext.WorkDirectory, "icon_report.txt"), report.Concat(failures.Select(f => "FAIL " + f))); + Assert.That(report, Is.Not.Empty); + Assert.That(failures, Is.Empty); + } +} diff --git a/design/grasshopper-icons/tests/GhIconTest/README.md b/design/grasshopper-icons/tests/GhIconTest/README.md new file mode 100644 index 00000000..0aee4777 --- /dev/null +++ b/design/grasshopper-icons/tests/GhIconTest/README.md @@ -0,0 +1,16 @@ +# GhIconTest: real Rhino 8 / Grasshopper icon load test + +Hosts the installed Rhino 8 + Grasshopper in-process (McNeel `Rhino.Testing`, the same setup as SAM's +`SAM.Core.Grasshopper.Tests`). Grasshopper loads the installed SAM plugins (`%APPDATA%\SAM` via `SAM.ghlink`). +For every manifest row the test: + +* emits the object by its ComponentGuid through `Grasshopper.Instances.ComponentServer` (it must load), +* checks name and category against the source, +* checks `Icon_24x24` is 24×24 and matches the manifest PNG (tolerance: 2 levels per channel, premultiplied-alpha rounding). + +It is not part of any solution. Build the repository first (post-build installs to `%APPDATA%\SAM`), then: + +``` +set SAM_ICON_MANIFESTS=\design\grasshopper-icons\manifest.json +dotnet test design\grasshopper-icons\tests\GhIconTest +``` diff --git a/design/grasshopper-icons/tests/GhIconTest/Rhino.Testing.Configs.xml b/design/grasshopper-icons/tests/GhIconTest/Rhino.Testing.Configs.xml new file mode 100644 index 00000000..e2892553 --- /dev/null +++ b/design/grasshopper-icons/tests/GhIconTest/Rhino.Testing.Configs.xml @@ -0,0 +1,5 @@ + + + C:\Program Files\Rhino 8\System + true + diff --git a/design/grasshopper-icons/tools/build.py b/design/grasshopper-icons/tools/build.py new file mode 100644 index 00000000..ccc07b1a --- /dev/null +++ b/design/grasshopper-icons/tools/build.py @@ -0,0 +1,145 @@ +"""Build this repository's SAM GH icons from manifest.json. + + python build.py -> svg/ (canonical), png/24/ (production), review/contact_sheet.png (+.html), + review/REVIEW.md (collisions + shared icons) +Deterministic: output depends only on manifest.json + icons.py + icons_ext.py. +Fails (exit 1) if two different icon ids rasterise to identical pixels. +""" +import collections +import hashlib +import html +import json +import os +import re +import sys + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import icons # noqa: E402 +import icons_ext # noqa: E402,F401 (registers the SAM-BIM extension glyphs) +import render # noqa: E402 + +DESIGN = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +REPO_NAME = os.path.basename(os.path.dirname(os.path.dirname(DESIGN))) +SVG = os.path.join(DESIGN, "svg") +PNG = os.path.join(DESIGN, "png", "24") +REVIEW = os.path.join(DESIGN, "review") + +CSS = """ +*{box-sizing:border-box}body{margin:0;background:#fff;color:#111;font:12px/1.3 'Segoe UI',system-ui,sans-serif;padding:20px 24px;width:%dpx} +h1{font-size:18px;margin:0 0 2px;text-transform:uppercase;letter-spacing:.02em}.bar{height:5px;width:120px;background:linear-gradient(90deg,#D32F2F 33%%,#F6C90E 33%% 66%%,#1565C0 66%%);margin:6px 0 10px} +h2{font-size:13px;margin:16px 0 6px;border-bottom:2px solid #111;padding-bottom:3px;text-transform:uppercase;letter-spacing:.03em} +.sub{color:#424242;margin:0 0 8px}.grid{display:grid;grid-template-columns:repeat(%d,1fr);gap:6px} +.c{border:1px solid #BDBDBD;padding:6px;display:flex;gap:8px;align-items:center;min-height:84px}.c.new{border-color:#277A45;border-width:2px} +.n{display:flex;flex-direction:column;gap:3px;align-items:center} +.gh{width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:3px} +.l{background:linear-gradient(#e6e6e6,#c9c9c9);border:1px solid #8a8a8a}.o{background:linear-gradient(#ffc680,#f0962a);border:1px solid #9a5a10} +.d{background:linear-gradient(#4a4a4a,#2e2e2e);border:1px solid #111} +img.px{image-rendering:pixelated}.t{font-size:10.5px;word-break:break-word;line-height:1.25}.t b{font-size:11px}.t i{color:#424242;font-style:normal} +""" + + +def display_name(r): + n = r["name"] or "" + m = re.match(r"^\{typeof\((?:[\w:.]+\.)?(\w+)\)\.Name\}$", n) + return (m.group(1) if m else n) + (" (param)" if r["kind"] == "param" else "") + + +def label(rows): + r = rows[0] + names = "
    ".join(html.escape(display_name(x)) + (" (hidden/obsolete)" if x["obsolete"] or "hidden" in (x["exposure"] or "") else "") for x in rows) + ext = " · new glyph" if r["glyph_origin"] != "SAM" else "" + ext += " · new verb" if r["badge_origin"] not in (None, "SAM") else "" + return (f"{names}
    {r['icon_id']} · {r['object']} · {r['op'] or 'param'}{' · plural' if r['plural'] else ''}" + f"{' · library' if r['container'] else ''}{ext}") + + +def sheet(title, subtitle, groups, out_png, cols=4, big=72, width=1500): + """groups: [(heading, [(png24, label_html, is_new)])]; native 24 px on GH normal / warning / dark bodies + 3x.""" + base = os.path.dirname(os.path.abspath(out_png)) + parts = [f"

    {html.escape(title)}

    {subtitle}

    "] + rows = 0 + for head, items in groups: + parts.append(f"

    {html.escape(head)} ({len(items)})

    ") + for png, lab, new in items: + rel = os.path.relpath(png, base).replace("\\", "/") + tiles = "".join(f"" for k in "lod") + parts.append(f"
    {tiles}
    " + f"
    {lab}
    ") + parts.append("
    ") + rows += (len(items) + cols - 1) // cols + doc = (f"{html.escape(title)}" + f"{''.join(parts)}") + html_path = os.path.splitext(out_png)[0] + ".html" + open(html_path, "w", encoding="utf-8", newline="\n").write(doc) + render._shot(os.path.abspath(html_path), os.path.abspath(out_png), width, 90 + len(groups) * 44 + rows * 118, scale=1) + render._trim(out_png) + + +def main(): + rows = json.load(open(os.path.join(DESIGN, "manifest.json"), encoding="utf-8")) + ids = {} + for r in rows: + ids.setdefault(r["icon_id"], r) + os.makedirs(SVG, exist_ok=True) + for fn in os.listdir(SVG): # svg/ mirrors the manifest exactly + if fn.endswith(".svg") and fn[:-4] not in ids: + os.remove(os.path.join(SVG, fn)) + svgs, pngs = [], [] + for iid, r in sorted(ids.items()): + svg = icons.icon_svg(r["object"], r["op"], plural=r["plural"], container=r["container"], comment=f"SAM GH icon {iid}") + p = os.path.join(SVG, iid + ".svg") + open(p, "w", encoding="utf-8", newline="\n").write(svg) + svgs.append(p) + pngs.append(os.path.join(PNG, iid + ".png")) + if os.path.isdir(PNG): + for fn in os.listdir(PNG): + if fn[:-4] not in ids: + os.remove(os.path.join(PNG, fn)) + render.rasterise(svgs, pngs) + + # ---- collision check: identical 24 px pixels for different icon ids + by_hash = collections.defaultdict(list) + for iid in ids: + by_hash[hashlib.sha1(open(os.path.join(PNG, iid + ".png"), "rb").read()).hexdigest()].append(iid) + dup = sorted(v for v in by_hash.values() if len(v) > 1) + + # ---- contact sheet: one tile per icon (objects sharing it listed together), grouped by object family + by_icon = collections.OrderedDict() + for r in sorted(rows, key=lambda r: (r["kind"] == "param", r["object"], r["op"] or "", r["icon_id"], r["name"] or "")): + by_icon.setdefault(r["icon_id"], []).append(r) + groups = collections.OrderedDict() + for iid, rs in by_icon.items(): + head = "Parameters: object glyph only, no badge" if rs[0]["kind"] == "param" else rs[0]["object"] + groups.setdefault(head, []).append((os.path.join(PNG, iid + ".png"), label(rs), + rs[0]["glyph_origin"] != "SAM" or rs[0]["badge_origin"] not in (None, "SAM"))) + os.makedirs(REVIEW, exist_ok=True) + n_new = sum(1 for r in ids.values() if r["glyph_origin"] != "SAM") + sheet(f"{REPO_NAME} - SAM GH icons", f"{len(rows)} Grasshopper objects · {len(ids)} distinct icons ({n_new} on new SAM-BIM glyphs, green frame). " + "Native 24 px on GH normal / orange-warning / dark bodies, plus 3x nearest-neighbour for inspection.", + list(groups.items()), os.path.join(REVIEW, "contact_sheet.png")) + + # ---- review report + shared = [(iid, rs) for iid, rs in by_icon.items() if len(rs) > 1] + lines = [f"# {REPO_NAME} - icon review", "", + f"- Objects: **{len(rows)}** ({sum(r['kind'] == 'component' for r in rows)} components, {sum(r['kind'] == 'param' for r in rows)} params)", + f"- Distinct icons: **{len(ids)}** ({len(ids) - n_new} on SAM glyphs, {n_new} on SAM-BIM extension glyphs)", + f"- Identical-pixel groups (different icon ids): **{len(dup)}** {dup if dup else ''}", + f"- Icons shared by several objects (intentional: qualifier variants / same noun+verb): **{len(shared)}**", ""] + for iid, rs in shared: + lines.append(f" - `{iid}`: " + ", ".join(display_name(r) for r in rs)) + open(os.path.join(REVIEW, "REVIEW.md"), "w", encoding="utf-8", newline="\n").write("\n".join(lines) + "\n") + + for r in rows: + r["status"] = "redesigned" if r["status"] == "classified" else r["status"] + json.dump(rows, open(os.path.join(DESIGN, "manifest.json"), "w", encoding="utf-8"), indent=1) + import csv + with open(os.path.join(DESIGN, "manifest.csv"), "w", newline="", encoding="utf-8") as fh: + w = csv.DictWriter(fh, fieldnames=list(rows[0].keys())) + w.writeheader() + w.writerows(rows) + print(f"{len(rows)} objects, {len(ids)} icons ({n_new} new-glyph), identical-pixel groups: {dup}") + return 1 if dup else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/design/grasshopper-icons/tools/check_assemblies.py b/design/grasshopper-icons/tools/check_assemblies.py new file mode 100644 index 00000000..5eb8db9c --- /dev/null +++ b/design/grasshopper-icons/tools/check_assemblies.py @@ -0,0 +1,73 @@ +"""Verify the built Grasshopper assemblies embed every SAM_GH_* icon their manifest rows need. + +Format-agnostic (byte[] resx, Bitmap resx via System.Resources.Extensions, or manifest resources): + * every required resource name must occur in the assembly (UTF-16LE resx name table or UTF-8 manifest name), and + * the assembly must embed at least as many 24x24 PNGs as required icons (legacy odd-size PNGs are reported). +Usage: python check_assemblies.py [ ...] (searched recursively; newest .gha/.dll per assembly wins) +""" +import io +import json +import os +import re +import sys + +from PIL import Image + +DESIGN = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +REPO = os.path.dirname(os.path.dirname(DESIGN)) +SIG, IEND = b"\x89PNG\r\n\x1a\n", b"IEND\xaeB`\x82" + + +def pngs(blob): + i = 0 + while True: + i = blob.find(SIG, i) + if i < 0: + return + j = blob.find(IEND, i) + yield Image.open(io.BytesIO(blob[i: j + len(IEND)])) + i = j + + +def assembly_name(project_dir): + pdir = os.path.join(REPO, project_dir) + csproj = [f for f in os.listdir(pdir) if f.endswith(".csproj")][0] + m = re.search(r"([^<]+)", open(os.path.join(pdir, csproj), encoding="utf-8-sig").read()) + return m.group(1).strip() if m else csproj[:-7] + + +def find(dirs, name): + hits = [] + for d in dirs: + for root, _, files in os.walk(d): + hits += [os.path.join(root, f) for f in files if f in (name + ".gha", name + ".dll")] + return max(hits, key=os.path.getmtime) if hits else None + + +def main(dirs): + rows = json.load(open(os.path.join(DESIGN, "manifest.json"), encoding="utf-8")) + need = {} + for r in rows: + need.setdefault(r["project_dir"], set()).add(r["resource"]) + fail = 0 + for pdir, names in sorted(need.items()): + asm = assembly_name(pdir) + path = find(dirs, asm) + if not path: + print(f"{asm}: NOT FOUND in {dirs} -> FAIL") + fail += 1 + continue + blob = open(path, "rb").read() + missing = [n for n in names if n.encode("utf-16-le") not in blob and n.encode("utf-8") not in blob] + imgs = list(pngs(blob)) + bad = [im.size for im in imgs if im.size != (24, 24)] + ok = not missing and sum(im.size == (24, 24) for im in imgs) >= len(names) + fail += not ok + print(f"{asm} ({os.path.relpath(path, REPO) if path.startswith(REPO) else path}): {len(names)} required icons, " + f"names missing {len(missing)}, embedded PNGs {len(imgs)} (legacy non-24x24: {len(bad)}) -> {'OK' if ok else 'FAIL'}") + print("RESULT:", "OK" if not fail else f"FAIL ({fail} assemblies)") + return 1 if fail else 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:] or [os.path.join(REPO, "build")])) diff --git a/design/grasshopper-icons/tools/check_source.py b/design/grasshopper-icons/tools/check_source.py new file mode 100644 index 00000000..0f0d7d9e --- /dev/null +++ b/design/grasshopper-icons/tools/check_source.py @@ -0,0 +1,91 @@ +"""Guard rails for the icon redesign diff. + + python check_source.py [base] (default base: origin/sow/2026-Q3) + +1. Vendored design-system files are byte-identical to SAM-BIM/SAM#166 @ cf4d924a (SHA-256). +2. Every changed line in a component .cs file is an icon-token swap inside an `Icon` getter + (`.OLD` -> `.SAM_GH_*`); generated Resources.Designer.cs / holder blocks are excluded. +3. The set of ComponentGuid values, names, nicknames, categories and exposures is unchanged vs base. +""" +import hashlib +import os +import re +import subprocess +import sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +REPO = os.path.dirname(os.path.dirname(os.path.dirname(HERE))) + +VENDORED = { # file -> SHA-256 (LF line endings) of SAM/design/grasshopper-icons/tools/ at SAM#166 head cf4d924a + "icons.py": "5ca1bfee3c0f19e55babff06120eee62c4a7468b141b608e8c386deaa998f0e7", + "render.py": "8a87f66c45e0bb3e04cc613f2b0f28a8cb8df951a7daad95bdec8e3851060a3f", + "sam_classify.py": "317064816c964e2268e9406aee9ca5f7d82c2bdb34da9c3225a344ca2464b864", # SAM classify.py +} +TOKEN = re.compile(r"\b\w+\.(SAM_GH_\w+|\w+)") +KEEP_RE = re.compile(r'ComponentGuid|base\(\s*"|GH_Exposure|Category|NickName|new Guid\(|new\("') + + +def git(*args): + return subprocess.run(["git", "-C", REPO, *args], check=True, capture_output=True, text=True, encoding="utf-8").stdout + + +def main(base): + ok = True + for f, h in VENDORED.items(): + got = hashlib.sha256(open(os.path.join(HERE, f), "rb").read().replace(b"\r\n", b"\n")).hexdigest() # autocrlf-safe + print(f"vendored {f}: {'OK' if got == h else 'MODIFIED'}") + ok &= got == h + files = [f for f in git("diff", "--name-only", base, "--", "*.cs").split("\n") if f and not f.startswith("design/")] + swaps, bad = 0, [] + for f in files: + if f.endswith("Resources.Designer.cs") or f.startswith("design/"): + continue + diff = git("diff", "-U0", base, "--", f) + if "// " in diff: # generated holder block: only additions inside the markers + block = re.findall(r"^[-+](?![-+]).*$", diff, re.M) + inside, outside = False, [] + for line in block: + if "// " in line: + inside = True + if not inside and line.strip() not in ("+", "-"): + outside.append(line) + if "// " in line: + inside = False + if outside: + bad.append((f, outside[:4])) + continue + minus = re.findall(r"^-(?!--)(.*)$", diff, re.M) + plus = re.findall(r"^\+(?!\+\+)(.*)$", diff, re.M) + if len(minus) != len(plus): + bad.append((f, "added/removed lines")) + continue + for a, b in zip(minus, plus): + if "Icon" not in a or TOKEN.sub("X", a) != TOKEN.sub("X", b) or "SAM_GH_" not in b or KEEP_RE.search(a): + bad.append((f, a.strip(), b.strip())) + else: + swaps += 1 + print(f"component .cs files changed: {len(files)}; icon-token swaps: {swaps}; non-icon changes: {len(bad)}") + for b in bad[:20]: + print(" NON-ICON CHANGE:", b) + ok &= not bad + + def guids(rev): + out = set() + listing = git("ls-tree", "-r", "--name-only", rev) if rev else git("ls-files") + for f in listing.split("\n"): + if f.endswith(".cs") and not f.startswith("design/"): + try: + t = git("show", f"{rev}:{f}") if rev else open(os.path.join(REPO, f), encoding="utf-8-sig").read() + except (subprocess.CalledProcessError, FileNotFoundError): + continue + out |= {(f, m.group(0)) for m in re.finditer(r'ComponentGuid[^"\n]*"[0-9a-fA-F-]+"', t)} + return out + g0, g1 = guids(base), guids(None) + print(f"ComponentGuid declarations: base {len(g0)}, now {len(g1)} -> {'UNCHANGED' if g0 == g1 else 'CHANGED'}") + ok &= g0 == g1 + print("RESULT:", "OK" if ok else "FAIL") + return 0 if ok else 1 + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1] if len(sys.argv) > 1 else "origin/sow/2026-Q3")) diff --git a/design/grasshopper-icons/tools/classify.py b/design/grasshopper-icons/tools/classify.py new file mode 100644 index 00000000..ba762089 --- /dev/null +++ b/design/grasshopper-icons/tools/classify.py @@ -0,0 +1,176 @@ +"""Classify every inventoried GH object into (object glyph, operation badge, modifiers). + +Input : ../manifest_raw.json (from inventory.py) +Output: ../manifest.json + ../manifest.csv (the source of truth for this repository's icons) + +Rule order (first hit wins, all deterministic): + 1. repo_rules.OVERRIDES, then SAM's OVERRIDES (sam_classify.py, vendored verbatim from SAM#166) + 2. verbs : SAM VERBS, then EXT_VERBS below + 3. nouns : repo_rules.OBJECTS, then EXT_OBJECTS below (new SAM-BIM glyphs), then SAM OBJECTS + 4. params : repo_rules.PARAM_OBJECTS, EXT_PARAM_OBJECTS, then SAM PARAM_OBJECTS +Qualifiers (`...By`) are not drawn, exactly as in SAM. +""" +import csv +import json +import os +import re +import sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +DESIGN = os.path.dirname(HERE) +sys.path.insert(0, HERE) +import icons # noqa: E402 +import icons_ext # noqa: E402 +import repo_rules as R # noqa: E402 +import sam_classify as C # noqa: E402 + +# ------------------------------------------------------------------ extra verbs (after SAM's VERBS) +EXT_VERBS = [ + (r"^(Run|Simulate|Execute|Solve|Workflow)", "run"), (r"^Open", "import"), (r"^Print", "export"), + (r"^(Show|Visuali[sz]e)", "display"), (r"^(Delete|Clear)", "remove"), (r"^Query", "get"), (r"^Assign", "set"), + (r"^(Renumber|Rationalise|Clean|Repair)", "modify"), (r"^(Verify|Validate)", "validate"), (r"^Compare", "analyse"), + (r"^(Assemble|Sew)", "merge"), (r"^Tag", "display"), (r"^(Duplicated|Connected|Ordered|Related)", "get"), +] + +# ------------------------------------------------------------------ extra nouns -> SAM-BIM extension glyphs (before SAM's OBJECTS) +EXT_OBJECTS = [ + ("AdiabaticHumidification", "processAdiabatic", None), ("IsothermalHumidification", "processHumidification", None), + ("SteamHumidification", "processHumidification", None), ("HeatingProcess", "processHeating", None), + ("CoolingProcess", "processCooling", None), ("MixingProcess", "processMixing", None), + ("HeatRecoveryProcess", "processHeatRecovery", None), ("FanProcess", "processFan", None), ("RoomProcess", "processRoom", None), + ("UndefinedProcess", "mollierProcess", None), ("MollierProcess", "mollierProcess", None), ("MollierPoint", "mollierPoint", None), + ("MollierGroup", "mollierProcess", None), ("MollierChart", "mollierChart", None), ("Diagram", "mollierChart", None), + ("Psychrometric", "mollierChart", None), ("Mollier", "mollierChart", None), + ("CellComplex", "cellComplex", None), ("Topology", "cellComplex", None), + ("Algorithm", "algorithm", None), ("GenOpt", "algorithm", None), ("Solver", "algorithm", None), ("Objective", "objective", None), + ("Script", "script", None), ("Python", "script", None), ("Macro", "script", None), ("Multitasker", "tasks", None), + ("Absorption", "sound", None), ("BandValues", "sound", None), ("Acoustic", "sound", None), + ("Sheet", "view", None), ("View", "view", None), ("ElementId", "element", None), ("UniqueId", "element", None), + ("Element", "element", None), + ("EnergyCentre", "energyCentre", None), ("PlantRoom", "plantRoom", None), ("Connector", "connector", None), + ("SunDirection", "sunPath", None), ("SunPath", "sunPath", None), ("Irradiance", "solar", None), ("SunExposure", "solar", None), + ("SunAnalysis", "solar", None), ("SolarSimulation", "solar", None), +] +EXT_PARAM_OBJECTS = { + "MollierPoint": "mollierPoint", "MollierProcess": "mollierProcess", "MollierGroup": ("mollierProcess", None, True), + "MollierObject": "mollierChart", "MollierChartObject": "mollierChart", "CellComplex": "cellComplex", "ResolvedCellComplex": "cellComplex", + "Algorithm": "algorithm", "Objective": "objective", "Script": "script", "BandValues": "sound", + "SystemEnergyCentre": "energyCentre", "SystemPlantRoom": "plantRoom", +} +NO_PLURAL = {g for g in icons_ext.EXT_GLYPHS if g.startswith(("mollier", "process"))} # charts do not stack + + +def _param_type(x): + """Type key of a param: from `{typeof(X).Name}` / a literal name, and from the GooParam class name.""" + name = x["name"] or "" + m = re.fullmatch(r"\{typeof\((?:[\w:.]+\.)?(\w+)\)\.Name\}", name) + by_name = m.group(1) if m else name.split(".")[-1] + by_class = re.sub(r"^Goo|Param$", "", x["class"]) + return by_class, by_name + + +def _lookup_param(x): + for key in _param_type(x): + for table in (R.PARAM_OBJECTS, EXT_PARAM_OBJECTS, C.PARAM_OBJECTS): + if key in table: + v = table[key] + obj, container, plural = (v, None, False) if isinstance(v, str) else (v + (False,))[:3] + if table is C.PARAM_OBJECTS and key in C.PARAM_LIBRARY: + container = "library" + return obj, container, bool(plural), key + raise KeyError(f"no param glyph for {x['class']} / {x['name']} (add it to repo_rules.PARAM_OBJECTS)") + + +def _short_candidates(name): + s = C.short(name) + out = [s] + t = re.sub(r"^\w+\.", "", s) # any plugin prefix: SAMMollier., Tas., SAMOCCT., Revit., ... + if t != s: + out.append(t) + return out + + +def classify(x): + name = x["name"] or "" + if x["category"] == "Params" or x["base_type"].startswith(("GH_PersistentParam", "GH_Param")): + obj, container, plural, key = _lookup_param(x) + return dict(kind="param", object=obj, op=None, plural=plural, container=container, rule="param:" + key) + for table, tag in ((R.OVERRIDES, "override"), (C.OVERRIDES, "sam-override")): + if name in table: + obj, op, extra = table[name] + return dict(kind="component", object=obj, op=op, plural=extra == "plural", + container="library" if extra == "library" else None, rule=tag, + note=extra if extra not in (None, "plural", "library") else None) + verbs = list(R.VERBS) + C.VERBS + EXT_VERBS + nouns = list(R.OBJECTS) + EXT_OBJECTS + C.OBJECTS + cands = _short_candidates(name) + s, op = cands[0], None + for cand in cands: + op = next((o for rx, o in verbs if re.match(rx, cand)), None) + if op: + s = cand + break + else: + s = cands[-1] + body = re.split(r"By[A-Z]", s, 1)[0] + obj, container = None, None + for text in (body, s): + for key, o, c in nouns: + if key in text: + obj, container = o, c + break + if obj: + break + if x["base_type"].startswith("GH_SAMEnumComponent") and op is None: + op = "value" + plural = bool(re.search(C.PLURAL_RE + r"(By|$|[A-Z])", body)) and container is None + return dict(kind="component", object=obj, op=op, plural=plural, container=container, rule="rule") + + +def normalise(c): + c = C.normalise(c) # ADD: plurality not drawn + if c["object"] in NO_PLURAL: + c["plural"] = False + return c + + +def origin(c): + g = "SAM-BIM ext v" + icons_ext.EXT_VERSION if c["object"] in icons_ext.EXT_GLYPHS else "SAM" + b = "SAM-BIM ext v" + icons_ext.EXT_VERSION if c["op"] in icons_ext.EXT_BADGES else "SAM" + return g, b + + +def main(): + raw = json.load(open(os.path.join(DESIGN, "manifest_raw.json"), encoding="utf-8")) + out, problems = [], [] + for x in raw: + c = normalise(classify(x)) + if not c["object"] or c["object"] not in icons.G or (c["kind"] == "component" and not c["op"]) or (c["op"] and c["op"] not in icons.BADGES): + problems.append((x["class"], x["name"], c)) + continue + iid = C.icon_id(c) + g_src, b_src = origin(c) + out.append({ + "class": x["class"], "name": x["name"], "nickname": x["nickname"], "category": x["category"], + "subcategory": x["subcategory"], "project": x["project"], "project_dir": x["project_dir"], "source": x["source"], + "guid": x["guid"], "kind": c["kind"], "exposure": x["exposure"], "obsolete": x["obsolete"], + "current_icon": x["icon_expr"], "icon_holder": x["icon_holder"], + "object": c["object"], "op": c["op"], "plural": c["plural"], "container": c["container"], + "glyph_origin": g_src, "badge_origin": b_src if c["op"] else None, + "rule": c["rule"], "note": c.get("note"), "icon_id": iid, "resource": C.resource_name(iid), + "icon_file": f"svg/{iid}.svg", "status": "classified", + }) + for cls, n, c in problems: + print("UNCLASSIFIED", cls, n, c) + out.sort(key=lambda r: (r["project"], r["object"], r["op"] or "", r["name"] or "", r["guid"])) + json.dump(out, open(os.path.join(DESIGN, "manifest.json"), "w", encoding="utf-8"), indent=1) + with open(os.path.join(DESIGN, "manifest.csv"), "w", newline="", encoding="utf-8") as fh: + w = csv.DictWriter(fh, fieldnames=list(out[0].keys()) if out else ["class"]) + w.writeheader() + w.writerows(out) + print(len(out), "classified,", len(problems), "unclassified,", len({r['icon_id'] for r in out}), "distinct icons") + return 1 if problems else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/design/grasshopper-icons/tools/icons.py b/design/grasshopper-icons/tools/icons.py new file mode 100644 index 00000000..cd7d9546 --- /dev/null +++ b/design/grasshopper-icons/tools/icons.py @@ -0,0 +1,782 @@ +"""SAM Grasshopper icon grammar: object glyphs + operation badges -> 24x24 SVG. + +Deterministic: the same (object, op, modifiers) always yields byte-identical SVG. +See ../ICON_DESIGN_SYSTEM.md for the rules this file implements. +""" +import math + +# ---------------------------------------------------------------- palette +# Taken from https://sambim.xyz (CSS custom properties + logo pixels, 2026-09-28). +INK = "#111111" # --text / --line +EMBLEM = "#81BC44" # SAM_BIM_logo.png tile green (averaged) +DEEP = "#277A45" # --green +BLUE = "#1565C0" # --blue +YELLOW = "#F6C90E" # --yellow +RED = "#D32F2F" # --red +MUTED = "#424242" # --muted +WHITE = "#FFFFFF" # --bg + +# Derived tones (flat, no gradients). Green = subject, neutral = context. +G_TOP, G_LEFT, G_RIGHT = "#ADD485", EMBLEM, "#659335" +N_TOP, N_LEFT, N_RIGHT = WHITE, "#E3E3E3", "#BDBDBD" # #BDBDBD = site border grey +N_FLAT = "#EDEDED" +SW = 1.1 # the one outline weight (px at 24x24) + + +def tones(subject): + return (G_TOP, G_LEFT, G_RIGHT) if subject else (N_TOP, N_LEFT, N_RIGHT) + + +def f(v): + s = ("%.2f" % v).rstrip("0").rstrip(".") + return "0" if s in ("-0", "") else s + + +def pts(p): + return " ".join(f(x) + "," + f(y) for x, y in p) + + +def poly(p, fill, stroke=INK, sw=SW, extra=""): + return f'' + + +def path(d, fill="none", stroke=INK, sw=SW, extra=""): + return f'' + + +def circle(cx, cy, r, fill, stroke=INK, sw=SW): + s = f' stroke="{stroke}" stroke-width="{f(sw)}"' if stroke else "" + return f'' + + +def rect(x, y, w, h, fill, rx=0, stroke=INK, sw=SW, extra=""): + r = f' rx="{f(rx)}"' if rx else "" + s = f' stroke="{stroke}" stroke-width="{f(sw)}"' if stroke else "" + return f'' + + +# ---------------------------------------------------------------- isometric helpers (2:1 pixel isometric) +def iso(ox, oy): + return lambda x, y, z: (ox + 2 * x - 2 * y, oy + x + y - z) + + +def box(P, x0, y0, z0, dx, dy, dz, t, dashed=False): + x1, y1, z1 = x0 + dx, y0 + dy, z0 + dz + ex = ' stroke-dasharray="1.6 1.1"' if dashed else "" + return "".join([ + poly([P(x0, y0, z1), P(x1, y0, z1), P(x1, y1, z1), P(x0, y1, z1)], t[0], extra=ex), + poly([P(x0, y1, z1), P(x1, y1, z1), P(x1, y1, z0), P(x0, y1, z0)], t[1], extra=ex), + poly([P(x1, y0, z1), P(x1, y1, z1), P(x1, y1, z0), P(x1, y0, z0)], t[2], extra=ex), + ]) + + +def prism(P, plan, z0, z1, t): + """Extruded convex plan polygon (counter-clockwise in plan). Visible sides + top.""" + out = [] + n = len(plan) + sides = [] + for i in range(n): + a, b = plan[i], plan[(i + 1) % n] + ex, ey = b[0] - a[0], b[1] - a[1] + nx, ny = ey, -ex # outward for CCW + if nx + ny > 1e-6: + depth = (a[0] + b[0] + a[1] + b[1]) + sides.append((depth, a, b, t[1] if ny > nx else t[2])) + for _, a, b, tone in sorted(sides, key=lambda s: s[0]): + out.append(poly([P(a[0], a[1], z1), P(b[0], b[1], z1), P(b[0], b[1], z0), P(a[0], a[1], z0)], tone)) + out.append(poly([P(x, y, z1) for x, y in plan], t[0])) + return "".join(out) + + +def hexplan(r, rot=0.0): + return [(r * math.cos(math.radians(rot + 60 * i)), r * math.sin(math.radians(rot + 60 * i))) for i in range(6)] + + +# ---------------------------------------------------------------- object glyphs +# Each returns SVG elements in the 24x24 frame. The bottom-right (≈ x,y > 14) is kept +# light because the operation badge lives there. subject=True -> SAM green. +G = {} + + +def glyph(name): + def deco(fn): + G[name] = fn + return fn + return deco + + +@glyph("space") +def _space(s=True): + return box(iso(10, 10), 0, 0, 0, 4, 4, 8, tones(s)) + + +@glyph("floor") +def _floor(s=True): + # approved exploratory icon: cutaway room corner, floor = subject + return (poly([(9, 8), (9, 2), (1, 6), (1, 12)], "#EFEFEF") + poly([(9, 8), (17, 12), (17, 6), (9, 2)], N_RIGHT) + + poly([(9, 8), (17, 12), (9, 16), (1, 12)], G_LEFT if s else N_TOP)) + + +@glyph("externalSpace") +def _external_space(s=True): + P = iso(10, 10) + return box(P, 0, 0, 0, 4, 4, 8, (N_TOP, N_LEFT, N_RIGHT), dashed=True) + + +@glyph("cluster") +def _cluster(s=True): + P = iso(7, 9) + t = (N_TOP, N_LEFT, N_RIGHT) + return box(P, 0, 0, 0, 6, 3, 7, t) + path( + "M13 5L7 8V15", stroke=DEEP if s else MUTED, sw=2.4) + + +@glyph("model") +def _model(s=True): + P = iso(9, 9) + t = tones(s) + out = [box(P, 0, 0, 0, 4.5, 3.5, 5.5, t)] + # gable roof, ridge along x at y=1.75 + out.append(poly([P(0, 3.5, 5.5), P(4.5, 3.5, 5.5), P(4.5, 1.75, 8.5), P(0, 1.75, 8.5)], t[0])) + out.append(poly([P(4.5, 0, 5.5), P(4.5, 3.5, 5.5), P(4.5, 1.75, 8.5)], t[2])) + return "".join(out) + + +@glyph("case") +def _case(s=True): + return compose_plural(G["model"], s) + + +@glyph("panel") +def _panel(s=True): + return poly([(2, 4), (14, 10), (14, 18), (2, 12)], G_LEFT if s else N_LEFT) + + +@glyph("aperture") +def _aperture(s=True): + return poly([(2, 4), (14, 10), (14, 18), (2, 12)], N_LEFT) + poly( + [(5, 7), (11, 10), (11, 14), (5, 11)], G_LEFT if s else N_TOP) + + +@glyph("openingProperties") +def _opening(s=True): + return (poly([(2, 4), (14, 10), (14, 18), (2, 12)], N_LEFT) + + poly([(5, 7), (11, 10), (11, 14), (5, 11)], MUTED) + + poly([(5, 7), (11, 10), (8, 15.5), (2, 12.5)], G_TOP if s else N_TOP)) + + +@glyph("shade") +def _shade(s=True): + return (poly([(7, 6), (17, 11), (17, 17), (7, 12)], N_LEFT) + + poly([(7, 6), (17, 11), (11, 14), (1, 9)], G_TOP if s else N_TOP)) + + +@glyph("zone") +def _zone(s=True): + P = iso(10, 7) + out = [poly([P(0, 0, 0), P(4.5, 0, 0), P(4.5, 4.5, 0), P(0, 4.5, 0)], G_LEFT if s else N_FLAT, sw=1.3)] + n = (N_TOP, N_LEFT, N_RIGHT) + out.append(box(P, 0.5, 0.5, 0, 1.6, 1.6, 5, n)) + out.append(box(P, 2.4, 2.4, 0, 1.6, 1.6, 5, n)) + return "".join(out) + + +@glyph("level") +def _level(s=True): + return (path("M2 13H20", sw=1.6) + path("M2 6.5H20", sw=1, extra=' stroke-dasharray="2 1.5"') + + poly([(3, 8), (9, 8), (6, 13)], G_LEFT if s else N_TOP)) + + +@glyph("shell") +def _shell(s=True): + return prism(iso(10, 13.5), hexplan(3.2, 15), 0, 8, tones(s)) + + +@glyph("face") +def _face(s=True): + P = iso(10, 7) + plan = [(0, 0), (5, 0), (5, 3), (3, 5), (0, 5)] + return prism(P, plan, 0, 1, tones(s)) + + +@glyph("geometry") +def _geometry(s=True): + h = [(10 + 7 * math.cos(math.radians(60 * i)), 10 + 7 * math.sin(math.radians(60 * i))) for i in range(6)] + out = [poly(h, G_TOP if s else N_FLAT)] + out += [circle(x, y, 1.5, G_RIGHT if s else MUTED, stroke=None) for x, y in h[3:6]] + return "".join(out) + + +@glyph("geometry2D") +def _geometry2d(s=True): + p = [(3, 4), (16, 4), (16, 10), (10, 10), (10, 17), (3, 17)] + return poly(p, G_TOP if s else N_FLAT) + "".join(circle(x, y, 1.4, G_RIGHT if s else MUTED, stroke=None) for x, y in p[:5:2]) + + +@glyph("plane") +def _plane(s=True): + P = iso(10, 9) + return (poly([P(0, 0, 0), P(4, 0, 0), P(4, 4, 0), P(0, 4, 0)], G_TOP if s else N_TOP) + + path("M10 13V3M8 5L10 3L12 5", sw=1.5)) + + +@glyph("transform3D") +def _transform(s=True): + return (path("M9 12V2.5M7.3 4.2L9 2.5L10.7 4.2", sw=1.5) + path("M9 12L17 16", sw=1.5) + + path("M9 12L1.5 15.8", sw=1.5) + circle(9, 12, 2.2, G_LEFT if s else N_TOP)) + + +@glyph("mesh") +def _mesh(s=True): + P = iso(10, 7) + a, b, c, d, m = P(0, 0, 0), P(5, 0, 0), P(5, 5, 0), P(0, 5, 0), P(2.5, 2.5, 0) + t1, t2 = (G_TOP, G_LEFT) if s else (N_TOP, N_LEFT) + return poly([a, b, m], t1) + poly([b, c, m], t2) + poly([c, d, m], t1) + poly([d, a, m], t2) + + +@glyph("polyloop") +def _polyloop(s=True): + p = [(3, 5), (12, 2.5), (17, 9), (11, 16), (4, 13)] + return poly(p, G_TOP if s else "none", stroke=DEEP if s else INK, sw=1.8) + "".join( + circle(x, y, 1.3, INK, stroke=None) for x, y in p) + + +@glyph("segment") +def _segment(s=True): + return path("M3 15L16 4", stroke=DEEP if s else INK, sw=2) + circle(3, 15, 2, WHITE) + circle(16, 4, 2, WHITE) + + +@glyph("points") +def _points(s=True): + fill = G_LEFT if s else N_TOP + return circle(5, 13, 2.4, fill) + circle(11, 4.5, 2.4, fill) + circle(15, 11, 2.4, fill) + + +@glyph("vector") +def _vector(s=True): + return path("M3 16L15 4M8.5 4H15V10.5", stroke=DEEP if s else INK, sw=2.2) + + +@glyph("sectionBox") +def _section_box(s=True): + P = iso(12, 12) + n = (N_TOP, N_LEFT, N_RIGHT) + out = [poly([P(0, 0, 3), P(4, 0, 3), P(4, 4, 3), P(0, 4, 3)], G_LEFT if s else N_TOP)] + out.append(poly([P(0, 4, 3), P(4, 4, 3), P(4, 4, 0), P(0, 4, 0)], n[1])) + out.append(poly([P(4, 0, 3), P(4, 4, 3), P(4, 4, 0), P(4, 0, 0)], n[2])) + out.append(box(P, 0, 0, 7, 4, 4, 3, n)) + return "".join(out) + + +def _slab(P, x0, dx, t, dy=3.5, dz=9): + return box(P, x0, 0, 0, dx, dy, dz, t) + + +@glyph("construction") +def _construction(s=True): + # one wall block, three adjoining layers: neutral | green core | neutral (ink only at seams) + P = iso(8, 11) + n = (N_TOP, N_LEFT, N_RIGHT) + return (box(P, 0, 0, 0, 1.3, 3.5, 9, n) + box(P, 1.3, 0, 0, 2.0, 3.5, 9, tones(s)) + + box(P, 3.3, 0, 0, 1.3, 3.5, 9, n)) + + +@glyph("constructionLayer") +def _construction_layer(s=True): + return _slab(iso(9, 11), 1.6, 1.1, tones(s)) + + +@glyph("materialLayer") +def _material_layer(s=True): + P = iso(9, 11) + h = "".join(f"M{f(P(2.7, y, 8.2)[0])} {f(P(2.7, y, 8.2)[1])}L{f(P(2.7, y - 1.4, 0.8)[0])} {f(P(2.7, y - 1.4, 0.8)[1])}" for y in (2, 3.3)) + return _slab(P, 1.6, 1.1, tones(s)) + path(h, sw=0.9) + + +@glyph("apertureConstruction") +def _aperture_construction(s=True): + # double-glazing unit: rear pane + front pane with SAM-green glass + rear = [(6, 2), (16, 7), (16, 15), (6, 10)] + front = [(2, 5), (12, 10), (12, 18), (2, 13)] + return (poly(rear, N_TOP) + poly(front, N_LEFT) + + poly([(4, 7.6), (10, 10.6), (10, 15.4), (4, 12.4)], G_LEFT if s else N_TOP)) + + +@glyph("material") +def _material(s=True): + # material sample sphere: body + shaded crescent + highlight + return (circle(10, 10, 7.5, G_LEFT if s else N_TOP) + + path("M4.2 13.6A7.5 7.5 0 0 0 17.5 10A7.5 6 0 0 1 4.2 13.6Z", fill=G_RIGHT if s else N_RIGHT, stroke="none") + + circle(10, 10, 7.5, "none") + circle(7.2, 6.8, 1.6, WHITE, stroke=None)) + + +@glyph("transparentMaterial") +def _transparent_material(s=True): + return (circle(10, 10, 7.5, "#F3F8EC" if s else WHITE) + path("M6.5 6.8A4.8 4.8 0 0 1 11 4.8", stroke=DEEP, sw=1.4) + + path("M5.5 14.5L14.5 5.5", stroke=G_LEFT if s else N_RIGHT, sw=1.2, extra=' stroke-dasharray="1.6 1.2"')) + + +@glyph("gasMaterial") +def _gas_material(s=True): + out = [circle(10, 10, 7.5, WHITE).replace("/>", ' stroke-dasharray="2 1.4"/>')] + out += [circle(x, y, 1.3, G_RIGHT if s else MUTED, stroke=None) for x, y in ((7, 7), (12.5, 6.5), (6.5, 12.5), (11, 11), (14, 13))] + return "".join(out) + + +@glyph("profile") +def _profile(s=True): + return (path("M3 13.5H6.5V6H11V10H16.5V16H3Z", fill=G_TOP if s else N_FLAT, stroke="none") + + path("M3 2.5V16H17", sw=1.3) + path("M3 13.5H6.5V6H11V10H16.5", stroke=DEEP if s else INK, sw=1.8)) + + +@glyph("internalCondition") +def _person(s=True): + fill = G_LEFT if s else N_TOP + return circle(10, 5.5, 3.2, fill) + path("M3.5 17.5a6.5 6.5 0 0 1 13 0z", fill=fill) + + +@glyph("degreeOfActivity") +def _activity(s=True): + return _person(s) + path("M1 8.5h2.2M0.8 11.5h2", sw=1.3) + path("M17 8.5h2.2M17.2 11.5h2", sw=1.3) + + +@glyph("lighting") +def _bulb(s=True): + return (path("M10 2.5a5.5 5.5 0 0 1 3.2 10v2.3h-6.4v-2.3A5.5 5.5 0 0 1 10 2.5z", fill=G_TOP if s else N_TOP) + + rect(7, 15.8, 6, 2.2, MUTED, rx=0.6, stroke=None)) + + +@glyph("equipment") +def _equipment(s=True): + return rect(2.5, 3, 15, 10, G_TOP if s else N_TOP, rx=1) + path("M10 13V16.5M6 17H14", sw=1.5) + + +@glyph("infiltration") +def _wind(s=True): + c = DEEP if s else INK + return (path("M2 7H12a2.4 2.4 0 1 0-2.4-2.4", stroke=c, sw=1.8) + path("M2 11H16", stroke=c, sw=1.8) + + path("M2 15H11a2.4 2.4 0 1 1-2.4 2.4", stroke=c, sw=1.8)) + + +@glyph("pollutant") +def _pollutant(s=True): + return (path("M5 15a3.5 3.5 0 0 1 0-7a4.5 4.5 0 0 1 8.6-1.2A3.8 3.8 0 0 1 15 15z", fill=G_TOP if s else N_TOP) + + circle(7.5, 11.5, 1.1, INK, stroke=None) + circle(11, 10, 1.1, INK, stroke=None) + circle(12.5, 13, 1.1, INK, stroke=None)) + + +@glyph("thermometer") +def _thermo(s=True): + return (path("M8 11.5V4a2 2 0 0 1 4 0v7.5a3.8 3.8 0 1 1-4 0z", fill=WHITE) + + path("M10 7.5V13", stroke=G_RIGHT if s else MUTED, sw=2.2) + circle(10, 14.5, 2.1, G_LEFT if s else MUTED, stroke=None) + + path("M13.5 5h2M13.5 8h2", sw=1)) + + +@glyph("fan") +def _fan(s=True): + out = [circle(10, 10, 7.5, G_TOP if s else N_TOP)] + for a in (0, 120, 240): + r = math.radians(a) + c, sn = math.cos(r), math.sin(r) + tip = (10 + 5.8 * c, 10 + 5.8 * sn) + side = (10 + 4.2 * math.cos(r + 0.9), 10 + 4.2 * math.sin(r + 0.9)) + out.append(poly([(10, 10), tip, side], G_RIGHT if s else MUTED, sw=0.8)) + out.append(circle(10, 10, 1.4, WHITE)) + return "".join(out) + + +@glyph("airflow") +def _airflow(s=True): + c = DEEP if s else INK + return "".join(path(f"M2 {y}H14M11 {y - 2.5}L14 {y}L11 {y + 2.5}", stroke=c, sw=1.8) for y in (5, 10, 15)) + + +@glyph("izam") +def _izam(s=True): + P = iso(9, 12) + n = (N_TOP, N_LEFT, N_RIGHT) + return (box(P, 0, 1, 0, 2.2, 2.2, 5, n) + box(P, 3.4, -1.2, 0, 2.2, 2.2, 5, n) + + path("M4 5.2Q9 0.6 14.5 3.2M11.8 1.6L14.5 3.2L12.3 5.2", stroke=DEEP if s else INK, sw=1.7)) + + +@glyph("ahu") +def _ahu(s=True): + P = iso(9, 11) + cx, cy = P(2.5, 2.5, 3) + return box(P, 0, 0, 0, 5, 2.5, 6, tones(s)) + circle(cx, cy, 2.4, WHITE) + path( + f"M{f(cx - 1.3)} {f(cy - 1.3)}L{f(cx + 1.3)} {f(cy + 1.3)}M{f(cx + 1.3)} {f(cy - 1.3)}L{f(cx - 1.3)} {f(cy + 1.3)}", sw=0.9) + + +@glyph("system") +def _system(s=True): + return (rect(2.5, 6, 15, 8, G_TOP if s else N_TOP, rx=1) + path("M2.5 10H0.8M17.5 10H19.2", sw=2) + + circle(10, 10, 2.8, WHITE) + path("M8.2 8.2L11.8 11.8M11.8 8.2L8.2 11.8", sw=1)) + + +@glyph("location") +def _pin(s=True): + return (path("M3 17.5H17", sw=1.3) + path("M10 17C6 12.5 4.2 9.8 4.2 7.2a5.8 5.8 0 0 1 11.6 0C15.8 9.8 14 12.5 10 17z", fill=G_LEFT if s else N_TOP) + + circle(10, 7.2, 2, WHITE)) + + +@glyph("address") +def _address(s=True): + return rect(1.5, 9.5, 12, 8, WHITE, rx=1) + path("M4 12.5h7M4 15h4.5", sw=1.1) + path( + "M13 12C10.5 9.2 9.5 7.6 9.5 6a3.5 3.5 0 0 1 7 0C16.5 7.6 15.5 9.2 13 12z", fill=G_LEFT if s else N_TOP) + circle(13, 6, 1.1, WHITE, stroke=None) + + +def _sun(cx, cy, r, rays=True): + out = "" + if rays: + d = "".join(f"M{f(cx + (r + 1.3) * math.cos(math.radians(a)))} {f(cy + (r + 1.3) * math.sin(math.radians(a)))}" + f"L{f(cx + (r + 3) * math.cos(math.radians(a)))} {f(cy + (r + 3) * math.sin(math.radians(a)))}" for a in range(0, 360, 45)) + out += path(d, sw=1.2) + return out + circle(cx, cy, r, YELLOW) + + +@glyph("weather") +def _weather(s=True): + return _sun(7.5, 7, 3.2) + path("M7 17.5a3.4 3.4 0 0 1 0-6.8a4.4 4.4 0 0 1 8.4-0.8A3.6 3.6 0 0 1 16 17.5z", fill=G_TOP if s else N_TOP) + + +@glyph("weatherData") +def _weather_data(s=True): + return _sun(6.5, 6, 2.6) + path("M2 17.5H18", sw=1.3) + "".join( + rect(x, y, 2.4, 17.5 - y, G_LEFT if s else N_TOP, stroke=INK, sw=0.9) for x, y in ((9, 11), (12.2, 8), (15.4, 12))) + + +@glyph("weatherYear") +def _weather_year(s=True): + return (rect(2.5, 4, 15, 13.5, WHITE, rx=1) + rect(2.5, 4, 15, 3.5, G_LEFT if s else N_LEFT, rx=1) + + "".join(circle(x, y, 0.9, INK, stroke=None) for x in (6, 10, 14) for y in (10.5, 14)) + _sun(15.5, 3.5, 2.2, rays=False)) + + +@glyph("designDay") +def _design_day(s=True): + return (path("M2 16H18", sw=1.3) + path("M3.5 16a6.5 6.5 0 0 1 13 0", stroke=DEEP if s else INK, sw=1.4, extra=' stroke-dasharray="1.8 1.3"') + + _sun(10, 9.5, 2.6, rays=True)) + + +@glyph("clock") +def _clock(s=True): + return circle(10, 10, 7.5, G_TOP if s else N_TOP) + path("M10 5.5V10L13.5 12", sw=1.7) + + +@glyph("calendar") +def _calendar(s=True): + return (rect(2.5, 4, 15, 13.5, WHITE, rx=1) + rect(2.5, 4, 15, 3.5, G_LEFT if s else N_LEFT, rx=1) + + "".join(circle(x, y, 0.9, INK, stroke=None) for x in (6, 10, 14) for y in (10.5, 14)) + path("M6.5 2.5v3M13.5 2.5v3", sw=1.4)) + + +@glyph("result") +def _result(s=True): + fill = G_LEFT if s else N_TOP + return path("M2 17.5H18", sw=1.3) + rect(3, 11, 3.4, 6.5, fill) + rect(8, 6, 3.4, 11.5, fill) + rect(13, 2.5, 3.4, 15, fill) + + +@glyph("table") +def _table(s=True): + return (rect(2, 3, 16, 14, WHITE, rx=1) + rect(2, 3, 16, 4, G_LEFT if s else N_LEFT, rx=1) + + path("M2 11.5H18M7.5 3V17M13 3V17", sw=0.9)) + + +@glyph("textMap") +def _text_map(s=True): + return (rect(1.5, 3, 6, 14, WHITE, rx=1) + rect(12.5, 3, 6, 14, G_TOP if s else N_TOP, rx=1) + + path("M3.5 7h2M3.5 10h2M3.5 13h2M14.5 7h2M14.5 10h2M14.5 13h2", sw=1.1) + path("M8.5 10H11.5M10.3 8.8L11.5 10L10.3 11.2", sw=1.1)) + + +@glyph("value") +def _tag(s=True): + return poly([(2, 10), (7, 4.5), (17.5, 4.5), (17.5, 15.5), (7, 15.5)], G_LEFT if s else N_TOP) + circle(7, 10, 1.4, WHITE) + + +@glyph("name") +def _name(s=True): + return rect(1.5, 5, 16, 10, WHITE, rx=2) + path("M4.5 8.5h10M4.5 11.5h6", stroke=DEEP if s else INK, sw=1.8) + + +@glyph("json") +def _json(s=True): + c = DEEP if s else INK + return (path("M7 3C4.5 3 5.5 9 3 10C5.5 11 4.5 17 7 17", stroke=c, sw=1.8) + path("M13 3C15.5 3 14.5 9 17 10C14.5 11 15.5 17 13 17", stroke=c, sw=1.8) + + circle(10, 10, 1.4, G_LEFT if s else INK, stroke=None)) + + +@glyph("file") +def _file(s=True): + return (path("M3.5 2H11.5L16 6.5V18H3.5Z", fill=WHITE) + path("M11.5 2V6.5H16", fill=G_LEFT if s else N_LEFT) + + path("M6 10h7.5M6 13h7.5M6 16h4", stroke=DEEP if s else INK, sw=1.1)) + + +@glyph("log") +def _log(s=True): + return (path("M3.5 2H16V18H3.5Z", fill=WHITE) + path("M6 5.5h7.5M6 8.5h7.5M6 11.5h7.5M6 14.5h4", sw=1.1) + + rect(3.5, 2, 2, 16, G_LEFT if s else N_LEFT)) + + +@glyph("colour") +def _colour(s=True): + return rect(2, 2, 6.5, 6.5, RED) + rect(6.5, 6.5, 6.5, 6.5, YELLOW) + rect(11, 11, 6.5, 6.5, BLUE) + + +@glyph("number") +def _number(s=True): + return (rect(1.5, 7, 17, 7, G_TOP if s else N_TOP, rx=1) + + path("M4.5 7v3M7.5 7v2M10.5 7v3M13.5 7v2M16.5 7v3", sw=1)) + + +@glyph("text") +def _text(s=True): + fill = G_LEFT if s else INK + return (path("M3 12.5a3 3 0 1 1 3 3c0 0 0 2.5-2.5 3.5c1-1.5 1-2 0.8-2.5A3 3 0 0 1 3 12.5z", fill=fill, sw=0.9) + + path("M10 12.5a3 3 0 1 1 3 3c0 0 0 2.5-2.5 3.5c1-1.5 1-2 0.8-2.5A3 3 0 0 1 10 12.5z", fill=fill, sw=0.9) + + path("M3 5.5h14", sw=1.3)) + + +@glyph("list") +def _list(s=True): + return "".join(circle(3.5, y, 1.5, G_LEFT if s else INK, stroke=None) + path(f"M7 {y}H17", sw=1.6) for y in (4.5, 10, 15.5)) + + +@glyph("tree") +def _tree(s=True): + fill = G_LEFT if s else N_TOP + return (path("M4 10H8M8 4V16M8 4H12M8 10H12M8 16H12", sw=1.4) + circle(3.5, 10, 2, fill) + + circle(14, 4, 2, fill) + circle(14, 10, 2, fill) + circle(14, 16, 2, fill)) + + +@glyph("folder") +def _folder(s=True): + return path("M2 5.5a1 1 0 0 1 1-1H8l1.8 2H17a1 1 0 0 1 1 1V16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1z", fill=G_LEFT if s else N_TOP) + + +@glyph("object") +def _object(s=True): + # echo of the SAM-BIM emblem: the green rounded tile (no lettering) + return rect(2.5, 2.5, 14, 14, EMBLEM if s else N_TOP, rx=2.5) + path("M6 8h7M6 11h4.5", stroke=WHITE if s else INK, sw=1.6) + + +@glyph("relation") +def _relation(s=True): + fill = G_LEFT if s else N_TOP + return (path("M5 14L10 4.5L15.5 13Z", sw=1.3) + circle(10, 4.5, 2.6, fill) + + circle(4.5, 14.5, 2.6, fill) + circle(15.5, 13, 2.6, fill)) + + +@glyph("group") +def _group(s=True): + return (rect(1.5, 2.5, 17, 15, "none", rx=2.5, extra=' stroke-dasharray="2 1.4"') + + rect(4, 5, 5.5, 5.5, G_LEFT if s else N_TOP, rx=1) + rect(10.5, 9, 5.5, 5.5, G_LEFT if s else N_TOP, rx=1)) + + +@glyph("indexed") +def _indexed(s=True): + return "".join(rect(2 + 5.5 * i, 7, 4.6, 6, G_LEFT if s and i == 1 else N_TOP, rx=0.8) for i in range(3)) + path( + "M4.3 4.5v1M9.8 4.5v1M15.3 4.5v1", sw=1.2) + + +@glyph("type") +def _type(s=True): + return (circle(5.5, 6, 3.5, N_TOP) + rect(10, 2.5, 7, 7, G_LEFT if s else N_TOP, rx=0.5) + + poly([(3, 17.5), (7.5, 10.5), (12, 17.5)], N_TOP)) + + +@glyph("settings") +def _settings(s=True): + return (path("M2 6H18M2 14H18", sw=1.4) + circle(12.5, 6, 2.6, G_LEFT if s else N_TOP) + + circle(6.5, 14, 2.6, G_LEFT if s else N_TOP)) + + +@glyph("compass") +def _compass(s=True): + return circle(10, 10, 7.5, WHITE) + poly([(10, 3.5), (12.4, 10), (7.6, 10)], G_LEFT if s else INK, sw=0.9) + poly( + [(10, 16.5), (12.4, 10), (7.6, 10)], N_LEFT, sw=0.9) + + +@glyph("heat") +def _heat(s=True): + c = DEEP if s else INK + return (rect(8, 2, 4, 16, N_LEFT) + path("M1.5 10H17.5M14.5 7L17.5 10L14.5 13", stroke=c, sw=1.8) + + path("M3 4.5q1.2 1.2 0 2.4t0 2.4", stroke=c, sw=1.1)) + + +@glyph("daylight") +def _daylight(s=True): + P = iso(11, 8) + return (poly([P(0, 0, 0), P(4, 0, 0), P(4, 4, 0), P(0, 4, 0)], G_LEFT if s else N_TOP) + + path("M5 5.5L9 11.5M8 3.5L13 11", stroke=INK, sw=1.1, extra=' stroke-dasharray="1.5 1"') + _sun(3.5, 3.5, 2.3, rays=False)) + + +@glyph("grid") +def _grid(s=True): + P = iso(10, 7) + out = [poly([P(0, 0, 0), P(5, 0, 0), P(5, 5, 0), P(0, 5, 0)], G_TOP if s else N_TOP)] + out += [circle(*P(i, j, 0), 0.9, INK, stroke=None) for i in (1, 2.5, 4) for j in (1, 2.5, 4)] + return "".join(out) + + +@glyph("normal") +def _normal(s=True): + return poly([(6, 4), (16, 9), (16, 17), (6, 12)], N_LEFT) + path("M11 10.5L2.5 14.8M3.4 12.2L2.5 14.8L5.2 15.4", stroke=DEEP if s else INK, sw=1.8) + + +@glyph("matrix") +def _matrix(s=True): + return (path("M4.5 3H2.5V17H4.5M15.5 3H17.5V17H15.5", sw=1.4) + + "".join(circle(x, y, 1.3, G_RIGHT if s and x == y else INK, stroke=None) for x in (6, 10, 14) for y in (6, 10, 14))) + + +@glyph("info") +def _info(s=True): + return rect(2.5, 2.5, 15, 15, EMBLEM, rx=2.5) + circle(10, 6.3, 1.4, WHITE, stroke=None) + path("M10 9.5V14.5", stroke=WHITE, sw=2.2) + + +@glyph("constructionManager") +def _manager(s=True): + return scaled(G["apertureConstruction"](False), 0.72, 6.5, -2.5) + scaled(G["construction"](s), 0.78, -2, 3) + + +# ---------------------------------------------------------------- composition modifiers +def scaled(svg, k, tx, ty): + """Place a glyph scaled by k while keeping the outline weight constant (SW at 24 px).""" + import re + svg = re.sub(r'stroke-width="([\d.]+)"', lambda m: f'stroke-width="{f(float(m.group(1)) / k)}"', svg) + return f'{svg}' + + +def compose_plural(fn, s): + return scaled(fn(s), 0.78, 5, -1.5) + scaled(fn(s), 0.78, -0.5, 3.6) + + +def compose_add(fn, s, plural=False): + """ADD: an existing (neutral) instance with the new one(s) in SAM green in front of it.""" + if plural: + return scaled(fn(False), 0.66, 7, -2) + scaled(fn(s), 0.66, 3.2, 1.2) + scaled(fn(s), 0.66, -0.6, 4.6) + return scaled(fn(False), 0.78, 5, -1.5) + scaled(fn(s), 0.78, -0.5, 3.6) + + +def compose_library(fn, s, add=False): + cards = (rect(7.5, 1.5, 12, 12, WHITE, rx=1.2) + rect(5.5, 3.5, 12, 12, WHITE, rx=1.2) + + path("M9.5 4.5h7M9.5 6.5h5", sw=1)) + if add: # a new green item going into an existing (neutral) library + return cards + scaled(fn(False), 0.74, -0.5, 4.2) + scaled(fn(s), 0.5, 10, -0.5) + return cards + scaled(fn(s), 0.74, -0.5, 4.2) + + +def effect_split(fn, s): + a = '' + b = '' + return (f'{a}{b}{fn(s)}' + f'{fn(s)}') + + +def effect_intersect(fn, s): + return (f'{_silhouette(fn)}' + + scaled(fn(False), 0.78, 5, -1.5) + scaled(fn(False), 0.78, -0.5, 3.6) + + f'{scaled(fn(True), 0.78, 5, -1.5)}') + + +def effect_difference(fn, s): + return scaled(fn(True), 0.78, -0.5, 3.6) + scaled(_cutter(fn), 0.78, 5, -1.5) + + +def _silhouette(fn): + import re + return re.sub(r' stroke="[^"]*"', "", fn(False)) + + +def _cutter(fn): + import re + s = fn(False) + s = re.sub(r'fill="(?!none)[^"]*"', 'fill="#FFFFFF"', s) + return s.replace("' + + +BADGES = { + # op: (family, glyph(c)) + "create": ("construct", lambda c: _g("M19 16.6v4.8M16.6 19h4.8", c, 1.7)), + "add": ("construct", lambda c: _g("M19 16.6v4.8M16.6 19h4.8", c, 1.7)), + "copy": ("construct", lambda c: _g("M16.9 17.8h2.7v3.3h-2.7zM18.4 17.8v-1.2h2.7v3.3h-1.5", c, 1.1)), + "get": ("query", lambda c: _g("M17 21L21 17M18.2 17H21V19.8", c)), + "filter": ("query", lambda c: _g("M16.5 17H21.5L19.8 19.2V21.4L18.2 20.6V19.2Z", c, 1.1, fill=c)), + "inspect": ("query", lambda c: _g("M18.4 18.4m-1.7 0a1.7 1.7 0 1 0 3.4 0a1.7 1.7 0 1 0-3.4 0M19.7 19.7L21.2 21.2", c, 1.3)), + "list": ("query", lambda c: _g("M16.8 17.3h4.4M16.8 19h4.4M16.8 20.7h4.4", c, 1.1)), + "display": ("query", lambda c: _g("M16.2 19Q19 15.6 21.8 19Q19 22.4 16.2 19Z", c, 1.1) + f''), + "set": ("change", lambda c: _g("M21.2 16.8L17.3 20.7M16.9 17.8V21.1H20.2", c, 1.7)), + "modify": ("change", lambda c: _g("M19 16.2L21.6 21H16.4Z", c, 1.6)), + "update": ("change", lambda c: _g("M21.3 18.6A2.4 2.4 0 1 1 20.1 16.9", c, 1.7) + ''), + "merge": ("change", lambda c: _g("M16.6 16.6L19 19.2L21.4 16.6M19 19.2V21.6", c, 1.8)), + "split": ("change", lambda c: _g("M19 16.4V18.8L16.6 21.4M19 18.8L21.4 21.4", c, 1.8)), + "section": ("change", lambda c: _g("M16.9 16.9h4.2v4.2h-4.2z", c, 1.2) + _g("M15.9 19h6.2", c, 1.7)), + "union": ("change", lambda c: _g("M16.9 16.6v2.4a2.1 2.1 0 0 0 4.2 0v-2.4", c, 1.7)), + "intersect": ("change", lambda c: _g("M16.9 21.4v-2.4a2.1 2.1 0 0 1 4.2 0v2.4", c, 1.7)), + "difference": ("change", lambda c: _g("M16.6 16.6h4.8v2.4h-2.4v2.4h-2.4z", c, 1.1, fill=c)), + "offset": ("change", lambda c: _g("M16.5 16.5h5v5h-5z", c, 1.3) + ''), + "transform": ("change", lambda c: _g("M17.6 19h2.8", c, 1.7) + ''), + "snap": ("change", lambda c: _g("M21 16.4V21.6", c, 1.8) + f''), + "align": ("change", lambda c: _g("M16.8 16.4V21.6", c, 1.6) + _g("M18.5 17.6h3.1M18.5 20.4h1.8", c, 1.8)), + "extend": ("change", lambda c: _g("M16.3 19h3", c, 1.8) + _g("M21.6 16.5V21.5", c, 1.6) + ''), + "flip": ("change", lambda c: _g("M17.6 21.4V17.6M20.4 16.6V20.4", c, 1.6) + ''), + "triangulate": ("change", lambda c: _g("M19 16.3L21.6 21.2H16.4ZM19 16.3V21.2", c, 1.4)), + "sort": ("change", lambda c: _g("M16.6 17.1h4.8M16.6 19h3.2M16.6 20.9h1.6", c, 1.6)), + "remove": ("remove", lambda c: _g("M16.6 19h4.8", c, 1.8)), + "error": ("remove", lambda c: _g("M19 16.7v2.7", c, 1.6) + f''), + "calculate": ("evaluate", lambda c: _g("M16.8 17.9h4.4M16.8 20.1h4.4", c, 1.4)), + "sum": ("evaluate", lambda c: _g("M19 16.8v4.4M16.8 19h4.4", c, 1.4)), + "multiply": ("evaluate", lambda c: _g("M17.3 17.3l3.4 3.4M20.7 17.3l-3.4 3.4", c, 1.4)), + "divide": ("evaluate", lambda c: _g("M16.8 19h4.4", c, 1.3) + f''), + "analyse": ("evaluate", lambda c: _g("M17.2 21.2v-1.8M19 21.2v-4.2M20.8 21.2v-2.8", c, 1.3)), + "validate": ("evaluate", lambda c: _g("M16.9 19.1L18.4 20.6L21.2 17.4", c, 1.5)), + "convert": ("transfer", lambda c: _g("M16.7 17.6H19.8M21.3 20.4H18.2", c, 1.5) + ''), + "import": ("transfer", lambda c: _g("M19 16.1V19.4", c, 2.0) + ''), + "export": ("transfer", lambda c: _g("M19 21.9V18.6", c, 2.0) + ''), + "value": ("value", lambda c: _g("M16.9 17.3h4.2M16.9 19h4.2M16.9 20.7h4.2", c, 1.3)), +} + + +def badge(op): + fam, g = BADGES[op] + disc, gc, ring = FAMILIES[fam] + r = f' stroke="{ring}" stroke-width="0.9"' if ring else "" + return (f'' + f'' + g(gc)) + + +# ---------------------------------------------------------------- icon +def icon_svg(obj, op=None, plural=False, container=None, subject=True, comment=""): + fn = G[obj] + if container == "library": + base = lambda s: compose_library(fn, s, add=op == "add") # noqa: E731 + elif op == "add": + base = lambda s: compose_add(fn, s, plural) # noqa: E731 + elif plural: + base = lambda s: compose_plural(fn, s) # noqa: E731 + else: + base = fn + body = EFFECTS[op](base, subject) if op in EFFECTS else base(subject) + b = badge(op) if op else "" + note = f"" if comment else "" + return (f'{note}' + f'{body}{b}\n') diff --git a/design/grasshopper-icons/tools/icons_ext.py b/design/grasshopper-icons/tools/icons_ext.py new file mode 100644 index 00000000..b222722e --- /dev/null +++ b/design/grasshopper-icons/tools/icons_ext.py @@ -0,0 +1,223 @@ +"""SAM-BIM extension glyphs for the Grasshopper icon grammar (shared by every SAM-BIM plugin repo). + +`icons.py` is the frozen SAM design system (SAM-BIM/SAM#166, vendored verbatim). This module only +*adds* object glyphs for domains that SAM itself has no noun for (psychrometrics, topology, +optimisation, scripting, acoustics, Revit documents, HVAC plant, solar). It adds one verb, `run` +(Evaluate family), and does not change any colour, family, badge, modifier or existing glyph. +The file is byte-identical in every SAM-BIM repository that uses it; see ICON_DESIGN_SYSTEM_EXT.md. +""" +import math + +import icons +from icons import (BLUE, DEEP, EMBLEM, G_LEFT, G_RIGHT, G_TOP, INK, MUTED, N_FLAT, N_LEFT, N_RIGHT, N_TOP, WHITE, # noqa: F401 + YELLOW, _g, _sun, box, circle, f, glyph, iso, path, poly, rect, tones) + +EXT_VERSION = "1" + + +# ---------------------------------------------------------------- psychrometrics (Mollier) +def _chart(s, strong=True): + """Psychrometric chart frame: axes + saturation curve. Green area when the chart is the subject.""" + out = "" + if strong: + out += path("M3.8 15.2C8.6 14.6 12.4 10.8 15.2 3.2V15.2Z", fill=G_TOP if s else N_FLAT, stroke="none") + out += path("M3 2.5V16H17", sw=1.3) + out += path("M3.8 15.2C8.6 14.6 12.4 10.8 15.2 3.2", stroke=DEEP if (s and strong) else (MUTED if strong else N_RIGHT), sw=1.6 if strong else 1.1) + return out + + +def _arrow(x0, y0, x1, y1, c=DEEP, sw=2.2, head=2.8): + """Bold line with a filled arrowhead at (x1, y1).""" + a = math.atan2(y1 - y0, x1 - x0) + bx, by = x1 - head * math.cos(a), y1 - head * math.sin(a) + l = (bx + head * 0.62 * math.sin(a), by - head * 0.62 * math.cos(a)) + r = (bx - head * 0.62 * math.sin(a), by + head * 0.62 * math.cos(a)) + return (path(f"M{f(x0)} {f(y0)}L{f(bx)} {f(by)}", stroke=c, sw=sw) + + f'') + + +@glyph("mollierChart") +def _mollier_chart(s=True): + return _chart(s) + + +@glyph("mollierPoint") +def _mollier_point(s=True): + return _chart(False, strong=False) + circle(9, 9.5, 2.6, G_LEFT if s else N_TOP, sw=1.2) + + +def _process(s, body): + # process arrows use the mid subject green (#659335): it reads on the light, orange and dark GH bodies + return _chart(False, strong=False) + body(G_RIGHT if s else INK) + + +@glyph("mollierProcess") +def _mollier_process(s=True): + # generic / undefined process: two states joined (no direction) + c = G_LEFT if s else N_TOP + return _chart(False, strong=False) + path("M5.5 12.5L13 6", stroke=G_RIGHT if s else INK, sw=2.2) + circle(5.5, 12.5, 2.1, c) + circle(13, 6, 2.1, c) + + +@glyph("processHeating") +def _p_heating(s=True): + return _process(s, lambda c: _arrow(4.5, 10, 14.5, 10, c)) + + +@glyph("processCooling") +def _p_cooling(s=True): + return _process(s, lambda c: _arrow(14.5, 10, 4.5, 10, c)) + + +@glyph("processHumidification") +def _p_humid(s=True): + return _process(s, lambda c: _arrow(9, 14.5, 9, 4, c)) + + +@glyph("processAdiabatic") +def _p_adiabatic(s=True): + return _process(s, lambda c: _arrow(13.5, 13.5, 5.5, 5, c)) + + +@glyph("processRoom") +def _p_room(s=True): + return _process(s, lambda c: _arrow(5, 13.5, 13.5, 5, c)) + + +@glyph("processMixing") +def _p_mixing(s=True): + return _process(s, lambda c: _arrow(4, 13.5, 8.2, 10.2, c, sw=1.8, head=2.3) + _arrow(14.5, 5, 10.2, 8.6, c, sw=1.8, head=2.3) + + circle(9.2, 9.4, 1.3, G_LEFT if s else N_TOP, sw=0.9)) + + +@glyph("processHeatRecovery") +def _p_heat_recovery(s=True): + return _process(s, lambda c: _arrow(4.5, 7.5, 14, 7.5, c, sw=1.8, head=2.3) + _arrow(14, 12, 4.5, 12, c, sw=1.8, head=2.3)) + + +@glyph("processFan") +def _p_fan(s=True): + def body(c): + out = _arrow(8.5, 10, 15, 10, c) + out += circle(5.8, 10, 2.9, WHITE, sw=1) + for a in (30, 150, 270): + r = math.radians(a) + out += poly([(5.8, 10), (5.8 + 2.4 * math.cos(r), 10 + 2.4 * math.sin(r)), + (5.8 + 1.6 * math.cos(r + 0.9), 10 + 1.6 * math.sin(r + 0.9))], c, sw=0.5) + return out + return _process(s, body) + + +# ---------------------------------------------------------------- topology +@glyph("cellComplex") +def _cell_complex(s=True): + # one solid subdivided into cells: 2 x 2 x 2 cube with the cell seams drawn + P = iso(10, 10) + t = tones(s) + out = box(P, 0, 0, 0, 5, 5, 7, t) + seams = [(P(2.5, 0, 7), P(2.5, 5, 7)), (P(0, 2.5, 7), P(5, 2.5, 7)), # top + (P(0, 5, 3.5), P(5, 5, 3.5)), (P(2.5, 5, 0), P(2.5, 5, 7)), # left face + (P(5, 0, 3.5), P(5, 5, 3.5)), (P(5, 2.5, 0), P(5, 2.5, 7))] # right face + return out + path("".join(f"M{f(a[0])} {f(a[1])}L{f(b[0])} {f(b[1])}" for a, b in seams), sw=0.9) + + +# ---------------------------------------------------------------- optimisation +@glyph("algorithm") +def _algorithm(s=True): + # objective curve converging on its optimum (green) + return (path("M3 2.5V16H17", sw=1.3) + path("M4.8 3.8C6.6 12.6 8.4 13.6 10.2 13.6S14 10.6 16.4 5.4", stroke=MUTED, sw=1.3) + + circle(10.2, 13.2, 2.3, G_LEFT if s else N_TOP, sw=1.1)) + + +@glyph("objective") +def _objective(s=True): + return circle(10, 10, 7.5, WHITE) + circle(10, 10, 5, G_LEFT if s else N_TOP) + circle(10, 10, 2.4, WHITE) + circle(10, 10, 0.9, INK, stroke=None) + + +# ---------------------------------------------------------------- scripting / automation +@glyph("script") +def _script(s=True): + c = G_TOP if s else WHITE + return (rect(1.5, 3, 17, 14, INK if s else MUTED, rx=1.5) + path("M4.5 7L8 10L4.5 13", stroke=c, sw=1.8) + + path("M9.5 13.2H14", stroke=c, sw=1.8)) + + +@glyph("tasks") +def _tasks(s=True): + # parallel tasks (multitasking): three lanes running side by side + out = "" + for y in (4, 9.5, 15): + out += rect(2, y - 2, 11, 4, G_LEFT if s else N_TOP, rx=1) + out += path(f"M13.5 {f(y)}H16.5", sw=1.4) + poly([(16.2, y - 1.6), (18.4, y), (16.2, y + 1.6)], INK, sw=0.6) + return out + + +# ---------------------------------------------------------------- acoustics +@glyph("sound") +def _sound(s=True): + return (poly([(2, 7.5), (5.5, 7.5), (10, 3.5), (10, 16.5), (5.5, 12.5), (2, 12.5)], G_LEFT if s else N_TOP) + + path("M12.6 7.2a4 4 0 0 1 0 5.6M14.9 4.9a7.2 7.2 0 0 1 0 10.2", sw=1.5)) + + +# ---------------------------------------------------------------- BIM documents (Revit) +@glyph("view") +def _view(s=True): + # drawing sheet: plan drawing (green) + title block + return (rect(1.5, 2.5, 17, 14, WHITE, rx=1) + path("M4 5H11V8.5H13.5V13.5H4Z", fill=G_TOP if s else N_FLAT, stroke=DEEP if s else INK, sw=1.2) + + path("M15.5 2.5V16.5", sw=1)) + + +@glyph("element") +def _element(s=True): + # a single BIM element instance: cube on a neutral base plate + P = iso(10, 11.5) + base = poly([P(-1, -1, 0), P(5.5, -1, 0), P(5.5, 5.5, 0), P(-1, 5.5, 0)], N_FLAT, sw=0.9) + return base + box(P, 0.5, 0.5, 0, 4, 4, 4.5, tones(s)) + + +# ---------------------------------------------------------------- HVAC plant (SAM Systems) +@glyph("energyCentre") +def _energy_centre(s=True): + # central plant building with a stack + P = iso(9, 12) + n = (N_TOP, N_LEFT, N_RIGHT) + return box(P, 3.4, 0.2, 0, 1.2, 1.2, 10, n) + box(P, 0, 1.6, 0, 5, 3, 4.5, tones(s)) + + +@glyph("plantRoom") +def _plant_room(s=True): + # cutaway room corner (the SAM `floor` walls, neutral floor) with a plant unit standing in it (green) + P = iso(9, 11.5) + walls = poly([(9, 8), (9, 2), (1, 6), (1, 12)], "#EFEFEF") + poly([(9, 8), (17, 12), (17, 6), (9, 2)], N_RIGHT) + floor = poly([(9, 8), (17, 12), (9, 16), (1, 12)], N_TOP) + return walls + floor + box(P, -0.4, 0, 0, 3.4, 2.4, 4.6, tones(s)) + + +@glyph("connector") +def _connector(s=True): + fill = G_LEFT if s else N_TOP + return (path("M6.5 10H13.5", stroke=DEEP if s else INK, sw=2.4) + rect(1.5, 6.5, 5, 7, fill, rx=1) + + rect(13.5, 6.5, 5, 7, fill, rx=1) + circle(10, 10, 1.5, WHITE, sw=1)) + + +# ---------------------------------------------------------------- solar +@glyph("sunPath") +def _sun_path(s=True): + # sun position -> direction vector (green) + return (path("M2 17H18", sw=1.3) + _sun(13.8, 5.2, 2.4, rays=True) + + _arrow(11.6, 7.4, 4.2, 14.6, DEEP if s else INK, sw=2.0)) + + +@glyph("solar") +def _solar(s=True): + # solar irradiance: parallel rays onto a surface (green) + return (poly([(10, 5), (17, 8.5), (17, 16), (10, 12.5)], G_LEFT if s else N_LEFT) + _sun(4, 4, 2.4, rays=False) + + _arrow(5.2, 7.6, 9.6, 10, INK, sw=1.3, head=1.9) + _arrow(7.8, 4.6, 12.4, 7.2, INK, sw=1.3, head=1.9)) + + +# ---------------------------------------------------------------- verb: run / simulate (Evaluate family) +icons.BADGES["run"] = ("evaluate", lambda c: f'') + +EXT_GLYPHS = ["mollierChart", "mollierPoint", "mollierProcess", "processHeating", "processCooling", "processHumidification", + "processAdiabatic", "processRoom", "processMixing", "processHeatRecovery", "processFan", "cellComplex", "algorithm", + "objective", "script", "tasks", "sound", "view", "element", "energyCentre", "plantRoom", "connector", "sunPath", "solar"] +EXT_BADGES = ["run"] diff --git a/design/grasshopper-icons/tools/integrate.py b/design/grasshopper-icons/tools/integrate.py new file mode 100644 index 00000000..eb7e20ea --- /dev/null +++ b/design/grasshopper-icons/tools/integrate.py @@ -0,0 +1,206 @@ +"""Wire the generated 24x24 PNGs into this repository's Grasshopper projects, using each project's EXISTING icon mechanism. + +Per project (project_dir from the manifest): + * copies png/24/.png -> /Resources/Icons/.png (only the icons that project uses) + * mechanism "resx" (SAM convention): ResXFileRef entries in Properties/Resources.resx + strongly-typed properties in + Properties/Resources.Designer.cs, typed byte[] or Bitmap to match the resources the project's Icon getters use today + * mechanism "holder" (e.g. SAMOCCTIcon): generated properties inside `// ` markers of the holder class, + loading manifest resources the same way the holder already does, plus one csproj EmbeddedResource line + * replaces the icon token inside each component's `Icon` getter (Resources.OLD -> Resources.NEW); nothing else. +Idempotent: re-running replaces previously generated SAM_GH_* entries. Old resources are left untouched. +""" +import json +import os +import re +import shutil +import subprocess +import sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +DESIGN = os.path.dirname(HERE) +REPO = os.path.dirname(os.path.dirname(DESIGN)) +PNG = os.path.join(DESIGN, "png", "24") +PREFIX = "SAM_GH_" + +TYPE_BITMAP = "System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" +TYPE_BYTES = "System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" + + +def read(p): + raw = open(p, "rb").read() + bom = raw.startswith(b"\xef\xbb\xbf") + text = raw.decode("utf-8-sig") + nl = "\r\n" if "\r\n" in text else "\n" + return text.replace("\r\n", "\n"), bom, nl + + +def write(p, text, bom, nl): + data = text.replace("\n", nl).encode("utf-8") + open(p, "wb").write((b"\xef\xbb\xbf" if bom else b"") + data) + + +# ------------------------------------------------------------------ resx mechanism (identical to SAM#166) +def update_resx(path, names, as_bytes): + text, bom, nl = read(path) + text = re.sub(r' \n [^<]*\n \n', "", text) + t = TYPE_BYTES if as_bytes else TYPE_BITMAP + entries = "".join( + f' \n' + f' ..\\Resources\\Icons\\{n}.png;{t}\n \n' for n in sorted(names)) + text = text.replace("", entries + "") + write(path, text, bom, nl) + + +def update_designer(path, names, as_bytes): + text, bom, nl = read(path) + text = re.sub(r" \n /// \n /// Looks up a localized resource of type [^\n]+\n /// \n" + r" internal static [^\n]+ " + PREFIX + r"\w+ \{\n(?: [^\n]*\n)+ \}\n", "", text) + typ = "byte[]" if as_bytes else "System.Drawing.Bitmap" + kind = "System.Byte[]" if as_bytes else "System.Drawing.Bitmap" + props = "".join( + f" \n /// \n /// Looks up a localized resource of type {kind}.\n /// \n" + f" internal static {typ} {n} {{\n get {{\n" + f" object obj = ResourceManager.GetObject(\"{n}\", resourceCulture);\n" + f" return (({typ})(obj));\n }}\n }}\n" for n in sorted(names)) + idx = text.rstrip().rfind("}") # namespace close + idx = text.rfind(" }", 0, idx) # class close + text = text[:idx].rstrip(" ") + props + text[idx:] + write(path, text, bom, nl) + + +def resource_is_bytes(designer, name): + """Type of an existing resource in Resources.Designer.cs (True = byte[], False = Bitmap).""" + text = read(designer)[0] + m = re.search(r"internal static ([\w.\[\]]+) " + re.escape(name) + r"\s*\{", text) + assert m, (designer, name) + return m.group(1) == "byte[]" + + +# ------------------------------------------------------------------ holder mechanism (manifest-resource icon class) +def update_holder(holder_path, names, csproj): + text, bom, nl = read(holder_path) + m = re.search(r'GetManifestResourceStream\("([\w.]+)\.Resources\.\w+\.png"\)', text) + assert m, holder_path + root = m.group(1) + text = re.sub(r"\n[ \t]*// .*?// \n", "\n", text, flags=re.S) + cls = re.search(r"\n([ \t]*)(?:internal|public) static class \w+\s*\n\1\{\n", text) + ind = cls.group(1) + " " + body = [f"{ind}// generated by design/grasshopper-icons/tools/integrate.py (SAM GH icon redesign)", + f"{ind}private static Bitmap LoadIcon(string name)", f"{ind}{{", + f"{ind} using (Stream stream = typeof({re.search(r'static class (\w+)', text).group(1)}).Assembly.GetManifestResourceStream(\"{root}.Resources.Icons.\" + name + \".png\"))", + f"{ind} {{", f"{ind} if (stream == null)", f"{ind} {{", f"{ind} return null;", f"{ind} }}", "", + f"{ind} using (Bitmap bitmap = new Bitmap(stream))", f"{ind} {{", f"{ind} return new Bitmap(bitmap);", + f"{ind} }}", f"{ind} }}", f"{ind}}}", ""] + body += [f"{ind}internal static Bitmap {n} => LoadIcon(\"{n}\");" for n in sorted(names)] + body += [f"{ind}// "] + close = text.rfind("\n" + cls.group(1) + "}") # class close brace + text = text[:close] + "\n\n" + "\n".join(body) + text[close:] + write(holder_path, text, bom, nl) + ctext, cbom, cnl = read(csproj) + line = '' + if line not in ctext: + mm = re.search(r'\n([ \t]*)', ctext) + assert mm, csproj + ctext = ctext[:mm.end()] + "\n" + mm.group(1) + line + ctext[mm.end():] + write(csproj, ctext, cbom, cnl) + + +# ------------------------------------------------------------------ Icon getter +CLASS_DECL = r"^\s*(?:\[[^\]]*\]\s*)*(?:public|internal)[\w\s]*\bclass\s+{}\b" + + +def update_icon(src_path, cls, holder, resource, guid, bytes_expr=None): + text, bom, nl = read(src_path) + # locate the class by its (unique) ComponentGuid: a file may declare the same class name twice + gpos = re.search(r'ComponentGuid[^\n]*"' + re.escape(guid) + '"', text, re.I) + assert gpos, (src_path, cls, guid) + m = None + for mm in re.finditer(CLASS_DECL.format(cls), text[:gpos.start()], re.M): + m = mm + assert m, (src_path, cls) + nxt = re.search(r"^\s*(?:public|internal)[\w\s]*\bclass\s+\w+", text[m.end():], re.M) + end = m.end() + nxt.start() if nxt else len(text) + body = text[m.end():end] + ic = re.search(r"override\s+(?:System\.Drawing\.)?Bitmap\s+Icon\b", body) + assert ic, (src_path, cls, "no Icon override") + seg_start = ic.end() + seg = body[seg_start: seg_start + 300] + # first .X that is not inside a // comment + hit = next((mm for mm in re.finditer(r"\b" + re.escape(holder) + r"\.\w+", seg) + if "//" not in seg[seg.rfind("\n", 0, mm.start()) + 1: mm.start()]), None) + assert hit, (src_path, cls) + new_seg = seg[:hit.start()] + holder + "." + resource + seg[hit.end():] + body = body[:seg_start] + new_seg + body[seg_start + 300:] + text = text[:m.end()] + body + text[end:] + write(src_path, text, bom, nl) + + +def verify(rows): + """Re-parse the C# source: every object must now reference its manifest resource, and the PNG must exist.""" + raw_path = os.path.join(DESIGN, "manifest_raw.json") + original = open(raw_path, "rb").read() # keep the pre-redesign inventory (records the old icons) + try: + subprocess.run([sys.executable, os.path.join(HERE, "inventory.py")], check=True, stdout=subprocess.DEVNULL) + now = {r["guid"] + "|" + r["source"]: r for r in json.load(open(raw_path, encoding="utf-8"))} + finally: + open(raw_path, "wb").write(original) + bad = [] + for r in rows: + cur = now[r["guid"] + "|" + r["source"]]["icon_expr"] + png = os.path.join(REPO, r["project_dir"], "Resources", "Icons", r["resource"] + ".png") + if cur != r["resource"] or not os.path.isfile(png): + bad.append((r["class"], cur, r["resource"])) + assert not bad, bad + assert len(now) == len(rows), (len(now), len(rows)) + print(f"verified: {len(rows)}/{len(rows)} objects reference their SAM_GH_* icon resource") + + +def main(): + rows = json.load(open(os.path.join(DESIGN, "manifest.json"), encoding="utf-8")) + by_proj = {} + for r in rows: + by_proj.setdefault(r["project_dir"], []).append(r) + for pdir_rel, items in sorted(by_proj.items()): + pdir = os.path.join(REPO, pdir_rel) + icon_dir = os.path.join(pdir, "Resources", "Icons") + if os.path.isdir(icon_dir): + shutil.rmtree(icon_dir) + os.makedirs(icon_dir) + names = {r["resource"]: r["icon_id"] for r in items} + for res, iid in names.items(): + shutil.copyfile(os.path.join(PNG, iid + ".png"), os.path.join(icon_dir, res + ".png")) + holders = {r["icon_holder"] for r in items} + assert len(holders) == 1, (pdir_rel, holders) + holder = holders.pop() + if holder == "Resources": + designer = os.path.join(pdir, "Properties", "Resources.Designer.cs") + kinds = {resource_is_bytes(designer, r["current_icon"]) for r in items if not r["current_icon"].startswith(PREFIX)} + if not kinds: # re-run: all getters already point at generated resources + kinds = {resource_is_bytes(designer, items[0]["resource"])} + assert len(kinds) == 1, (pdir_rel, "mixed byte[]/Bitmap icon resources") + as_bytes = kinds.pop() + update_resx(os.path.join(pdir, "Properties", "Resources.resx"), names, as_bytes) + update_designer(designer, names, as_bytes) + mech = "resx/" + ("byte[]" if as_bytes else "Bitmap") + else: + hp = [os.path.join(root, f) for root, _, fs in os.walk(pdir) for f in fs + if f == holder + ".cs" and "obj" not in root.split(os.sep)] + assert len(hp) == 1, (pdir_rel, holder, hp) + csproj = [os.path.join(pdir, f) for f in os.listdir(pdir) if f.endswith(".csproj")][0] + update_holder(hp[0], names, csproj) + mech = "holder/" + holder + for r in items: + update_icon(os.path.join(REPO, r["source"]), r["class"], holder, r["resource"], r["guid"]) + r["status"] = "integrated" + print(f"{r['project']}: {len(items)} objects, {len(names)} icon resources ({mech})") + verify(rows) + json.dump(rows, open(os.path.join(DESIGN, "manifest.json"), "w", encoding="utf-8"), indent=1) + import csv + with open(os.path.join(DESIGN, "manifest.csv"), "w", newline="", encoding="utf-8") as fh: + w = csv.DictWriter(fh, fieldnames=list(rows[0].keys())) + w.writeheader() + w.writerows(rows) + + +if __name__ == "__main__": + main() diff --git a/design/grasshopper-icons/tools/inventory.py b/design/grasshopper-icons/tools/inventory.py new file mode 100644 index 00000000..416b6e50 --- /dev/null +++ b/design/grasshopper-icons/tools/inventory.py @@ -0,0 +1,129 @@ +"""Inventory every Grasshopper document object (components + params) in this repository. + +Same parser as SAM/design/grasshopper-icons/tools/inventory.py (SAM#166), generalised to any +repository layout: every .cs file under a project whose .csproj references Grasshopper is scanned. +An object is inventoried when a non-abstract class declares `ComponentGuid`. +Writes ../manifest_raw.json. +""" +import json +import os +import re +import sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +DESIGN = os.path.dirname(HERE) +REPO = os.path.dirname(os.path.dirname(DESIGN)) +SKIP_DIRS = {"obj", "bin", ".git", "packages", "design", "build"} + +CLASS_RE = re.compile(r"^\s*(?:\[[^\]]*\]\s*)*((?:public|internal|private|protected|abstract|sealed|static|partial|\s)+)class\s+(\w+)(?:<[^>{]*>)?\s*(?::\s*([^{\n]+))?", re.M) +GUID_RE = re.compile(r"ComponentGuid\s*(?:=>|\{\s*get\s*\{\s*return)\s*new\s*(?:Guid\s*)?\(\s*\"([0-9a-fA-F-]+)\"") # new Guid("..") and target-typed new("..") +ICON_RE = re.compile(r"override\s+(?:System\.Drawing\.)?Bitmap\s+Icon\b(.{0,300})", re.S) +ICON_TOKEN_RE = re.compile(r"\b(?:Properties\.)?Resources\.(\w+)|\b(\w+Icon)\.(\w+)") +EXPOSURE_RE = re.compile(r"override\s+GH_Exposure\s+Exposure\s*=>\s*([^;]+);") + + +def long_path(p): + p = os.path.abspath(p) + return "\\\\?\\" + p if os.name == "nt" and not p.startswith("\\\\") else p + + +def base_args(text, pos): + """Split the argument list of the `base(` call starting at/after pos (string- and paren-aware).""" + i = text.index("(", pos) + 1 + args, depth, cur, instr = [], 0, "", False + while i < len(text): + ch = text[i] + if instr: + cur += ch + if ch == "\\": + cur += text[i + 1]; i += 1 + elif ch == '"': + instr = False + elif ch == '"': + instr = True; cur += ch + elif ch in "([{": + depth += 1; cur += ch + elif ch in ")]}": + if depth == 0: + args.append(cur.strip()); return args + depth -= 1; cur += ch + elif ch == "," and depth == 0: + args.append(cur.strip()); cur = "" + else: + cur += ch + i += 1 + return args + + +def lit(a): + a = a.strip() + if re.fullmatch(r'"(?:[^"\\]|\\.)*"', a): + return a[1:-1] + return "{" + a + "}" + + +def gh_projects(): + """{project dir (abs): project name} for every non-test .csproj that references Grasshopper.""" + out = {} + for root, dirs, files in os.walk(REPO): + dirs[:] = sorted(d for d in dirs if d not in SKIP_DIRS) + for f in files: + if f.endswith(".csproj") and "Test" not in f: + txt = open(long_path(os.path.join(root, f)), encoding="utf-8-sig", errors="replace").read() + if re.search(r"Grasshopper", txt, re.I) and re.search(r'Include="Grasshopper"|Grasshopper\.dll|GH_IO|"Grasshopper"', txt): + out[root] = f[:-7] + return out + + +def main(): + items = [] + for pdir, proj in sorted(gh_projects().items(), key=lambda kv: kv[1]): + for root, dirs, files in os.walk(pdir): + dirs[:] = sorted(d for d in dirs if d not in SKIP_DIRS) + for f in sorted(files): + if not f.endswith(".cs") or f.endswith(".Designer.cs"): + continue + path = os.path.join(root, f) + src = open(long_path(path), encoding="utf-8-sig").read() + if "ComponentGuid" not in src: + continue + # strip // comments to avoid template/commented code + code = re.sub(r"(?m)(^|[\s;{}])//[^\n]*", r"\1", src) + classes = list(CLASS_RE.finditer(code)) + for i, cm in enumerate(classes): + body = code[cm.end(): classes[i + 1].start() if i + 1 < len(classes) else len(code)] + g = GUID_RE.search(body) + if not g or "abstract" in cm.group(1): + continue + ic = ICON_RE.search(body) + tok = ICON_TOKEN_RE.search(ic.group(1)) if ic else None + ex = EXPOSURE_RE.search(body) + ctor = re.search(r"\b" + cm.group(2) + r"\s*\(\s*\)\s*(?=:\s*base\()", body) + b = base_args(body, ctor.end()) if ctor else None + if b and b[-1].startswith("GH_ParamAccess"): + b = b[:-1] + obsolete = bool(re.search(r"\[Obsolete", code[max(0, cm.start() - 200): cm.end()])) or "_Obsolete" in cm.group(2) + items.append({ + "project": proj, + "project_dir": os.path.relpath(pdir, REPO).replace("\\", "/"), + "class": cm.group(2), + "base_type": (cm.group(3) or "").strip(), + "guid": g.group(1).lower(), + "name": lit(b[0]) if b else None, + "nickname": lit(b[1]) if b and len(b) > 1 else None, + "category": lit(b[-2]) if b and len(b) >= 4 else None, + "subcategory": lit(b[-1]) if b and len(b) >= 4 else None, + "icon_expr": (tok.group(1) or tok.group(3)) if tok else None, + "icon_holder": (tok.group(2) if tok and tok.group(2) else ("Resources" if tok else None)), + "icon_via_bytes": bool(ic and ("ToBitmap" in ic.group(1) or "MemoryStream" in ic.group(1))), + "exposure": ex.group(1).strip() if ex else None, + "obsolete": obsolete, + "source": os.path.relpath(path, REPO).replace("\\", "/"), + }) + out = os.path.join(DESIGN, "manifest_raw.json") + json.dump(items, open(out, "w", encoding="utf-8"), indent=1) + print(len(items), "objects ->", out) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/design/grasshopper-icons/tools/render.py b/design/grasshopper-icons/tools/render.py new file mode 100644 index 00000000..8dae71ac --- /dev/null +++ b/design/grasshopper-icons/tools/render.py @@ -0,0 +1,132 @@ +"""Rasterise SVGs to exact 24x24 PNG and build review sheets, using headless Edge + PIL. + +Headless Edge is the reference renderer (same engine family as the WebView used to review +the sheets). Output PNGs are 24x24 RGBA with straight alpha. +""" +import html +import os +import subprocess +import tempfile + +from PIL import Image + +EDGE = r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" +PITCH = 32 # sprite cell (icons placed at integer offsets -> no resampling) + + +def _shot(html_path, png_path, w, h, scale=1): + profile = tempfile.mkdtemp(prefix="edge-prof-") # isolated profile: safe to run in parallel + try: + _shot_with(html_path, png_path, w, h, scale, profile) + finally: + import shutil + shutil.rmtree(profile, ignore_errors=True) + + +def _shot_with(html_path, png_path, w, h, scale, profile): + subprocess.run([ + EDGE, "--headless=new", "--disable-gpu", "--hide-scrollbars", f"--user-data-dir={profile}", + f"--force-device-scale-factor={scale}", "--default-background-color=00000000", + "--allow-file-access-from-files", f"--window-size={w},{h}", "--virtual-time-budget=5000", + f"--screenshot={png_path}", "file:///" + html_path.replace("\\", "/"), + ], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + +def rasterise(svg_paths, out_paths, size=24, workers=8): + """svg_paths[i] -> out_paths[i] at size x size. + + Each icon is rendered alone at the same page position (0,0), so its pixels depend only on its + own SVG. (A shared sprite made antialiasing depend on the icon's position in the sprite.) + """ + from concurrent.futures import ThreadPoolExecutor + + def one(pair): + svg, out = pair + with tempfile.TemporaryDirectory() as tmp: + page = os.path.join(tmp, "one.html") + src = "file:///" + os.path.abspath(svg).replace("\\", "/") + open(page, "w", encoding="utf-8").write( + "" + f"") + shot = os.path.join(tmp, "one.png") + _shot(page, shot, 64, 64) + os.makedirs(os.path.dirname(out), exist_ok=True) + Image.open(shot).convert("RGBA").crop((0, 0, size, size)).save(out, optimize=True) + + with ThreadPoolExecutor(max_workers=workers) as ex: + list(ex.map(one, zip(svg_paths, out_paths))) + + +def rasterise_sprite(svg_paths, out_paths, size=24): + """Legacy sprite rasteriser (position-sensitive antialiasing; kept for reference only).""" + cols = 40 + rows = (len(svg_paths) + cols - 1) // cols + with tempfile.TemporaryDirectory() as tmp: + page = os.path.join(tmp, "sprite.html") + imgs = [] + for i, p in enumerate(svg_paths): + x, y = (i % cols) * PITCH, (i // cols) * PITCH + src = "file:///" + os.path.abspath(p).replace("\\", "/") + imgs.append(f'') + open(page, "w", encoding="utf-8").write( + "" + "".join(imgs) + "") + shot = os.path.join(tmp, "sprite.png") + _shot(page, shot, cols * PITCH, max(rows * PITCH, 64)) + sheet = Image.open(shot).convert("RGBA") + for i, out in enumerate(out_paths): + x, y = (i % cols) * PITCH, (i // cols) * PITCH + os.makedirs(os.path.dirname(out), exist_ok=True) + sheet.crop((x, y, x + size, y + size)).save(out, optimize=True) + + +CSS = """ +:root{--ink:#111;--mut:#424242;--line:#BDBDBD} +*{box-sizing:border-box}body{margin:0;background:#fff;color:var(--ink);font:12px/1.3 'Segoe UI',system-ui,sans-serif;padding:20px 24px;width:%dpx} +h1{font-size:18px;margin:0 0 2px;text-transform:uppercase;letter-spacing:.02em}.bar{height:5px;width:120px;background:linear-gradient(90deg,#D32F2F 33%%,#F6C90E 33%% 66%%,#1565C0 66%%);margin:6px 0 10px} +h2{font-size:13px;margin:16px 0 6px;border-bottom:2px solid #111;padding-bottom:3px;text-transform:uppercase;letter-spacing:.03em} +.sub{color:var(--mut);margin:0 0 8px}.grid{display:grid;grid-template-columns:repeat(%d,1fr);gap:6px} +.c{border:1px solid var(--line);padding:6px;display:flex;gap:8px;align-items:center;min-height:%dpx} +.n{display:flex;flex-direction:column;gap:4px;align-items:center} +.gh{width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:3px} +.l{background:linear-gradient(#e6e6e6,#c9c9c9);border:1px solid #8a8a8a}.d{background:linear-gradient(#4a4a4a,#2e2e2e);border:1px solid #111} +img.px{image-rendering:pixelated}.t{font-size:10.5px;word-break:break-word;line-height:1.25}.t b{font-size:11px}.t i{color:var(--mut);font-style:normal} +""" + + +def sheet(title, subtitle, groups, out_png, cols=4, big=72, width=1400, mini=False): + """groups: [(heading, [(png24, label_html)])]. Writes an HTML next to out_png and screenshots it.""" + base = os.path.dirname(os.path.abspath(out_png)) + parts = [f"

    {html.escape(title)}

    {subtitle}

    "] + n = 0 + for head, items in groups: + parts.append(f"

    {html.escape(head)} ({len(items)})

    ") + for png, label in items: + rel = os.path.relpath(png, base).replace("\\", "/") + if mini: + parts.append(f"
    " + f"
    " + f"
    {label}
    ") + else: + parts.append(f"
    " + f"
    " + f"
    {label}
    ") + n += 1 + parts.append("
    ") + doc = f"{html.escape(title)}{''.join(parts)}" + html_path = os.path.splitext(out_png)[0] + ".html" + open(html_path, "w", encoding="utf-8").write(doc) + rows = sum((len(items) + cols - 1) // cols for _, items in groups) + est = 90 + len(groups) * 40 + rows * (big + 24) + _shot(os.path.abspath(html_path), os.path.abspath(out_png), width, est, scale=1) + _trim(out_png) + return html_path + + +def _trim(png): + im = Image.open(png).convert("RGBA") + bbox = im.getchannel("A").getbbox() + if bbox: + im = im.crop((0, 0, im.width, min(im.height, bbox[3] + 16))) + bg = Image.new("RGBA", im.size, (255, 255, 255, 255)) + bg.alpha_composite(im) + bg.convert("RGB").save(png, optimize=True) diff --git a/design/grasshopper-icons/tools/repo_rules.py b/design/grasshopper-icons/tools/repo_rules.py new file mode 100644 index 00000000..c1902ac2 --- /dev/null +++ b/design/grasshopper-icons/tools/repo_rules.py @@ -0,0 +1,41 @@ +"""Repository-specific classification decisions for SAM_Systems (the only non-shared tool file). + +OVERRIDES : component display name -> (object glyph, op, extra) extra: None | "plural" | "library" | note +PARAM_OBJECTS : param type key (GooParam class or typeof(X) name) -> glyph | (glyph, container, plural) +OBJECTS/VERBS : extra noun/verb rules tried before the shared ones (same shapes as SAM's OBJECTS/VERBS) +""" +OVERRIDES = { + # system components (coils, fans, exchangers...) are equipment objects -> SAM `ahu` glyph + "SAM.AnalyticalSystemComponentType": ("ahu", "value", None), + "SAMSystems.CreateComponentByMollierProcess": ("ahu", "create", "produces a SystemComponent from a Mollier process"), + "SAMAnalytical.SystemToAHU": ("ahu", "convert", None), + "SAMAnalytical.ConnectedSystemComponents": ("ahu", "get", "plural"), + "SAMAnalytical.OrderedSystemComponents": ("ahu", "sort", "plural"), + "SAMAnalytical.ConnectedSystemGroups": ("system", "get", "plural"), + "SAMAnalytical.ConnectedSystemObjects": ("object", "get", "plural"), + "SAMAnalytical.ConnectedSensor": ("thermometer", "get", "the sensor a controller reads"), + # connectors and display managers + "SAMAnalytical.SystemConnector": ("connector", "create", None), + "SAMAnalytical.CreateDisplaySystemConnectorManager": ("connector", "create", "plural"), + "SAMAnalytical.CreateDisplaySystemManager": ("settings", "create", "component-type -> symbol display settings"), + "SAMAnalytical.CreateSystemGeometrySymbol": ("geometry2D", "create", "2D schematic symbol"), + "SAMSystems.CreateDisplaySystemEnergyCentre": ("energyCentre", "display", "previewable schematic"), + # airflow edits on the energy centre + "SystemEnergyCentre.ModifyByAirflows": ("airflow", "set", None), + "SystemEnergyCentre.ModifyFanByAirflows": ("fan", "modify", None), + # results + "SAMAnalytical.SystemResults": ("result", "get", "plural"), + "SAMAnalytical.SystemResultValueByHourOfYear": ("result", "get", None), + # catalogue / examples + "SAMAnalytical.SystemVentilationUnitCatalogue": ("fan", "import", "library"), + "SAMSystems.MollierTwinWheelExample": ("processHeatRecovery", "create", "worked twin-wheel heat-recovery example"), +} +PARAM_OBJECTS = { + "SystemComponent": "ahu", "ISystemComponent": "ahu", + "SystemGroup": ("system", None, True), "ISystemGroup": ("system", None, True), + "SystemObject": "object", "ISystemObject": "object", + "SystemSpace": "space", "ISystemSpace": "space", + "SystemResult": "result", "ISystemResult": "result", +} +OBJECTS = [] +VERBS = [] diff --git a/design/grasshopper-icons/tools/sam_classify.py b/design/grasshopper-icons/tools/sam_classify.py new file mode 100644 index 00000000..16b2e565 --- /dev/null +++ b/design/grasshopper-icons/tools/sam_classify.py @@ -0,0 +1,422 @@ +"""Classify every inventoried GH object into (object glyph, operation badge, modifiers). + +Input : ../manifest_raw.json (from inventory.py) +Output: ../manifest.json + ../manifest.csv (the source of truth for the icon library) + +Rules are ordered and deterministic; per-component exceptions live in OVERRIDES +(keyed by component display name) with a reason. +""" +import csv +import json +import os +import re + +HERE = os.path.dirname(os.path.abspath(__file__)) +DESIGN = os.path.dirname(HERE) + +# ------------------------------------------------------------------ operation verbs (leading word) +VERBS = [ + # (regex on the short name, op) + (r"^(Create|New)", "create"), (r"^Add", "add"), (r"^(Copy|Duplicate)", "copy"), + (r"^Get", "get"), (r"^(Filter|Select)", "filter"), (r"^Inspect", "inspect"), (r"^Report", "list"), + (r"^Set", "set"), (r"^(Update|Map|Replace|Apply)", "update"), + (r"^(Modify|Fix|Adjust|Rename|Round|Convex|Fill|Resolve|Prepare)", "modify"), + (r"^(Merge|Join|Combine)", "merge"), (r"^(Split|Cut|Trim)", "split"), (r"^Section", "section"), + (r"^Offset", "offset"), (r"^(Transform|Move)", "transform"), (r"^Snap", "snap"), (r"^Align", "align"), + (r"^Extend", "extend"), (r"^Flip", "flip"), (r"^Triangulate", "triangulate"), (r"^Sort", "sort"), + (r"^Remove", "remove"), (r"^Calculate", "calculate"), (r"^(Check|Is[A-Z])", "validate"), + (r"^(Label|Display)", "display"), (r"^(Bake|Export|Save|Write)", "export"), (r"^(Load|Import|Read|From)", "import"), + (r"^To[A-Z]", "convert"), +] + +# ------------------------------------------------------------------ object nouns (first match wins; order matters) +OBJECTS = [ + ("ApertureConstructionLibrary", "apertureConstruction", "library"), ("ConstructionLibrary", "construction", "library"), + ("MaterialLibrary", "material", "library"), ("InternalConditionLibrary", "internalCondition", "library"), + ("DegreeOfActivityLibrary", "degreeOfActivity", "library"), ("ProfileLibrary", "profile", "library"), + ("SystemTypeLibrary", "system", "library"), ("SAMLibrary", "object", "library"), ("DefaultLibrary", "object", "library"), + ("ConstructionManager", "constructionManager", None), ("ApertureConstruction", "apertureConstruction", None), + ("ConstructionLayer", "constructionLayer", None), ("MaterialLayer", "materialLayer", None), + ("OpeningProperties", "openingProperties", None), ("Opening", "aperture", None), + ("AdjacencyCluster", "cluster", None), ("AnalyticalModel", "model", None), ("BuildingModel", "model", None), + ("ExternalSpace", "externalSpace", None), ("PerimeterSpace", "space", None), ("Space", "space", None), ("Room", "space", None), + ("Zone", "zone", None), ("IZAM", "izam", None), ("Aperture", "aperture", None), ("Window", "aperture", None), + ("FeatureShade", "shade", None), ("Shade", "shade", None), ("AirPanel", "panel", None), ("AirPartition", "panel", None), + ("Panel", "panel", None), ("Roof", "panel", None), ("HostPartition", "panel", None), ("Partition", "panel", None), + ("Construction", "construction", None), ("TransparentMaterial", "transparentMaterial", None), + ("GasMaterial", "gasMaterial", None), ("OpaqueMaterial", "material", None), ("Material", "material", None), + ("InternalCondition", "internalCondition", None), ("DegreeOfActivity", "degreeOfActivity", None), + ("OccupancyGain", "internalCondition", None), ("LightingGain", "lighting", None), ("EquipmentGain", "equipment", None), + ("InfiltrationGain", "infiltration", None), ("PollutantGain", "pollutant", None), ("SetPoint", "thermometer", None), + ("VentilationProfile", "airflow", None), ("Ventilation", "fan", None), ("AirFlow", "airflow", None), ("Airflow", "airflow", None), + ("AirHandlingUnit", "ahu", None), ("MechanicalSystem", "system", None), ("SystemType", "system", None), ("System", "system", None), + ("Profile", "profile", None), ("NCM", "internalCondition", None), + ("HeatTransferCoefficient", "heat", None), ("HeatFlow", "heat", None), ("Daylight", "daylight", None), + ("DesignDay", "designDay", None), ("WeatherData", "weatherData", None), ("WeatherYear", "weatherYear", None), + ("WeatherHour", "weatherData", None), ("Weather", "weather", None), ("Comfort", "thermometer", None), ("TM52", "thermometer", None), + ("Adaptive", "thermometer", None), ("OutdoorAirTemperature", "thermometer", None), + ("Level", "level", None), ("Elevation", "level", None), + ("Shell", "shell", None), ("Face3D", "face", None), ("PlanarBoundary", "face", None), ("Mesh", "mesh", None), + ("Plane", "plane", None), ("Transform3D", "transform3D", None), ("Segment", "segment", None), ("Point", "points", None), + ("Polycurve", "polyloop", None), ("Loop", "polyloop", None), ("SAMGeometry2D", "geometry2D", None), ("NTS", "geometry2D", None), + ("Geometry", "geometry", None), ("Vector", "vector", None), ("Normal", "normal", None), ("Grid", "grid", None), + ("Location", "location", None), ("Address", "address", None), ("CountryCode", "location", None), ("CoutryCode", "location", None), + ("Azimuth", "compass", None), ("Direction", "compass", None), + ("Result", "result", None), ("DesignExplorer", "result", None), ("Case", "case", None), ("Scenario", "case", None), + ("DelimitedFileTable", "table", None), ("Csv", "table", None), ("TableModifier", "table", None), + ("TextMap", "textMap", None), ("Json", "json", None), ("File", "file", None), ("Log", "log", None), + ("Color", "colour", None), ("Uint", "colour", None), ("ARGB", "colour", None), + ("HourOfYear", "clock", None), ("DateTime", "clock", None), ("DayOfYear", "calendar", None), ("Period", "clock", None), + ("Number", "number", None), ("String", "text", None), ("Text", "text", None), ("Name", "name", None), + ("Value", "value", None), ("Parameter", "value", None), ("Key", "list", None), ("List", "list", None), + ("DataTree", "tree", None), ("Path", "folder", None), ("Files", "folder", None), + ("RelationCluster", "relation", None), ("Related", "relation", None), ("Type", "type", None), ("Settings", "settings", None), + ("Object", "object", None), ("Guid", "object", None), +] + +PLURAL_RE = r"(Spaces|Panels|Apertures|Zones|Shells|Face3Ds|Materials|Constructions|Profiles|Levels|Objects|Results|Points|Point3Ds|Segment3Ds|Openings|Values|Names|Cases|Scenarios|IZAMs|Systems|Units|Elevations|Layers|Days|Geometries|Keys|Types|Rooms|Hours|Temperatures)" + +# ------------------------------------------------------------------ explicit exceptions: name -> (object, op, extra) +OVERRIDES = { + # --- about / diagnostics + "SAM.About": ("info", "value", "About enum: SAM emblem tile + info (identity exception)"), + "SAM.Version": ("info", "get", "Version: emblem tile + get"), + "SAM.Test": ("object", "validate", "test harness component"), + "SAMCore.Error": ("log", "error", None), + "LogToFile": ("log", "export", None), + "Inspect": ("object", "inspect", None), + "SAMCore.Convert": ("object", "convert", None), + "SAMCore.Update": ("object", "update", None), + "SAMCore.ReplaceByGuid": ("object", "update", None), + "SAMCore.GetType": ("type", "get", None), + "SAMCore.FilterByType": ("type", "filter", None), + "SAMCore.ParameterByType": ("value", "get", None), + "SAMCore.CombineResults": ("result", "merge", None), + "SAMCore.StringReplace": ("text", "update", None), + "SAMCore.TextMapValues": ("textMap", "get", None), + "SAMCore.NumberFilter": ("number", "filter", None), + "SAMCore.Round": ("number", "modify", None), + "SAMCore.TableModifier ": ("table", "create", None), + "SAMCore.CreateDelimitedFileTableBySAMObjects": ("table", "create", None), + "SAMCore.LoadMaterialLibrary": ("material", "import", "library"), + "SAMCore.SaveMaterialLibrary": ("material", "export", "library"), + "SAMCore.AddMaterials": ("material", "add", "library"), + "SAMCore.CopyMaterials": ("material", "copy", "library"), + "GetNames": ("name", "get", None), + "SelectByName": ("name", "filter", None), + "GetValue": ("value", "get", None), "SetValue": ("value", "set", None), "SetValues": ("value", "set", "plural"), + "RemoveValue": ("value", "remove", None), "GetValueFilter": ("value", "filter", None), + "ToList": ("list", "convert", None), "ToJson": ("json", "export", None), "FromJson": ("json", "import", None), + "ToFile": ("file", "export", None), "FromFile": ("file", "import", None), "ToCsv": ("table", "export", None), + "Csv.ToDelimitedFileTable": ("table", "import", None), + "DelimitedFileTable.GetValue": ("table", "get", None), "DelimitedFileTable.SetValue": ("table", "set", None), + "DelimitedFileTable.SetColumnNames": ("table", "set", None), "DelimitedFileTable.Map": ("table", "update", None), + "DelimitedFileTable.Sort": ("table", "sort", None), + "RelationCluster.AddObjects": ("relation", "add", None), "RelationCluster.Objects": ("relation", "get", None), + "RelationCluster.RelatedObjects": ("relation", "get", "plural"), "SAMLibrary.AddObjects": ("object", "add", "library"), + "SAMAnalytical.Objects": ("object", "get", "plural"), "Analytical.RelatedObjects": ("relation", "get", "plural"), + "SAMArchitectural.RelatedObjects": ("relation", "get", "plural"), + "AdjacencyCluster.UpdateObjects": ("cluster", "update", None), + "ARGBToUint": ("colour", "convert", None), "ColorToUint": ("colour", "convert", None), + "UintToARGB": ("colour", "convert", None), "UintToColor": ("colour", "convert", None), + "SAMCore.DateTimeToHourOfYear": ("clock", "convert", None), "SAMCore.DayOfYearToHourOfYear": ("calendar", "convert", None), + "SAMAnalytical.HourOfYearToDateTime": ("clock", "convert", None), + "SAMHydra.ExportFile": ("file", "export", None), + # --- enum value lists (GH_SAMEnumComponent): object of the enum + value badge + "SAMCore.CombineType": ("settings", "value", None), "SAMCore.CoutryCode": ("location", "value", None), + "SAMCore.Direction": ("compass", "value", None), "SAMCore.NumberComparisonType": ("number", "value", None), + "SAMCore.ParameterType": ("value", "value", None), "SAMCore.Period": ("clock", "value", None), + "SAMCore.TextComparisonType": ("text", "value", None), "SAMAnalytical.ApertureType": ("aperture", "value", None), + "SAMAnalytical.DefaultGasType": ("gasMaterial", "value", None), "SAMAnalytical.HeatFlowDirection": ("heat", "value", None), + "SAMAnalytical.InternalConditionParameter": ("internalCondition", "value", None), + "SAMAnalytical.LightingOccupancyControls": ("lighting", "value", None), + "SAMAnalytical.LightingPhotoelectricControls": ("lighting", "value", None), + "SAMAnalytical.NCMSystemType": ("system", "value", None), "SAMAnalytical.PanelGroup": ("panel", "value", None), + "SAMAnalytical.PanelType": ("panel", "value", None), "SAMAnalytical.ProfileGroup": ("profile", "value", None), + "SAMAnalytical.ProfileType": ("profile", "value", None), "SAMAnalytical.TM52BuildingCategory": ("thermometer", "value", None), + "SAMAnalytical.ZoneType": ("zone", "value", None), "SAMAnalytical.HostPartitionCategory": ("panel", "value", None), + "SAMWeather.WeatherDataType": ("weatherData", "value", None), + # --- analytical specials + "SAMAnalytical.AdjacentSpaces": ("cluster", "get", None), "SAMAnalytical.GetAdjacentSpaceNames": ("cluster", "list", None), + "SAMAnalytical.Airflow": ("airflow", "calculate", None), "SAMAnalytical.ApplyTargetedDesignAirFlow": ("airflow", "set", None), + "SAMAnalytical.ResolveTargetedDesignAirFlow": ("airflow", "calculate", None), "SAMAnalytical.SetAirflow": ("airflow", "set", None), + "SAMAnalytical.ApertureConstructions": ("apertureConstruction", "get", "plural"), + "SAMAnalytical.Bake": ("model", "export", None), "SAMAnalytical.Check": ("model", "validate", None), + "SAMAnalytical.CalculateDaylightFactor": ("daylight", "calculate", None), "SAMAnalytical.DaylightFactor": ("daylight", "analyse", None), + "SAMAnalytical.CalculateSpacePanelArea": ("space", "calculate", None), + "SAMAnalytical.CalculateGlazingValueByAperture": ("aperture", "calculate", None), + "SAMAnalytical.CalculateGlazingValueByConstruction": ("apertureConstruction", "calculate", None), + "SAMAnalytical.CreateCaseByShade": ("case", "create", None), "SAMAnalytical.CreateCaseByShade1": ("case", "create", None), + "SAMAnalytical.CreateCaseByVentilation": ("case", "create", None), "SAMAnalytical.CreateCaseByWindowSize": ("case", "create", None), + "SAMAnalytical.CreateOverheatingScenarios": ("case", "create", None), "SAMAnalytical.PreparePartOIteration": ("case", "modify", None), + "SAMAnalytical.CreateDegreeOfActivityByTemperature": ("degreeOfActivity", "create", None), + "SAMAnalytical.CreateIZAM": ("izam", "create", None), "SAMAnalytical.CreateIZAMBySetPoint": ("izam", "create", None), + "SAMAnalytical.CreateIZAMBySpaces": ("izam", "create", None), "SAMAnalytical.RemoveIZAMs": ("izam", "remove", None), + "SAMAnalytical.CreateLevels": ("level", "create", "plural"), "SAMArchitectural.CreateLevel": ("level", "create", None), + "SAMAnalytical.CreateShells": ("shell", "create", "plural"), "SAMAnalytical.CreateShellsByElevations": ("shell", "create", "plural"), + "SAMAnalytical.CreateShellsByElevationsAndAuxiliaryElevations": ("shell", "create", "plural"), + "SAMAnalytical.DailyIndoorComfortTemperatures": ("thermometer", "calculate", None), + "SAMAnalytical.DataTree": ("tree", "convert", None), "SAMAnalytical.DefaultColor": ("colour", "get", None), + "SAMAnalytical.DefaultConstructionManager": ("constructionManager", "get", None), + "SAMAnalytical.ExternalPanels": ("panel", "filter", "plural"), "SAMAnalytical.ExternalVector3D": ("vector", "get", None), + "SAMAnalytical.FillFloorsAndRoofs": ("panel", "add", "plural"), "SAMAnalytical.Filter": ("object", "filter", None), + "SAMAnalytical.Geometry": ("geometry", "convert", None), "SAMAnalytical.GetDefaultLibrary": ("object", "get", "library"), + "SAMAnalytical.GetInternalConditionTextMap": ("textMap", "get", None), "SAMAnalytical.GetSortedKeys": ("list", "sort", None), + "SAMAnalytical.GetValuesByReference": ("value", "get", "plural"), "SAMAnalytical.Grid": ("grid", "create", None), + "SAMAnalytical.HeatTransferCoefficientByDefaultGasType": ("heat", "calculate", None), + "SAMAnalytical.HourlyValues": ("weatherData", "get", "plural"), "SAMAnalytical.InsideSpace": ("space", "validate", None), + "SAMAnalytical.JoinSpacesByPanels": ("space", "merge", "plural"), "SAMAnalytical.LabelPanel": ("panel", "display", None), + "SAMAnalytical.LabelSpace": ("space", "display", None), "SAMAnalytical.MapAdjacencyCluster": ("cluster", "update", None), + "SAMAnalytical.Merge": ("model", "merge", None), "SAMAnalytical.MergeSettings": ("settings", "create", None), + "SAMAnalytical.TypeMergeSettings": ("settings", "create", None), "SAMAnalytical.ModifyObject": ("object", "modify", None), + "SAMAnalytical.NormalsDisplay": ("normal", "display", None), "SAMAnalytical.UpdateNormals": ("normal", "update", None), + "SAMAnalytical.FlipPanel": ("normal", "flip", None), "SAMAnalytical.PanelDistance": ("panel", "calculate", None), + "SAMAnalytical.PanelLocation": ("panel", "get", None), "SAMAnalytical.PanelSpacing": ("panel", "calculate", "plural"), + "SAMAnalytical.PanelTypeByText": ("panel", "convert", None), "SAMAnalytical.PanelsDifference": ("panel", "difference", None), + "SAMAnalytical.PanelsIntersection": ("panel", "intersect", None), "SAMAnalytical.PlaneIntersection": ("plane", "intersect", None), + "SAMAnalytical.Paths": ("folder", "list", None), "SAMAnalytical.Files": ("file", "list", None), + "SAMAnalytical.PerimeterSpaces": ("space", "filter", "plural"), "SAMAnalytical.PlanarBoundary3D": ("face", "get", None), + "SAMAnalytical.ProfileBySpace": ("profile", "get", None), "SAMAnalytical.ProfileDivide": ("profile", "divide", None), + "SAMAnalytical.ProfileMultiply": ("profile", "multiply", None), "SAMAnalytical.ProfileSum": ("profile", "sum", None), + "SAMAnalytical.SeasonProfileBySetPoint": ("profile", "create", None), "SAMAnalytical.ReplaceObject": ("object", "update", None), + "SAMAnalytical.ReportRooms": ("space", "list", "plural"), "SAMAnalytical.ReportRoomsList": ("space", "list", "plural"), + "SAMAnalytical.ReportSpaces": ("space", "list", "plural"), "SAMAnalytical.RoundAzimuth": ("compass", "modify", None), + "SAMAnalytical.Section": ("sectionBox", "section", None), "SAMAnalytical.SetAdiabatic": ("panel", "set", None), + "SAMAnalytical.SetLocation": ("location", "set", None), "SAMAnalytical.SnapPoints": ("points", "snap", None), + "SAMAnalytical.SystemTypes": ("system", "get", "plural"), "SAMAnalytical.TM52SpaceExtendedResultByDaysOfYears": ("thermometer", "analyse", None), + "SAMAnalytical.Transform": ("model", "transform", None), "SAMAnalytical.TriangulateConcavePanels": ("panel", "triangulate", None), + "SAMAnalytical.Convex": ("panel", "modify", None), "SAMAnalytical.RemoveInternalEdges": ("panel", "remove", None), + "SAMAnalytical.UpdateByModel": ("model", "update", None), "SAMAnalytical.UpdateGeometry": ("geometry", "update", None), + "SAMAnalytical.UpdateLibraries": ("object", "update", "library"), "SAMAnalytical.UpdateName": ("name", "update", None), + "SAMAnalytical.UpdateTypesByMap": ("type", "update", None), "SAMAnalytical.UpdateTypesByName": ("type", "update", None), + "SAMAnalytical.FixNames": ("name", "modify", None), "SAMAnalytical.RenameAnalyticalModel": ("model", "modify", None), + "SAMAnalytical.RenameConstruction": ("construction", "modify", None), "SAMAnalytical.UpdateSpaceNames": ("name", "update", "plural"), + "SAMAnalytical.UpdateSpaceLoactionPoint": ("space", "update", None), "SAMAnalytical.AlignSpaceLocation": ("space", "align", None), + "SAMAnalytical.UpdateNCM": ("internalCondition", "update", None), "SAMAnalytical.ModifyZone": ("zone", "modify", None), + "SAMAnalytical.MapPanels": ("panel", "update", "plural"), "SAMAnalytical.MapInternalConditions": ("internalCondition", "update", "plural"), + "SAMAnalytical.OverlapPanels": ("panel", "intersect", None), "SAMAnalytical.AddResults": ("result", "add", None), + "SAMAnalytical.AddMissingMaterials": ("material", "add", "library"), "SAMAnalytical.AddMaterials": ("material", "add", "library"), + "SAMAnalytical.AddMissingProfiles": ("profile", "add", "library"), + "SAMAnalytical.RemoveFromConstructionManager": ("constructionManager", "remove", None), + "SAMAnalytical.CreateHostPartitionType": ("construction", "create", None), + "SAMAnalytical.UpdateHostPartitionType": ("construction", "update", None), + "SAMAnalytical.CreateMaterialLayersByNames": ("materialLayer", "create", "plural"), + "SAMAnalytical.CreateConstructionLayersByMaterials": ("constructionLayer", "create", "plural"), + "SAMAnalytical.CreateConstructionLayersByNames": ("constructionLayer", "create", "plural"), + "SAMAnalytical.GetInternalConstructionLayers": ("constructionLayer", "get", "plural"), + "SAMAnalytical.CopyApertureConstructionLayers": ("apertureConstruction", "copy", None), + "SAMAnalytical.CopyConstructionLayers": ("constructionLayer", "copy", "plural"), + "SAMAdjacencyCluster.DuplicateConstructionByPanelType": ("construction", "copy", None), + "SAMAdjacencyCluster.SetDefaultApertureConstructionLayers": ("apertureConstruction", "set", None), + "SAMAnalytical.SetConstructionLayersByPanelType": ("constructionLayer", "set", "plural"), + "SAMAnalytical.SetDefaultConstructionLayerByPanelType": ("constructionLayer", "set", None), + "SAMAdjacencyCluster.PanelTypeUpdate": ("panel", "update", None), + "SAMAnalytical.UpdateBuildingModel": ("model", "update", None), + "SAMAnalytical.SetOccupancyGains": ("internalCondition", "set", None), + "SAMAnalytical.SetInternalConditionPerArea": ("internalCondition", "set", None), + "SAMAnalytical.GetExternalMaterials": ("material", "get", "plural"), "SAMAnalytical.GetInternalMaterials": ("material", "get", "plural"), + "SAMAnalytical.GetDefaultGasMaterials": ("gasMaterial", "get", "plural"), + "SAMAnalytical.CreatePerimeterZones": ("zone", "create", "plural"), "SAMAnalytical.CreatePerimeterZones_2": ("zone", "create", "plural"), + "SAMAnalytical.OffsetAperturesOnEdge": ("aperture", "offset", "plural"), + "SAMAnalytical.AddOpeningsByAzimuth": ("aperture", "add", "plural"), "SAMAnalytical.AddOpenings": ("aperture", "add", "plural"), + "SAMAnalytical.CreateOpeningsBy3DGeometry": ("aperture", "create", "plural"), + "SAMAnalytical.AddOpeningProperties": ("openingProperties", "add", None), + "SAMAnalytical.AddOpeningPropertiesByPartO": ("openingProperties", "add", None), + "SAMAnalytical.RemoveOpeningProperties": ("openingProperties", "remove", None), + "SAMAnalytical.AddVentilationPropertiesByPartF": ("openingProperties", "add", None), + "SAMAnalytical.AddTransferAirDoorsByPartF": ("aperture", "add", "plural"), + "SAMAnalytical.CreateBuildingModelBy2DGeometries(": ("model", "create", None), + "SAMAnalytical.CreateBuildingModelByShells": ("model", "create", None), + "SAMAnalytical.DesignDays": ("designDay", "create", "plural"), "SAMAnalytical.LoadWeatherData": ("weatherData", "import", None), + "SAMWeather.HourlyValue": ("weatherData", "get", None), "SAMWeather.HourlyValues": ("weatherData", "get", "plural"), + "SAMWeather.ModifyWeatherData": ("weatherData", "modify", None), + "SAMWeather.WeatherHoursByHourOfYear": ("weatherData", "filter", None), + "SAMWeather.WeatherHoursByPercentage": ("weatherData", "filter", None), + "SAMWeather.AdaptiveSetpointACCI": ("thermometer", "calculate", None), + "SAMWeather.AdaptiveSetpointACCIByTemperature": ("thermometer", "calculate", None), + "SAMWeather.PrevailingMeanOutdoorAirTemperatures": ("thermometer", "calculate", "plural"), + "SAMAnalytical.AddMechanicalSystems": ("system", "add", "plural"), + "SAMAnalytical.AddVentilationSystem": ("fan", "add", None), "SAMAnalytical.AddVentilationSystemsByZones": ("fan", "add", "plural"), + "SAMAnalytical.ModifyVentilationSystemsByZone": ("fan", "modify", "plural"), + "SAMAnalytical.SetSystemTypeNames": ("system", "set", None), + "SAMAnalytical.AddSpacesByBrep": ("space", "add", "plural"), "SAMAnalytical.RemoveSpacesByBrep": ("space", "remove", "plural"), + "SAMAnalytical.AddAirPanels": ("panel", "add", "plural"), "SAMAnalytical.AddAirPartitions": ("panel", "add", "plural"), + "SAMAnalytical.AddPanels": ("panel", "add", "plural"), "SAMAnalytical.AddFeatureShade": ("shade", "add", None), + "SAMAnalytical.CreateShade": ("shade", "create", None), "SAMAnalytical.CreateShadeByFeatureShade": ("shade", "create", None), + "SAMAnalytical.CreateFeatureShade": ("shade", "create", None), + "SAMAnalytical.MergeSpacesByAirPanels": ("space", "merge", "plural"), "SAMAnalytical.MergeSpacesByPanels": ("space", "merge", "plural"), + "SAMAnalytical.MergeSpacesByZones": ("space", "merge", "plural"), + "SAMAnalytical.CreateDesignExplorer": ("result", "create", None), + "SAMAnalytical.CalculateFloorArea": ("floor", "calculate", None), + "SAMAnalytical.FilterByMaxRectangle3D": ("panel", "filter", "plural"), "SAMAnalytical.Remove": ("object", "remove", None), + "SAMAnalytical.SnapByLines": ("panel", "snap", "plural"), "SAMAnalytical.SnapByOffset": ("panel", "snap", "plural"), + "SAMAnalytical.SplitByInternalEdges": ("panel", "split", None), + "SAMAnalytical.FilterByElevation": ("panel", "filter", "plural"), "SAMAnalytical.SnapByElevations": ("panel", "snap", "plural"), + "SAMAnalytical.FilterByBoundaryType": ("panel", "filter", "plural"), "SAMAnalytical.FilterByPanelType": ("panel", "filter", "plural"), + "SAMAnalytical.FilterByPanelAreaAndThinnessRatio": ("panel", "filter", "plural"), "SAMAnalytical.SnapByPoints": ("panel", "snap", "plural"), + "SAMAnalytical.CheckPartFCompliance": ("openingProperties", "validate", None), + "SAMAnalytical.SetPartFCommissioningData": ("openingProperties", "set", None), + "SAMAnalytical.CreateCaseByApertureByAzimuths": ("case", "create", None), "SAMAnalytical.CreateCaseByApertureConstruction": ("case", "create", None), + "SAMAnalytical.CreateCaseByOpening": ("case", "create", None), "SAMAnalytical.CreateCaseByWeather": ("case", "create", None), + "SAMAnalytical.FilterByAzimuth": ("panel", "filter", "plural"), "SAMAnalytical.FilterByGeometry": ("object", "filter", None), + "SAMAnalytical.FilterByPoints": ("object", "filter", None), "SAMCore.Samples": ("folder", "list", None), + # --- geometry + "Create.SAMTransform3DOriginToPlane": ("transform3D", "create", None), "Create.SAMTransform3DPlaneToOrigin": ("transform3D", "create", None), + "Create.SAMTransform3DPlaneToPlane": ("transform3D", "create", None), + "Geometry.PolycurveLoop2D": ("polyloop", "create", None), "Geometry.SAMGeometry": ("geometry", "convert", None), + "Geometry.MeshClose": ("mesh", "modify", None), "Geometry.MeshReduce": ("mesh", "modify", None), + "Geometry.ModifyDifference": ("shell", "difference", None), "Geometry.ModifyIntersection": ("shell", "intersect", None), + "Geometry.ModifyUnion": ("shell", "union", "plural"), "Geometry.Triangulate": ("face", "triangulate", None), + "Geometry.SnapByDistance": ("geometry", "snap", None), "Geometry.SnapByPoints": ("geometry", "snap", None), + "Geometry.ShellsSplitFace3Ds": ("face", "split", None), "Geometry.CutShell": ("shell", "split", None), + "NTS.SAMGeometry2D": ("geometry2D", "convert", None), "SAMGeometry.SAMGeometry2D": ("geometry2D", "convert", None), + "SAMGeometry2D.SAMGeometry": ("geometry2D", "convert", None), "SAMGeometry2D.ToNTS": ("geometry2D", "convert", None), + "SAMGeometry.Geometry": ("geometry", "convert", None), "SAMGeometry.Fill": ("face", "modify", None), + "SAMGeometry.FlipNormal": ("normal", "flip", None), "SAMGeometry.IsClosed": ("shell", "validate", None), + "SAMGeometry.ShellContains": ("shell", "validate", None), "SAMGeometry.NakedSegment3Ds": ("segment", "get", "plural"), + "SAMGeometry.ThinnessRatio": ("face", "calculate", None), "SAMGeometry.Face3DSpacing": ("face", "calculate", None), + "SAMGeometry.MergeOverlaps": ("face", "merge", None), "SAMGeometry.PlaneIntersection": ("plane", "intersect", None), + "SAMGeometry.Segment2DIntersection": ("segment", "intersect", None), + "SAMGeometry.SectionByFace3D": ("sectionBox", "section", None), "SAMGeometry.SectionByShell": ("sectionBox", "section", None), + "SAMGeometry.ShellDifference": ("shell", "difference", None), "SAMGeometry.ShellIntersection": ("shell", "intersect", None), + "SAMGeometry.ShellsUnion": ("shell", "union", "plural"), "SAMGeometry.ShellsSplit": ("shell", "split", None), + "SAMGeometry.ShellsSplitByFace3Ds": ("shell", "split", None), "SAMGeometry.Split": ("geometry", "split", None), + "SAMGeometry.SplitCoplanarFace3Ds": ("face", "split", None), "SAMGeometry.Transform": ("geometry", "transform", None), + "SAMGeometry.CreateShellsByOffset": ("shell", "offset", None), +} + +# Param (GH_PersistentParam / GH_Param) type-name -> object glyph +PARAM_OBJECTS = { + "Group": "group", "IndexedObjects": "indexed", "Object": "object", "Result": "result", "System": "system", + "SystemType": "system", "TableModifier": "table", "Address": "address", "AdjacencyCluster": "cluster", + "AirHandlingUnit": "ahu", "AnalyticalModel": "model", "Aperture": "aperture", "ApertureConstruction": "apertureConstruction", + "ApertureConstructionLibrary": "apertureConstruction", "BuildingModel": "model", "Construction": "construction", + "ConstructionLayer": "constructionLayer", "ConstructionLibrary": "construction", "ConstructionManager": "constructionManager", + "DegreeOfActivity": "degreeOfActivity", "DegreeOfActivityLibrary": "degreeOfActivity", "DelimitedFileTable": "table", + "DesignDay": "designDay", "ExternalSpace": "externalSpace", "FeatureShade": "shade", "FloorType": "construction", + "HostPartitionType": "construction", "IAnalyticalEquipment": "equipment", "IAnalyticalObject": "object", + "IOpening": "aperture", "IPartition": "panel", "IRelationCluster": "relation", "ISAMGeometry": "geometry", + "ISection": "sectionBox", "IWeatherObject": "weather", "InternalCondition": "internalCondition", + "InternalConditionLibrary": "internalCondition", "Level": "level", "Location": "location", "Log": "log", + "Material": "material", "MaterialLayer": "materialLayer", "MaterialLibrary": "material", "Matrix": "matrix", + "MergeSettings": "settings", "OpeningProperties": "openingProperties", "OpeningType": "apertureConstruction", + "Panel": "panel", "PlanarBoundary3D": "face", "Profile": "profile", "ProfileLibrary": "profile", "RoofType": "construction", + "SAMObject": "object", "Space": "space", "SystemTypeLibrary": "system", "T": "object", "TextMap": "textMap", + "Transform3D": "transform3D", "TypeMergeSettings": "settings", "WallType": "construction", "WeatherData": "weatherData", + "WeatherYear": "weatherYear", "Text3d": "text", +} +PARAM_LIBRARY = {"ApertureConstructionLibrary", "ConstructionLibrary", "DegreeOfActivityLibrary", "InternalConditionLibrary", + "MaterialLibrary", "ProfileLibrary", "SystemTypeLibrary"} + +# Batches (review sheets) by object family +BATCHES = [ + ("01 Model, cluster & cases", {"model", "cluster", "case", "sectionBox", "level"}), + ("02 Spaces & zones", {"space", "floor", "externalSpace", "zone", "izam"}), + ("03 Panels, apertures & shading", {"panel", "aperture", "openingProperties", "shade", "normal"}), + ("04 Constructions & materials", {"construction", "constructionLayer", "materialLayer", "apertureConstruction", "constructionManager", + "material", "transparentMaterial", "gasMaterial"}), + ("05 Profiles, internal conditions & gains", {"profile", "internalCondition", "degreeOfActivity", "lighting", "equipment", + "infiltration", "pollutant", "thermometer"}), + ("06 Systems & airflow", {"system", "ahu", "fan", "airflow", "heat", "daylight"}), + ("07 Geometry", {"shell", "face", "geometry", "geometry2D", "plane", "transform3D", "mesh", "polyloop", "segment", "points", "vector", "grid"}), + ("08 Weather, location & time", {"weather", "weatherData", "weatherYear", "designDay", "location", "address", "compass", "clock", "calendar"}), + ("09 Data, IO & utilities", {"object", "relation", "group", "indexed", "type", "value", "name", "text", "number", "list", "tree", + "table", "textMap", "json", "file", "folder", "log", "colour", "settings", "matrix", "result", "info"}), +] + + +def short(name): + return re.sub(r"^(SAM(Analytical|Geometry|Core|Weather|Architectural|Hydra|AdjacencyCluster)?|Geometry)\.", "", name) + + +def classify(x): + name = x["name"] or "" + if x["category"] == "Params" or x["base_type"].startswith(("GH_PersistentParam", "GH_Param")): + t = re.sub(r"^\{typeof\((?:global::[\w.]+\.)?(\w+)\)\.Name\}$", r"\1", name) + t = t.split(".")[-1] + obj = PARAM_OBJECTS[t] + return dict(kind="param", object=obj, op=None, plural=False, + container="library" if t in PARAM_LIBRARY else None, rule="param") + if name in OVERRIDES: + obj, op, extra = OVERRIDES[name] + return dict(kind="component", object=obj, op=op, plural=extra == "plural", + container="library" if extra == "library" else None, rule="override", + note=extra if extra not in (None, "plural", "library") else None) + s = short(name) + op = next((o for rx, o in VERBS if re.match(rx, s)), None) + body = re.split(r"By[A-Z]", s, 1)[0] + obj, container = None, None + for key, o, c in OBJECTS: + if key in body: + obj, container = o, c + break + if obj is None: + for key, o, c in OBJECTS: + if key in s: + obj, container = o, c + break + if x["base_type"].startswith("GH_SAMEnumComponent") and op is None: + op = "value" + plural = bool(re.search(PLURAL_RE + r"(By|$|[A-Z])", body)) and container is None + return dict(kind="component", object=obj, op=op, plural=plural, container=container, rule="rule") + + +def normalise(c): + """Grammar rules applied after classification (see ICON_DESIGN_SYSTEM.md).""" + if c["op"] == "add": + c["plural"] = False # ADD always draws existing (neutral) + new (green); plurality is not drawn + return c + + +def icon_id(c): + parts = [c["object"]] + if c["container"]: + parts.append(c["container"]) + if c["plural"]: + parts.append("plural") + if c["op"]: + parts.append(c["op"]) + return "_".join(parts) + + +def resource_name(iid): + return "SAM_GH_" + "".join(p[:1].upper() + p[1:] for p in iid.split("_")) + + +def main(): + raw = json.load(open(os.path.join(DESIGN, "manifest_raw.json"), encoding="utf-8")) + out, problems = [], [] + for x in raw: + c = normalise(classify(x)) + if not c["object"] or (c["kind"] == "component" and not c["op"]): + problems.append((x["name"], c)) + continue + iid = icon_id(c) + batch = next((b for b, objs in BATCHES if c["object"] in objs), "10 Other") + if c["kind"] == "param": + batch = "11 Parameters" + out.append({ + "class": x["class"], "name": x["name"], "nickname": x["nickname"], "category": x["category"], + "subcategory": x["subcategory"], "project": x["project"], "source": x["source"], "guid": x["guid"], + "kind": c["kind"], "exposure": x["exposure"], "obsolete": x["obsolete"], + "current_icon": x["icon_expr"] or "(inherited from A_SAMAnalyticalBase)", + "object": c["object"], "op": c["op"], "plural": c["plural"], "container": c["container"], + "rule": c["rule"], "note": c.get("note"), "icon_id": iid, "resource": resource_name(iid), + "icon_file": f"svg/{iid}.svg", "batch": batch, "status": "pending", + }) + if problems: + for n, c in problems: + print("UNCLASSIFIED", n, c) + out.sort(key=lambda r: (r["batch"], r["object"], r["op"] or "", r["name"] or "")) + json.dump(out, open(os.path.join(DESIGN, "manifest.json"), "w", encoding="utf-8"), indent=1) + cols = ["batch", "class", "name", "nickname", "category", "subcategory", "project", "source", "guid", "kind", "exposure", + "obsolete", "current_icon", "object", "op", "plural", "container", "rule", "note", "icon_id", "resource", "icon_file", "status"] + with open(os.path.join(DESIGN, "manifest.csv"), "w", newline="", encoding="utf-8") as fh: + w = csv.DictWriter(fh, fieldnames=cols) + w.writeheader() + w.writerows(out) + print(len(out), "classified,", len(problems), "unclassified,", len({r['icon_id'] for r in out}), "distinct icons") + + +if __name__ == "__main__": + main() From ac97f155349fac86a95ff4cb7eb9ef1b286ff9ed Mon Sep 17 00:00:00 2001 From: SAM-BIM-AI Date: Mon, 28 Sep 2026 17:50:58 +0200 Subject: [PATCH 2/8] docs(gh-icons): SAM_Systems icon redesign PR record Co-Authored-By: Claude Opus 5.5 (cherry picked from commit 5822f5e51f9868a546de1d0691686b4ede747b24) --- docs/GH-IconRedesign.md | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 docs/GH-IconRedesign.md diff --git a/docs/GH-IconRedesign.md b/docs/GH-IconRedesign.md new file mode 100644 index 00000000..40dc3991 --- /dev/null +++ b/docs/GH-IconRedesign.md @@ -0,0 +1,60 @@ +# SAM Grasshopper icon redesign — SAM_Systems PR record + +Branch `feature/sam-gh-icon-redesign`, based on `sow/2026-Q3` @ `fbef48f`. PR: (to be opened). +Propagates the SAM icon design system from SAM-BIM/SAM#166 (head `cf4d924a`, open, not merged) to this repository. + +## Current status +All **38** Grasshopper objects in this repo (30 components + 8 params) use redesigned icons: **38 / 38**. +Built and validated; ready for review. **Not merged.** + +## Work completed +- `design/grasshopper-icons/`: the shared SAM-BIM icon kit. `icons.py`, `render.py`, `sam_classify.py` and `ICON_DESIGN_SYSTEM.md` are vendored **verbatim** from SAM#166 (hash-checked). `icons_ext.py` and `ICON_DESIGN_SYSTEM_EXT.md` are the frozen SAM-BIM extension v1 (identical in every SAM-BIM repo). `tools/repo_rules.py` holds this repo's explicit decisions. +- **Inventory**: `tools/inventory.py` parses C# source (every non-abstract class declaring `ComponentGuid`). +- **Manifest** (source of truth): `manifest.json` / `manifest.csv` — per object: GUID, class, source, project, object glyph, operation, modifiers, icon id, resource, glyph/badge origin. +- **Generation**: 36 canonical SVGs → 24×24 PNGs; review sheet `review/contact_sheet.png` (native 24 px on GH normal / orange-warning / dark bodies + 3×) and `review/REVIEW.md`. +- **Integration**: each project's existing mechanism; only the icon token inside each `Icon` getter changes. + +| Project | Objects | Icon resources | Mechanism | +|---|---|---|---| +| `SAM.Analytical.Grasshopper.Systems` | 36 | 34 | resx / Bitmap | +| `SAM.Core.Grasshopper.Systems` | 2 | 2 | resx / Bitmap | + +## Design reuse +- **Reused SAM object families (11)**: `ahu`, `airflow`, `fan`, `geometry2D`, `object`, `relation`, `result`, `settings`, `space`, `system`, `thermometer` +- **New SAM-BIM ext v1 families used (4)**: `connector`, `energyCentre`, `plantRoom`, `processHeatRecovery` +- **Verbs**: `add`, `convert`, `create`, `display`, `get`, `import`, `merge`, `modify`, `set`, `sort`, `update`, `value` (all SAM) +- Distinct icons: **36** (25 on SAM glyphs, 11 on ext glyphs). Icon ids shared with SAM render pixel-identically to SAM's. + +## Decisions and assumptions +- Grammar, palette, badge families and construction rules are unchanged (SAM#166). No text, no new colours. +- Qualifier variants (`…By`) share an icon intentionally (see `review/REVIEW.md`). +- Interop direction: external → SAM = import ↓, SAM → external = export ↑. +- System components (coils, fans, exchangers) use SAM's `ahu` (equipment object) glyph; ISystem keeps `system`. +- `SystemEnergyCentre` / `SystemPlantRoom` get the ext glyphs `energyCentre` / `plantRoom`; connectors get `connector`. +- Connected*/Ordered* queries draw the object they return (components, groups, objects), per SAM's subject rule. +- Legacy icon resources are kept (still referenced by context menus / AssemblyInfo); no GUID, name, nickname, category, subcategory, parameter or behaviour change. + +## Files changed +- New: `design/grasshopper-icons/**`, `/Resources/Icons/SAM_GH_*.png`, `docs/GH-IconRedesign.md`. +- Modified: 38 component/param `.cs` files (one icon token each), 2× `Resources.resx`, 2× `Resources.Designer.cs`. No csproj change. + +## Validation +| Check | Result | +|---|---| +| `tools/classify.py` | 38 classified, 0 unclassified | +| `tools/build.py` identical-pixel collision check | 0 groups (36 distinct icons; 1 intentional shared icon: `energyCentre_create` ×3 qualifier variants) | +| Icon ids shared with SAM#166 vs SAM's `png/24` | 11/11 byte-identical | +| `tools/integrate.py` re-parse | 38/38 objects reference their `SAM_GH_*` resource; every PNG exists | +| `tools/check_source.py` vs `origin/sow/2026-Q3` | vendored files OK; 38 icon-token swaps, 0 non-icon C# changes; ComponentGuid set unchanged (38) | +| `dotnet build SAM_Systems.sln -c Debug` | Build succeeded, 0 errors | +| `tools/check_assemblies.py build` | both assemblies embed every required 24×24 icon (34 + 2) → OK | +| `tests/GhIconTest` (real Rhino 8 / Grasshopper, Rhino.Testing) | 38/38 objects load by GUID, name/category match, icon = manifest PNG (max diff 1 level, premultiplied-alpha rounding) | +| `SAM.Analytical.Systems.Tests` / `SAM.Analytical.Systems.Mollier.Tests` | 268/268 and 123/123 passed | +| Visual review (`review/contact_sheet.png`, 24 px on normal / warning / dark bodies) | all icons legible; no collisions | + +## Unresolved issues / risks +- Built against sibling SAM checked out on `feature/sam-gh-icon-redesign` (SAM#166); API-neutral, so the result is the same on `sow/2026-Q3`. +- Building a single csproj (outside the solution) hits the pre-existing post-build `xcopy "$(SolutionDir)…"` error; building the solution is clean. Not caused by this PR. + +## Recommended next step +Review this PR (compare `review/contact_sheet.png`), then merge by the maintainer. After merge, add the `PROJECT_PROGRESS.md` closeout entry on `sow/2026-Q3` with the merge SHA. SAM#166 (the reference design system) remains open. From 41a7dfb558a4a0f8cc95ca0499b8cea93e6335d6 Mon Sep 17 00:00:00 2001 From: SAM-BIM-AI Date: Mon, 28 Sep 2026 17:51:23 +0200 Subject: [PATCH 3/8] docs(gh-icons): record PR number Co-Authored-By: Claude Opus 5.5 (cherry picked from commit ca0cc8d21898e87c3e0ab96cfa2212f9ec174f59) --- docs/GH-IconRedesign.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/GH-IconRedesign.md b/docs/GH-IconRedesign.md index 40dc3991..2119de36 100644 --- a/docs/GH-IconRedesign.md +++ b/docs/GH-IconRedesign.md @@ -1,6 +1,6 @@ # SAM Grasshopper icon redesign — SAM_Systems PR record -Branch `feature/sam-gh-icon-redesign`, based on `sow/2026-Q3` @ `fbef48f`. PR: (to be opened). +Branch `feature/sam-gh-icon-redesign`, based on `sow/2026-Q3` @ `fbef48f`. PR: SAM-BIM/SAM_Systems#32. Propagates the SAM icon design system from SAM-BIM/SAM#166 (head `cf4d924a`, open, not merged) to this repository. ## Current status From e8a5448ff711aad1cd01cc98603b2de17a9165d2 Mon Sep 17 00:00:00 2001 From: SAM-BIM-AI Date: Mon, 28 Sep 2026 17:51:56 +0200 Subject: [PATCH 4/8] chore(gh-icons): sync SAM-BIM icon kit (MollierGroup -> SAM group glyph; no icon change here) Co-Authored-By: Claude Opus 5.5 (cherry picked from commit 028cca09b04396daa86bdf2260534eeceaae9819) --- design/grasshopper-icons/ICON_DESIGN_SYSTEM_EXT.md | 2 +- design/grasshopper-icons/tools/classify.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/design/grasshopper-icons/ICON_DESIGN_SYSTEM_EXT.md b/design/grasshopper-icons/ICON_DESIGN_SYSTEM_EXT.md index f6739e62..a548d0d9 100644 --- a/design/grasshopper-icons/ICON_DESIGN_SYSTEM_EXT.md +++ b/design/grasshopper-icons/ICON_DESIGN_SYSTEM_EXT.md @@ -21,7 +21,7 @@ vendored verbatim from SAM-BIM/SAM#166 @ `cf4d924a`) to the SAM-BIM plugin repos |---|---|---| | `mollierChart` | psychrometric chart axes + saturation curve, green area | Mollier/psychrometric chart, diagram, generic Mollier object | | `mollierPoint` | chart (thin) + green state point | MollierPoint | -| `mollierProcess` | chart (thin) + two green states joined | MollierProcess (generic, undefined, by two points), MollierGroup (plural param) | +| `mollierProcess` | chart (thin) + two green states joined | MollierProcess (generic, undefined, by two points); MollierGroup uses SAM `group` | | `processHeating` / `processCooling` | chart + bold green arrow → / ← (mirrored pair) | heating / cooling processes | | `processHumidification` | chart + arrow ↑ | isothermal and steam humidification | | `processAdiabatic` | chart + arrow ↖ | adiabatic humidification | diff --git a/design/grasshopper-icons/tools/classify.py b/design/grasshopper-icons/tools/classify.py index ba762089..942adfb1 100644 --- a/design/grasshopper-icons/tools/classify.py +++ b/design/grasshopper-icons/tools/classify.py @@ -39,7 +39,7 @@ ("CoolingProcess", "processCooling", None), ("MixingProcess", "processMixing", None), ("HeatRecoveryProcess", "processHeatRecovery", None), ("FanProcess", "processFan", None), ("RoomProcess", "processRoom", None), ("UndefinedProcess", "mollierProcess", None), ("MollierProcess", "mollierProcess", None), ("MollierPoint", "mollierPoint", None), - ("MollierGroup", "mollierProcess", None), ("MollierChart", "mollierChart", None), ("Diagram", "mollierChart", None), + ("MollierGroup", "group", None), ("MollierChart", "mollierChart", None), ("Diagram", "mollierChart", None), ("Psychrometric", "mollierChart", None), ("Mollier", "mollierChart", None), ("CellComplex", "cellComplex", None), ("Topology", "cellComplex", None), ("Algorithm", "algorithm", None), ("GenOpt", "algorithm", None), ("Solver", "algorithm", None), ("Objective", "objective", None), @@ -52,7 +52,7 @@ ("SunAnalysis", "solar", None), ("SolarSimulation", "solar", None), ] EXT_PARAM_OBJECTS = { - "MollierPoint": "mollierPoint", "MollierProcess": "mollierProcess", "MollierGroup": ("mollierProcess", None, True), + "MollierPoint": "mollierPoint", "MollierProcess": "mollierProcess", "MollierGroup": "group", "MollierObject": "mollierChart", "MollierChartObject": "mollierChart", "CellComplex": "cellComplex", "ResolvedCellComplex": "cellComplex", "Algorithm": "algorithm", "Objective": "objective", "Script": "script", "BandValues": "sound", "SystemEnergyCentre": "energyCentre", "SystemPlantRoom": "plantRoom", From 0869a8b99ff7a4004416cbc03f2cf0e3bb12ed90 Mon Sep 17 00:00:00 2001 From: SAM-BIM-AI Date: Mon, 28 Sep 2026 18:53:44 +0200 Subject: [PATCH 5/8] chore(gh-icons): sync shared SAM-BIM icon kit (tooling fixes; no icon or source change) Brings tools/ and tests/GhIconTest in line with the other SAM-BIM repos: inventory honours , check_source accepts multi-line Icon getters, check_assemblies skips obj/ reference assemblies, integrate matches public Designer visibility, harness gains the offline assembly mode. Re-running the inventory here gives an identical result. Co-Authored-By: Claude Opus 5.5 (cherry picked from commit 0a15f74b34322689a30fcf3f1e1216102f510c02) --- .../tests/GhIconTest/IconTests.cs | 41 +++++++++++++++++-- .../tests/GhIconTest/README.md | 6 +++ .../tools/check_assemblies.py | 3 +- .../grasshopper-icons/tools/check_source.py | 10 ++++- design/grasshopper-icons/tools/integrate.py | 8 ++-- design/grasshopper-icons/tools/inventory.py | 20 ++++++++- 6 files changed, 77 insertions(+), 11 deletions(-) diff --git a/design/grasshopper-icons/tests/GhIconTest/IconTests.cs b/design/grasshopper-icons/tests/GhIconTest/IconTests.cs index 782a0555..4a542182 100644 --- a/design/grasshopper-icons/tests/GhIconTest/IconTests.cs +++ b/design/grasshopper-icons/tests/GhIconTest/IconTests.cs @@ -24,18 +24,31 @@ public void EveryManifestObject_LoadsInGrasshopper_WithItsRedesignedIcon() { string repo = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(manifest), "..", "..")); var rows = JsonDocument.Parse(File.ReadAllText(manifest)).RootElement.EnumerateArray().ToList(); - int ok = 0; int globalMax = 0; + int ok = 0; int globalMax = 0; int offline = 0; foreach (var r in rows) { string guid = r.GetProperty("guid").GetString(), cls = r.GetProperty("class").GetString(); string png = Path.Combine(repo, r.GetProperty("project_dir").GetString(), "Resources", "Icons", r.GetProperty("resource").GetString() + ".png"); var obj = server.EmitObject(new Guid(guid)); - if (obj == null) { failures.Add($"{Path.GetFileName(repo)} {cls} {guid}: not loaded by Grasshopper"); continue; } + Bitmap icon; + if (obj == null) + { + // Offline fallback (e.g. Rhino.Inside.Revit plugins that plain Rhino cannot load): read the resource the + // Icon getter references straight from the built assembly. GUID -> resource is proven by the source re-parse. + string asmDir = Environment.GetEnvironmentVariable("SAM_ICON_ASSEMBLY_DIR"); + if (string.IsNullOrEmpty(asmDir)) { failures.Add($"{Path.GetFileName(repo)} {cls} {guid}: not loaded by Grasshopper"); continue; } + icon = OfflineIcon(asmDir, r.GetProperty("project").GetString(), r.GetProperty("resource").GetString()); + offline++; + if (icon == null) { failures.Add($"{cls}: resource {r.GetProperty("resource").GetString()} not found offline"); continue; } + } + else + { string name = r.GetProperty("name").GetString() ?? ""; if (!name.StartsWith("{") && obj.Name != name) failures.Add($"{cls}: name '{obj.Name}' != source '{name}'"); string cat = r.GetProperty("category").ValueKind == JsonValueKind.String ? r.GetProperty("category").GetString() : null; if (cat != null && !cat.StartsWith("{") && obj.Category != cat) failures.Add($"{cls}: category '{obj.Category}' != source '{cat}'"); - Bitmap icon = obj.Icon_24x24 as Bitmap; + icon = obj.Icon_24x24 as Bitmap; + } if (icon == null) { failures.Add($"{cls}: Icon_24x24 null"); continue; } if (icon.Width != 24 || icon.Height != 24) { failures.Add($"{cls}: icon {icon.Width}x{icon.Height}"); continue; } using var expected = new Bitmap(png); @@ -54,7 +67,7 @@ public void EveryManifestObject_LoadsInGrasshopper_WithItsRedesignedIcon() if (maxd > 2) { failures.Add($"{cls}: icon differs from {Path.GetFileName(png)} (max channel diff {maxd})"); continue; } ok++; } - report.Add($"{Path.GetFileName(repo)}: {ok}/{rows.Count} objects load in Grasshopper with their redesigned 24x24 icon (max channel diff vs manifest PNG: {globalMax}, premultiplied-alpha rounding; tolerance 2)"); + report.Add($"{Path.GetFileName(repo)}: {ok}/{rows.Count} objects verified ({rows.Count - offline} loaded in Grasshopper by GUID, {offline} offline from the built assembly) with their redesigned 24x24 icon (max channel diff vs manifest PNG: {globalMax}, premultiplied-alpha rounding; tolerance 2)"); } foreach (var l in report) TestContext.Progress.WriteLine(l); foreach (var f in failures) TestContext.Progress.WriteLine("FAIL " + f); @@ -62,4 +75,24 @@ public void EveryManifestObject_LoadsInGrasshopper_WithItsRedesignedIcon() Assert.That(report, Is.Not.Empty); Assert.That(failures, Is.Empty); } + + static readonly Dictionary Loaded = new(); + + static Bitmap OfflineIcon(string dir, string project, string resource) + { + string path = Directory.GetFiles(dir, project + ".dll", SearchOption.AllDirectories).OrderByDescending(File.GetLastWriteTimeUtc).FirstOrDefault(); + if (path == null) return null; + if (!Loaded.TryGetValue(path, out var asm)) Loaded[path] = asm = System.Reflection.Assembly.LoadFrom(path); + foreach (string res in asm.GetManifestResourceNames().Where(n => n.EndsWith(".resources"))) + { + var rm = new System.Resources.ResourceManager(res.Substring(0, res.Length - ".resources".Length), asm); + object o; + try { o = rm.GetObject(resource); } catch { continue; } + if (o is Bitmap b) return b; + if (o is byte[] bytes) return new Bitmap(new MemoryStream(bytes)); + } + foreach (string res in asm.GetManifestResourceNames().Where(n => n.EndsWith("." + resource + ".png"))) + return new Bitmap(asm.GetManifestResourceStream(res)); + return null; + } } diff --git a/design/grasshopper-icons/tests/GhIconTest/README.md b/design/grasshopper-icons/tests/GhIconTest/README.md index 0aee4777..ef9dd7c3 100644 --- a/design/grasshopper-icons/tests/GhIconTest/README.md +++ b/design/grasshopper-icons/tests/GhIconTest/README.md @@ -14,3 +14,9 @@ It is not part of any solution. Build the repository first (post-build installs set SAM_ICON_MANIFESTS=\design\grasshopper-icons\manifest.json dotnet test design\grasshopper-icons\tests\GhIconTest ``` + +**Offline mode.** Some plugins can't load in plain Rhino; for example the SAM_Revit plugins need Rhino.Inside.Revit. +For those, set `SAM_ICON_ASSEMBLY_DIR=\build`. Any object that Grasshopper can't emit then has its resource read +directly from the built assembly (`ResourceManager`, which resolves no plugin types) and compared with the manifest PNG. +The report counts loaded and offline objects separately. The link from GUID to resource is proven by `tools/integrate.py` +(source re-parse) and `tools/check_source.py`. diff --git a/design/grasshopper-icons/tools/check_assemblies.py b/design/grasshopper-icons/tools/check_assemblies.py index 5eb8db9c..117b0cb8 100644 --- a/design/grasshopper-icons/tools/check_assemblies.py +++ b/design/grasshopper-icons/tools/check_assemblies.py @@ -39,7 +39,8 @@ def assembly_name(project_dir): def find(dirs, name): hits = [] for d in dirs: - for root, _, files in os.walk(d): + for root, subdirs, files in os.walk(d): + subdirs[:] = [x for x in subdirs if x not in ("obj", ".git", "packages")] # skip reference assemblies (obj/*/ref, refint) hits += [os.path.join(root, f) for f in files if f in (name + ".gha", name + ".dll")] return max(hits, key=os.path.getmtime) if hits else None diff --git a/design/grasshopper-icons/tools/check_source.py b/design/grasshopper-icons/tools/check_source.py index 0f0d7d9e..a10345a9 100644 --- a/design/grasshopper-icons/tools/check_source.py +++ b/design/grasshopper-icons/tools/check_source.py @@ -21,7 +21,7 @@ "render.py": "8a87f66c45e0bb3e04cc613f2b0f28a8cb8df951a7daad95bdec8e3851060a3f", "sam_classify.py": "317064816c964e2268e9406aee9ca5f7d82c2bdb34da9c3225a344ca2464b864", # SAM classify.py } -TOKEN = re.compile(r"\b\w+\.(SAM_GH_\w+|\w+)") +TOKEN = re.compile(r"\b(?:\w+\.)+\w+") # any dotted chain, e.g. Properties.Resources.SAM_Small3 KEEP_RE = re.compile(r'ComponentGuid|base\(\s*"|GH_Exposure|Category|NickName|new Guid\(|new\("') @@ -59,8 +59,14 @@ def main(base): if len(minus) != len(plus): bad.append((f, "added/removed lines")) continue + now = open(os.path.join(REPO, f), encoding="utf-8-sig").read() + getters = [m.end() for m in re.finditer(r"Bitmap\s+Icon\b", now)] + + def in_icon_getter(line): # the line sits inside an `Icon` getter (single- or multi-line form) + i = now.find(line.strip()) + return i >= 0 and any(0 <= i - g <= 300 for g in getters) for a, b in zip(minus, plus): - if "Icon" not in a or TOKEN.sub("X", a) != TOKEN.sub("X", b) or "SAM_GH_" not in b or KEEP_RE.search(a): + if ("Icon" not in a and not in_icon_getter(b)) or TOKEN.sub("X", a) != TOKEN.sub("X", b) or "SAM_GH_" not in b or KEEP_RE.search(a): bad.append((f, a.strip(), b.strip())) else: swaps += 1 diff --git a/design/grasshopper-icons/tools/integrate.py b/design/grasshopper-icons/tools/integrate.py index eb7e20ea..c19f8d83 100644 --- a/design/grasshopper-icons/tools/integrate.py +++ b/design/grasshopper-icons/tools/integrate.py @@ -54,12 +54,14 @@ def update_resx(path, names, as_bytes): def update_designer(path, names, as_bytes): text, bom, nl = read(path) text = re.sub(r" \n /// \n /// Looks up a localized resource of type [^\n]+\n /// \n" - r" internal static [^\n]+ " + PREFIX + r"\w+ \{\n(?: [^\n]*\n)+ \}\n", "", text) + r" (?:internal|public) static [^\n]+ " + PREFIX + r"\w+ \{\n(?: [^\n]*\n)+ \}\n", "", text) typ = "byte[]" if as_bytes else "System.Drawing.Bitmap" + # match the generator in use (ResXFileCodeGenerator = internal, PublicResXFileCodeGenerator = public) + vis = "public" if re.search(r"\n public static [\w.\[\]]+ \w+\s*\{\s*\n\s*get", text) else "internal" kind = "System.Byte[]" if as_bytes else "System.Drawing.Bitmap" props = "".join( f" \n /// \n /// Looks up a localized resource of type {kind}.\n /// \n" - f" internal static {typ} {n} {{\n get {{\n" + f" {vis} static {typ} {n} {{\n get {{\n" f" object obj = ResourceManager.GetObject(\"{n}\", resourceCulture);\n" f" return (({typ})(obj));\n }}\n }}\n" for n in sorted(names)) idx = text.rstrip().rfind("}") # namespace close @@ -71,7 +73,7 @@ def update_designer(path, names, as_bytes): def resource_is_bytes(designer, name): """Type of an existing resource in Resources.Designer.cs (True = byte[], False = Bitmap).""" text = read(designer)[0] - m = re.search(r"internal static ([\w.\[\]]+) " + re.escape(name) + r"\s*\{", text) + m = re.search(r"(?:internal|public) static ([\w.\[\]]+) " + re.escape(name) + r"\s*\{", text) assert m, (designer, name) return m.group(1) == "byte[]" diff --git a/design/grasshopper-icons/tools/inventory.py b/design/grasshopper-icons/tools/inventory.py index 416b6e50..894ad7e8 100644 --- a/design/grasshopper-icons/tools/inventory.py +++ b/design/grasshopper-icons/tools/inventory.py @@ -2,7 +2,8 @@ Same parser as SAM/design/grasshopper-icons/tools/inventory.py (SAM#166), generalised to any repository layout: every .cs file under a project whose .csproj references Grasshopper is scanned. -An object is inventoried when a non-abstract class declares `ComponentGuid`. +An object is inventoried when a non-abstract class declares `ComponentGuid` in a file the project compiles +(files excluded by `` are skipped). Writes ../manifest_raw.json. """ import json @@ -62,6 +63,20 @@ def lit(a): return "{" + a + "}" +def compile_removed(pdir): + """Files excluded from compilation by the project's `` globs (SDK-style csproj).""" + import fnmatch + csproj = [f for f in os.listdir(pdir) if f.endswith(".csproj")] + pats = [] + for f in csproj: + txt = open(long_path(os.path.join(pdir, f)), encoding="utf-8-sig", errors="replace").read() + pats += [m.replace("\\", "/") for m in re.findall(r'): not a GH object of this plugin src = open(long_path(path), encoding="utf-8-sig").read() if "ComponentGuid" not in src: continue From 0c6d4187935d9e5eecfe1ab19764914f7da0360d Mon Sep 17 00:00:00 2001 From: SAM-BIM-AI Date: Mon, 28 Sep 2026 20:03:57 +0200 Subject: [PATCH 6/8] chore(spdx): add the repository SPDX/copyright header to .cs files changed by the icon PR The spdx-check workflow requires the LGPL-3.0-or-later SPDX line and the copyright line in every changed .cs file. Adds the standard header to the 10 pre-existing files touched by the icon-token swaps (and to the kit's IconTests.cs). No other change. check_source.py now accepts exactly this header as the only non-icon addition and diffs against the merge base. Co-Authored-By: Claude Opus 5.5 (cherry picked from commit 4c32610d2df24e6d201f55156b0ef6e253568af4) --- .../Classes/GooSystemComponent.cs | 5 +++- .../Classes/GooSystemEnergyCentre.cs | 5 +++- .../Classes/GooSystemGroup.cs | 5 +++- .../Classes/GooSystemPlantRoom.cs | 5 +++- .../Classes/GooSystemSpace.cs | 5 +++- .../SAMSystemsSystemEnergyCentreDataType.cs | 5 +++- .../Properties/Resources.Designer.cs | 5 +++- .../Classes/GooSystem.cs | 5 +++- .../Classes/GooSystemResult.cs | 5 +++- .../Properties/Resources.Designer.cs | 5 +++- .../tests/GhIconTest/IconTests.cs | 3 +++ .../grasshopper-icons/tools/check_source.py | 26 +++++++++++++++---- docs/GH-IconRedesign.md | 3 +++ 13 files changed, 67 insertions(+), 15 deletions(-) diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemComponent.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemComponent.cs index 2b3cf27e..97e3189d 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemComponent.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemComponent.cs @@ -1,4 +1,7 @@ -using Grasshopper.Kernel; +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +using Grasshopper.Kernel; using Grasshopper.Kernel.Types; using System; using System.Collections.Generic; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemEnergyCentre.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemEnergyCentre.cs index 402a7ad4..e5ae0f2d 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemEnergyCentre.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemEnergyCentre.cs @@ -1,4 +1,7 @@ -using Grasshopper.Kernel; +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +using Grasshopper.Kernel; using Grasshopper.Kernel.Types; using SAM.Analytical.Grasshopper.Systems.Properties; using System; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemGroup.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemGroup.cs index 17f8d337..33770f12 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemGroup.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemGroup.cs @@ -1,4 +1,7 @@ -using Grasshopper.Kernel; +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +using Grasshopper.Kernel; using Grasshopper.Kernel.Types; using Rhino; using Rhino.DocObjects; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemPlantRoom.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemPlantRoom.cs index 3b61e768..59664fc6 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemPlantRoom.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemPlantRoom.cs @@ -1,4 +1,7 @@ -using Grasshopper.Kernel; +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +using Grasshopper.Kernel; using Grasshopper.Kernel.Types; using SAM.Core.Grasshopper; using SAM.Analytical.Grasshopper.Systems.Properties; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemSpace.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemSpace.cs index f93e1bf9..8061f255 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemSpace.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Classes/GooSystemSpace.cs @@ -1,4 +1,7 @@ -using Grasshopper.Kernel; +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +using Grasshopper.Kernel; using Grasshopper.Kernel.Types; using SAM.Core.Grasshopper; using SAM.Analytical.Grasshopper.Systems.Properties; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsSystemEnergyCentreDataType.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsSystemEnergyCentreDataType.cs index 5c638079..b1364b67 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsSystemEnergyCentreDataType.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Component/SAMSystemsSystemEnergyCentreDataType.cs @@ -1,4 +1,7 @@ -using SAM.Core.Grasshopper; +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +using SAM.Core.Grasshopper; using System; using SAM.Analytical.Systems; using SAM.Analytical.Grasshopper.Systems.Properties; diff --git a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Properties/Resources.Designer.cs b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Properties/Resources.Designer.cs index 83216d8d..fd8e8195 100644 --- a/Grasshopper/SAM.Analytical.Grasshopper.Systems/Properties/Resources.Designer.cs +++ b/Grasshopper/SAM.Analytical.Grasshopper.Systems/Properties/Resources.Designer.cs @@ -1,4 +1,7 @@ -//------------------------------------------------------------------------------ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 diff --git a/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystem.cs b/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystem.cs index ab771175..2ff61f06 100644 --- a/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystem.cs +++ b/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystem.cs @@ -1,4 +1,7 @@ -using Grasshopper.Kernel; +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +using Grasshopper.Kernel; using Grasshopper.Kernel.Types; using SAM.Core.Grasshopper.Systems.Properties; using System; diff --git a/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystemResult.cs b/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystemResult.cs index f3d758b9..dfcd49bf 100644 --- a/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystemResult.cs +++ b/Grasshopper/SAM.Core.Grasshopper.Systems/Classes/GooSystemResult.cs @@ -1,4 +1,7 @@ -using Grasshopper.Kernel; +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +using Grasshopper.Kernel; using Grasshopper.Kernel.Types; using SAM.Core.Grasshopper.Systems.Properties; using SAM.Core.Systems; diff --git a/Grasshopper/SAM.Core.Grasshopper.Systems/Properties/Resources.Designer.cs b/Grasshopper/SAM.Core.Grasshopper.Systems/Properties/Resources.Designer.cs index 5ed58816..0730c90f 100644 --- a/Grasshopper/SAM.Core.Grasshopper.Systems/Properties/Resources.Designer.cs +++ b/Grasshopper/SAM.Core.Grasshopper.Systems/Properties/Resources.Designer.cs @@ -1,4 +1,7 @@ -//------------------------------------------------------------------------------ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 diff --git a/design/grasshopper-icons/tests/GhIconTest/IconTests.cs b/design/grasshopper-icons/tests/GhIconTest/IconTests.cs index 4a542182..31233ac5 100644 --- a/design/grasshopper-icons/tests/GhIconTest/IconTests.cs +++ b/design/grasshopper-icons/tests/GhIconTest/IconTests.cs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors + using System; using System.Collections.Generic; using System.Drawing; diff --git a/design/grasshopper-icons/tools/check_source.py b/design/grasshopper-icons/tools/check_source.py index a10345a9..7a2fdb48 100644 --- a/design/grasshopper-icons/tools/check_source.py +++ b/design/grasshopper-icons/tools/check_source.py @@ -1,10 +1,11 @@ """Guard rails for the icon redesign diff. - python check_source.py [base] (default base: origin/sow/2026-Q3) + python check_source.py [base] (default: merge-base of origin/sow/2026-Q3 and HEAD, so upstream moves are ignored) 1. Vendored design-system files are byte-identical to SAM-BIM/SAM#166 @ cf4d924a (SHA-256). 2. Every changed line in a component .cs file is an icon-token swap inside an `Icon` getter (`.OLD` -> `.SAM_GH_*`); generated Resources.Designer.cs / holder blocks are excluded. + The only other allowed change is the repository SPDX policy header (2 lines + blank) added at the top of a file. 3. The set of ComponentGuid values, names, nicknames, categories and exposures is unchanged vs base. """ import hashlib @@ -22,6 +23,8 @@ "sam_classify.py": "317064816c964e2268e9406aee9ca5f7d82c2bdb34da9c3225a344ca2464b864", # SAM classify.py } TOKEN = re.compile(r"\b(?:\w+\.)+\w+") # any dotted chain, e.g. Properties.Resources.SAM_Small3 +SPDX_HEADER = ("// SPDX-License-Identifier: LGPL-3.0-or-later", + "// Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors") KEEP_RE = re.compile(r'ComponentGuid|base\(\s*"|GH_Exposure|Category|NickName|new Guid\(|new\("') @@ -30,13 +33,14 @@ def git(*args): def main(base): + base = git("merge-base", base, "HEAD").strip() ok = True for f, h in VENDORED.items(): got = hashlib.sha256(open(os.path.join(HERE, f), "rb").read().replace(b"\r\n", b"\n")).hexdigest() # autocrlf-safe print(f"vendored {f}: {'OK' if got == h else 'MODIFIED'}") ok &= got == h files = [f for f in git("diff", "--name-only", base, "--", "*.cs").split("\n") if f and not f.startswith("design/")] - swaps, bad = 0, [] + swaps, bad, headers = 0, [], 0 for f in files: if f.endswith("Resources.Designer.cs") or f.startswith("design/"): continue @@ -54,8 +58,19 @@ def main(base): if outside: bad.append((f, outside[:4])) continue - minus = re.findall(r"^-(?!--)(.*)$", diff, re.M) - plus = re.findall(r"^\+(?!\+\+)(.*)$", diff, re.M) + minus = [x.lstrip("") for x in re.findall(r"^-(?!--)(.*)$", diff, re.M)] + plus = [x.lstrip("") for x in re.findall(r"^\+(?!\+\+)(.*)$", diff, re.M)] + top = open(os.path.join(REPO, f), encoding="utf-8-sig").read().replace("\r\n", "\n").split("\n")[:3] + if ([t.strip() for t in top] == [*SPDX_HEADER, ""] and all(any(p.strip() == h for p in plus) for h in SPDX_HEADER) + and all(h not in "\n".join(minus) for h in SPDX_HEADER)): + # repository SPDX policy header added at the top of the file (the only allowed non-icon addition) + for line in (*SPDX_HEADER, ""): + plus.remove(next(p for p in plus if p.strip() == line)) + headers += 1 + for m in list(minus): # a line displaced by the header insertion (e.g. the BOM moving) is unchanged + if m in plus: + minus.remove(m) + plus.remove(m) if len(minus) != len(plus): bad.append((f, "added/removed lines")) continue @@ -70,7 +85,8 @@ def in_icon_getter(line): # the line sits inside an `Icon` getter (single- or m bad.append((f, a.strip(), b.strip())) else: swaps += 1 - print(f"component .cs files changed: {len(files)}; icon-token swaps: {swaps}; non-icon changes: {len(bad)}") + print(f"component .cs files changed: {len(files)}; icon-token swaps: {swaps}; SPDX headers added: {headers}; " + f"non-icon changes: {len(bad)}") for b in bad[:20]: print(" NON-ICON CHANGE:", b) ok &= not bad diff --git a/docs/GH-IconRedesign.md b/docs/GH-IconRedesign.md index 2119de36..b518ae4a 100644 --- a/docs/GH-IconRedesign.md +++ b/docs/GH-IconRedesign.md @@ -58,3 +58,6 @@ Built and validated; ready for review. **Not merged.** ## Recommended next step Review this PR (compare `review/contact_sheet.png`), then merge by the maintainer. After merge, add the `PROJECT_PROGRESS.md` closeout entry on `sow/2026-Q3` with the merge SHA. SAM#166 (the reference design system) remains open. + +## SPDX header policy (CI `spdx-check`) +The repository SPDX check requires the LGPL-3.0-or-later SPDX line and the copyright line in every `.cs` file a PR changes. The icon-token swaps touched 10 older files that predated the policy (components, `Resources.Designer.cs`), and the kit test `IconTests.cs` had no header. The standard 2-line header was added to them; nothing else changed. `tools/check_source.py` accepts exactly this header as the only non-icon addition and compares against the merge base. From da912c1add048a74f19df7db121a2091ec90f8ff Mon Sep 17 00:00:00 2001 From: Michal Dengusiak Date: Tue, 6 Oct 2026 20:14:51 +0200 Subject: [PATCH 7/8] docs(gh-icons): record the Q4 migration PR Point the PR record at the replacement Q4 PR and base, keep the old Q3 PR referenced for provenance, and note the Q4 re-validation. Documentation only. Co-Authored-By: Claude Sonnet 5.5 --- docs/GH-IconRedesign.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/GH-IconRedesign.md b/docs/GH-IconRedesign.md index b518ae4a..421f849e 100644 --- a/docs/GH-IconRedesign.md +++ b/docs/GH-IconRedesign.md @@ -1,6 +1,6 @@ # SAM Grasshopper icon redesign — SAM_Systems PR record -Branch `feature/sam-gh-icon-redesign`, based on `sow/2026-Q3` @ `fbef48f`. PR: SAM-BIM/SAM_Systems#32. +Branch `feature/sam-gh-icon-redesign-q4`, based on `sow/2026-Q4` @ `0a7a1b07`. PR: SAM-BIM/SAM_Systems#37. Q4 migration of SAM-BIM/SAM_Systems#32 (`feature/sam-gh-icon-redesign` @ `4c32610`, based on `sow/2026-Q3` @ `fbef48f`, kept open for provenance): the same commits replayed onto `sow/2026-Q4`; Q3 history was not imported. Propagates the SAM icon design system from SAM-BIM/SAM#166 (head `cf4d924a`, open, not merged) to this repository. ## Current status @@ -57,7 +57,10 @@ Built and validated; ready for review. **Not merged.** - Building a single csproj (outside the solution) hits the pre-existing post-build `xcopy "$(SolutionDir)…"` error; building the solution is clean. Not caused by this PR. ## Recommended next step -Review this PR (compare `review/contact_sheet.png`), then merge by the maintainer. After merge, add the `PROJECT_PROGRESS.md` closeout entry on `sow/2026-Q3` with the merge SHA. SAM#166 (the reference design system) remains open. +Review this PR (compare `review/contact_sheet.png`), then merge by the maintainer. After merge, add the `PROJECT_PROGRESS.md` closeout entry on `sow/2026-Q4` with the merge SHA. SAM#166 (the reference design system) remains open. ## SPDX header policy (CI `spdx-check`) The repository SPDX check requires the LGPL-3.0-or-later SPDX line and the copyright line in every `.cs` file a PR changes. The icon-token swaps touched 10 older files that predated the policy (components, `Resources.Designer.cs`), and the kit test `IconTests.cs` had no header. The standard 2-line header was added to them; nothing else changed. `tools/check_source.py` accepts exactly this header as the only non-icon addition and compares against the merge base. + +## Q4 migration validation +Re-validated on `sow/2026-Q4` @ `0a7a1b07`: `design/grasshopper-icons/tools/check_source.py origin/sow/2026-Q4` OK (icon-token swaps: 38, SPDX headers added: 8, non-icon changes: 0, ComponentGuid declarations unchanged); `dotnet build SAM_Systems.sln -c Debug` succeeded with 0 errors; `check_assemblies.py build` OK; tests: `SAM.Analytical.Systems.Tests` (CI conformance suite) 305/305 passed; `SAM.Analytical.Systems.Mollier.Tests` 123/123 passed. The Q4 feature diff (before this record commit) has the same patch-id, file set and blobs as the Q3 PR's feature diff. From cb6043c7c60c5e24ff3ace157effede86a6f472d Mon Sep 17 00:00:00 2001 From: Michal Dengusiak Date: Sun, 11 Oct 2026 12:02:52 +0100 Subject: [PATCH 8/8] Complete icon migration and record current validation --- .../Icon-Migration-Validation-2026-10-11.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 documentation/Icon-Migration-Validation-2026-10-11.md diff --git a/documentation/Icon-Migration-Validation-2026-10-11.md b/documentation/Icon-Migration-Validation-2026-10-11.md new file mode 100644 index 00000000..566fb830 --- /dev/null +++ b/documentation/Icon-Migration-Validation-2026-10-11.md @@ -0,0 +1,19 @@ +# Icon migration validation — 2026-10-11 + +Base: `sow/2026-Q4`. Scope: SAM-BIM only. Reference: [SAM#179](https://github.com/SAM-BIM/SAM/pull/179); [SAM#166](https://github.com/SAM-BIM/SAM/pull/166) is the closed historical design source. + +## Changes and decisions + +- Grasshopper manifest coverage: 38 concrete objects. GUIDs, APIs, namespaces, component metadata and behavior are preserved. +- Reuse the frozen SAM glyph/palette/badge grammar and frozen SAM-BIM extension v1. Preserve plugin identity, external integration logos, severity symbols and historical attribution. +- Source comparison against current base: 38 icon resource token swaps; 0 other production C# changes, apart from standard SPDX headers and additive resource properties. +- Validated 38 manifest resource references; 0 errors. + +## Fresh validation + +- VS MSBuild Restore,Build, Release: **PASS**. Scratch APPDATA/USERPROFILE; current sibling SAM-BIM dependencies, OCCT native build skipped. +- Regression suites: SAM_Systems-0.trx: passed 305, failed 0, total 305; SAM_Systems-1.trx: passed 123, failed 0, total 123 +- Re-parsed compiled component declarations: 38/38 manifest rows; 0 coverage/canonical 24x24 RGBA PNG errors. +- Built assembly resource presence and exact embedded PNG bytes checked. + +Next step: verify final-head GitHub checks and merge only if green and safe under the owner authorization. No force-push or branch deletion. Hosted Rhino smoke is tracked separately; prior historical results are not fresh runs.