├── .gitattributes ├── .gitignore ├── BIMrx.Marconi SinglePage 1.1.pdf ├── LICENSE ├── README.md ├── graphiql.png └── src ├── GraphQL4Revit.sln ├── RevitGraphQLCommand ├── App.cs ├── EntryCommandSeparateThread.cs ├── Properties │ └── AssemblyInfo.cs ├── Resources │ └── graphql.png ├── Revit2GraphQL.addin ├── RevitGraphQLCommand.csproj ├── Ui.xaml ├── Ui.xaml.cs ├── Util.cs ├── app.config └── packages.config ├── RevitGraphQLResolver ├── GraphQL │ ├── GraphQLHelpers.cs │ ├── GraphQLQuery.cs │ ├── IQuery.cs │ ├── Mutation.cs │ ├── MySchema.cs │ └── Query.cs ├── GraphQLModel │ ├── IQLFamily.cs │ ├── IQLFamilyCategory.cs │ ├── IQLFamilySymbol.cs │ ├── QLAssemblyResolve.cs │ ├── QLElementCollectionResolve.cs │ ├── QLFabricationPartResolve.cs │ ├── QLFabricationServiceResolve.cs │ ├── QLFamilyCategoryResolve.cs │ ├── QLFamilyInstanceResolve.cs │ ├── QLFamilyResolve.cs │ ├── QLFamilySymbolResolve.cs │ ├── QLMepSystemResolve.cs │ ├── QLTammTreeNodeResolve.cs │ └── QLViewScheduleResolve.cs ├── ResolverEntry.cs ├── RevitGraphQLResolver.csproj └── TraversalTree │ ├── Options.cs │ ├── TraversalTree.cs │ └── Util.cs ├── RevitGraphQLSchema ├── GraphQLModel │ ├── QLAssembly.cs │ ├── QLElementCollection.cs │ ├── QLFabricationPart.cs │ ├── QLFabricationService.cs │ ├── QLFamily.cs │ ├── QLFamilyCategory.cs │ ├── QLFamilyInstance.cs │ ├── QLFamilySymbol.cs │ ├── QLMepSystem.cs │ ├── QLParameter.cs │ ├── QLTammTreeNode.cs │ ├── QLViewSchedule.cs │ ├── QLViewScheduleData.cs │ ├── QLViewScheduleRow.cs │ └── UpdateQLParameter.cs ├── GraphQLSchema.cs ├── IGraphQL │ ├── IMutation.cs │ └── IQuery.cs ├── MarconiUser.cs └── RevitGraphQLSchema.csproj ├── RevitMarconiCommand ├── App.cs ├── Class1.cs ├── EntryCommandSeparateThread.cs ├── Helpers │ ├── MsalAuthHelper.cs │ └── TokenCacheHelper.cs ├── Properties │ └── AssemblyInfo.cs ├── Resources │ └── phone.png ├── RevitMarconi.addin ├── RevitMarconiCommand.csproj ├── Ui.xaml ├── Ui.xaml.cs ├── Util.cs ├── app.config └── packages.config └── RevitWebServer ├── Controllers ├── AboutController.cs └── GraphqlController.cs ├── Properties └── AssemblyInfo.cs ├── RevitWebServer.csproj ├── Startup.cs ├── WebServer.cs ├── app.config └── packages.config /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /BIMrx.Marconi SinglePage 1.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BIMrxLAB/Revit2GraphQL/150d7d0de0be57fd433a4b2ff91886100130c182/BIMrx.Marconi SinglePage 1.1.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 gv73 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GraphQL for Revit 2 | This project contains a GraphQL endpoint for Revit that can be accessed locally as well as remotely over the web. 3 | 4 | ![GraphiQL Client](https://github.com/gregorvilkner/Revit2GraphQL/blob/master/graphiql.png) 5 | Check out [BIMrx.Marconi.pdf](https://github.com/gregorvilkner/Revit2GraphQL/blob/master/BIMrx.Marconi%20SinglePage%201.1.pdf) for more information. 6 | 7 | ## Current Itteration 8 | 9 | The current repo includes projects for 2 individual Revit addins: 10 | 1) a webapi hosted in Revit that exposes a GraphQL controller at http://localhost:9000/api/graphql. a very basic "about" controller that can be used for simple get requests at http://localhost:9000/api/about 11 | 1) a marconi client that allows interoperability with your revit session over the web at https://marconi4revitwebapp.azurewebsites.net/ 12 | 13 | ## Getting Started: Nuget Dance and Versioning 14 | 15 | Personally, I always love to get latest. When Nuget suggests consolidations or updates I usually go for it. ~~Unfortunately, this is not possible here.~~ The main components that make this project work are described below. 16 | 17 | Here is what we know should not be updated: 18 | 19 | 1) ~~GraphQL-Parser - leave it at 3.0.0, which otherwise breakes GraphQL 20 | 2) System.Diagnostics.DiagnosticSource - leave it at 4.5.1, which otherwise breakes ServiceBus 21 | 3) ~~Newtonsoft.Json - it's a bit of a mess. You want to go low for Revit, and you can't go too high for GraphQL. GraphQL is actively trying to loose the Newtonsoft.Json dependency. 22 | 23 | Update as of 9/6/2020: The upgrade to GraphQL for .NET 3.0 enabled us to ditch a lot of Newtonsoft.Json references and go with System.Text.Json instead. This is making it a lot easier to life side by side with Revit. The last required Newtonsoft references are with the Microsoft.AspNet.WebApi.Client (requires 6.0.4) and Microsoft.Azure.ServiceBus (requires 10.0.3). 24 | 25 | ### Shared Infrastructure 26 | 27 | The Schema and the Resolver are both .NET Standard 2.0 projects. We're using .NET Standard so we can reference them in .NET Core web projects and in .NET Framework Revit addins. Also, this forces the Revit addins to be .NET Framework 4.7 at least. 28 | 29 | #### RevitGraphQLSchema 30 | 31 | The Schema defines the various GraphQL object types and holds interfaces for queries and mutations. 32 | 33 | It's sole dependency should be GraphQL ~~2.4.0.~~ 3.0.0 34 | 35 | #### RevitGraphQLResolver 36 | 37 | The Resolver is where GraphQL queries are received and resolved against the Revit API. 38 | 39 | Dependencies include GraphQL ~~2.4.0.~~ 3.0.0, GraphQL.SystemTextJson 3.0.0, and the very awesome WhiteShareq RevitTask 3.0.0. 40 | 41 | ### Local GraphQL Endpoint for Revit 42 | 43 | There are 2 projects that make up the local GraphQL endpoint for Revit: a web server and the command. 44 | 45 | #### RevitWebServer 46 | 47 | The library basically builds a selfhosted OWIN web server with 2 controllers: a simple About controller with a single GET method and the GraphQL controller with it's standard sole POST method. I've followed a couple of tutorials for OWIN'ing: 48 | 49 | 1) https://braincadet.com/category/c-sharp/ 50 | 1) http://www.learnonlineasp.net/2017/10/use-owin-to-self-host-aspnet-web-api.html 51 | 52 | Dependencies include GraphQL ~~2.4.0.~~ 3.0.0, GraphQL.SystemTextJson 3.0.0, Newtonsoft.Json ~~12.0.3~~ 6.0.4, RevitTask 3.0.0, and a bunch of OWIN and AspNet.WebApi stuff. 53 | 54 | #### RevitGraphQLCommand 55 | 56 | This is the external command that hooks into Revit and has some very minimalistic WPF UI. 57 | 58 | Dependencies include ~~Newtonsoft.Json 9.0.1 (that's the on Revit likes),~~ RevitTask 3.0.0, and the Owin.Host.HttpListener 4.1.0 (that one trickled over from the webserver) 59 | 60 | ### Remote GraphQL using BIMrx.Marconi 61 | 62 | This external command uses the same resolver, but doesn't build an internal webserver. Instead we use a Azure ServiceBus client to listen and respond to queries from a messaging layer that uses Azure AMQP. The schema is exposed on a web page https://marconi4revitwebapp.azurewebsites.net/ and in the Revit addin. The request and response JObjects are routed through Azure Service Bus queues. 63 | 64 | Dependencies do not include OWIN stuff. Instead, we have GraphQL ~~2.4.0.~~ 3.0.0, GraphQL.SystemTextJson 3.0.0, Newtonsoft JSON 10.0.3 (required by ServiceBus ~~GraphQL, and newer versions won't work, unfortunately~~), RevitTask 3.0.0, and Microsoft.Azure.ServiceBus 4.1.3 together with Microsoft.Identity.Client 4.17.0. 65 | 66 | ## GraphQL Routes and Elements 67 | 68 | 1) hello returns the path of your revit file 69 | 1) FamilyCategories, Families, FamilySymbols 70 | 1) FamilyInstances with Parameters 71 | 1) ViewSchedules with data 72 | 1) MEP Systems - name, mep domain, and traversal of MEP Tree 73 | 1) Assemblies - entrance only: id, name 74 | 1) Sheets - entrance only: id, name 75 | 1) Phases - entrance only: id, name 76 | 77 | there is a mutation that let's you change parameters. 78 | 79 | ## .addin files to load the revit commands 80 | 81 | ~~~ XML 82 | 83 | 84 | 85 | Local GraphQL Endpoint 86 | C:\Users\xyz\source\repos\Revit2GraphQL\src\RevitGraphQLCommand\bin\Debug\RevitGraphQLCommand.dll 87 | 73dc677a-5a96-41dd-b3be-ca81d06dfc2c 88 | RevitGraphQLCommand.App 89 | Microdesk 90 | https://www.microdesk.com/bimrx/ 91 | 92 | 93 | ~~~ 94 | 95 | ~~~ XML 96 | 97 | 98 | 99 | BIMrx.Marconi 100 | C:\Users\xyz\source\repos\Revit2GraphQL\src\RevitMarconiCommand\bin\Debug\RevitMarconiCommand.dll 101 | 26516f0e-cdb2-43d0-9169-b4473db259ac 102 | RevitMarconiCommand.App 103 | Microdesk 104 | https://www.microdesk.com/bimrx/ 105 | 106 | 107 | ~~~ 108 | 109 | 110 | -------------------------------------------------------------------------------- /graphiql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BIMrxLAB/Revit2GraphQL/150d7d0de0be57fd433a4b2ff91886100130c182/graphiql.png -------------------------------------------------------------------------------- /src/GraphQL4Revit.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RevitGraphQLResolver", "RevitGraphQLResolver\RevitGraphQLResolver.csproj", "{F5E2F94E-DC93-4A71-A8DF-5C13D97BC601}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RevitWebServer", "RevitWebServer\RevitWebServer.csproj", "{053728E3-50DB-46BF-9D23-772570BD24B7}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RevitGraphQLSchema", "RevitGraphQLSchema\RevitGraphQLSchema.csproj", "{B5B78760-CC43-477D-A6EE-CE1276DCCB66}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RevitMarconiCommand", "RevitMarconiCommand\RevitMarconiCommand.csproj", "{DC38D4E5-D9CC-41B8-AA8E-B7722B6DB47A}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RevitGraphQLCommand", "RevitGraphQLCommand\RevitGraphQLCommand.csproj", "{A60D9874-A5E5-4E2B-8660-EB51CC2C60B3}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {F5E2F94E-DC93-4A71-A8DF-5C13D97BC601}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {F5E2F94E-DC93-4A71-A8DF-5C13D97BC601}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {F5E2F94E-DC93-4A71-A8DF-5C13D97BC601}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {F5E2F94E-DC93-4A71-A8DF-5C13D97BC601}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {053728E3-50DB-46BF-9D23-772570BD24B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {053728E3-50DB-46BF-9D23-772570BD24B7}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {053728E3-50DB-46BF-9D23-772570BD24B7}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {053728E3-50DB-46BF-9D23-772570BD24B7}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {B5B78760-CC43-477D-A6EE-CE1276DCCB66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {B5B78760-CC43-477D-A6EE-CE1276DCCB66}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {B5B78760-CC43-477D-A6EE-CE1276DCCB66}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {B5B78760-CC43-477D-A6EE-CE1276DCCB66}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {DC38D4E5-D9CC-41B8-AA8E-B7722B6DB47A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {DC38D4E5-D9CC-41B8-AA8E-B7722B6DB47A}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {DC38D4E5-D9CC-41B8-AA8E-B7722B6DB47A}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {DC38D4E5-D9CC-41B8-AA8E-B7722B6DB47A}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {A60D9874-A5E5-4E2B-8660-EB51CC2C60B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {A60D9874-A5E5-4E2B-8660-EB51CC2C60B3}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {A60D9874-A5E5-4E2B-8660-EB51CC2C60B3}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {A60D9874-A5E5-4E2B-8660-EB51CC2C60B3}.Release|Any CPU.Build.0 = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | GlobalSection(ExtensibilityGlobals) = postSolution 47 | SolutionGuid = {580F69E9-E6F4-4647-BB23-08D52F7315B7} 48 | EndGlobalSection 49 | EndGlobal 50 | -------------------------------------------------------------------------------- /src/RevitGraphQLCommand/App.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Threading; 6 | using System.Windows.Media.Imaging; 7 | using System.Windows.Threading; 8 | using Autodesk.Revit.UI; 9 | using Autodesk.Revit.UI.Events; 10 | 11 | namespace RevitGraphQLCommand 12 | { 13 | /// 14 | /// This is the main class which defines the Application, and inherits from Revit's 15 | /// IExternalApplication class. 16 | /// 17 | class App : IExternalApplication 18 | { 19 | // class instance 20 | public static App ThisApp; 21 | 22 | // ModelessForm instance 23 | private Ui _mMyForm; 24 | 25 | // Separate thread to run Ui on 26 | private Thread _uiThread; 27 | 28 | public Result OnStartup(UIControlledApplication a) 29 | { 30 | _mMyForm = null; // no dialog needed yet; the command will bring it 31 | ThisApp = this; // static access to this application instance 32 | 33 | // Method to add Tab and Panel 34 | RibbonPanel panel = RibbonPanel(a); 35 | string thisAssemblyPath = Assembly.GetExecutingAssembly().Location; 36 | 37 | // BUTTON FOR THE MULTI-THREADED WPF OPTION 38 | if (panel.AddItem( 39 | new PushButtonData("Local GraphQL", "Local GraphQL", thisAssemblyPath, 40 | "RevitGraphQLCommand.EntryCommandSeparateThread")) is PushButton button2) 41 | { 42 | button2.ToolTip = "Visual interface to start/stop local GraphQL endpoint."; 43 | Uri uriImage = new Uri("pack://application:,,,/RevitGraphQLCommand;component/Resources/graphql.png"); 44 | BitmapImage largeImage = new BitmapImage(uriImage); 45 | button2.LargeImage = largeImage; 46 | } 47 | 48 | 49 | 50 | // listeners/watchers for external events (if you choose to use them) 51 | a.ApplicationClosing += a_ApplicationClosing; //Set Application to Idling 52 | a.Idling += a_Idling; 53 | 54 | return Result.Succeeded; 55 | } 56 | 57 | /// 58 | /// What to do when the application is shut down. 59 | /// 60 | public Result OnShutdown(UIControlledApplication a) 61 | { 62 | return Result.Succeeded; 63 | } 64 | 65 | /// 66 | /// This is the method which launches the WPF window in a separate thread, and injects any methods that are 67 | /// wrapped by ExternalEventHandlers. This can be done in a number of different ways, and 68 | /// implementation will differ based on how the WPF is set up. 69 | /// 70 | /// The Revit UIApplication within the add-in will operate. 71 | public void ShowFormSeparateThread(UIApplication uiapp) 72 | { 73 | // If we do not have a thread started or has been terminated start a new one 74 | if (!(_uiThread is null) && _uiThread.IsAlive) return; 75 | //EXTERNAL EVENTS WITH ARGUMENTS 76 | //https://thebuildingcoder.typepad.com/blog/2020/02/external-communication-and-async-await-event-wrapper.html#2 77 | //https://github.com/WhiteSharq/RevitTask 78 | 79 | RevitTask aRevitTask = new RevitTask(); 80 | 81 | 82 | _uiThread = new Thread(() => 83 | { 84 | SynchronizationContext.SetSynchronizationContext( 85 | new DispatcherSynchronizationContext( 86 | Dispatcher.CurrentDispatcher)); 87 | // The dialog becomes the owner responsible for disposing the objects given to it. 88 | _mMyForm = new Ui(uiapp, aRevitTask); 89 | _mMyForm.Closed += (s, e) => Dispatcher.CurrentDispatcher.InvokeShutdown(); 90 | _mMyForm.Show(); 91 | Dispatcher.Run(); 92 | }); 93 | 94 | _uiThread.SetApartmentState(ApartmentState.STA); 95 | _uiThread.IsBackground = true; 96 | _uiThread.Start(); 97 | } 98 | 99 | #region Idling & Closing 100 | 101 | /// 102 | /// What to do when the application is idling. (Ideally nothing) 103 | /// 104 | void a_Idling(object sender, IdlingEventArgs e) 105 | { 106 | } 107 | 108 | /// 109 | /// What to do when the application is closing.) 110 | /// 111 | void a_ApplicationClosing(object sender, ApplicationClosingEventArgs e) 112 | { 113 | } 114 | 115 | #endregion 116 | 117 | #region Ribbon Panel 118 | 119 | public RibbonPanel RibbonPanel(UIControlledApplication a) 120 | { 121 | 122 | string tab = "GraphQL"; // Tab name 123 | 124 | // Empty ribbon panel 125 | RibbonPanel ribbonPanel = null; 126 | // Try to create ribbon tab. 127 | try 128 | { 129 | a.CreateRibbonTab(tab); 130 | } 131 | catch (Exception ex) 132 | { 133 | Util.HandleError(ex); 134 | } 135 | 136 | // Try to create ribbon panel. 137 | try 138 | { 139 | RibbonPanel panel = a.CreateRibbonPanel(tab, "Local"); 140 | } 141 | catch (Exception ex) 142 | { 143 | Util.HandleError(ex); 144 | } 145 | 146 | // Search existing tab for your panel. 147 | List panels = a.GetRibbonPanels(tab); 148 | foreach (RibbonPanel p in panels.Where(p => p.Name == "Local")) 149 | { 150 | ribbonPanel = p; 151 | } 152 | 153 | //return panel 154 | return ribbonPanel; 155 | } 156 | 157 | #endregion 158 | } 159 | } -------------------------------------------------------------------------------- /src/RevitGraphQLCommand/EntryCommandSeparateThread.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.Attributes; 2 | using Autodesk.Revit.DB; 3 | using Autodesk.Revit.UI; 4 | using RevitWebServer; 5 | using System; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Text; 10 | 11 | namespace RevitGraphQLCommand 12 | { 13 | 14 | /// 15 | /// This is the ExternalCommand which gets executed from the ExternalApplication. In a WPF context, 16 | /// this can be lean, as it just needs to show the WPF. Without a UI, this could contain the main 17 | /// order of operations for executing the business logic. 18 | /// 19 | [Transaction(TransactionMode.Manual)] 20 | public class EntryCommandSeparateThread : IExternalCommand 21 | { 22 | public virtual Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) 23 | { 24 | 25 | AppDomain currentDomain = AppDomain.CurrentDomain; 26 | currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler); 27 | 28 | try 29 | { 30 | App.ThisApp.ShowFormSeparateThread(commandData.Application); 31 | return Result.Succeeded; 32 | } 33 | catch (Exception ex) 34 | { 35 | message = ex.Message; 36 | return Result.Failed; 37 | } 38 | 39 | 40 | } 41 | 42 | 43 | // thank you Ken 44 | // https://forums.autodesk.com/t5/navisworks-api/could-not-load-file-or-assembly-newtonsoft-json/m-p/7460535#M3467 45 | private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args) 46 | { 47 | if (args.Name.Contains("Microsoft.Owin")) 48 | { 49 | string assemblyFileName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\Microsoft.Owin.dll"; 50 | return Assembly.LoadFrom(assemblyFileName); 51 | } 52 | else 53 | { 54 | return null; 55 | } 56 | } 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/RevitGraphQLCommand/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RevitCommand")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("RevitCommand")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a60d9874-a5e5-4e2b-8660-eb51cc2c60b3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/RevitGraphQLCommand/Resources/graphql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BIMrxLAB/Revit2GraphQL/150d7d0de0be57fd433a4b2ff91886100130c182/src/RevitGraphQLCommand/Resources/graphql.png -------------------------------------------------------------------------------- /src/RevitGraphQLCommand/Revit2GraphQL.addin: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Local GraphQL Endpoint 5 | RevitGraphQLCommand/RevitGraphQLCommand.dll 6 | 73dc677a-5a96-41dd-b3be-ca81d06dfc2c 7 | RevitGraphQLCommand.App 8 | Microdesk 9 | https://www.microdesk.com/bimrx/ 10 | 11 | -------------------------------------------------------------------------------- /src/RevitGraphQLCommand/RevitGraphQLCommand.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A60D9874-A5E5-4E2B-8660-EB51CC2C60B3} 8 | Library 9 | Properties 10 | RevitGraphQLCommand 11 | RevitGraphQLCommand 12 | v4.7.2 13 | 512 14 | true 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | ..\packages\Microsoft.Owin.Host.HttpListener.4.1.1\lib\net45\Microsoft.Owin.Host.HttpListener.dll 36 | 37 | 38 | 39 | 40 | False 41 | ..\..\..\..\..\..\..\Program Files\Autodesk\Revit 2020\RevitAPI.dll 42 | 43 | 44 | False 45 | ..\..\..\..\..\..\..\Program Files\Autodesk\Revit 2020\RevitAPIUI.dll 46 | 47 | 48 | ..\packages\RevitTask.3.0.0\lib\net47\RevitTask.dll 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | Ui.xaml 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | Always 75 | 76 | 77 | 78 | 79 | {f5e2f94e-dc93-4a71-a8df-5c13d97bc601} 80 | RevitGraphQLResolver 81 | 82 | 83 | {b5b78760-cc43-477d-a6ee-ce1276dccb66} 84 | RevitGraphQLSchema 85 | 86 | 87 | {053728e3-50db-46bf-9d23-772570bd24b7} 88 | RevitWebServer 89 | 90 | 91 | 92 | 93 | Designer 94 | MSBuild:Compile 95 | 96 | 97 | 98 | 99 | Always 100 | 101 | 102 | 103 | 104 | if $(ConfigurationName) == Debug ( 105 | mkdir "$(AppData)\Autodesk\REVIT\Addins\2020\$(TargetName)\" 106 | if exist "$(AppData)\Autodesk\REVIT\Addins\2020" copy "$(TargetDir)*.addin" "$(AppData)\Autodesk\REVIT\Addins\2020\" 107 | if exist "$(AppData)\Autodesk\REVIT\Addins\2020" copy "$(TargetDir)*" "$(AppData)\Autodesk\REVIT\Addins\2020\$(TargetName)\" 108 | 109 | ) 110 | 111 | 112 | -------------------------------------------------------------------------------- /src/RevitGraphQLCommand/Ui.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/RevitGraphQLCommand/Ui.xaml.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using Autodesk.Revit.UI; 3 | using RevitWebServer; 4 | using System; 5 | using System.Windows; 6 | 7 | namespace RevitGraphQLCommand 8 | { 9 | /// 10 | /// Interaction logic for UI.xaml 11 | /// 12 | public partial class Ui : Window 13 | { 14 | private readonly UIDocument _uiDoc; 15 | private readonly Document _doc; 16 | public WebServer aWebServer { get; set; } 17 | 18 | RevitTask aRevitTask; 19 | public Ui(UIApplication uiApp, RevitTask _aRevitTask) 20 | { 21 | _uiDoc = uiApp.ActiveUIDocument; 22 | _doc = _uiDoc.Document; 23 | 24 | Closed += MainWindow_Closed; 25 | 26 | InitializeComponent(); 27 | aRevitTask = _aRevitTask; 28 | 29 | } 30 | 31 | private void MainWindow_Closed(object sender, EventArgs e) 32 | { 33 | Close(); 34 | } 35 | 36 | private void CheckBox_Checked(object sender, RoutedEventArgs e) 37 | { 38 | aWebServer = new WebServer("localhost", txtPort.Text, _doc, _uiDoc, aRevitTask); 39 | aWebServer.Start(); 40 | } 41 | 42 | private void CheckBox_Unchecked(object sender, RoutedEventArgs e) 43 | { 44 | aWebServer.Stop(); 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/RevitGraphQLCommand/Util.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Threading; 4 | 5 | namespace RevitGraphQLCommand 6 | { 7 | public static class Util 8 | { 9 | public static void LogThreadInfo(string name = "") 10 | { 11 | Thread th = Thread.CurrentThread; 12 | Debug.WriteLine($"Task Thread ID: {th.ManagedThreadId}, Thread Name: {th.Name}, Process Name: {name}"); 13 | } 14 | 15 | public static void HandleError(Exception ex) 16 | { 17 | Debug.WriteLine(ex.Message); 18 | Debug.WriteLine(ex.Source); 19 | Debug.WriteLine(ex.StackTrace); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/RevitGraphQLCommand/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/RevitGraphQLCommand/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQL/GraphQLHelpers.cs: -------------------------------------------------------------------------------- 1 | using GraphQL; 2 | using GraphQL.Language.AST; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace RevitGraphQLResolver.GraphQL 7 | { 8 | public static class GraphQlHelpers 9 | { 10 | public static List GetArgumentStrings(Field aField, string name) 11 | { 12 | var nameFilterArgument = aField.Arguments?.FirstOrDefault(x => x.Name == name); 13 | List nameFilterStrings = new List(); 14 | if (nameFilterArgument != null) 15 | { 16 | nameFilterStrings = (nameFilterArgument.Value.Value as List).Select(x => x.ToString()).ToList(); 17 | } 18 | return nameFilterStrings; 19 | } 20 | public static double GetArgumentDouble(Field aField, string name) 21 | { 22 | var nameFilterArgument = aField.Arguments?.FirstOrDefault(x => x.Name == name); 23 | double argumentValueDouble = 0; 24 | if (nameFilterArgument != null) 25 | { 26 | argumentValueDouble = double.Parse(nameFilterArgument.Value.Value.ToString()); 27 | } 28 | return argumentValueDouble; 29 | } 30 | 31 | //public static Field GetFieldFromSelectionSet(Field aField, string name) 32 | //{ 33 | // return aField.SelectionSet.Children.FirstOrDefault(x => (x as Field).Name == name) as Field; 34 | //} 35 | //public static Field GetFieldFromContext(IResolveFieldContext context, string name) 36 | //{ 37 | // return context.SubFields.FirstOrDefault(x => x.Key == name).Value as Field; 38 | //} 39 | 40 | public static Field GetFieldFromFieldOrContext(object aFieldOrContext, string name) 41 | { 42 | //https://systemoutofmemory.com/blogs/the-programmer-blog/c-sharp-switch-on-type 43 | switch (aFieldOrContext) 44 | { 45 | case Field aField: 46 | return aField.SelectionSet.Children.FirstOrDefault(x => (x as Field).Name == name) as Field; 47 | case IResolveFieldContext aContext: 48 | return aContext.SubFields.FirstOrDefault(x => x.Key == name).Value as Field; 49 | default: 50 | return null; 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQL/GraphQLQuery.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | 3 | namespace RevitGraphQLResolver.GraphQL 4 | { 5 | public class GraphQLQuery 6 | { 7 | public string OperationName { get; set; } 8 | public string NamedQuery { get; set; } 9 | public string Query { get; set; } 10 | public JsonElement Variables { get; set; } 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQL/IQuery.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using RevitGraphQLResolver.GraphQLModel; 3 | using System.Collections.Generic; 4 | 5 | namespace RevitGraphQLResolver.GraphQl 6 | { 7 | public interface IQuery 8 | { 9 | List GetCategories(ResolveFieldContext context, string[] nameFilter = null); 10 | List GetFamilies(ResolveFieldContext context, string[] nameFilter = null); 11 | string GetHello(); 12 | List GetSchedules(ResolveFieldContext context); 13 | List GetSheets(ResolveFieldContext context); 14 | } 15 | } -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQL/Mutation.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using Autodesk.Revit.UI; 3 | using Autodesk.Revit.UI.Selection; 4 | using GraphQL; 5 | using GraphQL.Types; 6 | using RevitGraphQLResolver.GraphQLModel; 7 | using RevitGraphQLSchema.GraphQLModel; 8 | using RevitGraphQLSchema.IGraphQl; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace RevitGraphQLResolver.GraphQL 16 | { 17 | public class Mutation : ObjectGraphType, IMutation 18 | { 19 | [GraphQLMetadata("qlParameters")] 20 | public List UpdateParameters(IResolveFieldContext context, List input) 21 | { 22 | 23 | var _doc = ResolverEntry.Doc; 24 | var responseObject = new List(); 25 | 26 | ResolverEntry.aRevitTask.Run(app => 27 | { 28 | 29 | // we need a transaction to modify the model 30 | using (Transaction trans = new Transaction(_doc, "Change global parameters values")) 31 | { 32 | trans.Start(); 33 | 34 | foreach (var aUpdateParameter in input) 35 | { 36 | FamilyInstance aFamilyInstance = new FilteredElementCollector(_doc).OfClass(typeof(FamilyInstance)) 37 | .Select(x => (x as FamilyInstance)).FirstOrDefault(x => x.Id.ToString() == aUpdateParameter.instanceId); 38 | var aOne = _doc.GetElement(aUpdateParameter.instanceId); 39 | var aTwo = _doc.GetElement(aUpdateParameter.parameterId); 40 | if (aFamilyInstance != null) 41 | { 42 | foreach (Parameter aParameter in aFamilyInstance.Parameters) 43 | { 44 | if (aParameter.Id.ToString() == aUpdateParameter.parameterId) 45 | { 46 | if (!aParameter.IsReadOnly) 47 | { 48 | bool setSuccess = false; 49 | switch (aParameter.StorageType) 50 | { 51 | case StorageType.None: 52 | break; 53 | case StorageType.Integer: 54 | setSuccess = aParameter.Set(int.Parse(aUpdateParameter.updateValue)); 55 | break; 56 | case StorageType.Double: 57 | setSuccess = aParameter.Set(double.Parse(aUpdateParameter.updateValue)); 58 | break; 59 | case StorageType.String: 60 | setSuccess = aParameter.Set(aUpdateParameter.updateValue); 61 | break; 62 | case StorageType.ElementId: 63 | setSuccess = aParameter.Set(new ElementId(int.Parse(aUpdateParameter.updateValue))); 64 | break; 65 | default: 66 | break; 67 | } 68 | if (setSuccess) 69 | { 70 | responseObject.Add(new QLParameter() 71 | { 72 | id = aParameter.Id.ToString(), 73 | name = aParameter.Definition.Name, 74 | value = aParameter.AsValueString() == null ? aParameter.AsString() : aParameter.AsValueString(), 75 | userModifiable = aParameter.UserModifiable 76 | }); 77 | } 78 | } 79 | 80 | } 81 | } 82 | } 83 | } 84 | trans.Commit(); 85 | } 86 | 87 | }); 88 | 89 | return responseObject; 90 | 91 | } 92 | 93 | [GraphQLMetadata("qlElementSelection")] 94 | public QLElementCollection SetSelection(IResolveFieldContext context, List input) 95 | { 96 | Document _doc = ResolverEntry.Doc; 97 | UIDocument _uidoc = ResolverEntry.UiDoc; 98 | 99 | Selection selection = _uidoc.Selection; 100 | 101 | ICollection elementIds = selection.GetElementIds(); 102 | elementIds.Clear(); 103 | 104 | foreach(var aString in input) 105 | { 106 | elementIds.Add(new ElementId(int.Parse(aString))); 107 | } 108 | 109 | 110 | ResolverEntry.aRevitTask.Run(app => 111 | { 112 | if (elementIds.Count > 0) selection.SetElementIds(elementIds); 113 | }); 114 | 115 | //var qlFamilyInstancesField = GraphQlHelpers.GetFieldFromContext(context, "qlFamilyInstances"); 116 | //var qlFabricationPartsField = GraphQlHelpers.GetFieldFromContext(context, "qlFabricationParts"); 117 | 118 | QLElementCollection qlElementCollection = new QLElementCollectionResolve(elementIds, context); 119 | 120 | return qlElementCollection; 121 | } 122 | 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQL/MySchema.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using System; 3 | 4 | namespace RevitGraphQLResolver.GraphQL 5 | { 6 | public class MySchema 7 | { 8 | private ISchema _schema { get; set; } 9 | public ISchema GraphQLSchema 10 | { 11 | get 12 | { 13 | return this._schema; 14 | } 15 | } 16 | 17 | public MySchema() 18 | { 19 | try 20 | { 21 | this._schema = Schema.For(RevitGraphQLSchema.GraphQLSchema.schema, _ => 22 | { 23 | _.Types.Include(); 24 | _.Types.Include(); 25 | }); 26 | } 27 | catch(Exception e) 28 | { 29 | var m = e.Message; 30 | } 31 | } 32 | 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQL/Query.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using Autodesk.Revit.DB.Mechanical; 3 | using Autodesk.Revit.UI; 4 | using Autodesk.Revit.UI.Selection; 5 | using GraphQL; 6 | using GraphQL.Types; 7 | using RevitGraphQLResolver.GraphQLModel; 8 | using RevitGraphQLSchema.GraphQLModel; 9 | using RevitGraphQLSchema.IGraphQl; 10 | using System; 11 | using System.Collections.Concurrent; 12 | using System.Collections.Generic; 13 | using System.Linq; 14 | using System.Text; 15 | 16 | namespace RevitGraphQLResolver.GraphQL 17 | { 18 | public class Query : ObjectGraphType, IQuery 19 | { 20 | 21 | 22 | [GraphQLMetadata("hello")] 23 | public string GetHello() 24 | { 25 | return ResolverEntry.Doc.PathName; 26 | } 27 | 28 | [GraphQLMetadata("sheets")] 29 | public List GetSheets(IResolveFieldContext context) 30 | { 31 | Document _doc = ResolverEntry.Doc; 32 | 33 | var sheetList = new FilteredElementCollector(_doc) 34 | .OfClass(typeof(ViewSheet)) 35 | .Select(p => (ViewSheet)p).ToList(); 36 | 37 | var stringList = sheetList.Select(x => $"{x.Name} (ID: {x.Id})").OrderBy(x => x).ToList(); 38 | 39 | return stringList; 40 | } 41 | 42 | [GraphQLMetadata("phases")] 43 | public List GetPhases(IResolveFieldContext context) 44 | { 45 | Document _doc = ResolverEntry.Doc; 46 | 47 | List returnObject = new List(); 48 | foreach(Phase aPhase in _doc.Phases) 49 | { 50 | returnObject.Add($"{aPhase.Name} (ID: {aPhase.Id})"); 51 | } 52 | 53 | return returnObject.OrderBy(x => x).ToList(); 54 | } 55 | 56 | [GraphQLMetadata("qlViewSchedules")] 57 | public List GetViewSchedules(IResolveFieldContext context, string[] nameFilter = null) 58 | { 59 | 60 | Document _doc = ResolverEntry.Doc; 61 | var scheduleList = new FilteredElementCollector(_doc).OfClass(typeof(ViewSchedule)).Select(p => (ViewSchedule)p).Where(x=>!x.Name.Contains("Revision Schedule")).ToList(); 62 | 63 | var nameFilterStrings = nameFilter != null ? nameFilter.ToList() : new List(); 64 | //var qlViewScheduleData = GraphQlHelpers.GetFieldFromContext(context, "qlViewScheduleData"); 65 | 66 | var returnObject = new ConcurrentBag(); 67 | 68 | //Parallel.ForEach(objectList, aFamily => 69 | foreach (var aViewSchedule in scheduleList) 70 | { 71 | if (nameFilterStrings.Count == 0 || nameFilterStrings.Contains(aViewSchedule.Name)) 72 | { 73 | var qlViewScheudle = new QLViewScheduleResolve(aViewSchedule, context); 74 | returnObject.Add(qlViewScheudle); 75 | } 76 | } 77 | return returnObject.OrderBy(x => x.name).ToList(); 78 | } 79 | 80 | [GraphQLMetadata("qlFamilies")] 81 | public List GetFamilies(IResolveFieldContext context, string[] nameFilter = null) 82 | { 83 | 84 | Document _doc = ResolverEntry.Doc; 85 | 86 | List objectList = new FilteredElementCollector(_doc).OfClass(typeof(Family)).Select(x => (x as Family)).ToList(); 87 | 88 | var nameFilterStrings = nameFilter != null ? nameFilter.ToList() : new List(); 89 | //var qlFamilySymbolsField = GraphQlHelpers.GetFieldFromContext(context, "qlFamilySymbols"); 90 | //var qlFamilyInstancesField = GraphQlHelpers.GetFieldFromContext(context, "qlFamilyInstances"); 91 | 92 | var returnObject = new ConcurrentBag(); 93 | 94 | //Parallel.ForEach(objectList, aFamily => 95 | foreach(var aFamily in objectList) 96 | { 97 | if (nameFilterStrings.Count == 0 || nameFilterStrings.Contains(aFamily.Name)) 98 | { 99 | //var qlFamily = new QLFamilyResolve(aFamily, qlFamilySymbolsField, qlFamilyInstancesField); 100 | var qlFamily = new QLFamilyResolve(aFamily, context); 101 | returnObject.Add(qlFamily); 102 | } 103 | } 104 | return returnObject.OrderBy(x => x.name).ToList(); 105 | 106 | } 107 | 108 | [GraphQLMetadata("qlElementSelection")] 109 | public QLElementCollection GetSelection(IResolveFieldContext context, string[] nameFilter = null) 110 | { 111 | Document _doc = ResolverEntry.Doc; 112 | UIDocument _uidoc = ResolverEntry.UiDoc; 113 | 114 | Selection selection = _uidoc.Selection; 115 | //var qlFamilyInstancesField = GraphQlHelpers.GetFieldFromContext(context, "qlFamilyInstances"); 116 | //var qlFabricationPartsField = GraphQlHelpers.GetFieldFromContext(context, "qlFabricationParts"); 117 | 118 | ICollection elementIds = selection.GetElementIds(); 119 | //QLElementCollection qlElementCollection = new QLElementCollectionResolve(elementIds, qlFamilyInstancesField, qlFabricationPartsField); 120 | QLElementCollection qlElementCollection = new QLElementCollectionResolve(elementIds, context); 121 | 122 | return qlElementCollection; 123 | } 124 | 125 | [GraphQLMetadata("qlFamilyCategories")] 126 | public List GetCategories(IResolveFieldContext context, string[] nameFilter = null) 127 | { 128 | 129 | Document _doc = ResolverEntry.Doc; 130 | 131 | List objectList = new FilteredElementCollector(_doc).OfClass(typeof(Family)).Select(x => (x as Family).FamilyCategory).GroupBy(x => x.Id.ToString()).Select(x => x.First()).ToList(); 132 | //var stringList = objectList.Select(x => x.Name).OrderBy(x => x).Distinct().ToList(); 133 | //https://thebuildingcoder.typepad.com/blog/2010/05/categories.html 134 | //var objectList = _doc.Settings.Categories; 135 | 136 | var nameFilterStrings = nameFilter != null ? nameFilter.ToList() : new List(); 137 | //var qlFamiliesField = GraphQlHelpers.GetFieldFromContext(context, "qlFamilies"); 138 | //var qlFamilyInstancesField = GraphQlHelpers.GetFieldFromContext(context, "qlFamilyInstances"); 139 | 140 | 141 | var returnObject = new ConcurrentBag(); 142 | 143 | //Parallel.ForEach(stringList, aFamilyCategoryName => 144 | foreach(Category aCategory in objectList) 145 | { 146 | if (nameFilterStrings.Count == 0 || nameFilterStrings.Contains(aCategory.Name)) 147 | { 148 | var qlFamilyCategory = new QLFamilyCategoryResolve(aCategory, context); 149 | returnObject.Add(qlFamilyCategory); 150 | } 151 | } 152 | return returnObject.OrderBy(x => x.name).ToList(); 153 | 154 | } 155 | 156 | [GraphQLMetadata("qlMepSystems")] 157 | public List GetMepSystems(IResolveFieldContext context, string[] nameFilter = null) 158 | { 159 | 160 | Document _doc = ResolverEntry.Doc; 161 | 162 | //https://github.com/jeremytammik/TraverseAllSystems/blob/master/TraverseAllSystems/Command.cs 163 | var objectList = new FilteredElementCollector(_doc).OfClass(typeof(MEPSystem)); //.Select(x=>x as MEPSystem).ToList(); 164 | 165 | var nameFilterStrings = nameFilter != null ? nameFilter.ToList() : new List(); 166 | 167 | 168 | var returnObject = new ConcurrentBag(); 169 | 170 | //Parallel.ForEach(stringList, aFamilyCategoryName => 171 | foreach (MEPSystem aMepSystem in objectList) 172 | { 173 | if (nameFilterStrings.Count == 0 || nameFilterStrings.Contains(aMepSystem.Name)) 174 | { 175 | var qlMepSystem = new QLMepSystemResolve(aMepSystem); 176 | returnObject.Add(qlMepSystem); 177 | } 178 | } 179 | return returnObject.OrderBy(x => x.name).ToList(); 180 | 181 | } 182 | 183 | [GraphQLMetadata("qlAssemblies")] 184 | public List GetAssemblies(IResolveFieldContext context, string[] nameFilter = null) 185 | { 186 | 187 | Document _doc = ResolverEntry.Doc; 188 | 189 | //https://github.com/jeremytammik/TraverseAllSystems/blob/master/TraverseAllSystems/Command.cs 190 | var objectList = new FilteredElementCollector(_doc).OfClass(typeof(AssemblyInstance)); //.Select(x=>x as MEPSystem).ToList(); 191 | 192 | var nameFilterStrings = nameFilter != null ? nameFilter.ToList() : new List(); 193 | var qlFieldViews = GraphQlHelpers.GetFieldFromFieldOrContext(context, "hasViews"); 194 | //var qlElementCollectionField = GraphQlHelpers.GetFieldFromContext(context, "qlElementCollection"); 195 | 196 | List viewListing = null; 197 | if (qlFieldViews!=null) 198 | { 199 | viewListing = new FilteredElementCollector(ResolverEntry.Doc) 200 | .OfCategory(BuiltInCategory.OST_Views) 201 | .WhereElementIsNotElementType() 202 | .Cast().ToList(); 203 | } 204 | 205 | var returnObject = new ConcurrentBag(); 206 | 207 | //Parallel.ForEach(stringList, aFamilyCategoryName => 208 | foreach (AssemblyInstance aAssembly in objectList) 209 | { 210 | if (nameFilterStrings.Count == 0 || nameFilterStrings.Contains(aAssembly.Name)) 211 | { 212 | //var qlMepSystem = new QLAssemblyResolve(aAssembly, qlFieldViews, viewListing, qlElementCollectionField); 213 | var qlMepSystem = new QLAssemblyResolve(aAssembly, viewListing, context); 214 | returnObject.Add(qlMepSystem); 215 | } 216 | } 217 | return returnObject.OrderBy(x => x.name).ToList(); 218 | 219 | } 220 | 221 | [GraphQLMetadata("qlFabricationServices")] 222 | public List GetFabServices(IResolveFieldContext context, string[] nameFilter = null) 223 | { 224 | 225 | Document _doc = ResolverEntry.Doc; 226 | 227 | var stuff = ResolverEntry.aRevitTask.Run>(app => 228 | { 229 | 230 | 231 | var fabricationConfiguration = FabricationConfiguration.GetFabricationConfiguration(_doc); 232 | var objectList = fabricationConfiguration.GetAllServices(); 233 | 234 | var nameFilterStrings = nameFilter != null ? nameFilter.ToList() : new List(); 235 | //var qlFabricationPartsField = GraphQlHelpers.GetFieldFromContext(context, "qlFabricationParts"); 236 | 237 | 238 | var returnObject = new ConcurrentBag(); 239 | 240 | //Parallel.ForEach(stringList, aFamilyCategoryName => 241 | foreach (var aFabricationService in objectList) 242 | { 243 | if (nameFilterStrings.Count == 0 || nameFilterStrings.Contains(aFabricationService.Name)) 244 | { 245 | var qlFabricationService = new QLFabricationServiceResolve(aFabricationService, context); 246 | returnObject.Add(qlFabricationService); 247 | } 248 | } 249 | return returnObject.OrderBy(x => x.name).ToList(); 250 | }).Result; 251 | 252 | return stuff; 253 | } 254 | 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/IQLFamily.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RevitGraphQLResolver.GraphQLModel 4 | { 5 | public interface IQLFamily 6 | { 7 | string id { get; set; } 8 | string name { get; set; } 9 | List qlFamilySymbols { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/IQLFamilyCategory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RevitGraphQLResolver.GraphQLModel 4 | { 5 | public interface IQLFamilyCategory 6 | { 7 | string name { get; set; } 8 | List qlFamilies { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/IQLFamilySymbol.cs: -------------------------------------------------------------------------------- 1 | namespace RevitGraphQLResolver.GraphQLModel 2 | { 3 | public interface IQLFamilySymbol 4 | { 5 | string id { get; set; } 6 | string name { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/QLAssemblyResolve.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using GraphQL.Language.AST; 3 | using RevitGraphQLResolver.GraphQL; 4 | using RevitGraphQLSchema.GraphQLModel; 5 | using System.Collections.Concurrent; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace RevitGraphQLResolver.GraphQLModel 10 | { 11 | public class QLAssemblyResolve : QLAssembly 12 | { 13 | 14 | public QLAssemblyResolve(AssemblyInstance _assembly, List viewListing, object aFieldOrContext) 15 | { 16 | id = _assembly.Id.ToString(); 17 | name = _assembly.Name; 18 | 19 | var qlFieldViews = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "hasViews"); 20 | if (qlFieldViews != null && viewListing != null) 21 | { 22 | hasViews = viewListing.Any(v => v.AssociatedAssemblyInstanceId.IntegerValue == _assembly.Id.IntegerValue); 23 | } 24 | 25 | var queryFieldForElementCollection = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "qlElementCollection"); 26 | if (queryFieldForElementCollection != null) 27 | { 28 | //var qlFamilyInstancesField = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForEllementCollection, "qlFamilyInstances"); 29 | //var qlFabricationPartsField = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForEllementCollection, "qlFabricationParts"); 30 | ICollection elementIds = _assembly.GetMemberIds(); 31 | //qlElementCollection = new QLElementCollectionResolve(elementIds, qlFamilyInstancesField, qlFabricationPartsField); 32 | qlElementCollection = new QLElementCollectionResolve(elementIds, queryFieldForElementCollection); 33 | } 34 | 35 | } 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/QLElementCollectionResolve.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using GraphQL.Language.AST; 3 | using RevitGraphQLResolver.GraphQL; 4 | using RevitGraphQLSchema.GraphQLModel; 5 | using System.Collections.Concurrent; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace RevitGraphQLResolver.GraphQLModel 10 | { 11 | public class QLElementCollectionResolve : QLElementCollection 12 | { 13 | 14 | //public QLElementCollectionResolve(ICollection _ids, Field queryFieldForFamilyInstances, Field queryFieldForFabricationParts) 15 | //{ 16 | // elementIds = _ids.Select(x=>x.ToString()).ToList(); 17 | 18 | // if (queryFieldForFamilyInstances != null || queryFieldForFabricationParts != null) 19 | // { 20 | 21 | // var _doc = ResolverEntry.Doc; 22 | 23 | // var returnFamilyInstancesObject = new ConcurrentBag(); 24 | // var returnFabricationPartsObject = new ConcurrentBag(); 25 | 26 | 27 | // foreach (var aId in _ids) 28 | // { 29 | // var aElement = _doc.GetElement(aId); 30 | // if (aElement == null) 31 | // { 32 | 33 | // } 34 | // else 35 | // { 36 | // if (aElement is FamilyInstance && queryFieldForFamilyInstances != null) 37 | // { 38 | // var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(queryFieldForFamilyInstances, "nameFilter"); 39 | // var queryFieldForParameters = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForFamilyInstances, "qlParameters"); 40 | // if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(aElement.Name)) 41 | // { 42 | // returnFamilyInstancesObject.Add(new QLFamilyInstanceResolve(aElement as FamilyInstance, queryFieldForParameters)); 43 | // } 44 | // } 45 | // if (aElement is FabricationPart && queryFieldForFabricationParts != null) 46 | // { 47 | // var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(queryFieldForFabricationParts, "nameFilter"); 48 | // var queryFieldForParameters = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForFabricationParts, "qlParameters"); 49 | // if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(aElement.Name)) 50 | // { 51 | // returnFabricationPartsObject.Add(new QLFabricationPartResolve(aElement as FabricationPart, queryFieldForParameters)); 52 | // } 53 | // } 54 | // } 55 | // } 56 | 57 | // qlFamilyInstances = returnFamilyInstancesObject.OrderBy(x => x.name).ToList(); 58 | // qlFabricationParts = returnFabricationPartsObject.OrderBy(x => x.name).ToList(); 59 | // } 60 | 61 | //} 62 | 63 | public QLElementCollectionResolve(ICollection _ids, object aFieldOrContext) 64 | { 65 | elementIds = _ids.Select(x=>x.ToString()).ToList(); 66 | 67 | var queryFieldForFamilyInstances = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "qlFamilyInstances"); 68 | var queryFieldForFabricationParts = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "qlFabricationParts"); 69 | 70 | 71 | if (queryFieldForFamilyInstances != null || queryFieldForFabricationParts != null) 72 | { 73 | 74 | var _doc = ResolverEntry.Doc; 75 | 76 | var returnFamilyInstancesObject = new ConcurrentBag(); 77 | var returnFabricationPartsObject = new ConcurrentBag(); 78 | 79 | 80 | foreach (var aId in _ids) 81 | { 82 | var aElement = _doc.GetElement(aId); 83 | if (aElement == null) 84 | { 85 | 86 | } 87 | else 88 | { 89 | if (aElement is FamilyInstance && queryFieldForFamilyInstances != null) 90 | { 91 | var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(queryFieldForFamilyInstances, "nameFilter"); 92 | //var queryFieldForParameters = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForFamilyInstances, "qlParameters"); 93 | if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(aElement.Name)) 94 | { 95 | //returnFamilyInstancesObject.Add(new QLFamilyInstanceResolve(aElement as FamilyInstance, queryFieldForParameters)); 96 | returnFamilyInstancesObject.Add(new QLFamilyInstanceResolve(aElement as FamilyInstance, queryFieldForFamilyInstances)); 97 | } 98 | } 99 | if (aElement is FabricationPart && queryFieldForFabricationParts != null) 100 | { 101 | var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(queryFieldForFabricationParts, "nameFilter"); 102 | //var queryFieldForParameters = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForFabricationParts, "qlParameters"); 103 | if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(aElement.Name)) 104 | { 105 | //returnFabricationPartsObject.Add(new QLFabricationPartResolve(aElement as FabricationPart, queryFieldForParameters)); 106 | returnFabricationPartsObject.Add(new QLFabricationPartResolve(aElement as FabricationPart, queryFieldForFabricationParts)); 107 | } 108 | } 109 | } 110 | } 111 | 112 | qlFamilyInstances = returnFamilyInstancesObject.OrderBy(x => x.name).ToList(); 113 | qlFabricationParts = returnFabricationPartsObject.OrderBy(x => x.name).ToList(); 114 | } 115 | 116 | } 117 | 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/QLFabricationPartResolve.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using GraphQL.Language.AST; 3 | using RevitGraphQLResolver.GraphQL; 4 | using RevitGraphQLSchema.GraphQLModel; 5 | using System.Collections.Concurrent; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace RevitGraphQLResolver.GraphQLModel 10 | { 11 | public class QLFabricationPartResolve : QLFabricationPart 12 | { 13 | 14 | public QLFabricationPartResolve() 15 | { 16 | 17 | } 18 | //public QLFabricationPartResolve(FabricationPart _fabricationPart, Field queryFieldForParameters) 19 | //{ 20 | // id = _fabricationPart.Id.ToString(); 21 | // name = _fabricationPart.Name; 22 | 23 | // if (queryFieldForParameters != null) 24 | // { 25 | 26 | // var returnElementsObject = new ConcurrentBag(); 27 | 28 | // var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(queryFieldForParameters, "nameFilter"); 29 | 30 | // var _doc = ResolverEntry.Doc; 31 | // ParameterSet objectList = _fabricationPart.Parameters; 32 | 33 | // //Parallel.ForEach(objectList, x => 34 | // foreach (Parameter x in objectList) 35 | // { 36 | // if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(x.Definition.Name)) 37 | // { 38 | // returnElementsObject.Add(new QLParameter() 39 | // { 40 | // id = x.Id.ToString(), 41 | // name = x.Definition.Name, 42 | // value = x.AsValueString() == null ? x.AsString() : x.AsValueString(), 43 | // userModifiable = x.UserModifiable, 44 | // isReadOnly = x.IsReadOnly 45 | // }); 46 | // } 47 | // } 48 | 49 | // qlParameters = returnElementsObject.OrderBy(x => x.name).ToList(); 50 | // } 51 | 52 | //} 53 | public QLFabricationPartResolve(FabricationPart _fabricationPart, object aFieldOrContext) 54 | { 55 | id = _fabricationPart.Id.ToString(); 56 | name = _fabricationPart.Name; 57 | 58 | var queryFieldForParameters = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "qlParameters"); 59 | 60 | if (queryFieldForParameters != null) 61 | { 62 | 63 | var returnElementsObject = new ConcurrentBag(); 64 | 65 | var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(queryFieldForParameters, "nameFilter"); 66 | 67 | var _doc = ResolverEntry.Doc; 68 | ParameterSet objectList = _fabricationPart.Parameters; 69 | 70 | //Parallel.ForEach(objectList, x => 71 | foreach (Parameter x in objectList) 72 | { 73 | if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(x.Definition.Name)) 74 | { 75 | returnElementsObject.Add(new QLParameter() 76 | { 77 | id = x.Id.ToString(), 78 | name = x.Definition.Name, 79 | value = x.AsValueString() == null ? x.AsString() : x.AsValueString(), 80 | userModifiable = x.UserModifiable, 81 | isReadOnly = x.IsReadOnly 82 | }); 83 | } 84 | } 85 | 86 | qlParameters = returnElementsObject.OrderBy(x => x.name).ToList(); 87 | } 88 | 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/QLFabricationServiceResolve.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using GraphQL.Language.AST; 3 | using RevitGraphQLResolver.GraphQL; 4 | using RevitGraphQLSchema.GraphQLModel; 5 | using System.Collections.Concurrent; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace RevitGraphQLResolver.GraphQLModel 10 | { 11 | public class QLFabricationServiceResolve : QLFabricationService 12 | { 13 | 14 | //public QLFabricationServiceResolve(FabricationService _fabService, Field qlFabricationPartsField) 15 | //{ 16 | 17 | // id = _fabService.ServiceId.ToString(); 18 | // name = _fabService.Name; 19 | 20 | // if(qlFabricationPartsField != null) 21 | // { 22 | // Autodesk.Revit.DB.Document _doc = ResolverEntry.Doc; 23 | 24 | // List objectList = new FilteredElementCollector(_doc).OfClass(typeof(FabricationPart)). 25 | // Select(x => (x as FabricationPart)).Where(x=>x.ServiceId.ToString()==id).ToList(); 26 | 27 | // var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(qlFabricationPartsField, "nameFilter"); 28 | // //var queryFieldForParameters = GraphQlHelpers.GetFieldFromSelectionSet(qlFabricationPartsField, "qlParameters"); 29 | 30 | // qlFabricationParts = new List(); 31 | // foreach(FabricationPart aFabPart in objectList) 32 | // { 33 | // if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(aFabPart.Name)) 34 | // { 35 | 36 | // qlFabricationParts.Add(new QLFabricationPartResolve(aFabPart, qlFabricationPartsField)); 37 | // } 38 | // } 39 | // } 40 | 41 | //} 42 | 43 | public QLFabricationServiceResolve(FabricationService _fabService, object aFieldOrContext) 44 | { 45 | 46 | id = _fabService.ServiceId.ToString(); 47 | name = _fabService.Name; 48 | 49 | 50 | var qlFabricationPartsField = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "qlFabricationParts"); 51 | if (qlFabricationPartsField != null) 52 | { 53 | Autodesk.Revit.DB.Document _doc = ResolverEntry.Doc; 54 | 55 | List objectList = new FilteredElementCollector(_doc).OfClass(typeof(FabricationPart)). 56 | Select(x => (x as FabricationPart)).Where(x=>x.ServiceId.ToString()==id).ToList(); 57 | 58 | var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(qlFabricationPartsField, "nameFilter"); 59 | //var queryFieldForParameters = GraphQlHelpers.GetFieldFromSelectionSet(qlFabricationPartsField, "qlParameters"); 60 | 61 | qlFabricationParts = new List(); 62 | foreach(FabricationPart aFabPart in objectList) 63 | { 64 | if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(aFabPart.Name)) 65 | { 66 | 67 | qlFabricationParts.Add(new QLFabricationPartResolve(aFabPart, qlFabricationPartsField)); 68 | } 69 | } 70 | } 71 | 72 | } 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/QLFamilyCategoryResolve.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using GraphQL.Language.AST; 3 | using RevitGraphQLResolver.GraphQL; 4 | using RevitGraphQLSchema.GraphQLModel; 5 | using System.Collections.Concurrent; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace RevitGraphQLResolver.GraphQLModel 10 | { 11 | public class QLFamilyCategoryResolve : QLFamilyCategory 12 | { 13 | public QLFamilyCategoryResolve() 14 | { 15 | 16 | } 17 | 18 | //public QLFamilyCategoryResolve(Category aCategory, Field queryFieldForFamilies, Field qlFamilyInstancesField) 19 | //{ 20 | // id = aCategory.Id.ToString(); 21 | // name = aCategory.Name; 22 | 23 | // if (queryFieldForFamilies != null) 24 | // { 25 | 26 | // var returnElementsObject = new ConcurrentBag(); 27 | 28 | // var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(queryFieldForFamilies, "nameFilter"); 29 | // //var queryFieldForFamilySymbols = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForFamilies, "qlFamilySymbols"); 30 | // //var queryFieldForFamily2Instances = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForFamilies, "qlFamilyInstances"); 31 | 32 | // var _doc = ResolverEntry.Doc; 33 | // List objectList = new FilteredElementCollector(_doc).OfClass(typeof(Family)).Select(x => (x as Family)).Where(x => x.FamilyCategory.Id.ToString() == id).ToList(); 34 | 35 | // //Parallel.ForEach(objectList, x => 36 | // foreach(var x in objectList) 37 | // { 38 | // if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(x.Name)) 39 | // { 40 | // //returnElementsObject.Add(new QLFamilyResolve(x, queryFieldForFamilySymbols, queryFieldForFamily2Instances)); 41 | // returnElementsObject.Add(new QLFamilyResolve(x, queryFieldForFamilies)); 42 | // } 43 | // } 44 | 45 | 46 | 47 | // qlFamilies = returnElementsObject.OrderBy(x => x.name).ToList(); 48 | 49 | // } 50 | 51 | // if (qlFamilyInstancesField != null) 52 | // { 53 | 54 | // var returnElementsObject = new ConcurrentBag(); 55 | 56 | // var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(qlFamilyInstancesField, "nameFilter"); 57 | // //var queryFieldForParameters = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForFamilies, "qlParameters"); 58 | 59 | // var _doc = ResolverEntry.Doc; 60 | // List objectList = new FilteredElementCollector(_doc).OfClass(typeof(FamilyInstance)) 61 | // .Select(x => (x as FamilyInstance)).Where(x => x.Symbol.Family.FamilyCategory.Id.ToString() == id).ToList(); 62 | 63 | // //Parallel.ForEach(objectList, x => 64 | // foreach (var x in objectList) 65 | // { 66 | // if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(x.Name)) 67 | // { 68 | // returnElementsObject.Add(new QLFamilyInstanceResolve(x, queryFieldForFamilies)); 69 | // } 70 | // } 71 | 72 | // qlFamilyInstances = returnElementsObject.OrderBy(x => x.name).ToList(); 73 | // } 74 | 75 | //} 76 | public QLFamilyCategoryResolve(Category aCategory, object aFieldOrContext) 77 | { 78 | id = aCategory.Id.ToString(); 79 | name = aCategory.Name; 80 | 81 | var queryFieldForFamilies = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "qlFamilies"); 82 | if (queryFieldForFamilies != null) 83 | { 84 | 85 | var returnElementsObject = new ConcurrentBag(); 86 | 87 | var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(queryFieldForFamilies, "nameFilter"); 88 | //var queryFieldForFamilySymbols = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForFamilies, "qlFamilySymbols"); 89 | //var queryFieldForFamily2Instances = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForFamilies, "qlFamilyInstances"); 90 | 91 | var _doc = ResolverEntry.Doc; 92 | List objectList = new FilteredElementCollector(_doc).OfClass(typeof(Family)).Select(x => (x as Family)).Where(x => x.FamilyCategory.Id.ToString() == id).ToList(); 93 | 94 | //Parallel.ForEach(objectList, x => 95 | foreach(var x in objectList) 96 | { 97 | if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(x.Name)) 98 | { 99 | //returnElementsObject.Add(new QLFamilyResolve(x, queryFieldForFamilySymbols, queryFieldForFamily2Instances)); 100 | returnElementsObject.Add(new QLFamilyResolve(x, queryFieldForFamilies)); 101 | } 102 | } 103 | 104 | 105 | 106 | qlFamilies = returnElementsObject.OrderBy(x => x.name).ToList(); 107 | 108 | } 109 | 110 | var qlFamilyInstancesField = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "qlFamilyInstances"); 111 | if (qlFamilyInstancesField != null) 112 | { 113 | 114 | var returnElementsObject = new ConcurrentBag(); 115 | 116 | var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(qlFamilyInstancesField, "nameFilter"); 117 | //var queryFieldForParameters = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForFamilies, "qlParameters"); 118 | 119 | var _doc = ResolverEntry.Doc; 120 | List objectList = new FilteredElementCollector(_doc).OfClass(typeof(FamilyInstance)) 121 | .Select(x => (x as FamilyInstance)).Where(x => x.Symbol.Family.FamilyCategory.Id.ToString() == id).ToList(); 122 | 123 | //Parallel.ForEach(objectList, x => 124 | foreach (var x in objectList) 125 | { 126 | if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(x.Name)) 127 | { 128 | returnElementsObject.Add(new QLFamilyInstanceResolve(x, queryFieldForFamilies)); 129 | } 130 | } 131 | 132 | qlFamilyInstances = returnElementsObject.OrderBy(x => x.name).ToList(); 133 | } 134 | 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/QLFamilyInstanceResolve.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using GraphQL.Language.AST; 3 | using RevitGraphQLResolver.GraphQL; 4 | using RevitGraphQLSchema.GraphQLModel; 5 | using System.Collections.Concurrent; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace RevitGraphQLResolver.GraphQLModel 10 | { 11 | public class QLFamilyInstanceResolve : QLFamilyInstance 12 | { 13 | 14 | public QLFamilyInstanceResolve() 15 | { 16 | 17 | } 18 | //public QLFamilyInstanceResolve(FamilyInstance _familyInstance, Field queryFieldForParameters) 19 | //{ 20 | // id = _familyInstance.Id.ToString(); 21 | // name = _familyInstance.Name; 22 | 23 | // if (queryFieldForParameters != null) 24 | // { 25 | 26 | // var returnElementsObject = new ConcurrentBag(); 27 | 28 | // var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(queryFieldForParameters, "nameFilter"); 29 | 30 | // var _doc = ResolverEntry.Doc; 31 | // ParameterSet objectList = _familyInstance.Parameters; 32 | 33 | // //Parallel.ForEach(objectList, x => 34 | // foreach (Parameter x in objectList) 35 | // { 36 | // if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(x.Definition.Name)) 37 | // { 38 | // returnElementsObject.Add(new QLParameter() 39 | // { 40 | // id = x.Id.ToString(), 41 | // name = x.Definition.Name, 42 | // value = x.AsValueString() == null ? x.AsString() : x.AsValueString(), 43 | // userModifiable = x.UserModifiable, 44 | // isReadOnly = x.IsReadOnly 45 | // }); 46 | // } 47 | // } 48 | 49 | // qlParameters = returnElementsObject.OrderBy(x => x.name).ToList(); 50 | // } 51 | 52 | //} 53 | public QLFamilyInstanceResolve(FamilyInstance _familyInstance, object aFieldOrContext) 54 | { 55 | id = _familyInstance.Id.ToString(); 56 | name = _familyInstance.Name; 57 | 58 | var queryFieldForParameters = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "qlParameters"); 59 | 60 | if (queryFieldForParameters != null) 61 | { 62 | 63 | var returnElementsObject = new ConcurrentBag(); 64 | 65 | var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(queryFieldForParameters, "nameFilter"); 66 | 67 | var _doc = ResolverEntry.Doc; 68 | ParameterSet objectList = _familyInstance.Parameters; 69 | 70 | //Parallel.ForEach(objectList, x => 71 | foreach (Parameter x in objectList) 72 | { 73 | if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(x.Definition.Name)) 74 | { 75 | returnElementsObject.Add(new QLParameter() 76 | { 77 | id = x.Id.ToString(), 78 | name = x.Definition.Name, 79 | value = x.AsValueString() == null ? x.AsString() : x.AsValueString(), 80 | userModifiable = x.UserModifiable, 81 | isReadOnly = x.IsReadOnly 82 | }); 83 | } 84 | } 85 | 86 | qlParameters = returnElementsObject.OrderBy(x => x.name).ToList(); 87 | } 88 | 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/QLFamilyResolve.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using GraphQL.Language.AST; 3 | using RevitGraphQLResolver.GraphQL; 4 | using RevitGraphQLSchema.GraphQLModel; 5 | using System.Collections.Concurrent; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace RevitGraphQLResolver.GraphQLModel 10 | { 11 | public class QLFamilyResolve : QLFamily 12 | { 13 | 14 | public QLFamilyResolve() 15 | { 16 | 17 | } 18 | //public QLFamilyResolve(Family _family, Field queryFieldForFamilySymbols, Field queryFieldForFamilyInstances) 19 | //{ 20 | // id = _family.Id.ToString(); 21 | // name = _family.Name; 22 | 23 | // if (queryFieldForFamilySymbols != null) 24 | // { 25 | // var returnElementsObject = new ConcurrentBag(); 26 | 27 | // var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(queryFieldForFamilySymbols, "nameFilter"); 28 | // var queryFieldForFamily2Instances = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForFamilySymbols, "qlFamilyInstances"); 29 | 30 | // var _doc = ResolverEntry.Doc; 31 | // List objectList = new FilteredElementCollector(_doc).OfClass(typeof(FamilySymbol)) 32 | // .Select(x => (x as FamilySymbol)).Where(x => x.Family.Id.ToString() == id).ToList(); 33 | 34 | // //Parallel.ForEach(objectList, x => 35 | // foreach(var x in objectList) 36 | // { 37 | // if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(x.Name)) 38 | // { 39 | // returnElementsObject.Add(new QLFamilySymbolResolve(x, queryFieldForFamily2Instances)); 40 | // } 41 | // } 42 | 43 | // qlFamilySymbols = returnElementsObject.OrderBy(x => x.name).ToList(); 44 | 45 | // } 46 | 47 | // if(queryFieldForFamilyInstances!=null) 48 | // { 49 | 50 | // var returnElementsObject = new ConcurrentBag(); 51 | 52 | // var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(queryFieldForFamilyInstances, "nameFilter"); 53 | // var queryFieldForParameters = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForFamilyInstances, "qlParameters"); 54 | 55 | // var _doc = ResolverEntry.Doc; 56 | // List objectList = new FilteredElementCollector(_doc).OfClass(typeof(FamilyInstance)) 57 | // .Select(x => (x as FamilyInstance)).Where(x => x.Symbol.Family.Id.ToString() == id).ToList(); 58 | 59 | // //Parallel.ForEach(objectList, x => 60 | // foreach(var x in objectList) 61 | // { 62 | // if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(x.Name)) 63 | // { 64 | // returnElementsObject.Add(new QLFamilyInstanceResolve(x, queryFieldForParameters)); 65 | // } 66 | // } 67 | 68 | // qlFamilyInstances = returnElementsObject.OrderBy(x => x.name).ToList(); 69 | // } 70 | //} 71 | public QLFamilyResolve(Family _family, object aFieldOrContext) 72 | { 73 | id = _family.Id.ToString(); 74 | name = _family.Name; 75 | 76 | var qlFamilySymbolsField = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "qlFamilySymbols"); 77 | if (qlFamilySymbolsField != null) 78 | { 79 | var returnElementsObject = new ConcurrentBag(); 80 | 81 | var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(qlFamilySymbolsField, "nameFilter"); 82 | //var queryFieldForFamily2Instances = GraphQlHelpers.GetFieldFromSelectionSet(qlFamilySymbolsField, "qlFamilyInstances"); 83 | 84 | var _doc = ResolverEntry.Doc; 85 | List objectList = new FilteredElementCollector(_doc).OfClass(typeof(FamilySymbol)) 86 | .Select(x => (x as FamilySymbol)).Where(x => x.Family.Id.ToString() == id).ToList(); 87 | 88 | //Parallel.ForEach(objectList, x => 89 | foreach(var x in objectList) 90 | { 91 | if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(x.Name)) 92 | { 93 | //returnElementsObject.Add(new QLFamilySymbolResolve(x, queryFieldForFamily2Instances)); 94 | returnElementsObject.Add(new QLFamilySymbolResolve(x, qlFamilySymbolsField)); 95 | } 96 | } 97 | 98 | qlFamilySymbols = returnElementsObject.OrderBy(x => x.name).ToList(); 99 | 100 | } 101 | 102 | var qlFamilyInstancesField = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "qlFamilyInstances"); 103 | if (qlFamilyInstancesField != null) 104 | { 105 | 106 | var returnElementsObject = new ConcurrentBag(); 107 | 108 | var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(qlFamilyInstancesField, "nameFilter"); 109 | //var queryFieldForParameters = GraphQlHelpers.GetFieldFromSelectionSet(qlFamilyInstancesField, "qlParameters"); 110 | 111 | var _doc = ResolverEntry.Doc; 112 | List objectList = new FilteredElementCollector(_doc).OfClass(typeof(FamilyInstance)) 113 | .Select(x => (x as FamilyInstance)).Where(x => x.Symbol.Family.Id.ToString() == id).ToList(); 114 | 115 | //Parallel.ForEach(objectList, x => 116 | foreach(var x in objectList) 117 | { 118 | if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(x.Name)) 119 | { 120 | returnElementsObject.Add(new QLFamilyInstanceResolve(x, qlFamilyInstancesField)); 121 | } 122 | } 123 | 124 | qlFamilyInstances = returnElementsObject.OrderBy(x => x.name).ToList(); 125 | } 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/QLFamilySymbolResolve.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using GraphQL.Language.AST; 3 | using RevitGraphQLResolver.GraphQL; 4 | using RevitGraphQLSchema.GraphQLModel; 5 | using System.Collections.Concurrent; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace RevitGraphQLResolver.GraphQLModel 10 | { 11 | public class QLFamilySymbolResolve: QLFamilySymbol 12 | { 13 | 14 | public QLFamilySymbolResolve(FamilySymbol _familySymbol, object aFieldOrContext) 15 | { 16 | id = _familySymbol.Id.ToString(); 17 | name = _familySymbol.Name; 18 | 19 | var queryFieldForFamilyInstances = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "qlFamilyInstances"); 20 | 21 | if (queryFieldForFamilyInstances != null) 22 | { 23 | 24 | var returnElementsObject = new ConcurrentBag(); 25 | 26 | var nameFiltersContained = GraphQlHelpers.GetArgumentStrings(queryFieldForFamilyInstances, "nameFilter"); 27 | //var queryFieldForParameters = GraphQlHelpers.GetFieldFromSelectionSet(queryFieldForFamilyInstances, "qlParameters"); 28 | 29 | var _doc = ResolverEntry.Doc; 30 | List objectList = new FilteredElementCollector(_doc).OfClass(typeof(FamilyInstance)) 31 | .Select(x => (x as FamilyInstance)).Where(x => x.Symbol.Id.ToString() == id).ToList(); 32 | 33 | //Parallel.ForEach(objectList, x => 34 | foreach (var x in objectList) 35 | { 36 | if (nameFiltersContained.Count == 0 || nameFiltersContained.Contains(x.Name)) 37 | { 38 | returnElementsObject.Add(new QLFamilyInstanceResolve(x, queryFieldForFamilyInstances)); 39 | } 40 | } 41 | 42 | qlFamilyInstances = returnElementsObject.OrderBy(x => x.name).ToList(); 43 | } 44 | 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/QLMepSystemResolve.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using Autodesk.Revit.DB.Electrical; 3 | using Autodesk.Revit.DB.Mechanical; 4 | using Autodesk.Revit.DB.Plumbing; 5 | using RevitGraphQLSchema.GraphQLModel; 6 | using System.Text.Json; 7 | using TraverseAllSystems; 8 | 9 | namespace RevitGraphQLResolver.GraphQLModel 10 | { 11 | public class QLMepSystemResolve : QLMepSystem 12 | { 13 | 14 | public QLMepSystemResolve(MEPSystem _mepSystem) 15 | { 16 | id = _mepSystem.Id.ToString(); 17 | name = _mepSystem.Name; 18 | 19 | mepDomain = GetMepDomain(_mepSystem).ToString(); 20 | 21 | 22 | //https://thebuildingcoder.typepad.com/blog/2016/06/traversing-and-exporting-all-mep-system-graphs.html 23 | // to travers mep system from the root 24 | FamilyInstance root = _mepSystem.BaseEquipment; 25 | 26 | if (root != null && (_mepSystem.GetType() == typeof(MechanicalSystem))) 27 | { 28 | 29 | // Traverse the system and dump the 30 | // traversal graph into an XML file 31 | 32 | TraversalTree tree = new TraversalTree(_mepSystem); 33 | 34 | if (tree.Traverse()) 35 | { 36 | qlTammTreeNode = new QLTammTreeNodeResolve(JsonSerializer.Deserialize(tree.DumpToJsonTopDown())); 37 | } 38 | } 39 | } 40 | 41 | /// 42 | /// The thee MEP disciplines 43 | /// 44 | public enum MepDomain 45 | { 46 | Invalid = -1, 47 | Mechanical = 0, 48 | Electrical = 1, 49 | Piping = 2, 50 | Count = 3 51 | } 52 | MepDomain GetMepDomain(MEPSystem s) 53 | { 54 | return (s is MechanicalSystem) ? MepDomain.Mechanical 55 | : ((s is ElectricalSystem) ? MepDomain.Electrical 56 | : ((s is PipingSystem) ? MepDomain.Piping 57 | : MepDomain.Invalid)); 58 | } 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/QLTammTreeNodeResolve.cs: -------------------------------------------------------------------------------- 1 | using RevitGraphQLSchema.GraphQLModel; 2 | using System.Collections.Generic; 3 | using System.Text.Json; 4 | 5 | namespace RevitGraphQLResolver.GraphQLModel 6 | { 7 | public class QLTammTreeNodeResolve : QLTammTreeNode 8 | { 9 | public QLTammTreeNodeResolve(JsonElement aJTreeNode) 10 | { 11 | id = aJTreeNode.GetProperty("id").GetString(); 12 | text = aJTreeNode.GetProperty("text").GetString(); 13 | children = new List(); 14 | foreach (JsonElement aJChild in (aJTreeNode.GetProperty("children").EnumerateArray())) 15 | { 16 | children.Add(new QLTammTreeNodeResolve(aJChild)); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/GraphQLModel/QLViewScheduleResolve.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using GraphQL.Language.AST; 3 | using RevitGraphQLResolver.GraphQL; 4 | using RevitGraphQLSchema.GraphQLModel; 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | namespace RevitGraphQLResolver.GraphQLModel 9 | { 10 | public class QLViewScheduleResolve : QLViewSchedule 11 | { 12 | public QLViewScheduleResolve() 13 | { 14 | 15 | } 16 | 17 | //public QLViewScheduleResolve(ViewSchedule aViewSchedule, Field queryFieldForViewScheduleData) 18 | //{ 19 | // id = aViewSchedule.Id.ToString(); 20 | // name = aViewSchedule.Name; 21 | 22 | // if (queryFieldForViewScheduleData != null) 23 | // { 24 | // try 25 | // { 26 | // qlViewScheduleData = ResolverEntry.aRevitTask.Run(app => 27 | // { 28 | // ////https://thebuildingcoder.typepad.com/blog/2012/05/the-schedule-api-and-access-to-schedule-data.html 29 | // TableData table = aViewSchedule.GetTableData(); 30 | // var rowCount = aViewSchedule.GetTableData().GetSectionData(SectionType.Body).NumberOfRows; 31 | // var colCount = aViewSchedule.GetTableData().GetSectionData(SectionType.Body).NumberOfColumns; 32 | 33 | // QLViewScheduleData data = new QLViewScheduleData(); 34 | // data.headers = new List(); 35 | // data.rows = new List(); 36 | 37 | // for (int i = 0; i < rowCount; i++) 38 | // { 39 | // QLViewScheduleRow newRow = new QLViewScheduleRow(); 40 | // newRow.id = i.ToString(); 41 | // newRow.cells = new List(); 42 | // for (int j = 0; j < colCount; j++) 43 | // { 44 | // var cellString = aViewSchedule.GetCellText(SectionType.Body, i, j); 45 | // if (i == 0) 46 | // { 47 | // data.headers.Add(cellString); 48 | // } 49 | // else 50 | // { 51 | // newRow.cells.Add(cellString); 52 | // } 53 | // } 54 | // if (i == 0) 55 | // { 56 | // i++; // skip 2nd row - it's always blank 57 | // } 58 | // else 59 | // { 60 | // data.rows.Add(newRow); 61 | // } 62 | // } 63 | // return data; 64 | // }).Result; 65 | // } 66 | // catch (Exception ex) 67 | // { 68 | // var m = ex.Message; 69 | // } 70 | // } 71 | //} 72 | public QLViewScheduleResolve(ViewSchedule aViewSchedule, object aFieldOrContext) 73 | { 74 | id = aViewSchedule.Id.ToString(); 75 | name = aViewSchedule.Name; 76 | 77 | var queryFieldForViewScheduleData = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "qlViewScheduleData"); 78 | if (queryFieldForViewScheduleData != null) 79 | { 80 | try 81 | { 82 | qlViewScheduleData = ResolverEntry.aRevitTask.Run(app => 83 | { 84 | ////https://thebuildingcoder.typepad.com/blog/2012/05/the-schedule-api-and-access-to-schedule-data.html 85 | TableData table = aViewSchedule.GetTableData(); 86 | var rowCount = aViewSchedule.GetTableData().GetSectionData(SectionType.Body).NumberOfRows; 87 | var colCount = aViewSchedule.GetTableData().GetSectionData(SectionType.Body).NumberOfColumns; 88 | 89 | QLViewScheduleData data = new QLViewScheduleData(); 90 | data.headers = new List(); 91 | data.rows = new List(); 92 | 93 | for (int i = 0; i < rowCount; i++) 94 | { 95 | QLViewScheduleRow newRow = new QLViewScheduleRow(); 96 | newRow.id = i.ToString(); 97 | newRow.cells = new List(); 98 | for (int j = 0; j < colCount; j++) 99 | { 100 | var cellString = aViewSchedule.GetCellText(SectionType.Body, i, j); 101 | if (i == 0) 102 | { 103 | data.headers.Add(cellString); 104 | } 105 | else 106 | { 107 | newRow.cells.Add(cellString); 108 | } 109 | } 110 | if (i == 0) 111 | { 112 | i++; // skip 2nd row - it's always blank 113 | } 114 | else 115 | { 116 | data.rows.Add(newRow); 117 | } 118 | } 119 | return data; 120 | }).Result; 121 | } 122 | catch (Exception ex) 123 | { 124 | var m = ex.Message; 125 | } 126 | } 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/ResolverEntry.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using Autodesk.Revit.UI; 3 | using GraphQL; 4 | using GraphQL.Instrumentation; 5 | using RevitGraphQLResolver.GraphQL; 6 | using System; 7 | using System.Threading.Tasks; 8 | 9 | namespace RevitGraphQLResolver 10 | { 11 | public class ResolverEntry 12 | { 13 | public static Document Doc { get; set; } 14 | public static UIDocument UiDoc { get; set; } 15 | 16 | public static RevitTask aRevitTask; 17 | 18 | public ResolverEntry(Document _doc, UIDocument _uidoc, RevitTask _aRevitTask) 19 | { 20 | Doc = _doc; 21 | UiDoc = _uidoc; 22 | aRevitTask = _aRevitTask; 23 | } 24 | 25 | public async Task GetResultAsync(GraphQLQuery query) 26 | { 27 | var start = DateTime.UtcNow; 28 | 29 | var inputs = query.Variables.As(); 30 | 31 | var schema = new MySchema(); 32 | 33 | ExecutionResult result = await new DocumentExecuter().ExecuteAsync(_ => 34 | { 35 | _.Schema = schema.GraphQLSchema; 36 | _.Query = query.Query; 37 | _.OperationName = query.OperationName; 38 | _.Inputs = inputs; 39 | _.EnableMetrics = true; 40 | }); 41 | 42 | result.EnrichWithApolloTracing(start); 43 | 44 | return result; 45 | 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/RevitGraphQLResolver.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | ..\..\..\..\..\..\..\Program Files\Autodesk\Revit 2020\RevitAPI.dll 27 | 28 | 29 | ..\..\..\..\..\..\..\Program Files\Autodesk\Revit 2020\RevitAPIUI.dll 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/TraversalTree/Options.cs: -------------------------------------------------------------------------------- 1 | namespace TraverseAllSystems 2 | { 3 | class Options 4 | { 5 | /// 6 | /// Store element id or UniqueId in JSON output? 7 | /// 8 | public static bool StoreUniqueId = true; 9 | public static bool StoreElementId = !StoreUniqueId; 10 | 11 | /// 12 | /// Store parent node id in child, or recursive 13 | /// tree of children in parent? 14 | /// 15 | public static bool StoreJsonGraphBottomUp = false; 16 | public static bool StoreJsonGraphTopDown 17 | = !StoreJsonGraphBottomUp; 18 | 19 | /// 20 | /// Store entire JSON graph for all systems on 21 | /// project info element, or individual graph for 22 | /// each system seaparately in MEP system element? 23 | /// 24 | public static bool StoreEntireJsonGraphOnProjectInfo = true; 25 | public static bool StoreSeparateJsonGraphOnEachSystem 26 | = !StoreEntireJsonGraphOnProjectInfo; 27 | 28 | /// 29 | /// The JSON tag specifying the tree node label, 30 | /// normally either 'name' or 'text'. 31 | /// 32 | public static string NodeLabelTag = "text"; 33 | } 34 | } -------------------------------------------------------------------------------- /src/RevitGraphQLResolver/TraversalTree/Util.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | 3 | namespace TraverseAllSystems 4 | { 5 | class Util 6 | { 7 | /// 8 | /// Return a string describing the given element: 9 | /// .NET type name, 10 | /// category name, 11 | /// family and symbol name for a family instance, 12 | /// element id and element name. 13 | /// 14 | public static string ElementDescription( 15 | Element e) 16 | { 17 | if (null == e) 18 | { 19 | return ""; 20 | } 21 | 22 | // For a wall, the element name equals the 23 | // wall type name, which is equivalent to the 24 | // family name ... 25 | 26 | FamilyInstance fi = e as FamilyInstance; 27 | 28 | string typeName = e.GetType().Name; 29 | 30 | string categoryName = (null == e.Category) 31 | ? string.Empty 32 | : e.Category.Name + " "; 33 | 34 | string familyName = (null == fi) 35 | ? string.Empty 36 | : fi.Symbol.Family.Name + " "; 37 | 38 | string symbolName = (null == fi 39 | || e.Name.Equals(fi.Symbol.Name)) 40 | ? string.Empty 41 | : fi.Symbol.Name + " "; 42 | 43 | return string.Format("{0} {1}{2}{3}<{4} {5}>", 44 | typeName, categoryName, familyName, 45 | symbolName, e.Id.IntegerValue, e.Name); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLAssembly.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RevitGraphQLSchema.GraphQLModel 4 | { 5 | public class QLAssembly 6 | { 7 | public string id { get; set; } 8 | public string name { get; set; } 9 | 10 | public bool hasViews { get; set; } 11 | 12 | public QLElementCollection qlElementCollection { get; set; } 13 | 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLElementCollection.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RevitGraphQLSchema.GraphQLModel 4 | { 5 | public class QLElementCollection 6 | { 7 | public List elementIds { get; set; } 8 | 9 | public List qlFamilyInstances { get; set; } 10 | public List qlFabricationParts { get; set; } 11 | 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLFabricationPart.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RevitGraphQLSchema.GraphQLModel 4 | { 5 | public class QLFabricationPart 6 | { 7 | public string id { get; set; } 8 | public string name { get; set; } 9 | public List qlParameters { get; set; } 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLFabricationService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RevitGraphQLSchema.GraphQLModel 4 | { 5 | public class QLFabricationService 6 | { 7 | public string id { get; set; } 8 | public string name { get; set; } 9 | 10 | public List qlFabricationParts { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLFamily.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RevitGraphQLSchema.GraphQLModel 4 | { 5 | public class QLFamily 6 | { 7 | public string id { get; set; } 8 | public string name { get; set; } 9 | public List qlFamilySymbols { get; set; } 10 | public List qlFamilyInstances { get; set; } 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLFamilyCategory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RevitGraphQLSchema.GraphQLModel 4 | { 5 | public class QLFamilyCategory 6 | { 7 | public string id { get; set; } 8 | public string name { get; set; } 9 | public List qlFamilies { get; set; } 10 | 11 | public List qlFamilyInstances { get; set; } 12 | 13 | } 14 | } -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLFamilyInstance.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RevitGraphQLSchema.GraphQLModel 4 | { 5 | public class QLFamilyInstance 6 | { 7 | public string id { get; set; } 8 | public string name { get; set; } 9 | public List qlParameters { get; set; } 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLFamilySymbol.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RevitGraphQLSchema.GraphQLModel 4 | { 5 | public class QLFamilySymbol 6 | { 7 | public string id { get; set; } 8 | public string name { get; set; } 9 | 10 | public List qlFamilyInstances { get; set; } 11 | 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLMepSystem.cs: -------------------------------------------------------------------------------- 1 | namespace RevitGraphQLSchema.GraphQLModel 2 | { 3 | public class QLMepSystem 4 | { 5 | public string id { get; set; } 6 | public string name { get; set; } 7 | 8 | public QLTammTreeNode qlTammTreeNode { get; set; } 9 | 10 | public string mepDomain { get; set; } 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLParameter.cs: -------------------------------------------------------------------------------- 1 | namespace RevitGraphQLSchema.GraphQLModel 2 | { 3 | public class QLParameter 4 | { 5 | public string id { get; set; } 6 | public string name { get; set; } 7 | public string value { get; set; } 8 | 9 | public bool userModifiable { get; set; } 10 | 11 | public bool isReadOnly { get; set; } 12 | 13 | } 14 | } -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLTammTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RevitGraphQLSchema.GraphQLModel 4 | { 5 | public class QLTammTreeNode 6 | { 7 | public string id { get; set; } 8 | public string text { get; set; } 9 | public List children { get; set; } 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLViewSchedule.cs: -------------------------------------------------------------------------------- 1 | namespace RevitGraphQLSchema.GraphQLModel 2 | { 3 | public class QLViewSchedule 4 | { 5 | public string id { get; set; } 6 | public string name { get; set; } 7 | 8 | public QLViewScheduleData qlViewScheduleData { get; set; } 9 | 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLViewScheduleData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RevitGraphQLSchema.GraphQLModel 4 | { 5 | public class QLViewScheduleData 6 | { 7 | public List headers { get; set; } 8 | 9 | public List rows { get; set; } 10 | 11 | 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/QLViewScheduleRow.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RevitGraphQLSchema.GraphQLModel 4 | { 5 | public class QLViewScheduleRow 6 | { 7 | public string id { get; set; } 8 | public List cells { get; set; } 9 | 10 | 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLModel/UpdateQLParameter.cs: -------------------------------------------------------------------------------- 1 | namespace RevitGraphQLSchema.GraphQLModel 2 | { 3 | public class UpdateQLParameter 4 | { 5 | public string instanceId { get; set; } 6 | public string parameterId { get; set; } 7 | public string updateValue { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/GraphQLSchema.cs: -------------------------------------------------------------------------------- 1 | namespace RevitGraphQLSchema 2 | { 3 | public static class GraphQLSchema 4 | { 5 | public static readonly string schema = @" 6 | 7 | type QLFamilyCategory{ 8 | id: String 9 | name: String 10 | qlFamilies( 11 | nameFilter: [String] = [] 12 | ): [QLFamily] 13 | qlFamilyInstances( 14 | nameFilter: [String] = [] 15 | ): [QLFamilyInstance] 16 | } 17 | 18 | type QLFamily{ 19 | id: String 20 | name: String 21 | qlFamilySymbols( 22 | nameFilter: [String] = [] 23 | ): [QLFamilySymbol] 24 | qlFamilyInstances( 25 | nameFilter: [String] = [] 26 | ): [QLFamilyInstance] 27 | } 28 | 29 | type QLFamilySymbol{ 30 | id: String 31 | name: String 32 | qlFamilyInstances( 33 | nameFilter: [String] = [] 34 | ): [QLFamilyInstance] 35 | } 36 | 37 | type QLFamilyInstance{ 38 | id: String 39 | name: String 40 | qlParameters( 41 | nameFilter: [String] = [] 42 | ): [QLParameter] 43 | } 44 | 45 | type QLFabricationPart{ 46 | id: String 47 | name: String 48 | qlParameters( 49 | nameFilter: [String] = [] 50 | ): [QLParameter] 51 | } 52 | 53 | type QLParameter{ 54 | id: String 55 | name: String 56 | value: String 57 | userModifiable: Boolean 58 | isReadOnly: Boolean 59 | } 60 | 61 | input UpdateQLParameter{ 62 | instanceId: String 63 | parameterId: String 64 | updateValue: String 65 | } 66 | 67 | type QLViewSchedule{ 68 | id: String 69 | name: String 70 | qlViewScheduleData: QLViewScheduleData 71 | } 72 | 73 | type QLViewScheduleData{ 74 | headers: [String] 75 | rows: [QLViewScheduleRow] 76 | } 77 | 78 | type QLViewScheduleRow{ 79 | id: String 80 | cells: [String] 81 | } 82 | 83 | type QLMepSystem{ 84 | id: String 85 | name: String 86 | mepDomain: String 87 | qlTammTreeNode: QLTammTreeNode 88 | } 89 | 90 | type QLTammTreeNode{ 91 | id: String 92 | text: String 93 | children: [QLTammTreeNode] 94 | } 95 | 96 | type QLElementCollection{ 97 | elementIds: [String] 98 | qlFamilyInstances( 99 | nameFilter: [String] = [] 100 | ): [QLFamilyInstance] 101 | qlFabricationParts( 102 | nameFilter: [String] = [] 103 | ): [QLFabricationPart] 104 | } 105 | 106 | type QLAssembly{ 107 | id: String 108 | name: String 109 | hasViews: Boolean 110 | qlElementCollection: QLElementCollection 111 | } 112 | 113 | type QLFabricationService{ 114 | id: String 115 | name: String 116 | qlFabricationParts( 117 | nameFilter: [String] = [] 118 | ): [QLFabricationPart] 119 | } 120 | 121 | type Query{ 122 | hello: String 123 | sheets: [String] 124 | phases: [String] 125 | qlMepSystems( 126 | nameFilter: [String] = [] 127 | ): [QLMepSystem] 128 | qlAssemblies( 129 | nameFilter: [String] = [] 130 | ): [QLAssembly] 131 | qlFabricationServices( 132 | nameFilter: [String] = [] 133 | ): [QLFabricationService] 134 | qlViewSchedules( 135 | nameFilter: [String] = [] 136 | ): [QLViewSchedule] 137 | qlFamilyCategories( 138 | nameFilter: [String] = [] 139 | ): [QLFamilyCategory] 140 | qlFamilies( 141 | nameFilter: [String] = [] 142 | ): [QLFamily] 143 | qlElementSelection( 144 | nameFilter: [String] = [] 145 | ): QLElementCollection 146 | } 147 | 148 | type Mutation{ 149 | qlParameters( 150 | input: [UpdateQLParameter] = [] 151 | ): [QLParameter] 152 | qlElementSelection( 153 | input: [String] = [] 154 | ): QLElementCollection 155 | } 156 | schema{ 157 | query: Query, 158 | mutation: Mutation 159 | } 160 | "; 161 | 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/IGraphQL/IMutation.cs: -------------------------------------------------------------------------------- 1 | using GraphQL; 2 | using RevitGraphQLSchema.GraphQLModel; 3 | using System.Collections.Generic; 4 | 5 | namespace RevitGraphQLSchema.IGraphQl 6 | { 7 | public interface IMutation 8 | { 9 | List UpdateParameters(IResolveFieldContext context, List input); 10 | 11 | QLElementCollection SetSelection(IResolveFieldContext context, List input); 12 | } 13 | } -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/IGraphQL/IQuery.cs: -------------------------------------------------------------------------------- 1 | using GraphQL; 2 | using RevitGraphQLSchema.GraphQLModel; 3 | using System.Collections.Generic; 4 | 5 | namespace RevitGraphQLSchema.IGraphQl 6 | { 7 | public interface IQuery 8 | { 9 | [GraphQLMetadata("qlFamilyCategories")] 10 | List GetCategories(IResolveFieldContext context, string[] nameFilter = null); 11 | 12 | [GraphQLMetadata("qlFamilies")] 13 | List GetFamilies(IResolveFieldContext context, string[] nameFilter = null); 14 | 15 | string GetHello(); 16 | 17 | [GraphQLMetadata("qlViewSchedules")] 18 | List GetViewSchedules(IResolveFieldContext context, string[] nameFilter = null); 19 | 20 | [GraphQLMetadata("sheets")] 21 | List GetSheets(IResolveFieldContext context); 22 | 23 | [GraphQLMetadata("phases")] 24 | List GetPhases(IResolveFieldContext context); 25 | 26 | [GraphQLMetadata("qlMepSystems")] 27 | List GetMepSystems(IResolveFieldContext context, string[] nameFilter = null); 28 | 29 | [GraphQLMetadata("qlAssemblies")] 30 | List GetAssemblies(IResolveFieldContext context, string[] nameFilter = null); 31 | 32 | [GraphQLMetadata("qlElementSelection")] 33 | QLElementCollection GetSelection(IResolveFieldContext context, string[] nameFilter = null); 34 | 35 | [GraphQLMetadata("qlFabricationServices")] 36 | List GetFabServices(IResolveFieldContext context, string[] nameFilter = null); 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/MarconiUser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IdentityModel.Tokens.Jwt; 4 | using System.Linq; 5 | using System.Security.Claims; 6 | using System.Text; 7 | 8 | namespace RevitGraphQLSchema 9 | { 10 | public class MarconiUser 11 | { 12 | public string UserId { get; set; } 13 | public string UserName { get; set; } 14 | public string UserEmail { get; set; } 15 | 16 | public MarconiUser() 17 | { 18 | 19 | } 20 | 21 | //public MarconiUser(ClaimsIdentity aIdentity) 22 | //{ 23 | // UserId = aIdentity.FindFirst("oid").Value; 24 | // UserName = aIdentity.FindFirst("name").Value; 25 | // UserEmail = aIdentity.FindFirst("email").Value; 26 | //} 27 | 28 | public MarconiUser(ClaimsPrincipal aPrincipal) 29 | { 30 | UserId = aPrincipal.FindFirst(ClaimTypes.NameIdentifier).Value; 31 | UserName = aPrincipal.FindFirst("name").Value; 32 | UserEmail = aPrincipal.FindFirst("emails").Value; 33 | } 34 | public MarconiUser(JwtSecurityToken aToken) 35 | { 36 | UserEmail = aToken.Claims.FirstOrDefault(x => x.Type == "emails")?.Value; 37 | UserName = aToken.Claims.FirstOrDefault(x => x.Type == "name")?.Value; 38 | UserId = aToken.Claims.FirstOrDefault(x => x.Type == "oid")?.Value; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/RevitGraphQLSchema/RevitGraphQLSchema.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/RevitMarconiCommand/App.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.UI; 2 | using Autodesk.Revit.UI.Events; 3 | using RevitMarconiCommand.Helpers; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Threading; 10 | using System.Windows.Media.Imaging; 11 | using System.Windows.Threading; 12 | 13 | namespace RevitMarconiCommand 14 | { 15 | class App : IExternalApplication 16 | { 17 | // class instance 18 | public static App ThisApp; 19 | 20 | // ModelessForm instance 21 | private Ui _mMyForm; 22 | 23 | // Separate thread to run Ui on 24 | private Thread _uiThread; 25 | 26 | private MsalAuthHelper _msalAuthHelper; 27 | public MsalAuthHelper msalAuthHelper 28 | { 29 | get 30 | { 31 | if (_msalAuthHelper == null) _msalAuthHelper = new MsalAuthHelper(); 32 | return _msalAuthHelper; 33 | } 34 | } 35 | 36 | public Result OnStartup(UIControlledApplication a) 37 | { 38 | _mMyForm = null; // no dialog needed yet; the command will bring it 39 | ThisApp = this; // static access to this application instance 40 | 41 | // Method to add Tab and Panel 42 | RibbonPanel panel = RibbonPanel(a); 43 | string thisAssemblyPath = Assembly.GetExecutingAssembly().Location; 44 | 45 | // BUTTON FOR THE MULTI-THREADED WPF OPTION 46 | if (panel.AddItem( 47 | new PushButtonData("BIMrx.Marconi", "BIMrx.Marconi", thisAssemblyPath, 48 | "RevitMarconiCommand.EntryCommandSeparateThread")) is PushButton button2) 49 | { 50 | button2.ToolTip = "Visual interface to start/stop BIMrx.Marconi."; 51 | Uri uriImage = new Uri("pack://application:,,,/RevitMarconiCommand;component/Resources/phone.png"); 52 | BitmapImage largeImage = new BitmapImage(uriImage); 53 | button2.LargeImage = largeImage; 54 | } 55 | 56 | 57 | 58 | // listeners/watchers for external events (if you choose to use them) 59 | a.ApplicationClosing += a_ApplicationClosing; //Set Application to Idling 60 | a.Idling += a_Idling; 61 | 62 | AppDomain currentDomain = AppDomain.CurrentDomain; 63 | 64 | currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler); 65 | 66 | 67 | return Result.Succeeded; 68 | } 69 | 70 | private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args) 71 | { 72 | if (args.Name.Contains("System.Buffers")) 73 | { 74 | string assemblyFileName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\System.Buffers.dll"; 75 | return Assembly.LoadFrom(assemblyFileName); 76 | } 77 | else if (args.Name.Contains("System.Runtime.CompilerServices.Unsafe")) 78 | { 79 | string assemblyFileName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\System.Runtime.CompilerServices.Unsafe.dll"; 80 | return Assembly.LoadFrom(assemblyFileName); 81 | } 82 | else if (args.Name.Contains("System.Threading.Tasks.Extensions")) 83 | { 84 | string assemblyFileName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\System.Threading.Tasks.Extensions.dll"; 85 | return Assembly.LoadFrom(assemblyFileName); 86 | } 87 | else 88 | { 89 | return null; 90 | } 91 | } 92 | 93 | 94 | /// 95 | /// What to do when the application is shut down. 96 | /// 97 | public Result OnShutdown(UIControlledApplication a) 98 | { 99 | return Result.Succeeded; 100 | } 101 | 102 | /// 103 | /// This is the method which launches the WPF window in a separate thread, and injects any methods that are 104 | /// wrapped by ExternalEventHandlers. This can be done in a number of different ways, and 105 | /// implementation will differ based on how the WPF is set up. 106 | /// 107 | /// The Revit UIApplication within the add-in will operate. 108 | public void ShowFormSeparateThread(UIApplication uiapp) 109 | { 110 | // If we do not have a thread started or has been terminated start a new one 111 | if (!(_uiThread is null) && _uiThread.IsAlive) return; 112 | 113 | //https://thebuildingcoder.typepad.com/blog/2020/02/external-communication-and-async-await-event-wrapper.html#2 114 | //https://github.com/WhiteSharq/RevitTask 115 | 116 | RevitTask aRevitTask = new RevitTask(); 117 | 118 | _uiThread = new Thread(() => 119 | { 120 | SynchronizationContext.SetSynchronizationContext( 121 | new DispatcherSynchronizationContext( 122 | Dispatcher.CurrentDispatcher)); 123 | // The dialog becomes the owner responsible for disposing the objects given to it. 124 | _mMyForm = new Ui(uiapp, aRevitTask, msalAuthHelper); 125 | _mMyForm.Closed += (s, e) => Dispatcher.CurrentDispatcher.InvokeShutdown(); 126 | _mMyForm.Show(); 127 | Dispatcher.Run(); 128 | }); 129 | 130 | _uiThread.SetApartmentState(ApartmentState.STA); 131 | _uiThread.IsBackground = true; 132 | _uiThread.Start(); 133 | } 134 | 135 | #region Idling & Closing 136 | 137 | /// 138 | /// What to do when the application is idling. (Ideally nothing) 139 | /// 140 | void a_Idling(object sender, IdlingEventArgs e) 141 | { 142 | } 143 | 144 | /// 145 | /// What to do when the application is closing.) 146 | /// 147 | void a_ApplicationClosing(object sender, ApplicationClosingEventArgs e) 148 | { 149 | } 150 | 151 | #endregion 152 | 153 | #region Ribbon Panel 154 | 155 | public RibbonPanel RibbonPanel(UIControlledApplication a) 156 | { 157 | 158 | string tab = "GraphQL"; // Tab name 159 | 160 | // Empty ribbon panel 161 | RibbonPanel ribbonPanel = null; 162 | // Try to create ribbon tab. 163 | try 164 | { 165 | a.CreateRibbonTab(tab); 166 | } 167 | catch (Exception ex) 168 | { 169 | Util.HandleError(ex); 170 | } 171 | 172 | // Try to create ribbon panel. 173 | try 174 | { 175 | RibbonPanel panel = a.CreateRibbonPanel(tab, "Remote"); 176 | } 177 | catch (Exception ex) 178 | { 179 | Util.HandleError(ex); 180 | } 181 | 182 | // Search existing tab for your panel. 183 | List panels = a.GetRibbonPanels(tab); 184 | foreach (RibbonPanel p in panels.Where(p => p.Name == "Remote")) 185 | { 186 | ribbonPanel = p; 187 | } 188 | 189 | //return panel 190 | return ribbonPanel; 191 | } 192 | 193 | #endregion 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /src/RevitMarconiCommand/Class1.cs: -------------------------------------------------------------------------------- 1 | namespace RevitCommand 2 | { 3 | public class Class1 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/RevitMarconiCommand/EntryCommandSeparateThread.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.Attributes; 2 | using Autodesk.Revit.DB; 3 | using Autodesk.Revit.UI; 4 | using System; 5 | 6 | namespace RevitMarconiCommand 7 | { 8 | /// 9 | /// This is the ExternalCommand which gets executed from the ExternalApplication. In a WPF context, 10 | /// this can be lean, as it just needs to show the WPF. Without a UI, this could contain the main 11 | /// order of operations for executing the business logic. 12 | /// 13 | [Transaction(TransactionMode.Manual)] 14 | public class EntryCommandSeparateThread : IExternalCommand 15 | { 16 | public virtual Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) 17 | { 18 | 19 | try 20 | { 21 | App.ThisApp.ShowFormSeparateThread(commandData.Application); 22 | return Result.Succeeded; 23 | } 24 | catch (Exception ex) 25 | { 26 | message = ex.Message; 27 | return Result.Failed; 28 | } 29 | 30 | 31 | } 32 | 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/RevitMarconiCommand/Helpers/MsalAuthHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.Identity.Client; 7 | using System.Configuration; 8 | using System.Globalization; 9 | using System.Windows.Forms; 10 | using System.Net; 11 | using System.IdentityModel.Tokens.Jwt; 12 | 13 | namespace RevitMarconiCommand.Helpers 14 | { 15 | public class MsalAuthHelper 16 | { 17 | 18 | private IPublicClientApplication _app; 19 | 20 | private static readonly string ClientId = "294c8f2a-d3cf-48af-be60-83b7b94552ec"; 21 | private static readonly string Authority = "https://BIMrxB2C.b2clogin.com/tfp/BIMrxB2C.onmicrosoft.com/B2C_1_SignUpSignIn"; 22 | private static readonly string SpListScope = "https://BIMrxB2C.onmicrosoft.com/72cf8896-fd75-46cf-966a-1b6d14cb6483/API.Access"; 23 | private static readonly string[] Scopes = { SpListScope }; 24 | 25 | private IList accounts; 26 | public AuthenticationResult AuthenticationResult; 27 | 28 | public IAccount ActiveAccount 29 | { 30 | get 31 | { 32 | return accounts.FirstOrDefault(); 33 | } 34 | } 35 | 36 | public async Task GetTokenAsync() 37 | { 38 | var aAccount = accounts.FirstOrDefault(); 39 | if (aAccount == null) 40 | { 41 | return ""; 42 | } 43 | else 44 | { 45 | AuthenticationResult = await _app.AcquireTokenSilent(Scopes, aAccount) 46 | .ExecuteAsync() 47 | .ConfigureAwait(false); 48 | return AuthenticationResult.AccessToken; 49 | } 50 | } 51 | 52 | public MsalAuthHelper() 53 | { 54 | //ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; 55 | 56 | _app = PublicClientApplicationBuilder.Create(ClientId) 57 | .WithB2CAuthority(Authority) 58 | //.WithRedirectUri("msal294c8f2a-d3cf-48af-be60-83b7b94552ec://auth") 59 | .WithRedirectUri("http://localhost") 60 | .Build(); 61 | TokenCacheHelper.EnableSerialization(_app.UserTokenCache); 62 | accounts = _app.GetAccountsAsync().Result.ToList(); 63 | } 64 | 65 | public async Task SignInAsync() 66 | { 67 | accounts = (await _app.GetAccountsAsync()).ToList(); 68 | AuthenticationResult = null; 69 | try 70 | { 71 | AuthenticationResult = await _app.AcquireTokenInteractive(Scopes) 72 | .WithUseEmbeddedWebView(false) 73 | .WithAccount(accounts.FirstOrDefault()) 74 | //.WithPrompt(Prompt.SelectAccount) 75 | .ExecuteAsync(); 76 | 77 | accounts = (await _app.GetAccountsAsync()).ToList(); 78 | 79 | } 80 | catch (MsalUiRequiredException) 81 | { 82 | 83 | } 84 | catch (MsalException ex) 85 | { 86 | // An unexpected error occurred. 87 | string message = ex.Message; 88 | if (ex.InnerException != null) 89 | { 90 | message += "Error Code: " + ex.ErrorCode + "Inner Exception : " + ex.InnerException.Message; 91 | } 92 | MessageBox.Show(message); 93 | } 94 | 95 | 96 | } 97 | 98 | public async Task SignOutAsync() 99 | { 100 | // clear the cache 101 | while (accounts.Any()) 102 | { 103 | await _app.RemoveAsync(accounts.First()); 104 | accounts = (await _app.GetAccountsAsync()).ToList(); 105 | } 106 | AuthenticationResult = null; 107 | } 108 | 109 | public bool IsSignedIn() 110 | { 111 | if (accounts.Any()) 112 | { 113 | return true; 114 | } 115 | else 116 | { 117 | return false; 118 | } 119 | } 120 | 121 | internal async Task GetNameOfActiveAccountAsync() 122 | { 123 | //using System.IdentityModel.Tokens.Jwt; 124 | var handler = new JwtSecurityTokenHandler(); 125 | var tokenContent = (JwtSecurityToken)handler.ReadToken(await GetTokenAsync()); 126 | var email = tokenContent.Claims.FirstOrDefault(x => x.Type == "emails")?.Value; 127 | var name = tokenContent.Claims.FirstOrDefault(x => x.Type == "name")?.Value; 128 | return name; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/RevitMarconiCommand/Helpers/TokenCacheHelper.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Security.Cryptography; 3 | using Microsoft.Identity.Client; 4 | 5 | namespace RevitMarconiCommand.Helpers 6 | { 7 | static class TokenCacheHelper 8 | { 9 | 10 | /// 11 | /// Path to the token cache 12 | /// 13 | private static readonly string CacheFilePath = System.Reflection.Assembly.GetExecutingAssembly().Location + ".msalcache.bin"; 14 | 15 | private static readonly object FileLock = new object(); 16 | 17 | private static void BeforeAccessNotification(TokenCacheNotificationArgs args) 18 | { 19 | lock (FileLock) 20 | { 21 | args.TokenCache.DeserializeMsalV3(File.Exists(CacheFilePath) 22 | ? ProtectedData.Unprotect(File.ReadAllBytes(CacheFilePath), 23 | null, 24 | DataProtectionScope.CurrentUser) 25 | : null); 26 | } 27 | } 28 | 29 | private static void AfterAccessNotification(TokenCacheNotificationArgs args) 30 | { 31 | // if the access operation resulted in a cache update 32 | if (args.HasStateChanged) 33 | { 34 | lock (FileLock) 35 | { 36 | // reflect changes in the persistent store 37 | File.WriteAllBytes(CacheFilePath, 38 | ProtectedData.Protect(args.TokenCache.SerializeMsalV3(), 39 | null, 40 | DataProtectionScope.CurrentUser) 41 | ); 42 | } 43 | } 44 | } 45 | internal static void EnableSerialization(ITokenCache tokenCache) 46 | { 47 | tokenCache.SetBeforeAccess(BeforeAccessNotification); 48 | tokenCache.SetAfterAccess(AfterAccessNotification); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/RevitMarconiCommand/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RevitCommand")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("RevitCommand")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("dc38d4e5-d9cc-41b8-aa8e-b7722b6db47a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/RevitMarconiCommand/Resources/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BIMrxLAB/Revit2GraphQL/150d7d0de0be57fd433a4b2ff91886100130c182/src/RevitMarconiCommand/Resources/phone.png -------------------------------------------------------------------------------- /src/RevitMarconiCommand/RevitMarconi.addin: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | BIMrx.Marconi 5 | RevitMarconiCommand\RevitMarconiCommand.dll 6 | 26516f0e-cdb2-43d0-9169-b4473db259ac 7 | RevitMarconiCommand.App 8 | Microdesk 9 | https://www.microdesk.com/bimrx/ 10 | 11 | -------------------------------------------------------------------------------- /src/RevitMarconiCommand/RevitMarconiCommand.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {DC38D4E5-D9CC-41B8-AA8E-B7722B6DB47A} 8 | Library 9 | Properties 10 | RevitMarconiCommand 11 | RevitMarconiCommand 12 | v4.7.2 13 | 512 14 | true 15 | 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\packages\Revit.2020.Assemblies.1.0.0\lib\AdWindows.dll 38 | 39 | 40 | ..\packages\GraphQL.3.0.0\lib\netstandard2.0\GraphQL.dll 41 | 42 | 43 | ..\packages\GraphQL-Parser.5.3.0\lib\netstandard2.0\GraphQL-Parser.dll 44 | 45 | 46 | ..\packages\GraphQL.SystemTextJson.3.0.0\lib\netstandard2.0\GraphQL.SystemTextJson.dll 47 | 48 | 49 | ..\packages\Microsoft.Azure.Amqp.2.4.6\lib\net45\Microsoft.Azure.Amqp.dll 50 | 51 | 52 | ..\packages\Microsoft.Azure.ServiceBus.5.0.0\lib\netstandard2.0\Microsoft.Azure.ServiceBus.dll 53 | 54 | 55 | ..\packages\Microsoft.Azure.Services.AppAuthentication.1.5.0\lib\net472\Microsoft.Azure.Services.AppAuthentication.dll 56 | 57 | 58 | ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.1\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll 59 | 60 | 61 | ..\packages\Microsoft.Identity.Client.4.18.0\lib\net461\Microsoft.Identity.Client.dll 62 | 63 | 64 | ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.5.2.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll 65 | 66 | 67 | ..\packages\Microsoft.IdentityModel.JsonWebTokens.6.7.1\lib\net461\Microsoft.IdentityModel.JsonWebTokens.dll 68 | 69 | 70 | ..\packages\Microsoft.IdentityModel.Logging.6.7.1\lib\net461\Microsoft.IdentityModel.Logging.dll 71 | 72 | 73 | ..\packages\Microsoft.IdentityModel.Tokens.6.7.1\lib\net461\Microsoft.IdentityModel.Tokens.dll 74 | 75 | 76 | ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll 77 | 78 | 79 | 80 | 81 | ..\packages\Revit.2020.Assemblies.1.0.0\lib\RevitAPI.dll 82 | 83 | 84 | ..\packages\Revit.2020.Assemblies.1.0.0\lib\RevitAPIIFC.dll 85 | 86 | 87 | ..\packages\Revit.2020.Assemblies.1.0.0\lib\RevitAPIMacros.dll 88 | 89 | 90 | ..\packages\Revit.2020.Assemblies.1.0.0\lib\RevitAPIUI.dll 91 | 92 | 93 | ..\packages\Revit.2020.Assemblies.1.0.0\lib\RevitAPIUIMacros.dll 94 | 95 | 96 | ..\packages\RevitTask.3.0.0\lib\net47\RevitTask.dll 97 | 98 | 99 | 100 | ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll 101 | 102 | 103 | ..\packages\System.ComponentModel.Annotations.4.7.0\lib\net461\System.ComponentModel.Annotations.dll 104 | 105 | 106 | 107 | 108 | 109 | ..\packages\System.Diagnostics.DiagnosticSource.4.5.1\lib\net46\System.Diagnostics.DiagnosticSource.dll 110 | 111 | 112 | 113 | 114 | ..\packages\System.IdentityModel.Tokens.Jwt.6.7.1\lib\net461\System.IdentityModel.Tokens.Jwt.dll 115 | 116 | 117 | ..\packages\System.IO.4.3.0\lib\net462\System.IO.dll 118 | True 119 | True 120 | 121 | 122 | ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll 123 | 124 | 125 | ..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll 126 | True 127 | True 128 | 129 | 130 | ..\packages\System.Net.WebSockets.4.3.0\lib\net46\System.Net.WebSockets.dll 131 | True 132 | True 133 | 134 | 135 | ..\packages\System.Net.WebSockets.Client.4.3.2\lib\net46\System.Net.WebSockets.Client.dll 136 | True 137 | True 138 | 139 | 140 | 141 | ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll 142 | 143 | 144 | ..\packages\System.Reactive.4.4.1\lib\net46\System.Reactive.dll 145 | 146 | 147 | ..\packages\System.Reactive.Core.4.4.1\lib\net46\System.Reactive.Core.dll 148 | 149 | 150 | ..\packages\System.Reactive.Interfaces.4.4.1\lib\net46\System.Reactive.Interfaces.dll 151 | 152 | 153 | ..\packages\System.Reactive.Linq.4.4.1\lib\net46\System.Reactive.Linq.dll 154 | 155 | 156 | ..\packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll 157 | True 158 | True 159 | 160 | 161 | ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll 162 | 163 | 164 | 165 | ..\packages\System.Runtime.Serialization.Primitives.4.3.0\lib\net46\System.Runtime.Serialization.Primitives.dll 166 | True 167 | True 168 | 169 | 170 | 171 | ..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net463\System.Security.Cryptography.Algorithms.dll 172 | True 173 | True 174 | 175 | 176 | ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll 177 | True 178 | True 179 | 180 | 181 | ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll 182 | True 183 | True 184 | 185 | 186 | ..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll 187 | True 188 | True 189 | 190 | 191 | ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll 192 | 193 | 194 | ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll 195 | 196 | 197 | ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll 198 | 199 | 200 | ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | Ui.xaml 220 | 221 | 222 | 223 | 224 | 225 | Designer 226 | MSBuild:Compile 227 | 228 | 229 | 230 | 231 | 232 | 233 | Always 234 | 235 | 236 | 237 | 238 | Always 239 | 240 | 241 | 242 | 243 | {f5e2f94e-dc93-4a71-a8df-5c13d97bc601} 244 | RevitGraphQLResolver 245 | 246 | 247 | 248 | 249 | if $(ConfigurationName) == Debug ( 250 | mkdir "$(AppData)\Autodesk\REVIT\Addins\2020\$(TargetName)\" 251 | if exist "$(AppData)\Autodesk\REVIT\Addins\2020" copy "$(TargetDir)*.addin" "$(AppData)\Autodesk\REVIT\Addins\2020\" 252 | if exist "$(AppData)\Autodesk\REVIT\Addins\2020" copy "$(TargetDir)*" "$(AppData)\Autodesk\REVIT\Addins\2020\$(TargetName)\" 253 | 254 | ) 255 | 256 | 257 | -------------------------------------------------------------------------------- /src/RevitMarconiCommand/Ui.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 |