Compare commits
768 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 891e032f8e | |||
| 8b7c127e93 | |||
| de9b56bf18 | |||
| c10c03637a | |||
| c4f734329a | |||
| 2f8f0d0f6f | |||
| c60e8d6feb | |||
| 67a8592a8a | |||
| 6f11d50445 | |||
| bfd741e707 | |||
| 6652f7534c | |||
| 7b092ec5e4 | |||
| 175454bda2 | |||
| 00d59913c2 | |||
| 373b0e5397 | |||
| e9ebe65775 | |||
| 249fc40105 | |||
| a81261a0e3 | |||
| 6e4894d3bc | |||
| e4f1ef8564 | |||
| 2cd7f4f905 | |||
| c6d06fbda1 | |||
| 6337a9e220 | |||
| 65f97b4f4a | |||
| cf570342d2 | |||
| 33e4008e4b | |||
| bcefe3b4c4 | |||
| 13f3bb8ae5 | |||
| d31cb47a85 | |||
| 378438f1bc | |||
| b485a4ff6f | |||
| 5697afc292 | |||
| 07a681eda7 | |||
| 4ec45d3cd5 | |||
| 939c710bf2 | |||
| ac1345bbaf | |||
| 95a7bdb81f | |||
| b1a5824bcd | |||
| 09f9b1ee51 | |||
| 1a687fb188 | |||
| 30e050fff2 | |||
| 30ab3b108e | |||
| 1f3ac7a5ad | |||
| 33e515efb6 | |||
| 4a5c91231d | |||
| 97a8df93d9 | |||
| 0106befa7d | |||
| ef87d5838b | |||
| 295162127a | |||
| 6d336fbac4 | |||
| 6b2078fadb | |||
| bfd465449a | |||
| a9a4893bdb | |||
| 21066eebbb | |||
| 9d5ff85cff | |||
| 64befa758d | |||
| d9a0cbb4bf | |||
| 50807b1e88 | |||
| 7780071073 | |||
| be63b4ab55 | |||
| 63c5bb26cb | |||
| f7a1d98d8a | |||
| a14de5bdde | |||
| a89407ae3c | |||
| a3285a4f67 | |||
| ae4b1b0ab5 | |||
| ed9d81d206 | |||
| a2fc846613 | |||
| 184953f5f0 | |||
| d71b36c2f7 | |||
| f152cff619 | |||
| 4aed602089 | |||
| 63c4d31467 | |||
| b807be35ff | |||
| 32ea041c5e | |||
| 950c8373d9 | |||
| 9d5faa92e8 | |||
| fd88fc2eeb | |||
| 9d2ae1ca55 | |||
| 670a562d48 | |||
| e6d983302c | |||
| fe5b77e766 | |||
| 663fe445bf | |||
| 74d2d2860c | |||
| 2e405b2f28 | |||
| 331c631b35 | |||
| ddd6039722 | |||
| 835e3ba005 | |||
| af548ba626 | |||
| 3ff40757e0 | |||
| a8571fdd61 | |||
| f8a6d27c6d | |||
| 4e1604f77e | |||
| 00af4ad338 | |||
| 7fed9e03e9 | |||
| e9c2c85a7f | |||
| 82c7877425 | |||
| 2338be46c2 | |||
| 8f72eb35d3 | |||
| a3f7069c37 | |||
| 3842e109b6 | |||
| 4ae2106608 | |||
| 3656587081 | |||
| b315cebf3a | |||
| fb18466aba | |||
| b721c2fb31 | |||
| 76aa953210 | |||
| 52d15dc827 | |||
| dbbc4f7fcd | |||
| 85b4a88407 | |||
| 65a2e674bb | |||
| 9a84e4469e | |||
| b8a49d5fed | |||
| 12dcf471d3 | |||
| 42e45affbd | |||
| fcce4e3f63 | |||
| 370c5b2064 | |||
| 39dfb0f426 | |||
| 1c62fbbe99 | |||
| 6f03aa8678 | |||
| f882b0f5bd | |||
| 4ffe9fe4b0 | |||
| d50b095683 | |||
| daebbbef1c | |||
| b43631e46b | |||
| ea9768b1f2 | |||
| 2756555eb9 | |||
| 1f1422900e | |||
| 45a76eada4 | |||
| 0e65b6aa57 | |||
| 5c2c0ff303 | |||
| a6fd4547ea | |||
| 0d27eadfeb | |||
| 0b26e021cd | |||
| a0d5e3b2d4 | |||
| 1ebc32f07e | |||
| a3b1cd52ad | |||
| c7cfb8c6c7 | |||
| 93246157c7 | |||
| 18499bdc69 | |||
| feaae9e5ee | |||
| 4ee48bdfae | |||
| 1c11e4a6c5 | |||
| 413c1ad562 | |||
| d9adca0154 | |||
| 74870a6a8e | |||
| cba391081c | |||
| ccc3187e78 | |||
| 1e8ad93dbe | |||
| a2b01c0bbb | |||
| a70a894089 | |||
| 65baf4221d | |||
| 2a4b5f7218 | |||
| cfa723d164 | |||
| 143da829d8 | |||
| a8a98fe824 | |||
| efadfdc479 | |||
| f7ee2555f4 | |||
| 286a1c070c | |||
| 4af90950ff | |||
| a23f9c1ffa | |||
| 64dfa44692 | |||
| 573c63fa62 | |||
| 52aeb36f19 | |||
| 593f95daf6 | |||
| e5e02bdab1 | |||
| e9f3701a86 | |||
| 3a7baf0659 | |||
| 24bff4b1ce | |||
| 184c53c3a2 | |||
| 16ce6ac09f | |||
| f379996f31 | |||
| 48e66f9084 | |||
| f2249356d8 | |||
| f4765b9e82 | |||
| e4a29085f3 | |||
| 462d01a3b2 | |||
| 8ca43a1ad5 | |||
| bb252a5115 | |||
| 4d7225fab4 | |||
| 9219cdfc53 | |||
| 03f0b1fc56 | |||
| 9e18134c5e | |||
| 67c7ddbf0a | |||
| 79a6062923 | |||
| 81c3c420a7 | |||
| 315a0cbf5e | |||
| d753ea47e2 | |||
| da5caa8319 | |||
| ca7714a8a3 | |||
| 4b5f3981d3 | |||
| 7eb1de4709 | |||
| e52df074a1 | |||
| 9846817c7f | |||
| c9ca1c0a25 | |||
| fd2dd9a165 | |||
| 83efebfed9 | |||
| 00669ea3c5 | |||
| f02bf2630a | |||
| db4d2f7eb0 | |||
| b9d2f376d6 | |||
| 49baeae780 | |||
| d76865e621 | |||
| bedf363810 | |||
| 48670c4030 | |||
| ba0cdd307f | |||
| 2a508e6302 | |||
| 9d70579c40 | |||
| e4ac573631 | |||
| 11327cf544 | |||
| 029e10b661 | |||
| c1c8b645e0 | |||
| 49ef7d1353 | |||
| 745886e9dd | |||
| 825945a547 | |||
| e9556170f5 | |||
| 87ffe5b5f8 | |||
| 9466d8b883 | |||
| 25e37e257e | |||
| 165c0c9f0d | |||
| 98cfebf5bc | |||
| 1d910bfc45 | |||
| 94104c2365 | |||
| c5d37a1250 | |||
| 5812e1c976 | |||
| 01bc8bf929 | |||
| dbefb1b290 | |||
| b5b9d061ef | |||
| 20e08bba76 | |||
| 23710ee3fb | |||
| 9b5cc21aa4 | |||
| 1016c9b82b | |||
| c6b9651d08 | |||
| 73302f101a | |||
| 516b4d785f | |||
| a9850c2eec | |||
| 64c5503637 | |||
| d15ea4310a | |||
| 9fa3ef83e5 | |||
| 724e8fe029 | |||
| 3ea5677497 | |||
| a1e3e509fd | |||
| 95b3731df2 | |||
| dcc29f3461 | |||
| 13740de72f | |||
| f2f11c3f2b | |||
| abc2d9b517 | |||
| dc93a688f5 | |||
| 737195e2b1 | |||
| 9964ec9ff5 | |||
| 08d1cc1881 | |||
| 960044556d | |||
| 629378e5a9 | |||
| 33a4e0b910 | |||
| f674024673 | |||
| f10a5475c3 | |||
| 6c8fc5bd88 | |||
| 5a9846600c | |||
| e855f92c35 | |||
| 0a7d8474b1 | |||
| 7f6d23f006 | |||
| ee71915590 | |||
| 68b8848d4a | |||
| d6d16e5967 | |||
| ee0724aedd | |||
| f924a5903a | |||
| 1171638f2a | |||
| bc4757bfc5 | |||
| 744ba6163c | |||
| 2c7e8796b6 | |||
| 647ebdcc9c | |||
| 34a5acdc41 | |||
| 8276cf6d60 | |||
| 0d0331ca2f | |||
| e2423700ea | |||
| 9b7f11d6dd | |||
| 7f179fc2af | |||
| 3e91040017 | |||
| b47dea38e5 | |||
| 3defd285e9 | |||
| 90a09fad44 | |||
| 196c503789 | |||
| 0e0dd81b56 | |||
| 0341ebc953 | |||
| f0e54ca883 | |||
| 6bfd6749e1 | |||
| 7c28a9f9d2 | |||
| 040d8c1feb | |||
| f1f5403132 | |||
| d63ebf9268 | |||
| 9a148b96c0 | |||
| 15579fa702 | |||
| c2bafc6613 | |||
| 1ba3f890e7 | |||
| 48096fbbe1 | |||
| f53e52bbfe | |||
| 332ab25e64 | |||
| 792bd9305c | |||
| c3f2115fb2 | |||
| 2cc09d43ac | |||
| 18140fe4af | |||
| 437e948052 | |||
| e777a2572d | |||
| 6dd9b31108 | |||
| 10055aa06e | |||
| 481f81fe6e | |||
| 0100c67a33 | |||
| 0a0a1358cb | |||
| 2e41d15f0d | |||
| d0e77d29ec | |||
| 4880d41e5a | |||
| 92a8cf1510 | |||
| 7639259c43 | |||
| 262062464e | |||
| 474b9eb364 | |||
| e5a1f62ccf | |||
| eea6924e17 | |||
| 0ae1ec0236 | |||
| ace52876ac | |||
| 467db204a8 | |||
| 0be8897dd6 | |||
| 13f48d95e1 | |||
| f194448d94 | |||
| a99083f03f | |||
| 85bd01790e | |||
| 0ccefeaa99 | |||
| 3ad4d46993 | |||
| 9d6c7decbc | |||
| 329315f461 | |||
| c5e14e78f0 | |||
| 92acb31ece | |||
| 2688546c7a | |||
| 7c346a3ac5 | |||
| abcf58d369 | |||
| 2211428614 | |||
| 08d31ff0d6 | |||
| e055030291 | |||
| 1e5cca5ffb | |||
| 85abeaf7f0 | |||
| 47480809d0 | |||
| 885bb41f27 | |||
| c74e92fb2e | |||
| a4f27b5c1d | |||
| a7941bb4c8 | |||
| 13c29412eb | |||
| 774e24d441 | |||
| 8822761c48 | |||
| 4215f90456 | |||
| c8ac385b88 | |||
| b1ef5c74c8 | |||
| a5ff2ca780 | |||
| f84c4b2d31 | |||
| b03e848669 | |||
| 76ea67af54 | |||
| 12c80e2d40 | |||
| c013953368 | |||
| 34457ead0a | |||
| 5e92889825 | |||
| b2606d209d | |||
| a18beeca1b | |||
| c1293ff395 | |||
| bc6f6c4c39 | |||
| befb84db5f | |||
| 2403288678 | |||
| cac8e1ba18 | |||
| 06255370f7 | |||
| 6ba70a76c2 | |||
| dd53b70b36 | |||
| 6873af5ac3 | |||
| 35d8c41a2b | |||
| 5f4eebe536 | |||
| ba4cfca45b | |||
| f6e4fcd2d0 | |||
| d5f1f76e24 | |||
| 8a0c9d0128 | |||
| a1ff69502a | |||
| b06cf0a06b | |||
| 5d976141fc | |||
| be8f9e2b5a | |||
| 6bf18096e7 | |||
| b7f0f5df90 | |||
| c4c06f0dc4 | |||
| ed569cde55 | |||
| 558a16d273 | |||
| 9290261fef | |||
| e2251c111c | |||
| 21ed17bb2c | |||
| 8cfe0bfe11 | |||
| 54ce865e45 | |||
| ae6d788aff | |||
| f0cfc860a1 | |||
| becdc060e9 | |||
| 9d25e61043 | |||
| 0debe8f7f9 | |||
| 9e68b55018 | |||
| 5783b83168 | |||
| f7060c7287 | |||
| e2866d2595 | |||
| 76701627b6 | |||
| 7f91ac734a | |||
| af7bc47cbf | |||
| a14b0a6fd0 | |||
| 855fedf3aa | |||
| 900427ad30 | |||
| 08bf19f74f | |||
| 68f7cb8f41 | |||
| 3088fae8a2 | |||
| 6d375312ae | |||
| 797a2b70f3 | |||
| 29cf1327ff | |||
| 613d45da37 | |||
| f29926748c | |||
| 9855ca8c15 | |||
| 7644decc64 | |||
| 81bf501c85 | |||
| ecf508ca93 | |||
| 2724b03301 | |||
| b2eb5efa12 | |||
| 661273f7bd | |||
| 5e37195591 | |||
| 0d85ad48de | |||
| 02ad0445b9 | |||
| 2bfe780faf | |||
| 284c1cfaf6 | |||
| a37d1c5f85 | |||
| 639e2c05bf | |||
| 7e5fb055c8 | |||
| 528c692f13 | |||
| dd17d364c7 | |||
| 6e56c3c190 | |||
| 617bb5f12d | |||
| fa1fa359fc | |||
| e9084847cf | |||
| da0a35a5d1 | |||
| 5fb3616c1a | |||
| 4f04e9e1b5 | |||
| 0c5b5ed59c | |||
| de167cdfb6 | |||
| 0a27fc1c2b | |||
| 1e537009e0 | |||
| 188f23faf4 | |||
| dca243825a | |||
| 650022ee10 | |||
| 98a7064f43 | |||
| 9804acd10c | |||
| 51550c96a6 | |||
| 491490c559 | |||
| ec1f13754d | |||
| b840988bbe | |||
| bd4b565799 | |||
| 102a7cbd9e | |||
| 8c34416b1a | |||
| 77af0b4ae4 | |||
| ed2d3ed931 | |||
| 0d584bb0ac | |||
| a95e7cc225 | |||
| c2caeb5900 | |||
| fe6e195c0a | |||
| 027a550c97 | |||
| 1074932eb5 | |||
| 9f0b0837d8 | |||
| d3f32288bf | |||
| c251db709e | |||
| 56d0eb0d0b | |||
| bbd4beeafe | |||
| 460719e0f0 | |||
| eed7f913e5 | |||
| e153eebe87 | |||
| c7eee14f7c | |||
| 48b4be68bd | |||
| 685da9af3e | |||
| ddaf329167 | |||
| 794af5e501 | |||
| 3028e9e29d | |||
| 704a75a2b4 | |||
| 63ae8e3ca5 | |||
| 0f09a15f20 | |||
| 23fbe106a7 | |||
| c7665a7845 | |||
| 41da92e43a | |||
| 9780cb6e35 | |||
| 7d2f5a4385 | |||
| 7144d81059 | |||
| ae162e3a46 | |||
| 311963f8ea | |||
| 2e70c24f29 | |||
| 7300d53a50 | |||
| b338f7750d | |||
| b9bb8d52f4 | |||
| 48396e7eaa | |||
| 27f959990f | |||
| e7d165d99b | |||
| 7df01df8fc | |||
| 896de431be | |||
| e0e6f416c0 | |||
| 07ded4986d | |||
| 0eb2b867c8 | |||
| aaf6759075 | |||
| bce9ed7a6f | |||
| 9edba5d992 | |||
| f9bcb47903 | |||
| 4333bfbeb3 | |||
| b821a15701 | |||
| 5b2ab8b401 | |||
| 7bf287f706 | |||
| 79b907f014 | |||
| 6115620d7d | |||
| b086d16faf | |||
| 9f402e852e | |||
| 2bb558548b | |||
| 7f6029d757 | |||
| df1b972d72 | |||
| 7a3013dcaf | |||
| fa31283d94 | |||
| 2bf6c834c1 | |||
| 94117e0345 | |||
| d8f3fa73ee | |||
| 6defdbe353 | |||
| f59a3744b0 | |||
| 51a0d62723 | |||
| c802e77acb | |||
| db9637bd4d | |||
| 304ce7e703 | |||
| 9ff60f3108 | |||
| 41c8e4e4bd | |||
| 02a1e3fe06 | |||
| f5f8e46f6e | |||
| 09502028ee | |||
| 49e918ff93 | |||
| 1c90a8aa12 | |||
| 6eba1939ef | |||
| 3227d09958 | |||
| c805ff0650 | |||
| 7ee5d9ec0e | |||
| b98e564cd1 | |||
| fd992d6471 | |||
| 50414e95ad | |||
| 6d3eb88b20 | |||
| 33bf13602a | |||
| 0c007d33ae | |||
| 61ea029d76 | |||
| ef7ff4b42a | |||
| f99eca8537 | |||
| c8c50fa4be | |||
| 7307e83860 | |||
| e1e762642a | |||
| 6deb59e7f0 | |||
| cb78f42c41 | |||
| 4e48427bee | |||
| 2418b3e564 | |||
| 4a2233e167 | |||
| 1dbb2b6abe | |||
| b52d66c522 | |||
| 3454587330 | |||
| ac1e402d1d | |||
| 8d0d7a89f7 | |||
| cc285e99ee | |||
| eb8f8defc0 | |||
| 466ac5e49d | |||
| 359954cd11 | |||
| 55e8ad8493 | |||
| 3d64a3c4b7 | |||
| d358a75769 | |||
| 75ebf8f549 | |||
| 4c462923f2 | |||
| 53522a8307 | |||
| c42ad3f042 | |||
| e75ca72abd | |||
| 7e4125cb93 | |||
| 0a568ac9fd | |||
| 859193be37 | |||
| 49c2494d3c | |||
| cfe1980e7a | |||
| f1a5a4cbfe | |||
| ddccb44341 | |||
| 98f43032a0 | |||
| 7bbc3a0121 | |||
| 02e7ed95b4 | |||
| ff540caad7 | |||
| d78345367b | |||
| 236cdb4a23 | |||
| 9d6c91485e | |||
| 077ac246a8 | |||
| 7852b1d2ff | |||
| 6b7574e5fb | |||
| e821e93ba5 | |||
| 8744331ebb | |||
| a5012eda02 | |||
| f9a8831fec | |||
| 39ff7c9bba | |||
| 2d345e606b | |||
| 93f2df0c9e | |||
| 2916af03e6 | |||
| 14a429f4de | |||
| ace7bdf3b4 | |||
| 41c96a032c | |||
| e369292979 | |||
| eab6770695 | |||
| 5cbb59db0a | |||
| a18c1b5ecf | |||
| 2c46b1d0b8 | |||
| 953ffcc293 | |||
| dc23b80352 | |||
| 944e7c4326 | |||
| a89de6bcc4 | |||
| bc3d7da65a | |||
| f2a6619013 | |||
| 1415f89a8c | |||
| cc2c847fd3 | |||
| 8b17f6f5f7 | |||
| d0d1f681ca | |||
| e37009095e | |||
| c75961cd19 | |||
| a30b2cad90 | |||
| 18ea2fea54 | |||
| 53cd73c806 | |||
| 0c03d664b0 | |||
| efaf8e3d0f | |||
| 802a109abd | |||
| 13490d9862 | |||
| c42441dc76 | |||
| 81cd2fc7d9 | |||
| e7c3d2054c | |||
| 8a0dfca204 | |||
| dbc359f0e4 | |||
| 5c3249ca0b | |||
| 3301ebae27 | |||
| fa48f5db1d | |||
| db375abfc7 | |||
| 7044014a73 | |||
| fa9cd87013 | |||
| 4a7474053a | |||
| 00d62c56b0 | |||
| 58e7c1a449 | |||
| cd3944cbb8 | |||
| be572a20af | |||
| b9411f4609 | |||
| 4adbe2a775 | |||
| fcc22076a7 | |||
| 42b6f297f5 | |||
| 22f62b34a3 | |||
| df13216cf4 | |||
| af97f2cd7a | |||
| 145afc049e | |||
| 20e7ebe476 | |||
| 4e220db35d | |||
| d25272f5af | |||
| f87b2b7206 | |||
| 7ecd862879 | |||
| 647cbb5e55 | |||
| db60e3e725 | |||
| 56fd9289c2 | |||
| 7f717585c9 | |||
| df158832ee | |||
| 98e2b47496 | |||
| e85c568228 | |||
| a1e95ee7de | |||
| acb8a8b6c4 | |||
| 6fb4081efd | |||
| 46bb442f02 | |||
| 65a8106a52 | |||
| b8d4b03be0 | |||
| d4c47a050f | |||
| 158027eb72 | |||
| 92af8677e9 | |||
| 891a18819b | |||
| 6615badfe5 | |||
| a0d44150e9 | |||
| f0745cae97 | |||
| 3cb527667c | |||
| 5f9c718056 | |||
| dfe2f71b67 | |||
| 1d8e585500 | |||
| cea5750cae | |||
| 82e95f9c00 | |||
| 3074855cde | |||
| 764c804461 | |||
| 6366f03d07 | |||
| bf0f2b3884 | |||
| c23bd8ee70 | |||
| ad9fb2d4be | |||
| 9e6d07b6fa | |||
| 3601bdc438 | |||
| e432183df3 | |||
| b11cb91a4d | |||
| 08d1e4578d | |||
| 12094d1dbe | |||
| 5361af8c76 | |||
| 7d42d52efd | |||
| 77e6f74fd3 | |||
| 36cfa1d6fd | |||
| 05aa73dad1 | |||
| 8a9ada020b | |||
| a5d0b861c2 | |||
| 96671f713d | |||
| bba22eef77 | |||
| f4d77bf8ce | |||
| 0806284288 | |||
| dc57a34990 | |||
| 4ed8175bdc | |||
| c2a53f6f1e | |||
| a1c0fbec3e | |||
| 78fc084c15 | |||
| 0c8a3b0c06 | |||
| ea5910b102 | |||
| f1febb5e37 | |||
| ca25470ba0 | |||
| ffc84bac10 | |||
| 3a94a63c1d | |||
| ba26ee0910 | |||
| 722d091bcd | |||
| 4237d8ac22 | |||
| b07a61aaef | |||
| f4e7214130 | |||
| c639fcb64e | |||
| a554a2ab9d | |||
| 27fde075b8 | |||
| e0f26d2816 | |||
| 088a46b8ff | |||
| 6437cdcd5c | |||
| 8d20c7a6c4 | |||
| ea8b8dddce | |||
| 369eb05737 | |||
| f6ae5ea1fc | |||
| ef2bb15b30 | |||
| f4a542b913 | |||
| 6f74f768af | |||
| 3a322ee1e4 | |||
| 132aaf6340 | |||
| 59fc2a47d1 | |||
| 7fad22b72c | |||
| 22757465eb | |||
| 9a26ce9f81 | |||
| 7bad788e54 | |||
| 6fba41d80d | |||
| 841054d6a4 | |||
| 438df1240f | |||
| 3498e5854e | |||
| ecf8884136 | |||
| 46c125cbf3 | |||
| 1123054216 | |||
| 22497c8db9 | |||
| 3ea6841e53 | |||
| a2761a4584 | |||
| 40795997dc | |||
| 09172a171c | |||
| abe5a07e6a | |||
| 99caeb28dc | |||
| faa5208bc4 | |||
| 3cc20e6275 | |||
| 7e5a7e525f | |||
| 6502efd4b4 | |||
| a1e183be29 | |||
| c164860994 | |||
| 8e7cfd0919 | |||
| 527216b678 | |||
| d35e25d5f7 | |||
| c241028079 | |||
| 7cdf86345b | |||
| 9d0635ce1c | |||
| 22f7ab8608 | |||
| 8b4aed0d98 | |||
| cfb77eec46 | |||
| 6e6e2fcffe | |||
| 49a0af8165 | |||
| 91a69a897a | |||
| 3cbed42bdb | |||
| ce815aac76 |
@@ -6,7 +6,15 @@
|
||||
"version": "0.28.2",
|
||||
"commands": [
|
||||
"dotnet-csharpier"
|
||||
]
|
||||
],
|
||||
"rollForward": false
|
||||
},
|
||||
"dotnet-affected": {
|
||||
"version": "5.0.0",
|
||||
"commands": [
|
||||
"dotnet-affected"
|
||||
],
|
||||
"rollForward": false
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-2
@@ -212,6 +212,7 @@ dotnet_diagnostic.ide0058.severity = none # Remove unnecessary expression value:
|
||||
dotnet_diagnostic.ide0010.severity = none # Add missing cases to switch statement: Too verbose
|
||||
dotnet_diagnostic.ide0200.severity = none # Remove unnecessary lambda expression: may be performance reasons not to
|
||||
dotnet_diagnostic.ide0058.severity = none # Remove unnecessary expression value: Subjective
|
||||
dotnet_diagnostic.ide0305.severity = none # Use collection expression for fluent: Can obfuscate intent
|
||||
dotnet_diagnostic.ide0001.severity = suggestion # Name can be simplified: Non enforceable in build
|
||||
dotnet_diagnostic.ide0046.severity = suggestion # Use conditional expression for return: Subjective
|
||||
dotnet_diagnostic.ide0045.severity = suggestion # Use conditional expression for assignment: Subjective
|
||||
@@ -233,6 +234,15 @@ dotnet_diagnostic.ide0042.severity = suggestion # Deconstruct variable declarati
|
||||
dotnet_diagnostic.ide0028.severity = suggestion # Use collection initializers: Subjective
|
||||
dotnet_diagnostic.ide0072.severity = suggestion # Populate switch statement: Subjective
|
||||
dotnet_diagnostic.ide0074.severity = suggestion # Use compound assignment: Subjective
|
||||
dotnet_diagnostic.ide0300.severity = suggestion # Use collection expression for array: Subjective, maybe aspirational
|
||||
dotnet_diagnostic.ide0290.severity = suggestion # primary constructors: subjective, and readonly properties are not a thing
|
||||
dotnet_diagnostic.ide0290.severity = suggestion # Use primary constructor: Subjective
|
||||
dotnet_diagnostic.ide0037.severity = suggestion # Use inferred member names: Sometimes its nice to be explicit
|
||||
dotnet_diagnostic.ide0301.severity = suggestion # Use collection expression for empty: Subjective, intent
|
||||
dotnet_diagnostic.ide0021.severity = suggestion # Use expression body for constructors : Subjective
|
||||
dotnet_diagnostic.ide0090.severity = suggestion # Simplify new expression : Subjective
|
||||
|
||||
dotnet_diagnostic.ide0047.severity = suggestion # Parentheses preferences: IDEs don't properly pick it up
|
||||
|
||||
# Maintainability rules
|
||||
dotnet_diagnostic.ca1501.severity = warning # Avoid excessive inheritance
|
||||
@@ -244,9 +254,10 @@ dotnet_diagnostic.ca1508.severity = warning # Avoid dead conditional code
|
||||
dotnet_diagnostic.ca1509.severity = warning # Invalid entry in code metrics configuration file
|
||||
dotnet_diagnostic.ca1861.severity = none # Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
|
||||
|
||||
# CA2007: Consider calling ConfigureAwait on the awaited task (this is not needed for application code, in fact we don't want to call anything but ConfigureAwait(true) which is the default)
|
||||
dotnet_diagnostic.CA2007.severity = none
|
||||
|
||||
dotnet_diagnostic.cs8618.severity = suggestion # nullable problem
|
||||
dotnet_diagnostic.CS0809.severity = suggestion # obsolete errors
|
||||
dotnet_diagnostic.CS0618.severity = suggestion # obsolete errors
|
||||
|
||||
|
||||
# Performance rules
|
||||
|
||||
+29
-26
@@ -4,33 +4,36 @@
|
||||
|
||||
# * @specklesystems/connectors
|
||||
|
||||
# Core
|
||||
# Not needed, falls back on team approval
|
||||
|
||||
# Objects
|
||||
# Converters require product owner approval, anything else falls back to team approval
|
||||
|
||||
Objects/ConverterAutocadCivil/* @clairekuang @connorivy
|
||||
Objects/ConverterCSI/* @connorivy
|
||||
Objects/ConverterDynamo/* @teocomi @alanrynne
|
||||
Objects/ConverterMicrostation/* @connorivy
|
||||
Objects/ConverterRevit/* @connorivy @teocomi
|
||||
Objects/ConverterRhinoGh/* @alanrynne @clairekuang
|
||||
Objects/ConverterTeklaStructures/* @connorivy
|
||||
Objects/StructuralUtilities/PolygonMesher/* @connorivy
|
||||
|
||||
# Connectors
|
||||
|
||||
ConnectorAutocadCivil/* @clairekuang
|
||||
ConnectorArchicad/* @jozseflkiss
|
||||
ConnectorCSI/* @connorivy
|
||||
ConnectorDynamo/* @teocomi @alanrynne
|
||||
ConnectorGrasshopper/* @alanrynne @clairekuang
|
||||
ConnectorMicrostation/* @clairekuang
|
||||
ConnectorRevit/* @teocomi @connorivy
|
||||
ConnectorRhino/* @clairekuang @alanrynne
|
||||
ConnectorTeklaStructures/* @connorivy
|
||||
/Connectors/ArcGIS/* @KatKatKateryna
|
||||
/Connectors/Autocad/* @clairekuang @oguzhankoral @didimitrie
|
||||
/Connectors/Civil3d/* @clairekuang @oguzhankoral @didimitrie
|
||||
/Connectors/CSi/* @bjoernsteinhagen @dogukankaratas
|
||||
/Connectors/Navisworks/* @jsdbroughton
|
||||
/Connectors/Revit/* @clairekuang @oguzhankoral @didimitrie
|
||||
/Connectors/Rhino/* @clairekuang @oguzhankoral @didimitrie
|
||||
/Connectors/Tekla/* @bjoernsteinhagen @dogukankaratas
|
||||
|
||||
# DesktopUI
|
||||
# Converters
|
||||
/Convertors/ArcGIS/* @KatKatKateryna
|
||||
/Convertors/Autocad/* @clairekuang @oguzhankoral @didimitrie
|
||||
/Convertors/Civil3d/* @clairekuang @oguzhankoral @didimitrie
|
||||
/Convertors/CSi/* @bjoernsteinhagen @dogukankaratas
|
||||
/Convertors/Navisworks/* @jsdbroughton
|
||||
/Convertors/Revit/* @clairekuang @oguzhankoral @didimitrie
|
||||
/Convertors/Rhino/* @clairekuang @oguzhankoral @didimitrie
|
||||
/Convertors/Tekla/* @bjoernsteinhagen @dogukankaratas
|
||||
|
||||
DesktopUI2/* @teocomi @clairekuang
|
||||
# DUI
|
||||
|
||||
/DUI3/* @clairekuang @oguzhankoral @didimitrie
|
||||
|
||||
# Importers
|
||||
/Importers/* @JR-Morgan @didimitrie @oguzhankoral @adamhathcock
|
||||
|
||||
# SDK
|
||||
/SDK/* @JR-Morgan @clairekuang @didimitrie @oguzhankoral @adamhathcock
|
||||
|
||||
# Build
|
||||
/Build/* @JR-Morgan @oguzhankoral @adamhathcock
|
||||
|
||||
@@ -1,30 +1,46 @@
|
||||
<!---
|
||||
|
||||
Provide a short summary in the Title above. Examples of good PR titles:
|
||||
Provide a short summary in the Title above. Use the following template:
|
||||
|
||||
* "Feature: adds metrics to component"
|
||||
category(project): summary
|
||||
|
||||
* "Fix: resolves duplication in comment thread"
|
||||
Categories:
|
||||
|
||||
* "Update: apollo v2.34.0"
|
||||
* feat: (new feature for the user, not a new feature for build script)
|
||||
* fix: (bug fix for the user, not a fix to a build script)
|
||||
* docs: (changes to the documentation)
|
||||
* style: (formatting, missing semi colons, etc; no production code change)
|
||||
* refactor: (refactoring production code, eg. renaming a variable)
|
||||
* test: (adding missing tests, refactoring tests; no production code change)
|
||||
* chore: (updating grunt tasks etc; no production code change)
|
||||
|
||||
Example:
|
||||
|
||||
feat(revit): added category filter to send
|
||||
|
||||
-->
|
||||
|
||||
## Description & motivation
|
||||
## Description
|
||||
|
||||
<!---
|
||||
|
||||
Describe your changes, and why you're making them. What benefit will this have to others?
|
||||
Describe your changes, and why you're making them.
|
||||
|
||||
Is this linked to an open Github issue, a thread in Speckle community,
|
||||
or another pull request? Link it here.
|
||||
|
||||
If it is related to a Github issue, and resolves it, please link to the issue number, e.g.:
|
||||
Fixes #85, Fixes #22, Fixes username/repo#123
|
||||
Connects #123
|
||||
Link related github issues here ->
|
||||
Fixes #85, Fixes #22, Connects #123
|
||||
|
||||
-->
|
||||
|
||||
## User Value
|
||||
|
||||
<!---
|
||||
|
||||
Describe in 1 sentence the user value.
|
||||
|
||||
This can also be a link to the relevant thread in Speckle community, or a link to the Linear issue.
|
||||
-->
|
||||
|
||||
|
||||
## Changes:
|
||||
|
||||
<!---
|
||||
@@ -68,35 +84,10 @@ Describe what tests have been added or amended, and why these demonstrate it wor
|
||||
|
||||
<!---
|
||||
|
||||
This checklist is mostly useful as a reminder of small things that can easily be
|
||||
|
||||
forgotten – it is meant as a helpful tool rather than hoops to jump through.
|
||||
|
||||
Put an `x` between the square brackets, e.g. [x], for all the items that apply,
|
||||
|
||||
make notes next to any that haven't been addressed, and remove any items that are not relevant to this PR.
|
||||
This checklist is a useful reminder of related tasks to uphold our repo quality. Amend this list as needed for the pr.
|
||||
|
||||
-->
|
||||
|
||||
- [ ] My pull request follows the guidelines in the [Contributing guide](https://github.com/specklesystems/speckle-server/blob/main/CONTRIBUTING.md)?
|
||||
- [ ] My pull request does not duplicate any other open [Pull Requests](../../pulls) for the same update/change?
|
||||
- [ ] My commits are related to the pull request and do not amend unrelated code or documentation.
|
||||
- [ ] My code follows a similar style to existing code.
|
||||
- [ ] I have added appropriate tests.
|
||||
- [ ] I have updated or added relevant documentation.
|
||||
|
||||
## References
|
||||
|
||||
<!---
|
||||
|
||||
(Optional -- remove this section if not needed )
|
||||
|
||||
Include **important** links regarding the implementation of this PR.
|
||||
|
||||
This usually includes a RFC or an aggregation of issues and/or individual conversations
|
||||
|
||||
that helped put this solution together. This helps ensure we retain and share knowledge
|
||||
|
||||
regarding the implementation, and may help others understand motivation and design decisions etc..
|
||||
|
||||
-->
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
name: .NET Build
|
||||
|
||||
on:
|
||||
pull_request: # Run build on every pull request that is not to main/dev
|
||||
branches-ignore:
|
||||
- main
|
||||
- dev
|
||||
workflow_call:
|
||||
outputs:
|
||||
version:
|
||||
value: ${{ jobs.build.outputs.version }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
outputs:
|
||||
version: ${{ steps.set-version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.2xx # Align with global.json (including roll forward rules)
|
||||
|
||||
- name: Cache Nuget
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-nuget-
|
||||
|
||||
- name: ⚒️ Run GitVersion
|
||||
run: ./build.ps1 build-server-version
|
||||
|
||||
- name: ⚒️ Run build
|
||||
run: ./build.ps1
|
||||
|
||||
- name: ⬆️ Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: output-${{ env.GitVersion_FullSemVer }}
|
||||
path: output/*.*
|
||||
compression-level: 0 # no compression
|
||||
|
||||
- id: set-version
|
||||
name: Set version to output
|
||||
run: echo "version=${{ env.GitVersion_FullSemVer }}" >> "$GITHUB_OUTPUT"
|
||||
@@ -1,30 +0,0 @@
|
||||
name: .NET Build and Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main", "dev"] # Continuous delivery on every long-lived branch
|
||||
tags: ["3.*"] # Manual delivery on every 3.x tag
|
||||
pull_request:
|
||||
branches: ["main", "dev"] # Releases on every PR that targets main or dev
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: ./.github/workflows/ci.yml
|
||||
|
||||
# deploy-installers:
|
||||
# runs-on: ubuntu-latest
|
||||
# needs: build
|
||||
# steps:
|
||||
# - name: 🔫 Trigger Build Installers
|
||||
# uses: ALEEF02/workflow-dispatch@v3.0.0
|
||||
# with:
|
||||
# workflow: Build Installers
|
||||
# repo: specklesystems/connector-installers
|
||||
# token: ${{ secrets.CONNECTORS_GH_TOKEN }}
|
||||
# inputs: '{ "run_id": "${{ github.run_id }}", "version": "${{ needs.build.outputs.version }}" }'
|
||||
# ref: main
|
||||
# wait-for-completion: true
|
||||
# wait-for-completion-interval: 10s
|
||||
# wait-for-completion-timeout: 10m
|
||||
# display-workflow-run-url: true
|
||||
# display-workflow-run-url-interval: 10s
|
||||
@@ -0,0 +1,59 @@
|
||||
name: .NET Build
|
||||
|
||||
on:
|
||||
pull_request
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
outputs:
|
||||
version: ${{ steps.set-version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.4xx # Align with global.json (including roll forward rules)
|
||||
|
||||
- name: Cache Nuget
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
|
||||
- name: ⚒️ Run build
|
||||
run: ./build.ps1 test
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.4xx # Align with global.json (including roll forward rules)
|
||||
|
||||
- name: Cache Nuget
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
|
||||
- name: ⚒️ Run Build on Linux
|
||||
run: ./build.sh build-linux
|
||||
|
||||
- name: ⚒️ Run tests
|
||||
run: ./build.sh test-only
|
||||
|
||||
- name: Upload coverage reports to Codecov with GitHub Action
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
file: Converters/**/coverage.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
@@ -0,0 +1,105 @@
|
||||
name: .NET Build and Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main", "installer-test/**"]
|
||||
tags: ["v3.*"] # Manual delivery on every 3.x tag
|
||||
|
||||
jobs:
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
SPECKLE_VERSION: "unset"
|
||||
outputs:
|
||||
version: ${{ steps.set-version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.4xx # Align with global.json (including roll forward rules)
|
||||
|
||||
- name: Cache Nuget
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
|
||||
- name: ⚒️ Run build on Windows
|
||||
run: ./build.ps1 zip
|
||||
|
||||
- name: ⬆️ Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: output-${{ env.SPECKLE_VERSION }}
|
||||
path: output/*.*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
compression-level: 0 # no compression
|
||||
- id: set-version
|
||||
name: Set version to output
|
||||
run: echo "version=${{ env.SPECKLE_VERSION }}" >> "$Env:GITHUB_OUTPUT"
|
||||
|
||||
deploy-installers:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-windows
|
||||
env:
|
||||
IS_PUBLIC_RELEASE: ${{ github.ref_type == 'tag' }}
|
||||
IS_TEST_INSTALLER: ${{ github.ref_type != 'tag' }}
|
||||
steps:
|
||||
- name: 🔫 Trigger Build Installers
|
||||
uses: ALEEF02/workflow-dispatch@v3.0.0
|
||||
with:
|
||||
workflow: Build Installers
|
||||
repo: specklesystems/connector-installers
|
||||
token: ${{ secrets.CONNECTORS_GH_TOKEN }}
|
||||
inputs: '{ "run_id": "${{ github.run_id }}", "version": "${{ needs.build-windows.outputs.version }}", "public_release": ${{ env.IS_PUBLIC_RELEASE }}, "store_artifacts": ${{ env.IS_TEST_INSTALLER }} }'
|
||||
ref: main
|
||||
wait-for-completion: true
|
||||
wait-for-completion-interval: 10s
|
||||
wait-for-completion-timeout: 10m
|
||||
display-workflow-run-url: true
|
||||
display-workflow-run-url-interval: 10s
|
||||
|
||||
- uses: geekyeggo/delete-artifact@v5
|
||||
with:
|
||||
name: output-*
|
||||
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.4xx # Align with global.json (including roll forward rules)
|
||||
|
||||
- name: Cache Nuget
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
|
||||
- name: ⚒️ Run tests on Linux
|
||||
run: ./build.sh test-only
|
||||
|
||||
- name: ⚒️ Run Build and Pack on Linux
|
||||
run: ./build.sh build-linux
|
||||
|
||||
- name: Upload coverage reports to Codecov with GitHub Action
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: Converters/**/coverage.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
- name: Push to nuget.org
|
||||
if: (github.ref_type == 'tag')
|
||||
run: dotnet nuget push output/*.nupkg --source "https://api.nuget.org/v3/index.json" --api-key ${{secrets.CONNECTORS_NUGET_TOKEN }} --skip-duplicate
|
||||
@@ -19,3 +19,5 @@ tools
|
||||
.DS_Store
|
||||
*.snupkg
|
||||
coverage.xml
|
||||
output/
|
||||
Images/Thumbs.db
|
||||
|
||||
@@ -0,0 +1,424 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.10.35027.167
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{85A13E25-EB29-4F31-8853-B9EE83275B3D}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.csharpierrc.yaml = .csharpierrc.yaml
|
||||
.editorconfig = .editorconfig
|
||||
codecov.yml = codecov.yml
|
||||
Directory.Build.props = Directory.Build.props
|
||||
Directory.Build.targets = Directory.Build.targets
|
||||
Directory.Packages.props = Directory.Packages.props
|
||||
global.json = global.json
|
||||
README.md = README.md
|
||||
CodeMetricsConfig.txt = CodeMetricsConfig.txt
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DUI3", "DUI3", "{FD4D6594-D81E-456F-8F2E-35B09E04A755}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Revit", "Revit", "{D92751C8-1039-4005-90B2-913E55E0B8BD}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{2E00592E-558D-492D-88F9-3ECEE4C0C7DA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Revit2023", "Connectors\Revit\Speckle.Connectors.Revit2023\Speckle.Connectors.Revit2023.csproj", "{01F98733-7352-47AD-A594-537D979DE3DE}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Connectors.RevitShared", "Connectors\Revit\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.shproj", "{DC570FFF-6FE5-47BD-8BC1-B471A6067786}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.RevitShared", "Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.shproj", "{E1C43415-3200-45F4-8BF9-A4DD7D7F2ED6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2023.DependencyInjection", "Converters\Revit\Speckle.Converters.Revit2023.DependencyInjection\Speckle.Converters.Revit2023.DependencyInjection.csproj", "{83EAD6F0-3CB3-456A-AD81-072127D0DE0E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2023", "Converters\Revit\Speckle.Converters.Revit2023\Speckle.Converters.Revit2023.csproj", "{26391930-F86F-47E0-A5F6-B89919E38CE1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.DUI", "DUI3\Speckle.Connectors.DUI\Speckle.Connectors.DUI.csproj", "{D81C0B87-F0C1-4297-A147-02F001FB7E1E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Autofac", "Sdk\Speckle.Autofac\Speckle.Autofac.csproj", "{C9D4CA21-182B-4ED2-81BB-280A6FD713F6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Utils", "Sdk\Speckle.Connectors.Utils\Speckle.Connectors.Utils.csproj", "{7291B93C-615D-42DE-B8C1-3F9DF643E0FC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Common", "Sdk\Speckle.Converters.Common\Speckle.Converters.Common.csproj", "{8AEF06C0-CA5C-4460-BC2D-ADE5F35D0434}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Rhino", "Rhino", "{9584AEE5-CD59-46E6-93E6-2DC2B5285B75}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Rhino7", "Connectors\Rhino\Speckle.Connectors.Rhino7\Speckle.Connectors.Rhino7.csproj", "{1E2644A9-6B31-4350-8772-CEAAD6EE0B21}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Rhino7", "Converters\Rhino\Speckle.Converters.Rhino7\Speckle.Converters.Rhino7.csproj", "{65A2F556-F14A-49F3-8A92-7F2E1E7ED3B5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Rhino7.DependencyInjection", "Converters\Rhino\Speckle.Converters.Rhino7.DependencyInjection\Speckle.Converters.Rhino7.DependencyInjection.csproj", "{9C1ECA1D-DE98-4FB7-92D0-FC45BB308E5D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.ArcGIS3", "Connectors\ArcGIS\Speckle.Connectors.ArcGIS3\Speckle.Connectors.ArcGIS3.csproj", "{A97F7177-86C7-4B38-A6ED-DA51BF762471}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.ArcGIS3", "Converters\ArcGIS\Speckle.Converters.ArcGIS3\Speckle.Converters.ArcGIS3.csproj", "{139F7A79-69E4-4B8A-B2A5-6A30A66C495C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.ArcGIS3.DependencyInjection", "Converters\ArcGIS\Speckle.Converters.ArcGIS3.DependencyInjection\Speckle.Converters.ArcGIS3.DependencyInjection.csproj", "{7DFF1591-237D-499E-A767-EE37B93FB958}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ArcGIS", "ArcGIS", "{CCF48B65-33D1-4E8B-A57B-E03394730B21}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Autocad2023", "Connectors\Autocad\Speckle.Connectors.Autocad2023\Speckle.Connectors.Autocad2023.csproj", "{89C4CBC7-1606-40DE-B6DA-FBE3AAC98395}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Connectors.AutocadShared", "Connectors\Autocad\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.shproj", "{41BC679F-887F-44CF-971D-A5502EE87DB0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Common.DependencyInjection", "Sdk\Speckle.Converters.Common.DependencyInjection\Speckle.Converters.Common.DependencyInjection.csproj", "{11F7D41B-AFCA-4D29-BC08-285A14BF3A3B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Autocad", "Autocad", "{804E065F-914C-414A-AF84-009312C3CFF6}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.AutocadShared", "Converters\Autocad\Speckle.Converters.AutocadShared\Speckle.Converters.AutocadShared.shproj", "{9ADD1B7A-6401-4202-8613-F668E2FBC0A4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Autocad2023", "Converters\Autocad\Speckle.Converters.Autocad2023\Speckle.Converters.Autocad2023.csproj", "{631C295A-7CCF-4B42-8686-7034E31469E7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Autocad2023.DependencyInjection", "Converters\Autocad\Speckle.Converters.Autocad2023.DependencyInjection\Speckle.Converters.Autocad2023.DependencyInjection.csproj", "{D940853C-003A-482C-BDB0-665367F274A0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.DUI.WebView", "DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj", "{7420652C-3046-4F38-BE64-9B9E69D76FA2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Build", "Build\Build.csproj", "{C50AA3E3-8C31-4131-9DEC-1D8B377D5A89}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HostApps", "HostApps", "{42826721-9A18-4762-8BA9-F1429DD5C5B1}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{59E8E8F3-4E42-4E92-83B3-B1C2AB901D18}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.github\workflows\ci.yml = .github\workflows\ci.yml
|
||||
.github\workflows\main.yml = .github\workflows\main.yml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Civil3d2024", "Connectors\Autocad\Speckle.Connectors.Civil3d2024\Speckle.Connectors.Civil3d2024.csproj", "{CA8EAE01-AB9F-4EC1-B6F3-73721487E9E1}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.Civil3dShared", "Converters\Civil3d\Speckle.Converters.Civil3dShared\Speckle.Converters.Civil3dShared.shproj", "{35175682-DA83-4C0A-A49D-B191F5885D8E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Civil3d2024.DependencyInjection", "Converters\Civil3d\Speckle.Converters.Civil3d2024.DependencyInjection\Speckle.Converters.Civil3d2024.DependencyInjection.csproj", "{80F965C4-E2A8-4F54-985D-73D06E45F9CE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Autocad2024", "Converters\Autocad\Speckle.Converters.Autocad2024\Speckle.Converters.Autocad2024.csproj", "{C2DE264A-AA87-4012-B954-17E3F403A237}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Autocad2024.DependencyInjection", "Converters\Autocad\Speckle.Converters.Autocad2024.DependencyInjection\Speckle.Converters.Autocad2024.DependencyInjection.csproj", "{AF507D61-6766-4C20-9F58-23DC29508219}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Civil3d2024", "Converters\Civil3d\Speckle.Converters.Civil3d2024\Speckle.Converters.Civil3d2024.csproj", "{25172C49-7AA4-4739-BB07-69785094C379}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.RhinoShared", "Converters\Rhino\Speckle.Converters.RhinoShared\Speckle.Converters.RhinoShared.shproj", "{E1C43415-3200-45F4-8BF9-A4DD7D7F2ED9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Rhino7.Tests", "Converters\Rhino\Speckle.Converters.Rhino7.Tests\Speckle.Converters.Rhino7.Tests.csproj", "{AC2DB416-F05C-4296-9040-56D6AD4FCD27}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2023.Tests", "Converters\Revit\Speckle.Converters.Revit2023.Tests\Speckle.Converters.Revit2023.Tests.csproj", "{68CF9BDF-94AC-4D2D-A7BD-D1C064F97051}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Testing", "Sdk\Speckle.Testing\Speckle.Testing.csproj", "{A3869243-B462-4986-914B-94E407D8D20F}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.RevitShared.DependencyInjection", "Converters\Revit\Speckle.Converters.RevitShared.DependencyInjection\Speckle.Converters.RevitShared.DependencyInjection.shproj", "{6067BA60-D279-4156-8AE1-6B44E2D19187}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Revit2024", "Connectors\Revit\Speckle.Connectors.Revit2024\Speckle.Connectors.Revit2024.csproj", "{617BD3C7-87D9-4D28-8AC9-4910945BB9FC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2024", "Converters\Revit\Speckle.Converters.Revit2024\Speckle.Converters.Revit2024.csproj", "{67B888D9-C6C4-49F1-883C-5B964151D889}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2024.DependencyInjection", "Converters\Revit\Speckle.Converters.Revit2024.DependencyInjection\Speckle.Converters.Revit2024.DependencyInjection.csproj", "{7F3055BA-70AA-424C-8748-345AF35127E9}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2023", "2023", "{E9DEBA00-50A4-485D-BA65-D8AB3E3467AB}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2024", "2024", "{57F59C0C-5687-4AF9-AE1C-1933B539F0E4}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{FC224610-32D3-454E-9BC1-1219FE8ACD5F}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.RevitShared.Tests", "Converters\Revit\Speckle.Converters.RevitShared.Tests\Speckle.Converters.RevitShared.Tests.shproj", "{E1C43415-3202-45F4-8BF9-A4DD7D7F2ED6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2024.Tests", "Converters\Revit\Speckle.Converters.Revit2024.Tests\Speckle.Converters.Revit2024.Tests.csproj", "{C32274D9-1B66-4D5C-82F9-EB3F10F46752}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Connectors.RevitShared.Cef", "Connectors\Revit\Speckle.Connectors.RevitShared.Cef\Speckle.Connectors.RevitShared.Cef.shproj", "{6A40CBE4-ECAB-4CED-9917-5C64CBF75DA6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2025", "2025", "{8AC2AD6D-6C74-4B24-8DF6-42717FC9B804}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Revit2025", "Connectors\Revit\Speckle.Connectors.Revit2025\Speckle.Connectors.Revit2025.csproj", "{A6DE3DA0-B242-4F49-AEF0-4E26AF92D16C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2025", "Converters\Revit\Speckle.Converters.Revit2025\Speckle.Converters.Revit2025.csproj", "{4D40A101-07E6-4FF2-8934-83434932591D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2025.DependencyInjection", "Converters\Revit\Speckle.Converters.Revit2025.DependencyInjection\Speckle.Converters.Revit2025.DependencyInjection.csproj", "{20751904-0DFC-4126-BF2A-834B53841010}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Revit2022", "Connectors\Revit\Speckle.Connectors.Revit2022\Speckle.Connectors.Revit2022.csproj", "{7F1FDCF2-0CE8-4119-B3C1-F2CC6D7E1C36}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2022", "Converters\Revit\Speckle.Converters.Revit2022\Speckle.Converters.Revit2022.csproj", "{19424B55-058C-4E9C-B86F-700AEF9EAEC3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2022.DependencyInjection", "Converters\Revit\Speckle.Converters.Revit2022.DependencyInjection\Speckle.Converters.Revit2022.DependencyInjection.csproj", "{881D71A3-D276-4108-98C6-0FFD32129B9C}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2022", "2022", "{0AF38BA3-65A0-481B-8CBB-B82E406E1575}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Connectors.DUI.Tests", "DUI3\Speckle.Connectors.DUI.Tests\Speckle.Connectors.DUI.Tests.csproj", "{EB83A3A3-F9B6-4281-8EBF-F7289FB5D885}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2022.Tests", "Converters\Revit\Speckle.Converters.Revit2022.Tests\Speckle.Converters.Revit2022.Tests.csproj", "{D8069A23-AD2E-4C9E-8574-7E8C45296A46}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2023", "2023", "{2D5AE63D-85C0-43D1-84BF-04418ED93F63}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2024", "2024", "{2F45036E-D817-41E9-B82F-DBE013EC95D0}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Civil3d", "Civil3d", "{91D70DE1-DC8E-4AE1-B100-0671D6263FC5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{4721AA15-AF6E-4A62-A2C3-65564DC563E6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{01F98733-7352-47AD-A594-537D979DE3DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{01F98733-7352-47AD-A594-537D979DE3DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{01F98733-7352-47AD-A594-537D979DE3DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{01F98733-7352-47AD-A594-537D979DE3DE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{83EAD6F0-3CB3-456A-AD81-072127D0DE0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{83EAD6F0-3CB3-456A-AD81-072127D0DE0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{83EAD6F0-3CB3-456A-AD81-072127D0DE0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{83EAD6F0-3CB3-456A-AD81-072127D0DE0E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{26391930-F86F-47E0-A5F6-B89919E38CE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{26391930-F86F-47E0-A5F6-B89919E38CE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{26391930-F86F-47E0-A5F6-B89919E38CE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{26391930-F86F-47E0-A5F6-B89919E38CE1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D81C0B87-F0C1-4297-A147-02F001FB7E1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D81C0B87-F0C1-4297-A147-02F001FB7E1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D81C0B87-F0C1-4297-A147-02F001FB7E1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D81C0B87-F0C1-4297-A147-02F001FB7E1E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C9D4CA21-182B-4ED2-81BB-280A6FD713F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C9D4CA21-182B-4ED2-81BB-280A6FD713F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C9D4CA21-182B-4ED2-81BB-280A6FD713F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C9D4CA21-182B-4ED2-81BB-280A6FD713F6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7291B93C-615D-42DE-B8C1-3F9DF643E0FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7291B93C-615D-42DE-B8C1-3F9DF643E0FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7291B93C-615D-42DE-B8C1-3F9DF643E0FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7291B93C-615D-42DE-B8C1-3F9DF643E0FC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8AEF06C0-CA5C-4460-BC2D-ADE5F35D0434}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8AEF06C0-CA5C-4460-BC2D-ADE5F35D0434}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8AEF06C0-CA5C-4460-BC2D-ADE5F35D0434}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8AEF06C0-CA5C-4460-BC2D-ADE5F35D0434}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1E2644A9-6B31-4350-8772-CEAAD6EE0B21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1E2644A9-6B31-4350-8772-CEAAD6EE0B21}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1E2644A9-6B31-4350-8772-CEAAD6EE0B21}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1E2644A9-6B31-4350-8772-CEAAD6EE0B21}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{65A2F556-F14A-49F3-8A92-7F2E1E7ED3B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{65A2F556-F14A-49F3-8A92-7F2E1E7ED3B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{65A2F556-F14A-49F3-8A92-7F2E1E7ED3B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{65A2F556-F14A-49F3-8A92-7F2E1E7ED3B5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9C1ECA1D-DE98-4FB7-92D0-FC45BB308E5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9C1ECA1D-DE98-4FB7-92D0-FC45BB308E5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9C1ECA1D-DE98-4FB7-92D0-FC45BB308E5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9C1ECA1D-DE98-4FB7-92D0-FC45BB308E5D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A97F7177-86C7-4B38-A6ED-DA51BF762471}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A97F7177-86C7-4B38-A6ED-DA51BF762471}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A97F7177-86C7-4B38-A6ED-DA51BF762471}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A97F7177-86C7-4B38-A6ED-DA51BF762471}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{139F7A79-69E4-4B8A-B2A5-6A30A66C495C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{139F7A79-69E4-4B8A-B2A5-6A30A66C495C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{139F7A79-69E4-4B8A-B2A5-6A30A66C495C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{139F7A79-69E4-4B8A-B2A5-6A30A66C495C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7DFF1591-237D-499E-A767-EE37B93FB958}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7DFF1591-237D-499E-A767-EE37B93FB958}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7DFF1591-237D-499E-A767-EE37B93FB958}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7DFF1591-237D-499E-A767-EE37B93FB958}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{89C4CBC7-1606-40DE-B6DA-FBE3AAC98395}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{89C4CBC7-1606-40DE-B6DA-FBE3AAC98395}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{89C4CBC7-1606-40DE-B6DA-FBE3AAC98395}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{89C4CBC7-1606-40DE-B6DA-FBE3AAC98395}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{11F7D41B-AFCA-4D29-BC08-285A14BF3A3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{11F7D41B-AFCA-4D29-BC08-285A14BF3A3B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{11F7D41B-AFCA-4D29-BC08-285A14BF3A3B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{11F7D41B-AFCA-4D29-BC08-285A14BF3A3B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{631C295A-7CCF-4B42-8686-7034E31469E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{631C295A-7CCF-4B42-8686-7034E31469E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{631C295A-7CCF-4B42-8686-7034E31469E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{631C295A-7CCF-4B42-8686-7034E31469E7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D940853C-003A-482C-BDB0-665367F274A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D940853C-003A-482C-BDB0-665367F274A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D940853C-003A-482C-BDB0-665367F274A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D940853C-003A-482C-BDB0-665367F274A0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7420652C-3046-4F38-BE64-9B9E69D76FA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7420652C-3046-4F38-BE64-9B9E69D76FA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7420652C-3046-4F38-BE64-9B9E69D76FA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7420652C-3046-4F38-BE64-9B9E69D76FA2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C50AA3E3-8C31-4131-9DEC-1D8B377D5A89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C50AA3E3-8C31-4131-9DEC-1D8B377D5A89}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C50AA3E3-8C31-4131-9DEC-1D8B377D5A89}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C50AA3E3-8C31-4131-9DEC-1D8B377D5A89}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CA8EAE01-AB9F-4EC1-B6F3-73721487E9E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CA8EAE01-AB9F-4EC1-B6F3-73721487E9E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA8EAE01-AB9F-4EC1-B6F3-73721487E9E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA8EAE01-AB9F-4EC1-B6F3-73721487E9E1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{80F965C4-E2A8-4F54-985D-73D06E45F9CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{80F965C4-E2A8-4F54-985D-73D06E45F9CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{80F965C4-E2A8-4F54-985D-73D06E45F9CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{80F965C4-E2A8-4F54-985D-73D06E45F9CE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C2DE264A-AA87-4012-B954-17E3F403A237}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C2DE264A-AA87-4012-B954-17E3F403A237}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C2DE264A-AA87-4012-B954-17E3F403A237}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C2DE264A-AA87-4012-B954-17E3F403A237}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AF507D61-6766-4C20-9F58-23DC29508219}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AF507D61-6766-4C20-9F58-23DC29508219}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AF507D61-6766-4C20-9F58-23DC29508219}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AF507D61-6766-4C20-9F58-23DC29508219}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{25172C49-7AA4-4739-BB07-69785094C379}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{25172C49-7AA4-4739-BB07-69785094C379}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{25172C49-7AA4-4739-BB07-69785094C379}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{25172C49-7AA4-4739-BB07-69785094C379}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AC2DB416-F05C-4296-9040-56D6AD4FCD27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AC2DB416-F05C-4296-9040-56D6AD4FCD27}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AC2DB416-F05C-4296-9040-56D6AD4FCD27}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AC2DB416-F05C-4296-9040-56D6AD4FCD27}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{68CF9BDF-94AC-4D2D-A7BD-D1C064F97051}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{68CF9BDF-94AC-4D2D-A7BD-D1C064F97051}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{68CF9BDF-94AC-4D2D-A7BD-D1C064F97051}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{68CF9BDF-94AC-4D2D-A7BD-D1C064F97051}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A3869243-B462-4986-914B-94E407D8D20F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A3869243-B462-4986-914B-94E407D8D20F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A3869243-B462-4986-914B-94E407D8D20F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A3869243-B462-4986-914B-94E407D8D20F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{617BD3C7-87D9-4D28-8AC9-4910945BB9FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{617BD3C7-87D9-4D28-8AC9-4910945BB9FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{617BD3C7-87D9-4D28-8AC9-4910945BB9FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{617BD3C7-87D9-4D28-8AC9-4910945BB9FC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{67B888D9-C6C4-49F1-883C-5B964151D889}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{67B888D9-C6C4-49F1-883C-5B964151D889}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{67B888D9-C6C4-49F1-883C-5B964151D889}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{67B888D9-C6C4-49F1-883C-5B964151D889}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7F3055BA-70AA-424C-8748-345AF35127E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7F3055BA-70AA-424C-8748-345AF35127E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7F3055BA-70AA-424C-8748-345AF35127E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7F3055BA-70AA-424C-8748-345AF35127E9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C32274D9-1B66-4D5C-82F9-EB3F10F46752}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C32274D9-1B66-4D5C-82F9-EB3F10F46752}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C32274D9-1B66-4D5C-82F9-EB3F10F46752}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C32274D9-1B66-4D5C-82F9-EB3F10F46752}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A6DE3DA0-B242-4F49-AEF0-4E26AF92D16C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A6DE3DA0-B242-4F49-AEF0-4E26AF92D16C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A6DE3DA0-B242-4F49-AEF0-4E26AF92D16C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A6DE3DA0-B242-4F49-AEF0-4E26AF92D16C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4D40A101-07E6-4FF2-8934-83434932591D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4D40A101-07E6-4FF2-8934-83434932591D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4D40A101-07E6-4FF2-8934-83434932591D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4D40A101-07E6-4FF2-8934-83434932591D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{20751904-0DFC-4126-BF2A-834B53841010}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{20751904-0DFC-4126-BF2A-834B53841010}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{20751904-0DFC-4126-BF2A-834B53841010}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{20751904-0DFC-4126-BF2A-834B53841010}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7F1FDCF2-0CE8-4119-B3C1-F2CC6D7E1C36}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{7F1FDCF2-0CE8-4119-B3C1-F2CC6D7E1C36}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{7F1FDCF2-0CE8-4119-B3C1-F2CC6D7E1C36}.Release|Any CPU.ActiveCfg = Debug|x64
|
||||
{7F1FDCF2-0CE8-4119-B3C1-F2CC6D7E1C36}.Release|Any CPU.Build.0 = Debug|x64
|
||||
{19424B55-058C-4E9C-B86F-700AEF9EAEC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{19424B55-058C-4E9C-B86F-700AEF9EAEC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{19424B55-058C-4E9C-B86F-700AEF9EAEC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{19424B55-058C-4E9C-B86F-700AEF9EAEC3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{881D71A3-D276-4108-98C6-0FFD32129B9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{881D71A3-D276-4108-98C6-0FFD32129B9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{881D71A3-D276-4108-98C6-0FFD32129B9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{881D71A3-D276-4108-98C6-0FFD32129B9C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EB83A3A3-F9B6-4281-8EBF-F7289FB5D885}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EB83A3A3-F9B6-4281-8EBF-F7289FB5D885}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EB83A3A3-F9B6-4281-8EBF-F7289FB5D885}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EB83A3A3-F9B6-4281-8EBF-F7289FB5D885}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D8069A23-AD2E-4C9E-8574-7E8C45296A46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D8069A23-AD2E-4C9E-8574-7E8C45296A46}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D8069A23-AD2E-4C9E-8574-7E8C45296A46}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D8069A23-AD2E-4C9E-8574-7E8C45296A46}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{D92751C8-1039-4005-90B2-913E55E0B8BD} = {42826721-9A18-4762-8BA9-F1429DD5C5B1}
|
||||
{01F98733-7352-47AD-A594-537D979DE3DE} = {E9DEBA00-50A4-485D-BA65-D8AB3E3467AB}
|
||||
{DC570FFF-6FE5-47BD-8BC1-B471A6067786} = {FC224610-32D3-454E-9BC1-1219FE8ACD5F}
|
||||
{E1C43415-3200-45F4-8BF9-A4DD7D7F2ED6} = {FC224610-32D3-454E-9BC1-1219FE8ACD5F}
|
||||
{83EAD6F0-3CB3-456A-AD81-072127D0DE0E} = {E9DEBA00-50A4-485D-BA65-D8AB3E3467AB}
|
||||
{26391930-F86F-47E0-A5F6-B89919E38CE1} = {E9DEBA00-50A4-485D-BA65-D8AB3E3467AB}
|
||||
{D81C0B87-F0C1-4297-A147-02F001FB7E1E} = {FD4D6594-D81E-456F-8F2E-35B09E04A755}
|
||||
{C9D4CA21-182B-4ED2-81BB-280A6FD713F6} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
|
||||
{7291B93C-615D-42DE-B8C1-3F9DF643E0FC} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
|
||||
{8AEF06C0-CA5C-4460-BC2D-ADE5F35D0434} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
|
||||
{9584AEE5-CD59-46E6-93E6-2DC2B5285B75} = {42826721-9A18-4762-8BA9-F1429DD5C5B1}
|
||||
{1E2644A9-6B31-4350-8772-CEAAD6EE0B21} = {9584AEE5-CD59-46E6-93E6-2DC2B5285B75}
|
||||
{65A2F556-F14A-49F3-8A92-7F2E1E7ED3B5} = {9584AEE5-CD59-46E6-93E6-2DC2B5285B75}
|
||||
{9C1ECA1D-DE98-4FB7-92D0-FC45BB308E5D} = {9584AEE5-CD59-46E6-93E6-2DC2B5285B75}
|
||||
{A97F7177-86C7-4B38-A6ED-DA51BF762471} = {CCF48B65-33D1-4E8B-A57B-E03394730B21}
|
||||
{139F7A79-69E4-4B8A-B2A5-6A30A66C495C} = {CCF48B65-33D1-4E8B-A57B-E03394730B21}
|
||||
{7DFF1591-237D-499E-A767-EE37B93FB958} = {CCF48B65-33D1-4E8B-A57B-E03394730B21}
|
||||
{CCF48B65-33D1-4E8B-A57B-E03394730B21} = {42826721-9A18-4762-8BA9-F1429DD5C5B1}
|
||||
{11F7D41B-AFCA-4D29-BC08-285A14BF3A3B} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
|
||||
{804E065F-914C-414A-AF84-009312C3CFF6} = {42826721-9A18-4762-8BA9-F1429DD5C5B1}
|
||||
{7420652C-3046-4F38-BE64-9B9E69D76FA2} = {FD4D6594-D81E-456F-8F2E-35B09E04A755}
|
||||
{C50AA3E3-8C31-4131-9DEC-1D8B377D5A89} = {59E8E8F3-4E42-4E92-83B3-B1C2AB901D18}
|
||||
{E1C43415-3200-45F4-8BF9-A4DD7D7F2ED9} = {9584AEE5-CD59-46E6-93E6-2DC2B5285B75}
|
||||
{AC2DB416-F05C-4296-9040-56D6AD4FCD27} = {9584AEE5-CD59-46E6-93E6-2DC2B5285B75}
|
||||
{68CF9BDF-94AC-4D2D-A7BD-D1C064F97051} = {E9DEBA00-50A4-485D-BA65-D8AB3E3467AB}
|
||||
{A3869243-B462-4986-914B-94E407D8D20F} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
|
||||
{6067BA60-D279-4156-8AE1-6B44E2D19187} = {FC224610-32D3-454E-9BC1-1219FE8ACD5F}
|
||||
{617BD3C7-87D9-4D28-8AC9-4910945BB9FC} = {57F59C0C-5687-4AF9-AE1C-1933B539F0E4}
|
||||
{67B888D9-C6C4-49F1-883C-5B964151D889} = {57F59C0C-5687-4AF9-AE1C-1933B539F0E4}
|
||||
{7F3055BA-70AA-424C-8748-345AF35127E9} = {57F59C0C-5687-4AF9-AE1C-1933B539F0E4}
|
||||
{E9DEBA00-50A4-485D-BA65-D8AB3E3467AB} = {D92751C8-1039-4005-90B2-913E55E0B8BD}
|
||||
{57F59C0C-5687-4AF9-AE1C-1933B539F0E4} = {D92751C8-1039-4005-90B2-913E55E0B8BD}
|
||||
{FC224610-32D3-454E-9BC1-1219FE8ACD5F} = {D92751C8-1039-4005-90B2-913E55E0B8BD}
|
||||
{E1C43415-3202-45F4-8BF9-A4DD7D7F2ED6} = {FC224610-32D3-454E-9BC1-1219FE8ACD5F}
|
||||
{C32274D9-1B66-4D5C-82F9-EB3F10F46752} = {57F59C0C-5687-4AF9-AE1C-1933B539F0E4}
|
||||
{6A40CBE4-ECAB-4CED-9917-5C64CBF75DA6} = {FC224610-32D3-454E-9BC1-1219FE8ACD5F}
|
||||
{8AC2AD6D-6C74-4B24-8DF6-42717FC9B804} = {D92751C8-1039-4005-90B2-913E55E0B8BD}
|
||||
{A6DE3DA0-B242-4F49-AEF0-4E26AF92D16C} = {8AC2AD6D-6C74-4B24-8DF6-42717FC9B804}
|
||||
{4D40A101-07E6-4FF2-8934-83434932591D} = {8AC2AD6D-6C74-4B24-8DF6-42717FC9B804}
|
||||
{20751904-0DFC-4126-BF2A-834B53841010} = {8AC2AD6D-6C74-4B24-8DF6-42717FC9B804}
|
||||
{7F1FDCF2-0CE8-4119-B3C1-F2CC6D7E1C36} = {0AF38BA3-65A0-481B-8CBB-B82E406E1575}
|
||||
{19424B55-058C-4E9C-B86F-700AEF9EAEC3} = {0AF38BA3-65A0-481B-8CBB-B82E406E1575}
|
||||
{881D71A3-D276-4108-98C6-0FFD32129B9C} = {0AF38BA3-65A0-481B-8CBB-B82E406E1575}
|
||||
{0AF38BA3-65A0-481B-8CBB-B82E406E1575} = {D92751C8-1039-4005-90B2-913E55E0B8BD}
|
||||
{EB83A3A3-F9B6-4281-8EBF-F7289FB5D885} = {FD4D6594-D81E-456F-8F2E-35B09E04A755}
|
||||
{D8069A23-AD2E-4C9E-8574-7E8C45296A46} = {0AF38BA3-65A0-481B-8CBB-B82E406E1575}
|
||||
{2D5AE63D-85C0-43D1-84BF-04418ED93F63} = {804E065F-914C-414A-AF84-009312C3CFF6}
|
||||
{89C4CBC7-1606-40DE-B6DA-FBE3AAC98395} = {2D5AE63D-85C0-43D1-84BF-04418ED93F63}
|
||||
{631C295A-7CCF-4B42-8686-7034E31469E7} = {2D5AE63D-85C0-43D1-84BF-04418ED93F63}
|
||||
{D940853C-003A-482C-BDB0-665367F274A0} = {2D5AE63D-85C0-43D1-84BF-04418ED93F63}
|
||||
{2F45036E-D817-41E9-B82F-DBE013EC95D0} = {804E065F-914C-414A-AF84-009312C3CFF6}
|
||||
{C2DE264A-AA87-4012-B954-17E3F403A237} = {2F45036E-D817-41E9-B82F-DBE013EC95D0}
|
||||
{AF507D61-6766-4C20-9F58-23DC29508219} = {2F45036E-D817-41E9-B82F-DBE013EC95D0}
|
||||
{91D70DE1-DC8E-4AE1-B100-0671D6263FC5} = {804E065F-914C-414A-AF84-009312C3CFF6}
|
||||
{CA8EAE01-AB9F-4EC1-B6F3-73721487E9E1} = {91D70DE1-DC8E-4AE1-B100-0671D6263FC5}
|
||||
{25172C49-7AA4-4739-BB07-69785094C379} = {91D70DE1-DC8E-4AE1-B100-0671D6263FC5}
|
||||
{80F965C4-E2A8-4F54-985D-73D06E45F9CE} = {91D70DE1-DC8E-4AE1-B100-0671D6263FC5}
|
||||
{35175682-DA83-4C0A-A49D-B191F5885D8E} = {91D70DE1-DC8E-4AE1-B100-0671D6263FC5}
|
||||
{4721AA15-AF6E-4A62-A2C3-65564DC563E6} = {804E065F-914C-414A-AF84-009312C3CFF6}
|
||||
{41BC679F-887F-44CF-971D-A5502EE87DB0} = {4721AA15-AF6E-4A62-A2C3-65564DC563E6}
|
||||
{9ADD1B7A-6401-4202-8613-F668E2FBC0A4} = {4721AA15-AF6E-4A62-A2C3-65564DC563E6}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {EE253116-7070-4E9A-BCE8-2911C251B8C8}
|
||||
EndGlobalSection
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared.Cef\Speckle.Connectors.RevitShared.Cef.projitems*{01f98733-7352-47ad-a594-537d979de3de}*SharedItemsImports = 5
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.projitems*{01f98733-7352-47ad-a594-537d979de3de}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{19424b55-058c-4e9c-b86f-700aef9eaec3}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.DependencyInjection\Speckle.Converters.RevitShared.DependencyInjection.projitems*{20751904-0dfc-4126-bf2a-834b53841010}*SharedItemsImports = 5
|
||||
Converters\Autocad\Speckle.Converters.AutocadShared\Speckle.Converters.AutocadShared.projitems*{25172c49-7aa4-4739-bb07-69785094c379}*SharedItemsImports = 5
|
||||
Converters\Civil3d\Speckle.Converters.Civil3dShared\Speckle.Converters.Civil3dShared.projitems*{25172c49-7aa4-4739-bb07-69785094c379}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{26391930-f86f-47e0-a5f6-b89919e38ce1}*SharedItemsImports = 5
|
||||
Converters\Civil3d\Speckle.Converters.Civil3dShared\Speckle.Converters.Civil3dShared.projitems*{35175682-da83-4c0a-a49d-b191f5885d8e}*SharedItemsImports = 13
|
||||
Connectors\Autocad\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems*{41bc679f-887f-44cf-971d-a5502ee87db0}*SharedItemsImports = 13
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{4d40a101-07e6-4ff2-8934-83434932591d}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.DependencyInjection\Speckle.Converters.RevitShared.DependencyInjection.projitems*{6067ba60-d279-4156-8ae1-6b44e2d19187}*SharedItemsImports = 13
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared.Cef\Speckle.Connectors.RevitShared.Cef.projitems*{617bd3c7-87d9-4d28-8ac9-4910945bb9fc}*SharedItemsImports = 5
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.projitems*{617bd3c7-87d9-4d28-8ac9-4910945bb9fc}*SharedItemsImports = 5
|
||||
Converters\Autocad\Speckle.Converters.AutocadShared\Speckle.Converters.AutocadShared.projitems*{631c295a-7ccf-4b42-8686-7034e31469e7}*SharedItemsImports = 5
|
||||
Converters\Rhino\Speckle.Converters.RhinoShared\Speckle.Converters.RhinoShared.projitems*{65a2f556-f14a-49f3-8a92-7f2e1e7ed3b5}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{67b888d9-c6c4-49f1-883c-5b964151d889}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.Tests\Speckle.Converters.RevitShared.Tests.projitems*{68cf9bdf-94ac-4d2d-a7bd-d1c064f97051}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{68cf9bdf-94ac-4d2d-a7bd-d1c064f97051}*SharedItemsImports = 5
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared.Cef\Speckle.Connectors.RevitShared.Cef.projitems*{6a40cbe4-ecab-4ced-9917-5c64cbf75da6}*SharedItemsImports = 13
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared.Cef\Speckle.Connectors.RevitShared.Cef.projitems*{7f1fdcf2-0ce8-4119-b3c1-f2cc6d7e1c36}*SharedItemsImports = 5
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.projitems*{7f1fdcf2-0ce8-4119-b3c1-f2cc6d7e1c36}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.DependencyInjection\Speckle.Converters.RevitShared.DependencyInjection.projitems*{7f3055ba-70aa-424c-8748-345af35127e9}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.DependencyInjection\Speckle.Converters.RevitShared.DependencyInjection.projitems*{83ead6f0-3cb3-456a-ad81-072127d0de0e}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.DependencyInjection\Speckle.Converters.RevitShared.DependencyInjection.projitems*{881d71a3-d276-4108-98c6-0ffd32129b9c}*SharedItemsImports = 5
|
||||
Connectors\Autocad\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems*{89c4cbc7-1606-40de-b6da-fbe3aac98395}*SharedItemsImports = 5
|
||||
Converters\Autocad\Speckle.Converters.AutocadShared\Speckle.Converters.AutocadShared.projitems*{9add1b7a-6401-4202-8613-f668e2fbc0a4}*SharedItemsImports = 13
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.projitems*{a6de3da0-b242-4f49-aef0-4e26af92d16c}*SharedItemsImports = 5
|
||||
Converters\Rhino\Speckle.Converters.RhinoShared\Speckle.Converters.RhinoShared.projitems*{ac2db416-f05c-4296-9040-56d6ad4fcd27}*SharedItemsImports = 5
|
||||
Converters\Autocad\Speckle.Converters.AutocadShared\Speckle.Converters.AutocadShared.projitems*{c2de264a-aa87-4012-b954-17e3f403a237}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.Tests\Speckle.Converters.RevitShared.Tests.projitems*{c32274d9-1b66-4d5c-82f9-eb3f10f46752}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{c32274d9-1b66-4d5c-82f9-eb3f10f46752}*SharedItemsImports = 5
|
||||
Connectors\Autocad\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems*{ca8eae01-ab9f-4ec1-b6f3-73721487e9e1}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.Tests\Speckle.Converters.RevitShared.Tests.projitems*{d8069a23-ad2e-4c9e-8574-7e8c45296a46}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{d8069a23-ad2e-4c9e-8574-7e8c45296a46}*SharedItemsImports = 5
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.projitems*{dc570fff-6fe5-47bd-8bc1-b471a6067786}*SharedItemsImports = 13
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{e1c43415-3200-45f4-8bf9-a4dd7d7f2ed6}*SharedItemsImports = 13
|
||||
Converters\Rhino\Speckle.Converters.RhinoShared\Speckle.Converters.RhinoShared.projitems*{e1c43415-3200-45f4-8bf9-a4dd7d7f2ed9}*SharedItemsImports = 13
|
||||
Converters\Revit\Speckle.Converters.RevitShared.Tests\Speckle.Converters.RevitShared.Tests.projitems*{e1c43415-3202-45f4-8bf9-a4dd7d7f2ed6}*SharedItemsImports = 13
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,116 @@
|
||||
using GlobExpressions;
|
||||
using Microsoft.Build.Construction;
|
||||
using static SimpleExec.Command;
|
||||
|
||||
namespace Build;
|
||||
|
||||
public static class Affected
|
||||
{
|
||||
public static readonly string Root = Environment.CurrentDirectory;
|
||||
public const string AFFECTED_PROJECT = "affected.proj";
|
||||
|
||||
private static IEnumerable<string> GetAffectedProjects()
|
||||
{
|
||||
var projFile = Path.Combine(Root, AFFECTED_PROJECT);
|
||||
Console.WriteLine("Affected project file: " + projFile);
|
||||
var project = ProjectRootElement.Open(projFile) ?? throw new InvalidOperationException();
|
||||
var references = project.ItemGroups.SelectMany(x => x.Items).Where(x => x.ItemType == "ProjectReference");
|
||||
|
||||
foreach (var refe in references)
|
||||
{
|
||||
var referencePath = refe.Include[(Root.Length + 1)..];
|
||||
referencePath = Path.GetDirectoryName(referencePath) ?? throw new InvalidOperationException();
|
||||
if (Path.DirectorySeparatorChar != '/')
|
||||
{
|
||||
referencePath = referencePath.Replace(Path.DirectorySeparatorChar, '/');
|
||||
}
|
||||
|
||||
yield return referencePath;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<IEnumerable<string>> GetTestProjects()
|
||||
{
|
||||
await ComputeAffected();
|
||||
var projFile = Path.Combine(Root, AFFECTED_PROJECT);
|
||||
if (File.Exists(projFile))
|
||||
{
|
||||
var references = GetAffectedProjects();
|
||||
return references.Where(x => x.Contains("Tests"));
|
||||
}
|
||||
return Glob.Files(Root, "**/*.Tests.csproj");
|
||||
}
|
||||
|
||||
public static async Task<ProjectGroup[]> GetAffectedProjectGroups()
|
||||
{
|
||||
await ComputeAffected();
|
||||
var projFile = Path.Combine(Root, AFFECTED_PROJECT);
|
||||
if (File.Exists(projFile))
|
||||
{
|
||||
var references = GetAffectedProjects().ToList();
|
||||
var groups = new List<ProjectGroup>();
|
||||
foreach (var projectGroup in Consts.ProjectGroups)
|
||||
{
|
||||
foreach (var referencePath in references)
|
||||
{
|
||||
if (projectGroup.Projects.Any(x => x.ProjectPath.Contains(referencePath)))
|
||||
{
|
||||
groups.Add(projectGroup);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var group in groups)
|
||||
{
|
||||
Console.WriteLine("Affected project group being built: " + group.HostAppSlug);
|
||||
}
|
||||
|
||||
return groups.ToArray();
|
||||
}
|
||||
|
||||
Console.WriteLine("Using all project groups: " + string.Join(',', Consts.ProjectGroups));
|
||||
return Consts.ProjectGroups;
|
||||
}
|
||||
|
||||
private static bool s_affectedComputed;
|
||||
|
||||
public static async Task ComputeAffected()
|
||||
{
|
||||
if (s_affectedComputed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var currentTag = await Versions.GetCurrentTag();
|
||||
var currentVersion = await Versions.ComputeVersion();
|
||||
var lastTag = await Versions.GetPreviousTag(currentTag);
|
||||
var lastVersion = await Versions.ComputePreviousVersion(currentTag);
|
||||
|
||||
Console.WriteLine($"Last tag: {lastTag}, Current tag: {currentTag}");
|
||||
Console.WriteLine($"Last parsed version: {lastVersion}, Current parsed version: {currentVersion}");
|
||||
|
||||
var sort = currentVersion.CompareSortOrderTo(lastVersion);
|
||||
if (sort == -1)
|
||||
{
|
||||
Console.WriteLine($"Current version {currentVersion} is less than: {lastVersion}");
|
||||
s_affectedComputed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var majorEquals = currentVersion.Major == lastVersion.Major;
|
||||
if (!majorEquals)
|
||||
{
|
||||
Console.WriteLine($"Current version {currentVersion} is not matching major version: {lastVersion}");
|
||||
s_affectedComputed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
//use tags no matter the version if major versions match
|
||||
var (currentCommit, _) = await ReadAsync("git", $"rev-list -n 1 {currentTag}");
|
||||
var (lastCommit, _) = await ReadAsync("git", $"rev-list -n 1 {lastTag}");
|
||||
await RunAsync("dotnet", $"affected -v --from {currentCommit.Trim()} --to {lastCommit.Trim()}", Root);
|
||||
|
||||
s_affectedComputed = true;
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,13 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Bullseye" />
|
||||
<PackageReference Include="Glob" />
|
||||
<PackageReference Include="Microsoft.Build" />
|
||||
<PackageReference Include="Semver" />
|
||||
<PackageReference Include="SimpleExec" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
+66
-32
@@ -1,46 +1,80 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Build;
|
||||
namespace Build;
|
||||
|
||||
public static class Consts
|
||||
{
|
||||
public static readonly string[] Solutions = { "DUI3-DX.slnf" };
|
||||
public static readonly string[] TestProjects = System.Array.Empty<string>();
|
||||
public static readonly string[] Solutions = ["Speckle.Connectors.sln"];
|
||||
|
||||
public static readonly InstallerProject[] InstallerManifests =
|
||||
public static readonly ProjectGroup[] ProjectGroups =
|
||||
{
|
||||
new("arcgis", [new("Connectors/ArcGIS/Speckle.Connectors.ArcGIS3", "net6.0-windows")]),
|
||||
new(
|
||||
"arcgis",
|
||||
new InstallerAsset[] { new("DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3", "net6.0-windows") }
|
||||
"rhino",
|
||||
[
|
||||
new("Connectors/Rhino/Speckle.Connectors.Rhino7", "net48"),
|
||||
new("Connectors/Rhino/Speckle.Connectors.Rhino8", "net48")
|
||||
]
|
||||
),
|
||||
new("rhino", new InstallerAsset[] { new("DUI3-DX/Connectors/Rhino/Speckle.Connectors.Rhino7", "net48") }),
|
||||
new("revit", new InstallerAsset[] { new("DUI3-DX/Connectors/Revit/Speckle.Connectors.Revit2023", "net48") }),
|
||||
new("autocad", new InstallerAsset[] { new("DUI3-DX/Connectors/Autocad/Speckle.Connectors.Autocad2023", "net48") })
|
||||
new(
|
||||
"revit",
|
||||
[
|
||||
new("Connectors/Revit/Speckle.Connectors.Revit2022", "net48"),
|
||||
new("Connectors/Revit/Speckle.Connectors.Revit2023", "net48"),
|
||||
new("Connectors/Revit/Speckle.Connectors.Revit2024", "net48"),
|
||||
new("Connectors/Revit/Speckle.Connectors.Revit2025", "net8.0-windows")
|
||||
]
|
||||
),
|
||||
new(
|
||||
"autocad",
|
||||
[
|
||||
new("Connectors/Autocad/Speckle.Connectors.Autocad2022", "net48"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Autocad2023", "net48"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Autocad2024", "net48"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Autocad2025", "net8.0-windows"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Autocad2026", "net8.0-windows")
|
||||
]
|
||||
),
|
||||
new(
|
||||
"civil3d",
|
||||
[
|
||||
new("Connectors/Autocad/Speckle.Connectors.Civil3d2022", "net48"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Civil3d2023", "net48"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Civil3d2024", "net48"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Civil3d2025", "net8.0-windows"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Civil3d2026", "net8.0-windows")
|
||||
]
|
||||
),
|
||||
new(
|
||||
"navisworks",
|
||||
[
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2020", "net48"),
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2021", "net48"),
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2022", "net48"),
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2023", "net48"),
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2024", "net48"),
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2025", "net48"),
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2026", "net48")
|
||||
]
|
||||
),
|
||||
new(
|
||||
"teklastructures",
|
||||
[
|
||||
new("Connectors/Tekla/Speckle.Connector.Tekla2023", "net48"),
|
||||
new("Connectors/Tekla/Speckle.Connector.Tekla2024", "net48")
|
||||
]
|
||||
),
|
||||
new(
|
||||
"etabs",
|
||||
[
|
||||
new("Connectors/CSi/Speckle.Connectors.ETABS21", "net48"),
|
||||
new("Connectors/CSi/Speckle.Connectors.ETABS22", "net8.0-windows"),
|
||||
]
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
public readonly struct InstallerProject
|
||||
public readonly record struct ProjectGroup(string HostAppSlug, IReadOnlyList<InstallerAsset> Projects)
|
||||
{
|
||||
public string HostAppSlug { get; init; }
|
||||
public IReadOnlyList<InstallerAsset> Projects { get; init; }
|
||||
|
||||
public InstallerProject(string hostAppSlug, IReadOnlyList<InstallerAsset> projects)
|
||||
{
|
||||
HostAppSlug = hostAppSlug;
|
||||
Projects = projects;
|
||||
}
|
||||
|
||||
public override string ToString() => $"{HostAppSlug}";
|
||||
}
|
||||
|
||||
public readonly struct InstallerAsset
|
||||
{
|
||||
public InstallerAsset(string projectPath, string targetName)
|
||||
{
|
||||
ProjectPath = projectPath;
|
||||
TargetName = targetName;
|
||||
}
|
||||
|
||||
public string ProjectPath { get; init; }
|
||||
public string TargetName { get; init; }
|
||||
}
|
||||
public readonly record struct InstallerAsset(string ProjectPath, string TargetName);
|
||||
|
||||
+3
-6
@@ -1,9 +1,6 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Mime;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Build;
|
||||
|
||||
@@ -31,11 +28,11 @@ public static class Github
|
||||
Content = content
|
||||
};
|
||||
request.Headers.Add("X-GitHub-Api-Version", "2022-11-28");
|
||||
var response = await client.SendAsync(request).ConfigureAwait(false);
|
||||
var response = await client.SendAsync(request);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"{response.StatusCode} {response.ReasonPhrase} {await response.Content.ReadAsStringAsync().ConfigureAwait(false)}"
|
||||
$"{response.StatusCode} {response.ReasonPhrase} {await response.Content.ReadAsStringAsync()}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+184
-76
@@ -1,6 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using Build;
|
||||
using GlobExpressions;
|
||||
@@ -10,12 +7,17 @@ using static SimpleExec.Command;
|
||||
const string CLEAN = "clean";
|
||||
const string RESTORE = "restore";
|
||||
const string BUILD = "build";
|
||||
const string BUILD_LINUX = "build-linux";
|
||||
const string TEST = "test";
|
||||
const string TEST_ONLY = "test-only";
|
||||
const string FORMAT = "format";
|
||||
const string ZIP = "zip";
|
||||
const string VERSION = "version";
|
||||
const string RESTORE_TOOLS = "restore-tools";
|
||||
const string BUILD_SERVER_VERSION = "build-server-version";
|
||||
const string CLEAN_LOCKS = "clean-locks";
|
||||
const string CHECK_SOLUTIONS = "check-solutions";
|
||||
const string DEEP_CLEAN = "deep-clean";
|
||||
const string DEEP_CLEAN_LOCAL = "deep-clean-local";
|
||||
const string DETECT_AFFECTED = "detect-affected";
|
||||
|
||||
//need to pass arguments
|
||||
/*var arguments = new List<string>();
|
||||
@@ -25,6 +27,76 @@ if (args.Length > 1)
|
||||
args = new[] { arguments.First() };
|
||||
//arguments = arguments.Skip(1).ToList();
|
||||
}*/
|
||||
void Build(string solution, string configuration)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Building solution '{solution}' as '{configuration}'");
|
||||
Console.WriteLine();
|
||||
Run("dotnet", $"build \".\\{solution}\" --configuration {configuration} --no-restore");
|
||||
}
|
||||
void Restore(string solution)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Restoring solution '{solution}'");
|
||||
Console.WriteLine();
|
||||
Run("dotnet", $"restore \".\\{solution}\" --no-cache");
|
||||
}
|
||||
void DeleteFiles(string pattern)
|
||||
{
|
||||
foreach (var f in Glob.Files(".", pattern))
|
||||
{
|
||||
Console.WriteLine("Found and will delete: " + f);
|
||||
File.Delete(f);
|
||||
}
|
||||
}
|
||||
void DeleteDirectories(string pattern)
|
||||
{
|
||||
foreach (var f in Glob.Directories(".", pattern))
|
||||
{
|
||||
if (f.StartsWith("Build"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Console.WriteLine("Found and will delete: " + f);
|
||||
Directory.Delete(f, true);
|
||||
}
|
||||
}
|
||||
|
||||
void CleanSolution(string solution, string configuration)
|
||||
{
|
||||
Console.WriteLine("Cleaning solution: " + solution);
|
||||
|
||||
DeleteDirectories("**/bin");
|
||||
DeleteDirectories("**/obj");
|
||||
DeleteFiles("**/*.lock.json");
|
||||
Restore(solution);
|
||||
Build(solution, configuration);
|
||||
}
|
||||
|
||||
Target(
|
||||
CLEAN_LOCKS,
|
||||
() =>
|
||||
{
|
||||
DeleteFiles("**/*.lock.json");
|
||||
Restore("Speckle.Connectors.sln");
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
DEEP_CLEAN,
|
||||
() =>
|
||||
{
|
||||
CleanSolution("Speckle.Connectors.sln", "debug");
|
||||
}
|
||||
);
|
||||
Target(
|
||||
DEEP_CLEAN_LOCAL,
|
||||
() =>
|
||||
{
|
||||
CleanSolution("Local.sln", "local");
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
CLEAN,
|
||||
@@ -52,17 +124,6 @@ Target(
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
VERSION,
|
||||
async () =>
|
||||
{
|
||||
var (output, _) = await ReadAsync("dotnet", "minver -v w").ConfigureAwait(false);
|
||||
output = output.Trim();
|
||||
Console.WriteLine($"Version: {output}");
|
||||
Run("echo", $"\"version={output}\" >> $GITHUB_OUTPUT");
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
RESTORE_TOOLS,
|
||||
() =>
|
||||
@@ -71,6 +132,18 @@ Target(
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
DETECT_AFFECTED,
|
||||
DependsOn(RESTORE_TOOLS),
|
||||
async () =>
|
||||
{
|
||||
foreach (var group in await Affected.GetAffectedProjectGroups())
|
||||
{
|
||||
Console.WriteLine("Affected project group being built: " + group.HostAppSlug);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
FORMAT,
|
||||
DependsOn(RESTORE_TOOLS),
|
||||
@@ -82,19 +155,14 @@ Target(
|
||||
|
||||
Target(
|
||||
RESTORE,
|
||||
DependsOn(FORMAT, DETECT_AFFECTED),
|
||||
Consts.Solutions,
|
||||
s =>
|
||||
async s =>
|
||||
{
|
||||
Run("dotnet", $"restore {s} --locked-mode");
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
BUILD_SERVER_VERSION,
|
||||
DependsOn(RESTORE_TOOLS),
|
||||
() =>
|
||||
{
|
||||
Run("dotnet", "tool run dotnet-gitversion /output json /output buildserver");
|
||||
var version = await Versions.ComputeVersion();
|
||||
var fileVersion = await Versions.ComputeFileVersion();
|
||||
Console.WriteLine($"Restoring: {s} - Version: {version} & {fileVersion}");
|
||||
await RunAsync("dotnet", $"restore \"{s}\" --locked-mode");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -102,80 +170,120 @@ Target(
|
||||
BUILD,
|
||||
DependsOn(RESTORE),
|
||||
Consts.Solutions,
|
||||
s =>
|
||||
async s =>
|
||||
{
|
||||
var version = Environment.GetEnvironmentVariable("GitVersion_FullSemVer") ?? "3.0.0-localBuild";
|
||||
var fileVersion = Environment.GetEnvironmentVariable("GitVersion_AssemblySemFileVer") ?? "3.0.0.0";
|
||||
Console.WriteLine($"Version: {version} & {fileVersion}");
|
||||
var version = await Versions.ComputeVersion();
|
||||
var fileVersion = await Versions.ComputeFileVersion();
|
||||
Console.WriteLine($"Restoring: {s} - Version: {version} & {fileVersion}");
|
||||
await RunAsync(
|
||||
"dotnet",
|
||||
$"build \"{s}\" -c Release --no-restore -warnaserror -p:Version={version} -p:FileVersion={fileVersion} -v:m"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Target(CHECK_SOLUTIONS, Solutions.CompareConnectorsToLocal);
|
||||
|
||||
Target(
|
||||
TEST,
|
||||
DependsOn(BUILD, CHECK_SOLUTIONS),
|
||||
async () =>
|
||||
{
|
||||
foreach (var s in await Affected.GetTestProjects())
|
||||
{
|
||||
await RunAsync("dotnet", $"test \"{s}\" -c Release --no-build --no-restore --verbosity=minimal");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
//all tests on purpose
|
||||
Target(
|
||||
TEST_ONLY,
|
||||
DependsOn(FORMAT),
|
||||
Glob.Files(".", "**/*.Tests.csproj"),
|
||||
file =>
|
||||
{
|
||||
Run("dotnet", $"build \"{file}\" -c Release --no-incremental");
|
||||
Run(
|
||||
"dotnet",
|
||||
$"build {s} -c Release --no-restore -p:IsDesktopBuild=false -p:Version={version} -p:FileVersion={fileVersion} -v:m"
|
||||
$"test \"{file}\" -c Release --no-build --verbosity=minimal /p:AltCover=true /p:AltCoverAttributeFilter=ExcludeFromCodeCoverage /p:AltCoverVerbosity=Warning"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
TEST,
|
||||
DependsOn(BUILD),
|
||||
Consts.TestProjects,
|
||||
t =>
|
||||
BUILD_LINUX,
|
||||
DependsOn(FORMAT),
|
||||
Glob.Files(".", "**/Speckle.Importers.Ifc.csproj"),
|
||||
async file =>
|
||||
{
|
||||
IEnumerable<string> GetFiles(string d)
|
||||
{
|
||||
return Glob.Files(".", d);
|
||||
}
|
||||
await RunAsync("dotnet", $"restore \"{file}\" --locked-mode");
|
||||
var version = await Versions.ComputeVersion();
|
||||
var fileVersion = await Versions.ComputeFileVersion();
|
||||
Console.WriteLine($"Version: {version} & {fileVersion}");
|
||||
await RunAsync(
|
||||
"dotnet",
|
||||
$"build \"{file}\" -c Release --no-restore -warnaserror -p:Version={version} -p:FileVersion={fileVersion} -v:m"
|
||||
);
|
||||
|
||||
foreach (var file in GetFiles($"**/{t}.csproj"))
|
||||
{
|
||||
Run("dotnet", $"test {file} -c Release --no-build --no-restore --verbosity=normal");
|
||||
}
|
||||
await RunAsync(
|
||||
"dotnet",
|
||||
$"pack \"{file}\" -c Release -o output --no-build -p:Version={version} -p:FileVersion={fileVersion} -v:m"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
ZIP,
|
||||
DependsOn(TEST),
|
||||
Consts.InstallerManifests,
|
||||
x =>
|
||||
async () =>
|
||||
{
|
||||
var outputDir = Path.Combine(".", "output");
|
||||
var slugDir = Path.Combine(outputDir, x.HostAppSlug);
|
||||
|
||||
Directory.CreateDirectory(outputDir);
|
||||
Directory.CreateDirectory(slugDir);
|
||||
|
||||
foreach (var asset in x.Projects)
|
||||
var version = await Versions.ComputeVersion();
|
||||
foreach (var group in await Affected.GetAffectedProjectGroups())
|
||||
{
|
||||
var fullPath = Path.Combine(".", asset.ProjectPath, "bin", "Release", asset.TargetName);
|
||||
if (!Directory.Exists(fullPath))
|
||||
Console.WriteLine($"Zipping: {group.HostAppSlug} as {version}");
|
||||
var outputDir = Path.Combine(".", "output");
|
||||
var slugDir = Path.Combine(outputDir, group.HostAppSlug);
|
||||
|
||||
Directory.CreateDirectory(outputDir);
|
||||
Directory.CreateDirectory(slugDir);
|
||||
|
||||
foreach (var asset in group.Projects)
|
||||
{
|
||||
throw new InvalidOperationException("Could not find: " + fullPath);
|
||||
var fullPath = Path.Combine(".", asset.ProjectPath, "bin", "Release", asset.TargetName);
|
||||
if (!Directory.Exists(fullPath))
|
||||
{
|
||||
throw new InvalidOperationException("Could not find: " + fullPath);
|
||||
}
|
||||
|
||||
var assetName = Path.GetFileName(asset.ProjectPath);
|
||||
var connectorDir = Path.Combine(slugDir, assetName);
|
||||
|
||||
Directory.CreateDirectory(connectorDir);
|
||||
foreach (var directory in Directory.EnumerateDirectories(fullPath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
Directory.CreateDirectory(directory.Replace(fullPath, connectorDir));
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(fullPath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
Console.WriteLine(file);
|
||||
File.Copy(file, file.Replace(fullPath, connectorDir), true);
|
||||
}
|
||||
}
|
||||
|
||||
var assetName = Path.GetFileName(asset.ProjectPath);
|
||||
var connectorDir = Path.Combine(slugDir, assetName);
|
||||
|
||||
Directory.CreateDirectory(connectorDir);
|
||||
foreach (var directory in Directory.EnumerateDirectories(fullPath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
Directory.CreateDirectory(directory.Replace(fullPath, connectorDir));
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(fullPath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
Console.WriteLine(file);
|
||||
File.Copy(file, file.Replace(fullPath, connectorDir), true);
|
||||
}
|
||||
var outputPath = Path.Combine(outputDir, $"{group.HostAppSlug}.zip");
|
||||
File.Delete(outputPath);
|
||||
Console.WriteLine($"Zipping: '{slugDir}' to '{outputPath}'");
|
||||
ZipFile.CreateFromDirectory(slugDir, outputPath);
|
||||
}
|
||||
|
||||
var outputPath = Path.Combine(outputDir, $"{x.HostAppSlug}.zip");
|
||||
File.Delete(outputPath);
|
||||
Console.WriteLine($"Zipping: '{slugDir}' to '{outputPath}'");
|
||||
ZipFile.CreateFromDirectory(slugDir, outputPath);
|
||||
// Directory.Delete(slugDir, true);
|
||||
string githubEnv = Environment.GetEnvironmentVariable("GITHUB_ENV") ?? "Unset";
|
||||
Console.WriteLine($"GITHUB_ENV: {githubEnv}");
|
||||
File.AppendAllText(githubEnv, $"SPECKLE_VERSION={version}{Environment.NewLine}");
|
||||
}
|
||||
);
|
||||
|
||||
Target("default", DependsOn(FORMAT, ZIP), () => Console.WriteLine("Done!"));
|
||||
Target("default", DependsOn(TEST), () => Console.WriteLine("Done!"));
|
||||
|
||||
await RunTargetsAndExitAsync(args).ConfigureAwait(true);
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
using Microsoft.Build.Construction;
|
||||
|
||||
namespace Build;
|
||||
|
||||
public static class Solutions
|
||||
{
|
||||
private static bool ValidProjects(KeyValuePair<string, ProjectInSolution> projectInSolution) =>
|
||||
projectInSolution.Value.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat;
|
||||
|
||||
public static void CompareConnectorsToLocal()
|
||||
{
|
||||
var localSln = SolutionFile.Parse(Path.Combine(Environment.CurrentDirectory, "Local.sln"));
|
||||
var connectorsSln = SolutionFile.Parse(Path.Combine(Environment.CurrentDirectory, "Speckle.Connectors.sln"));
|
||||
var localProjects = localSln.ProjectsByGuid.Where(ValidProjects).ToDictionary();
|
||||
|
||||
foreach ((string? _, ProjectInSolution? value) in connectorsSln.ProjectsByGuid.Where(ValidProjects))
|
||||
{
|
||||
var localProject = localProjects.Values.FirstOrDefault(x => x.ProjectName == value.ProjectName);
|
||||
if (localProject is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find in LOCAL solution: {value.ProjectName}");
|
||||
}
|
||||
|
||||
if (value.ProjectName != localProject.ProjectName)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Projects with different names have same Guid in solution: "
|
||||
+ value.ProjectName
|
||||
+ " and "
|
||||
+ localProject.ProjectName
|
||||
);
|
||||
}
|
||||
localProjects.Remove(localProjects.Single(x => x.Value.ProjectName == value.ProjectName).Key);
|
||||
}
|
||||
|
||||
void CheckAndRemoveKnown(string projectName)
|
||||
{
|
||||
var localProject = localProjects.Values.FirstOrDefault(x => x.ProjectName == projectName);
|
||||
if (localProject is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find in LOCAL solution: {projectName}");
|
||||
}
|
||||
localProjects.Remove(localProjects.Single(x => x.Value.ProjectName == projectName).Key);
|
||||
}
|
||||
|
||||
CheckAndRemoveKnown("Speckle.Objects");
|
||||
CheckAndRemoveKnown("Speckle.Sdk");
|
||||
CheckAndRemoveKnown("Speckle.Sdk.Dependencies");
|
||||
if (localProjects.Count != 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Could not find in CONNECTOR solution: " + localProjects.First().Value.ProjectName
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using Semver;
|
||||
using static SimpleExec.Command;
|
||||
|
||||
namespace Build;
|
||||
|
||||
public static class Versions
|
||||
{
|
||||
private static string? s_currentTag;
|
||||
private static SemVersion? s_currentVersion;
|
||||
|
||||
public static async Task<string> GetCurrentTag()
|
||||
{
|
||||
if (s_currentTag is not null)
|
||||
{
|
||||
return s_currentTag;
|
||||
}
|
||||
//finds current tag or makes one
|
||||
var (currentTag, _) = await ReadAsync("git", "describe --tags");
|
||||
currentTag = currentTag.Trim();
|
||||
s_currentTag = currentTag;
|
||||
return s_currentTag;
|
||||
}
|
||||
|
||||
public static async Task<SemVersion> ComputeVersion()
|
||||
{
|
||||
if (s_currentVersion is not null)
|
||||
{
|
||||
return s_currentVersion;
|
||||
}
|
||||
var currentTag = await GetCurrentTag();
|
||||
|
||||
if (!SemVersion.TryParse(currentTag, SemVersionStyles.AllowLowerV, out var currentVersion))
|
||||
{
|
||||
throw new InvalidOperationException($"Could not parse version: '{currentTag}'");
|
||||
}
|
||||
s_currentVersion = currentVersion;
|
||||
return s_currentVersion;
|
||||
}
|
||||
|
||||
private static string? s_currentFileVersion;
|
||||
|
||||
public static async Task<string> ComputeFileVersion()
|
||||
{
|
||||
if (s_currentFileVersion is not null)
|
||||
{
|
||||
return s_currentFileVersion;
|
||||
}
|
||||
var currentVersion = await ComputeVersion();
|
||||
s_currentFileVersion = currentVersion.WithoutPrereleaseOrMetadata() + ".0";
|
||||
return s_currentFileVersion;
|
||||
}
|
||||
|
||||
public static async Task<string> GetPreviousTag(string currentTag)
|
||||
{
|
||||
//finds a tag starting with current tag and adds no abbrevation
|
||||
var (lastTag, _) = await ReadAsync("git", $"describe --abbrev=0 --tags {currentTag}^");
|
||||
lastTag = lastTag.Trim();
|
||||
|
||||
return lastTag;
|
||||
}
|
||||
|
||||
private static SemVersion? s_previousVersion;
|
||||
|
||||
public static async Task<SemVersion> ComputePreviousVersion(string currentTag)
|
||||
{
|
||||
if (s_previousVersion is not null)
|
||||
{
|
||||
return s_previousVersion;
|
||||
}
|
||||
var lastTag = await GetPreviousTag(currentTag);
|
||||
|
||||
if (!SemVersion.TryParse(lastTag, SemVersionStyles.AllowLowerV, out var lastVersion))
|
||||
{
|
||||
throw new InvalidOperationException($"Could not parse version: '{lastTag}'");
|
||||
}
|
||||
s_previousVersion = lastVersion;
|
||||
return s_previousVersion;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,29 @@
|
||||
"resolved": "1.1.9",
|
||||
"contentHash": "AfK5+ECWYTP7G3AAdnU8IfVj+QpGjrh9GC2mpdcJzCvtQ4pnerAGwHsxJ9D4/RnhDUz2DSzd951O/lQjQby2Sw=="
|
||||
},
|
||||
"Microsoft.Build": {
|
||||
"type": "Direct",
|
||||
"requested": "[17.11.4, )",
|
||||
"resolved": "17.11.4",
|
||||
"contentHash": "UMC7DfeFEHY2GGHHaghybUuUlLaByFHEFudR2PehMgDBuRuLAUePp1iaa4eFtVzepRzMtIbeSCVJCzzX3NV2Gg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Build.Framework": "17.11.4",
|
||||
"Microsoft.NET.StringTools": "17.11.4",
|
||||
"System.Collections.Immutable": "8.0.0",
|
||||
"System.Configuration.ConfigurationManager": "8.0.0",
|
||||
"System.Reflection.Metadata": "8.0.0",
|
||||
"System.Reflection.MetadataLoadContext": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
@@ -30,6 +53,15 @@
|
||||
"resolved": "1.14.1",
|
||||
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
|
||||
},
|
||||
"Semver": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.0.0, )",
|
||||
"resolved": "3.0.0",
|
||||
"contentHash": "9jZCicsVgTebqkAujRWtC9J1A5EQVlu0TVKHcgoCuv345ve5DYf4D1MjhKEnQjdRZo6x/vdv6QQrYFs7ilGzLA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "5.0.1"
|
||||
}
|
||||
},
|
||||
"SimpleExec": {
|
||||
"type": "Direct",
|
||||
"requested": "[12.0.0, )",
|
||||
@@ -38,19 +70,80 @@
|
||||
},
|
||||
"Speckle.InterfaceGenerator": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.9.5, )",
|
||||
"resolved": "0.9.5",
|
||||
"contentHash": "oU/L7pN1R7q8KkbrpQ3WJnHirPHqn+9DEA7asOcUiggV5dzVg1A/VYs7GOSusD24njxXh03tE3a2oTLOjt3cVg=="
|
||||
"requested": "[0.9.6, )",
|
||||
"resolved": "0.9.6",
|
||||
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
|
||||
},
|
||||
"Microsoft.Build.Framework": {
|
||||
"type": "Transitive",
|
||||
"resolved": "17.11.4",
|
||||
"contentHash": "u28uDihlqxtt8h2dL1ZJOZ7TRkxBK+HGr+3FgQpILVo7Q7gErkw8mYW9R+RM5PtxvZTdYb/4MWDL66vdIsANBQ=="
|
||||
},
|
||||
"Microsoft.Build.Tasks.Git": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.1",
|
||||
"contentHash": "5WPSmL4YeP7eW+Vc8XZ4DwjYWBAiSwDV9Hm63JJWcz1Ie3Xjv4KuJXzgCstj48LkLfVCYa7mLcx7y+q6yqVvtw=="
|
||||
},
|
||||
"Microsoft.NET.StringTools": {
|
||||
"type": "Transitive",
|
||||
"resolved": "17.11.4",
|
||||
"contentHash": "mudqUHhNpeqIdJoUx2YDWZO/I9uEDYVowan89R6wsomfnUJQk6HteoQTlNjZDixhT2B4IXMkMtgZtoceIjLRmA=="
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"System.Collections.Immutable": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg=="
|
||||
},
|
||||
"System.Configuration.ConfigurationManager": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "JlYi9XVvIREURRUlGMr1F6vOFLk7YSY4p1vHo4kX3tQ0AGrjqlRWHDi66ImHhy6qwXBG3BJ6Y1QlYQ+Qz6Xgww==",
|
||||
"dependencies": {
|
||||
"System.Diagnostics.EventLog": "8.0.0",
|
||||
"System.Security.Cryptography.ProtectedData": "8.0.0"
|
||||
}
|
||||
},
|
||||
"System.Diagnostics.EventLog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A=="
|
||||
},
|
||||
"System.Reflection.Metadata": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "ptvgrFh7PvWI8bcVqG5rsA/weWM09EnthFHR5SCnS6IN+P4mj6rE1lBDC4U8HL9/57htKAqy4KQ3bBj84cfYyQ==",
|
||||
"dependencies": {
|
||||
"System.Collections.Immutable": "8.0.0"
|
||||
}
|
||||
},
|
||||
"System.Reflection.MetadataLoadContext": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "SZxrQ4sQYnIcdwiO3G/lHZopbPYQ2lW0ioT4JezgccWUrKaKbHLJbAGZaDfkYjWcta1pWssAo3MOXLsR0ie4tQ==",
|
||||
"dependencies": {
|
||||
"System.Collections.Immutable": "8.0.0",
|
||||
"System.Reflection.Metadata": "8.0.0"
|
||||
}
|
||||
},
|
||||
"System.Security.Cryptography.ProtectedData": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "+TUFINV2q2ifyXauQXRwy4CiBhqvDEDZeVJU7qfxya4aRYOKzVBpN+4acx25VcPB9ywUN6C0n8drWl110PhZEg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
CA1502: 25
|
||||
CA1501: 5
|
||||
CA1506(Method): 50
|
||||
CA1506(Type): 95
|
||||
@@ -1,36 +1,52 @@
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using ArcGIS.Desktop.Core;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Logging;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Connectors.Utils.Cancellation;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Converters.ArcGIS3;
|
||||
using Speckle.Converters.ArcGIS3.Utils;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Bindings;
|
||||
|
||||
public sealed class ArcGISReceiveBinding : IReceiveBinding
|
||||
{
|
||||
public string Name { get; } = "receiveBinding";
|
||||
private readonly CancellationManager _cancellationManager;
|
||||
private readonly ICancellationManager _cancellationManager;
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IOperationProgressManager _operationProgressManager;
|
||||
private readonly ILogger<ArcGISReceiveBinding> _logger;
|
||||
private readonly IArcGISConversionSettingsFactory _arcGISConversionSettingsFactory;
|
||||
|
||||
public ReceiveBindingUICommands Commands { get; }
|
||||
public IBridge Parent { get; }
|
||||
private ReceiveBindingUICommands Commands { get; }
|
||||
public IBrowserBridge Parent { get; }
|
||||
|
||||
public ArcGISReceiveBinding(
|
||||
DocumentModelStore store,
|
||||
IBridge parent,
|
||||
CancellationManager cancellationManager,
|
||||
IUnitOfWorkFactory unitOfWorkFactory
|
||||
IBrowserBridge parent,
|
||||
ICancellationManager cancellationManager,
|
||||
IServiceProvider serviceProvider,
|
||||
IOperationProgressManager operationProgressManager,
|
||||
ILogger<ArcGISReceiveBinding> logger,
|
||||
IArcGISConversionSettingsFactory arcGisConversionSettingsFactory
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_cancellationManager = cancellationManager;
|
||||
Parent = parent;
|
||||
Commands = new ReceiveBindingUICommands(parent);
|
||||
_unitOfWorkFactory = unitOfWorkFactory;
|
||||
_serviceProvider = serviceProvider;
|
||||
_operationProgressManager = operationProgressManager;
|
||||
_logger = logger;
|
||||
_arcGISConversionSettingsFactory = arcGisConversionSettingsFactory;
|
||||
}
|
||||
|
||||
public async Task Receive(string modelCardId)
|
||||
@@ -44,38 +60,45 @@ public sealed class ArcGISReceiveBinding : IReceiveBinding
|
||||
throw new InvalidOperationException("No download model card was found.");
|
||||
}
|
||||
|
||||
// Init cancellation token source -> Manager also cancel it if exist before
|
||||
CancellationTokenSource cts = _cancellationManager.InitCancellationTokenSource(modelCardId);
|
||||
|
||||
using IUnitOfWork<ReceiveOperation> unitOfWork = _unitOfWorkFactory.Resolve<ReceiveOperation>();
|
||||
|
||||
using var cancellationItem = _cancellationManager.GetCancellationItem(modelCardId);
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
scope
|
||||
.ServiceProvider.GetRequiredService<IConverterSettingsStore<ArcGISConversionSettings>>()
|
||||
.Initialize(
|
||||
_arcGISConversionSettingsFactory.Create(
|
||||
Project.Current,
|
||||
MapView.Active.Map,
|
||||
new CRSoffsetRotation(MapView.Active.Map)
|
||||
)
|
||||
);
|
||||
// Receive host objects
|
||||
var receiveOperationResults = await unitOfWork.Service
|
||||
var receiveOperationResults = await scope
|
||||
.ServiceProvider.GetRequiredService<ReceiveOperation>()
|
||||
.Execute(
|
||||
modelCard.AccountId.NotNull(), // POC: I hear -you are saying why we're passing them separately. Not sure pass the DUI3-> Connectors.DUI project dependency to the SDK-> Connector.Utils
|
||||
modelCard.ProjectId.NotNull(),
|
||||
modelCard.ProjectName.NotNull(),
|
||||
modelCard.ModelName.NotNull(),
|
||||
modelCard.SelectedVersionId.NotNull(),
|
||||
cts.Token,
|
||||
(status, progress) =>
|
||||
Commands.SetModelProgress(modelCardId, new ModelCardProgress(modelCardId, status, progress), cts)
|
||||
)
|
||||
.ConfigureAwait(false);
|
||||
modelCard.GetReceiveInfo("ArcGIS"), // POC: get host app name from settings? same for GetSendInfo
|
||||
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationItem.Token),
|
||||
cancellationItem.Token
|
||||
);
|
||||
|
||||
modelCard.BakedObjectIds = receiveOperationResults.BakedObjectIds.ToList();
|
||||
Commands.SetModelReceiveResult(
|
||||
await Commands.SetModelReceiveResult(
|
||||
modelCardId,
|
||||
receiveOperationResults.BakedObjectIds,
|
||||
receiveOperationResults.ConversionResults
|
||||
);
|
||||
}
|
||||
// Catch here specific exceptions if they related to model card.
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything for now!
|
||||
// Idea for later -> when cancel called, create promise from UI to solve it later with this catch block.
|
||||
// So have 3 state on UI -> Cancellation clicked -> Cancelling -> Cancelled
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // UX reasons - we will report operation exceptions as model card error. We may change this later when we have more exception documentation
|
||||
{
|
||||
_logger.LogModelCardHandledError(ex);
|
||||
await Commands.SetModelError(modelCardId, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelReceive(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
|
||||
@@ -1,22 +1,29 @@
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using ArcGIS.Desktop.Mapping.Events;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using ArcGIS.Desktop.Mapping.Events;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Bindings;
|
||||
|
||||
public class ArcGISSelectionBinding : ISelectionBinding
|
||||
{
|
||||
private readonly MapMembersUtils _mapMemberUtils;
|
||||
public string Name => "selectionBinding";
|
||||
public IBridge Parent { get; }
|
||||
public IBrowserBridge Parent { get; }
|
||||
|
||||
public ArcGISSelectionBinding(IBridge parent, ITopLevelExceptionHandler topLevelHandler)
|
||||
public ArcGISSelectionBinding(
|
||||
IBrowserBridge parent,
|
||||
MapMembersUtils mapMemberUtils,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
)
|
||||
{
|
||||
_mapMemberUtils = mapMemberUtils;
|
||||
Parent = parent;
|
||||
|
||||
// example: https://github.com/Esri/arcgis-pro-sdk-community-samples/blob/master/Map-Authoring/QueryBuilderControl/DefinitionQueryDockPaneViewModel.cs
|
||||
// MapViewEventArgs args = new(MapView.Active);
|
||||
TOCSelectionChangedEvent.Subscribe(_ => topLevelHandler.CatchUnhandled(OnSelectionChanged), true);
|
||||
TOCSelectionChangedEvent.Subscribe(_ => topLevelExceptionHandler.CatchUnhandled(OnSelectionChanged), true);
|
||||
}
|
||||
|
||||
private void OnSelectionChanged()
|
||||
@@ -25,6 +32,22 @@ public class ArcGISSelectionBinding : ISelectionBinding
|
||||
Parent.Send(SelectionBindingEvents.SET_SELECTION, selInfo);
|
||||
}
|
||||
|
||||
private void GetLayersFromGroup(GroupLayer group, List<MapMember> nestedLayers)
|
||||
{
|
||||
nestedLayers.Add(group);
|
||||
foreach (MapMember member in group.Layers)
|
||||
{
|
||||
if (member is GroupLayer subGroup)
|
||||
{
|
||||
GetLayersFromGroup(subGroup, nestedLayers);
|
||||
}
|
||||
else
|
||||
{
|
||||
nestedLayers.Add(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SelectionInfo GetSelection()
|
||||
{
|
||||
MapView mapView = MapView.Active;
|
||||
@@ -32,13 +55,17 @@ public class ArcGISSelectionBinding : ISelectionBinding
|
||||
selectedMembers.AddRange(mapView.GetSelectedLayers());
|
||||
selectedMembers.AddRange(mapView.GetSelectedStandaloneTables());
|
||||
|
||||
List<string> objectTypes = selectedMembers
|
||||
List<MapMember> allNestedMembers = new();
|
||||
var layerMapMembers = _mapMemberUtils.UnpackMapLayers(selectedMembers);
|
||||
allNestedMembers.AddRange(layerMapMembers);
|
||||
|
||||
List<string> objectTypes = allNestedMembers
|
||||
.Select(o => o.GetType().ToString().Split(".").Last())
|
||||
.Distinct()
|
||||
.ToList();
|
||||
return new SelectionInfo(
|
||||
selectedMembers.Select(x => x.URI).ToList(),
|
||||
$"{selectedMembers.Count} layers ({string.Join(", ", objectTypes)})"
|
||||
allNestedMembers.Select(x => x.URI).ToList(),
|
||||
$"{allNestedMembers.Count} layers ({string.Join(", ", objectTypes)})"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,32 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using ArcGIS.Core.Data;
|
||||
using ArcGIS.Desktop.Core;
|
||||
using ArcGIS.Desktop.Editing.Events;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using ArcGIS.Desktop.Mapping.Events;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.ArcGIS.Filters;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.Utils.Cancellation;
|
||||
using Speckle.Connectors.DUI.Exceptions;
|
||||
using Speckle.Connectors.DUI.Logging;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Connectors.DUI.Settings;
|
||||
using ArcGIS.Desktop.Mapping.Events;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Connectors.ArcGIS.Filters;
|
||||
using ArcGIS.Desktop.Editing.Events;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using ArcGIS.Core.Data;
|
||||
using Speckle.Connectors.DUI.Exceptions;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Connectors.Utils.Caching;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Converters.ArcGIS3;
|
||||
using Speckle.Converters.ArcGIS3.Utils;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Bindings;
|
||||
|
||||
@@ -24,102 +34,145 @@ public sealed class ArcGISSendBinding : ISendBinding
|
||||
{
|
||||
public string Name => "sendBinding";
|
||||
public SendBindingUICommands Commands { get; }
|
||||
public IBridge Parent { get; }
|
||||
public IBrowserBridge Parent { get; }
|
||||
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly IUnitOfWorkFactory _unitOfWorkFactory; // POC: unused? :D
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly List<ISendFilter> _sendFilters;
|
||||
private readonly CancellationManager _cancellationManager;
|
||||
private readonly ICancellationManager _cancellationManager;
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly IOperationProgressManager _operationProgressManager;
|
||||
private readonly ILogger<ArcGISSendBinding> _logger;
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
private readonly IArcGISConversionSettingsFactory _arcGISConversionSettingsFactory;
|
||||
private readonly IThreadContext _threadContext;
|
||||
private readonly ISpeckleApplication _speckleApplication;
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to aggregate the changed objects' id.
|
||||
/// Used internally to aggregate the changed objects' id. Note we're using a concurrent dictionary here as the expiry check method is not thread safe, and this was causing problems. See:
|
||||
/// [CNX-202: Unhandled Exception Occurred when receiving in Rhino](https://linear.app/speckle/issue/CNX-202/unhandled-exception-occurred-when-receiving-in-rhino)
|
||||
/// As to why a concurrent dictionary, it's because it's the cheapest/easiest way to do so.
|
||||
/// https://stackoverflow.com/questions/18922985/concurrent-hashsett-in-net-framework
|
||||
/// </summary>
|
||||
private HashSet<string> ChangedObjectIds { get; set; } = new();
|
||||
private ConcurrentDictionary<string, byte> ChangedObjectIds { get; set; } = new();
|
||||
|
||||
private List<FeatureLayer> SubscribedLayers { get; set; } = new();
|
||||
private List<StandaloneTable> SubscribedTables { get; set; } = new();
|
||||
private readonly MapMembersUtils _mapMemberUtils;
|
||||
|
||||
public ArcGISSendBinding(
|
||||
DocumentModelStore store,
|
||||
IBridge parent,
|
||||
IBrowserBridge parent,
|
||||
IEnumerable<ISendFilter> sendFilters,
|
||||
IUnitOfWorkFactory unitOfWorkFactory,
|
||||
CancellationManager cancellationManager,
|
||||
IServiceProvider serviceProvider,
|
||||
ICancellationManager cancellationManager,
|
||||
ISendConversionCache sendConversionCache,
|
||||
IOperationProgressManager operationProgressManager,
|
||||
ILogger<ArcGISSendBinding> logger,
|
||||
IArcGISConversionSettingsFactory arcGisConversionSettingsFactory,
|
||||
MapMembersUtils mapMemberUtils,
|
||||
IThreadContext threadContext,
|
||||
ISpeckleApplication speckleApplication,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_unitOfWorkFactory = unitOfWorkFactory;
|
||||
_serviceProvider = serviceProvider;
|
||||
_sendFilters = sendFilters.ToList();
|
||||
_cancellationManager = cancellationManager;
|
||||
_sendConversionCache = sendConversionCache;
|
||||
_operationProgressManager = operationProgressManager;
|
||||
_logger = logger;
|
||||
_topLevelExceptionHandler = topLevelExceptionHandler;
|
||||
_arcGISConversionSettingsFactory = arcGisConversionSettingsFactory;
|
||||
_mapMemberUtils = mapMemberUtils;
|
||||
_threadContext = threadContext;
|
||||
_speckleApplication = speckleApplication;
|
||||
|
||||
Parent = parent;
|
||||
Commands = new SendBindingUICommands(parent);
|
||||
SubscribeToArcGISEvents();
|
||||
_store.DocumentChanged += (_, _) =>
|
||||
{
|
||||
_sendConversionCache.ClearCache();
|
||||
};
|
||||
}
|
||||
|
||||
private void OnDocumentStoreChangedEvent(object _) => _sendConversionCache.ClearCache();
|
||||
|
||||
private void SubscribeToArcGISEvents()
|
||||
{
|
||||
LayersRemovedEvent.Subscribe(
|
||||
a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForLayersRemovedEvent(a)),
|
||||
a =>
|
||||
_topLevelExceptionHandler.FireAndForget(
|
||||
async () => await QueuedTask.Run(async () => await GetIdsForLayersRemovedEvent(a))
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
StandaloneTablesRemovedEvent.Subscribe(
|
||||
a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForStandaloneTablesRemovedEvent(a)),
|
||||
a =>
|
||||
_topLevelExceptionHandler.FireAndForget(
|
||||
async () => await QueuedTask.Run(async () => await GetIdsForStandaloneTablesRemovedEvent(a))
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
MapPropertyChangedEvent.Subscribe(
|
||||
a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForMapPropertyChangedEvent(a)),
|
||||
a =>
|
||||
_topLevelExceptionHandler.FireAndForget(
|
||||
async () => await QueuedTask.Run(async () => await GetIdsForMapPropertyChangedEvent(a))
|
||||
),
|
||||
true
|
||||
); // Map units, CRS etc.
|
||||
|
||||
MapMemberPropertiesChangedEvent.Subscribe(
|
||||
a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForMapMemberPropertiesChangedEvent(a)),
|
||||
a =>
|
||||
_topLevelExceptionHandler.FireAndForget(
|
||||
async () => await QueuedTask.Run(async () => await GetIdsForMapMemberPropertiesChangedEvent(a))
|
||||
),
|
||||
true
|
||||
); // e.g. Layer name
|
||||
|
||||
ActiveMapViewChangedEvent.Subscribe(
|
||||
_ => _topLevelExceptionHandler.CatchUnhandled(SubscribeToMapMembersDataSourceChange),
|
||||
_ =>
|
||||
_topLevelExceptionHandler.FireAndForget(async () =>
|
||||
{
|
||||
await QueuedTask.Run(SubscribeToMapMembersDataSourceChange);
|
||||
}),
|
||||
true
|
||||
);
|
||||
|
||||
/*
|
||||
LayersAddedEvent.Subscribe(a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForLayersAddedEvent(a)), true);
|
||||
|
||||
StandaloneTablesAddedEvent.Subscribe(
|
||||
a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForStandaloneTablesAddedEvent(a)),
|
||||
true
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
private void SubscribeToMapMembersDataSourceChange()
|
||||
{
|
||||
var task = QueuedTask.Run(() =>
|
||||
if (MapView.Active == null)
|
||||
{
|
||||
if (MapView.Active == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// subscribe to layers
|
||||
foreach (Layer layer in MapView.Active.Map.Layers)
|
||||
// subscribe to layers
|
||||
foreach (Layer layer in MapView.Active.Map.Layers)
|
||||
{
|
||||
if (layer is FeatureLayer featureLayer)
|
||||
{
|
||||
if (layer is FeatureLayer featureLayer)
|
||||
{
|
||||
SubscribeToFeatureLayerDataSourceChange(featureLayer);
|
||||
}
|
||||
SubscribeToFeatureLayerDataSourceChange(featureLayer);
|
||||
}
|
||||
// subscribe to tables
|
||||
foreach (StandaloneTable table in MapView.Active.Map.StandaloneTables)
|
||||
{
|
||||
SubscribeToTableDataSourceChange(table);
|
||||
}
|
||||
});
|
||||
task.Wait();
|
||||
}
|
||||
// subscribe to tables
|
||||
foreach (StandaloneTable table in MapView.Active.Map.StandaloneTables)
|
||||
{
|
||||
SubscribeToTableDataSourceChange(table);
|
||||
}
|
||||
}
|
||||
|
||||
private void SubscribeToFeatureLayerDataSourceChange(FeatureLayer layer)
|
||||
@@ -154,28 +207,31 @@ public sealed class ArcGISSendBinding : ISendBinding
|
||||
{
|
||||
RowCreatedEvent.Subscribe(
|
||||
(args) =>
|
||||
{
|
||||
OnRowChanged(args);
|
||||
},
|
||||
_topLevelExceptionHandler.FireAndForget(async () =>
|
||||
{
|
||||
await OnRowChanged(args);
|
||||
}),
|
||||
layerTable
|
||||
);
|
||||
RowChangedEvent.Subscribe(
|
||||
(args) =>
|
||||
{
|
||||
OnRowChanged(args);
|
||||
},
|
||||
_topLevelExceptionHandler.FireAndForget(async () =>
|
||||
{
|
||||
await OnRowChanged(args);
|
||||
}),
|
||||
layerTable
|
||||
);
|
||||
RowDeletedEvent.Subscribe(
|
||||
(args) =>
|
||||
{
|
||||
OnRowChanged(args);
|
||||
},
|
||||
_topLevelExceptionHandler.FireAndForget(async () =>
|
||||
{
|
||||
await OnRowChanged(args);
|
||||
}),
|
||||
layerTable
|
||||
);
|
||||
}
|
||||
|
||||
private void OnRowChanged(RowChangedEventArgs args)
|
||||
private async Task OnRowChanged(RowChangedEventArgs args)
|
||||
{
|
||||
if (args == null || MapView.Active == null)
|
||||
{
|
||||
@@ -183,54 +239,69 @@ public sealed class ArcGISSendBinding : ISendBinding
|
||||
}
|
||||
|
||||
// get the path of the edited dataset
|
||||
var datasetURI = args.Row.GetTable().GetPath();
|
||||
Uri datasetPath = args.Row.GetTable().GetPath();
|
||||
|
||||
// find all layers & tables reading from the dataset
|
||||
foreach (Layer layer in MapView.Active.Map.Layers)
|
||||
{
|
||||
if (layer.GetPath() == datasetURI)
|
||||
try
|
||||
{
|
||||
ChangedObjectIds.Add(layer.URI);
|
||||
if (layer.GetPath() == datasetPath)
|
||||
{
|
||||
ChangedObjectIds[layer.URI] = 1;
|
||||
}
|
||||
}
|
||||
catch (UriFormatException) // layer.GetPath() or table.GetPath() can throw this error, if data source was removed from the hard drive
|
||||
{
|
||||
// ignore layers with invalid source URI
|
||||
}
|
||||
}
|
||||
foreach (StandaloneTable table in MapView.Active.Map.StandaloneTables)
|
||||
{
|
||||
if (table.GetPath() == datasetURI)
|
||||
try
|
||||
{
|
||||
ChangedObjectIds.Add(table.URI);
|
||||
if (table.GetPath() == datasetPath)
|
||||
{
|
||||
ChangedObjectIds[table.URI] = 1;
|
||||
}
|
||||
}
|
||||
catch (UriFormatException) // layer.GetPath() or table.GetPath() can throw this error, if data source was removed from the hard drive
|
||||
{
|
||||
// ignore layers with invalid source URI
|
||||
}
|
||||
}
|
||||
RunExpirationChecks(false);
|
||||
|
||||
await RunExpirationChecks(false);
|
||||
}
|
||||
|
||||
private void GetIdsForLayersRemovedEvent(LayerEventsArgs args)
|
||||
private async Task GetIdsForLayersRemovedEvent(LayerEventsArgs args)
|
||||
{
|
||||
foreach (Layer layer in args.Layers)
|
||||
{
|
||||
ChangedObjectIds.Add(layer.URI);
|
||||
ChangedObjectIds[layer.URI] = 1;
|
||||
}
|
||||
RunExpirationChecks(true);
|
||||
await RunExpirationChecks(true);
|
||||
}
|
||||
|
||||
private void GetIdsForStandaloneTablesRemovedEvent(StandaloneTableEventArgs args)
|
||||
private async Task GetIdsForStandaloneTablesRemovedEvent(StandaloneTableEventArgs args)
|
||||
{
|
||||
foreach (StandaloneTable table in args.Tables)
|
||||
{
|
||||
ChangedObjectIds.Add(table.URI);
|
||||
ChangedObjectIds[table.URI] = 1;
|
||||
}
|
||||
RunExpirationChecks(true);
|
||||
await RunExpirationChecks(true);
|
||||
}
|
||||
|
||||
private void GetIdsForMapPropertyChangedEvent(MapPropertyChangedEventArgs args)
|
||||
private async Task GetIdsForMapPropertyChangedEvent(MapPropertyChangedEventArgs args)
|
||||
{
|
||||
foreach (Map map in args.Maps)
|
||||
{
|
||||
foreach (MapMember member in map.Layers)
|
||||
List<MapMember> allMapMembers = _mapMemberUtils.GetAllMapMembers(map);
|
||||
foreach (MapMember member in allMapMembers)
|
||||
{
|
||||
ChangedObjectIds.Add(member.URI);
|
||||
ChangedObjectIds[member.URI] = 1;
|
||||
}
|
||||
}
|
||||
RunExpirationChecks(false);
|
||||
await RunExpirationChecks(false);
|
||||
}
|
||||
|
||||
private void GetIdsForLayersAddedEvent(LayerEventsArgs args)
|
||||
@@ -252,7 +323,7 @@ public sealed class ArcGISSendBinding : ISendBinding
|
||||
}
|
||||
}
|
||||
|
||||
private void GetIdsForMapMemberPropertiesChangedEvent(MapMemberPropertiesChangedEventArgs args)
|
||||
private async Task GetIdsForMapMemberPropertiesChangedEvent(MapMemberPropertiesChangedEventArgs args)
|
||||
{
|
||||
// don't subscribe to all events (e.g. expanding group, changing visibility etc.)
|
||||
bool validEvent = false;
|
||||
@@ -278,28 +349,15 @@ public sealed class ArcGISSendBinding : ISendBinding
|
||||
{
|
||||
foreach (MapMember member in args.MapMembers)
|
||||
{
|
||||
ChangedObjectIds.Add(member.URI);
|
||||
ChangedObjectIds[member.URI] = 1;
|
||||
}
|
||||
RunExpirationChecks(false);
|
||||
await RunExpirationChecks(false);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ISendFilter> GetSendFilters() => _sendFilters;
|
||||
|
||||
// POC: delete this
|
||||
public List<CardSetting> GetSendSettings()
|
||||
{
|
||||
return new List<CardSetting>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Id = "includeAttributes",
|
||||
Title = "Include Attributes",
|
||||
Value = true,
|
||||
Type = "boolean"
|
||||
},
|
||||
};
|
||||
}
|
||||
public List<ICardSetting> GetSendSettings() => [];
|
||||
|
||||
[SuppressMessage(
|
||||
"Maintainability",
|
||||
@@ -309,7 +367,7 @@ public sealed class ArcGISSendBinding : ISendBinding
|
||||
public async Task Send(string modelCardId)
|
||||
{
|
||||
//poc: dupe code between connectors
|
||||
using var unitOfWork = _unitOfWorkFactory.Resolve<SendOperation<MapMember>>();
|
||||
|
||||
try
|
||||
{
|
||||
if (_store.GetModelById(modelCardId) is not SenderModelCard modelCard)
|
||||
@@ -318,60 +376,74 @@ public sealed class ArcGISSendBinding : ISendBinding
|
||||
throw new InvalidOperationException("No publish model card was found.");
|
||||
}
|
||||
|
||||
// Init cancellation token source -> Manager also cancel it if exist before
|
||||
CancellationTokenSource cts = _cancellationManager.InitCancellationTokenSource(modelCardId);
|
||||
using var cancellationItem = _cancellationManager.GetCancellationItem(modelCardId);
|
||||
|
||||
var sendInfo = new SendInfo(
|
||||
modelCard.AccountId.NotNull(),
|
||||
modelCard.ProjectId.NotNull(),
|
||||
modelCard.ModelId.NotNull(),
|
||||
"ArcGIS"
|
||||
);
|
||||
|
||||
var sendResult = await QueuedTask
|
||||
.Run(async () =>
|
||||
{
|
||||
List<MapMember> mapMembers = modelCard.SendFilter
|
||||
.NotNull()
|
||||
.GetObjectIds()
|
||||
.Select(id => (MapMember)MapView.Active.Map.FindLayer(id) ?? MapView.Active.Map.FindStandaloneTable(id))
|
||||
.Where(obj => obj != null)
|
||||
.ToList();
|
||||
|
||||
if (mapMembers.Count == 0)
|
||||
{
|
||||
// Handle as CARD ERROR in this function
|
||||
throw new SpeckleSendFilterException(
|
||||
"No objects were found to convert. Please update your publish filter!"
|
||||
);
|
||||
}
|
||||
|
||||
var result = await unitOfWork.Service
|
||||
.Execute(
|
||||
mapMembers,
|
||||
sendInfo,
|
||||
(status, progress) =>
|
||||
Commands.SetModelProgress(modelCardId, new ModelCardProgress(modelCardId, status, progress), cts),
|
||||
cts.Token
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
List<MapMember> mapMembers = await QueuedTask.Run(() =>
|
||||
{
|
||||
scope
|
||||
.ServiceProvider.GetRequiredService<IConverterSettingsStore<ArcGISConversionSettings>>()
|
||||
.Initialize(
|
||||
_arcGISConversionSettingsFactory.Create(
|
||||
Project.Current,
|
||||
MapView.Active.Map,
|
||||
new CRSoffsetRotation(MapView.Active.Map)
|
||||
)
|
||||
.ConfigureAwait(false);
|
||||
);
|
||||
|
||||
return result;
|
||||
})
|
||||
.ConfigureAwait(false);
|
||||
return modelCard
|
||||
.SendFilter.NotNull()
|
||||
.RefreshObjectIds()
|
||||
.Select(id => (MapMember)MapView.Active.Map.FindLayer(id) ?? MapView.Active.Map.FindStandaloneTable(id))
|
||||
.Where(obj => obj != null)
|
||||
.ToList();
|
||||
});
|
||||
|
||||
Commands.SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults);
|
||||
}
|
||||
// Catch here specific exceptions if they related to model card.
|
||||
catch (SpeckleSendFilterException e)
|
||||
{
|
||||
Commands.SetModelError(modelCardId, e);
|
||||
if (mapMembers.Count == 0)
|
||||
{
|
||||
// Handle as CARD ERROR in this function
|
||||
throw new SpeckleSendFilterException("No objects were found to convert. Please update your publish filter!");
|
||||
}
|
||||
|
||||
await QueuedTask.Run(() =>
|
||||
{
|
||||
// subscribe to the selected layer events
|
||||
foreach (MapMember mapMember in mapMembers)
|
||||
{
|
||||
if (mapMember is FeatureLayer featureLayer)
|
||||
{
|
||||
SubscribeToFeatureLayerDataSourceChange(featureLayer);
|
||||
}
|
||||
else if (mapMember is StandaloneTable table)
|
||||
{
|
||||
SubscribeToTableDataSourceChange(table);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var sendResult = await scope
|
||||
.ServiceProvider.GetRequiredService<SendOperation<MapMember>>()
|
||||
.Execute(
|
||||
mapMembers,
|
||||
modelCard.GetSendInfo(_speckleApplication.ApplicationAndVersion),
|
||||
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationItem.Token),
|
||||
cancellationItem.Token
|
||||
);
|
||||
|
||||
await Commands.SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything for now!
|
||||
// Idea for later -> when cancel called, create promise from UI to solve it later with this catch block.
|
||||
// So have 3 state on UI -> Cancellation clicked -> Cancelling -> Cancelled
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // UX reasons - we will report operation exceptions as model card error. We may change this later when we have more exception documentation
|
||||
{
|
||||
_logger.LogModelCardHandledError(ex);
|
||||
await Commands.SetModelError(modelCardId, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelSend(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
@@ -379,19 +451,19 @@ public sealed class ArcGISSendBinding : ISendBinding
|
||||
/// <summary>
|
||||
/// Checks if any sender model cards contain any of the changed objects. If so, also updates the changed objects hashset for each model card - this last part is important for on send change detection.
|
||||
/// </summary>
|
||||
private void RunExpirationChecks(bool idsDeleted)
|
||||
private async Task RunExpirationChecks(bool idsDeleted)
|
||||
{
|
||||
var senders = _store.GetSenders();
|
||||
List<string> expiredSenderIds = new();
|
||||
string[] objectIdsList = ChangedObjectIds.ToArray();
|
||||
string[] objectIdsList = ChangedObjectIds.Keys.ToArray();
|
||||
|
||||
_sendConversionCache.EvictObjects(objectIdsList);
|
||||
|
||||
foreach (SenderModelCard sender in senders)
|
||||
{
|
||||
var objIds = sender.SendFilter.NotNull().GetObjectIds();
|
||||
var objIds = sender.SendFilter.NotNull().RefreshObjectIds();
|
||||
var intersection = objIds.Intersect(objectIdsList).ToList();
|
||||
bool isExpired = sender.SendFilter.NotNull().CheckExpiry(ChangedObjectIds.ToArray());
|
||||
bool isExpired = intersection.Count != 0;
|
||||
if (isExpired)
|
||||
{
|
||||
expiredSenderIds.Add(sender.ModelCardId.NotNull());
|
||||
@@ -405,7 +477,7 @@ public sealed class ArcGISSendBinding : ISendBinding
|
||||
}
|
||||
}
|
||||
|
||||
Commands.SetModelsExpired(expiredSenderIds);
|
||||
ChangedObjectIds = new HashSet<string>();
|
||||
await Commands.SetModelsExpired(expiredSenderIds);
|
||||
ChangedObjectIds = new();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
using System.Reflection;
|
||||
using ArcGIS.Core.Data;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Connectors.ArcGIS.HostApp;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Connectors.Utils.Reflection;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
using ArcProject = ArcGIS.Desktop.Core.Project;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Bindings;
|
||||
|
||||
@@ -17,30 +16,38 @@ namespace Speckle.Connectors.ArcGIS.Bindings;
|
||||
public class BasicConnectorBinding : IBasicConnectorBinding
|
||||
{
|
||||
public string Name => "baseBinding";
|
||||
public IBridge Parent { get; }
|
||||
public IBrowserBridge Parent { get; }
|
||||
|
||||
public BasicConnectorBindingCommands Commands { get; }
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly ArcGISSettings _settings;
|
||||
private readonly ISpeckleApplication _speckleApplication;
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
|
||||
public BasicConnectorBinding(DocumentModelStore store, ArcGISSettings settings, IBridge parent)
|
||||
public BasicConnectorBinding(
|
||||
DocumentModelStore store,
|
||||
IBrowserBridge parent,
|
||||
ISpeckleApplication speckleApplication,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_settings = settings;
|
||||
_speckleApplication = speckleApplication;
|
||||
_topLevelExceptionHandler = topLevelExceptionHandler;
|
||||
Parent = parent;
|
||||
Commands = new BasicConnectorBindingCommands(parent);
|
||||
|
||||
_store.DocumentChanged += (_, _) =>
|
||||
{
|
||||
Commands.NotifyDocumentChanged();
|
||||
};
|
||||
_topLevelExceptionHandler.FireAndForget(async () =>
|
||||
{
|
||||
await Commands.NotifyDocumentChanged();
|
||||
});
|
||||
}
|
||||
|
||||
public string GetSourceApplicationName() => _settings.HostAppInfo.Slug;
|
||||
public string GetSourceApplicationName() => _speckleApplication.Slug;
|
||||
|
||||
public string GetSourceApplicationVersion() => _settings.HostAppInfo.GetVersion(_settings.HostAppVersion);
|
||||
public string GetSourceApplicationVersion() => _speckleApplication.HostApplicationVersion;
|
||||
|
||||
public string GetConnectorVersion() => Assembly.GetAssembly(GetType()).NotNull().GetVersion();
|
||||
public string GetConnectorVersion() => _speckleApplication.SpeckleVersion;
|
||||
|
||||
public DocumentInfo? GetDocumentInfo()
|
||||
{
|
||||
@@ -49,21 +56,25 @@ public class BasicConnectorBinding : IBasicConnectorBinding
|
||||
return null;
|
||||
}
|
||||
|
||||
return new DocumentInfo(MapView.Active.Map.URI, MapView.Active.Map.Name, MapView.Active.Map.Name);
|
||||
return new DocumentInfo(ArcProject.Current.URI, MapView.Active.Map.Name, MapView.Active.Map.URI);
|
||||
}
|
||||
|
||||
public DocumentModelStore GetDocumentState() => _store;
|
||||
|
||||
public void AddModel(ModelCard model) => _store.Models.Add(model);
|
||||
public void AddModel(ModelCard model) => _store.AddModel(model);
|
||||
|
||||
public void UpdateModel(ModelCard model) => _store.UpdateModel(model);
|
||||
|
||||
public void RemoveModel(ModelCard model) => _store.RemoveModel(model);
|
||||
|
||||
public void HighlightObjects(List<string> objectIds) =>
|
||||
HighlightObjectsOnView(objectIds.Select(x => new ObjectID(x)).ToList());
|
||||
public void RemoveModels(List<ModelCard> models) => _store.RemoveModels(models);
|
||||
|
||||
public void HighlightModel(string modelCardId)
|
||||
public async Task HighlightObjects(IReadOnlyList<string> objectIds)
|
||||
{
|
||||
await HighlightObjectsOnView(objectIds.Select(x => new ObjectID(x)).ToList());
|
||||
}
|
||||
|
||||
public async Task HighlightModel(string modelCardId)
|
||||
{
|
||||
var model = _store.GetModelById(modelCardId);
|
||||
|
||||
@@ -76,7 +87,7 @@ public class BasicConnectorBinding : IBasicConnectorBinding
|
||||
|
||||
if (model is SenderModelCard senderModelCard)
|
||||
{
|
||||
objectIds = senderModelCard.SendFilter.NotNull().GetObjectIds().Select(x => new ObjectID(x)).ToList();
|
||||
objectIds = senderModelCard.SendFilter.NotNull().RefreshObjectIds().Select(x => new ObjectID(x)).ToList();
|
||||
}
|
||||
|
||||
if (model is ReceiverModelCard receiverModelCard)
|
||||
@@ -88,27 +99,25 @@ public class BasicConnectorBinding : IBasicConnectorBinding
|
||||
{
|
||||
return;
|
||||
}
|
||||
HighlightObjectsOnView(objectIds);
|
||||
await HighlightObjectsOnView(objectIds);
|
||||
}
|
||||
|
||||
private async void HighlightObjectsOnView(List<ObjectID> objectIds)
|
||||
private async Task HighlightObjectsOnView(IReadOnlyList<ObjectID> objectIds)
|
||||
{
|
||||
MapView mapView = MapView.Active;
|
||||
await QueuedTask.Run(() =>
|
||||
{
|
||||
MapView mapView = MapView.Active;
|
||||
|
||||
await QueuedTask
|
||||
.Run(() =>
|
||||
{
|
||||
List<MapMemberFeature> mapMembersFeatures = GetMapMembers(objectIds, mapView);
|
||||
ClearSelectionInTOC();
|
||||
ClearSelection();
|
||||
SelectMapMembersInTOC(mapMembersFeatures);
|
||||
SelectMapMembersAndFeatures(mapMembersFeatures);
|
||||
mapView.ZoomToSelected();
|
||||
})
|
||||
.ConfigureAwait(false);
|
||||
List<MapMemberFeature> mapMembersFeatures = GetMapMembers(objectIds, mapView);
|
||||
ClearSelectionInTOC();
|
||||
ClearSelection();
|
||||
SelectMapMembersInTOC(mapMembersFeatures);
|
||||
SelectMapMembersAndFeatures(mapMembersFeatures);
|
||||
mapView.ZoomToSelected();
|
||||
});
|
||||
}
|
||||
|
||||
private List<MapMemberFeature> GetMapMembers(List<ObjectID> objectIds, MapView mapView)
|
||||
private List<MapMemberFeature> GetMapMembers(IReadOnlyList<ObjectID> objectIds, MapView mapView)
|
||||
{
|
||||
// find the layer on the map (from the objectID) and add the featureID is available
|
||||
List<MapMemberFeature> mapMembersFeatures = new();
|
||||
@@ -146,7 +155,7 @@ public class BasicConnectorBinding : IBasicConnectorBinding
|
||||
MapView.Active.ClearTOCSelection();
|
||||
}
|
||||
|
||||
private void SelectMapMembersAndFeatures(List<MapMemberFeature> mapMembersFeatures)
|
||||
private void SelectMapMembersAndFeatures(IReadOnlyList<MapMemberFeature> mapMembersFeatures)
|
||||
{
|
||||
foreach (MapMemberFeature mapMemberFeat in mapMembersFeatures)
|
||||
{
|
||||
@@ -171,7 +180,7 @@ public class BasicConnectorBinding : IBasicConnectorBinding
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectMapMembersInTOC(List<MapMemberFeature> mapMembersFeatures)
|
||||
private void SelectMapMembersInTOC(IReadOnlyList<MapMemberFeature> mapMembersFeatures)
|
||||
{
|
||||
List<Layer> layers = new();
|
||||
List<StandaloneTable> tables = new();
|
||||
@@ -185,6 +194,10 @@ public class BasicConnectorBinding : IBasicConnectorBinding
|
||||
{
|
||||
layers.Add(layer);
|
||||
}
|
||||
else
|
||||
{
|
||||
layer.SetExpanded(true);
|
||||
}
|
||||
}
|
||||
else if (member is StandaloneTable table)
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<ArcGIS defaultAssembly="Speckle.Connectors.ArcGIS3.dll" defaultNamespace="Speckle.Connectors.ArcGIS" xmlns="http://schemas.esri.com/DADF/Registry" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.esri.com/DADF/Registry file:///C:/Program%20Files/ArcGIS/Pro/bin/ArcGIS.Desktop.Framework.xsd">
|
||||
<AddInInfo id="{6CB1D25C-B8BF-4A33-9099-C1F8D1B32EFC}" version="1.0" desktopVersion="3.0.34047">
|
||||
<Name>Speckle</Name>
|
||||
<Description>Speckle connector for ArcGIS</Description>
|
||||
<Description>Next Gen Speckle Connector (Beta) for ArcGIS</Description>
|
||||
<Image>Images\AddinDesktop32.png</Image>
|
||||
<Author>Speckle Systems</Author>
|
||||
<Company>Speckle Systems</Company>
|
||||
@@ -33,21 +33,21 @@
|
||||
<insertModule id="ConnectorArcGIS_Module" className="SpeckleModule" autoLoad="false" caption="SpeckleModule">
|
||||
<!-- uncomment to have the control hosted on a separate tab-->
|
||||
<tabs>
|
||||
<!--<tab id="Speckle_Tab1" caption="New Tab">
|
||||
<tab id="Speckle_Tab1" caption="Speckle">
|
||||
<group refID="Speckle_Group1"/>
|
||||
</tab>-->
|
||||
</tab>
|
||||
</tabs>
|
||||
<groups>
|
||||
<!-- comment this out if you have no controls on the Addin tab to avoid
|
||||
an empty group-->
|
||||
<group id="Speckle_Group1" caption="Speckle" appearsOnAddInTab="true" keytip="G1">
|
||||
an empty group. change appearsOnAddinTab to "True" if control is to be in the addin tab-->
|
||||
<group id="Speckle_Group1" caption="Speckle" appearsOnAddInTab="false" keytip="G1">
|
||||
<!-- host controls within groups -->
|
||||
<button refID="SpeckleDUI3_SpeckleDUI3OpenButton" size="large" />
|
||||
</group>
|
||||
</groups>
|
||||
<controls>
|
||||
<!-- add your controls here -->
|
||||
<button id="SpeckleDUI3_SpeckleDUI3OpenButton" caption="SpeckleNewUI"
|
||||
<button id="SpeckleDUI3_SpeckleDUI3OpenButton" caption="Speckle (Beta)"
|
||||
className="SpeckleDUI3OpenButton" loadOnClick="true"
|
||||
keytip="B1"
|
||||
smallImage="Images/s2logo_16.png"
|
||||
@@ -59,7 +59,7 @@
|
||||
</controls>
|
||||
|
||||
<dockPanes>
|
||||
<dockPane id="SpeckleDUI3_SpeckleDUI3" caption="SpeckleNewUI" className="SpeckleDUI3ViewModel" keytip="DockPane" initiallyVisible="true" dock="group" dockWith="esri_core_contentsDockPane">
|
||||
<dockPane id="SpeckleDUI3_SpeckleDUI3" caption="Speckle (Beta)" className="SpeckleDUI3ViewModel" keytip="DockPane" initiallyVisible="true" dock="group" dockWith="esri_core_projectDockPane">
|
||||
<content className="SpeckleDUI3Wrapper" />
|
||||
</dockPane>
|
||||
</dockPanes>
|
||||
|
||||
+45
-42
@@ -1,63 +1,66 @@
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.ArcGIS.Bindings;
|
||||
using Speckle.Connectors.ArcGis.Operations.Send;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.ArcGIS.Operations.Receive;
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Connectors.DUI.WebView;
|
||||
using Speckle.Connectors.Utils.Builders;
|
||||
using Speckle.Autofac;
|
||||
using Speckle.Connectors.ArcGIS.Filters;
|
||||
using Speckle.Connectors.ArcGIS.HostApp;
|
||||
using Speckle.Connectors.ArcGIS.Operations.Receive;
|
||||
using Speckle.Connectors.ArcGis.Operations.Send;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.Common;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Connectors.Utils.Caching;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Core.Models.GraphTraversal;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Connectors.DUI.WebView;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
|
||||
// POC: This is a temp reference to root object senders to tweak CI failing after having generic interfaces into common project.
|
||||
// This should go whenever it is aligned.
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.DependencyInjection;
|
||||
|
||||
public class ArcGISConnectorModule : ISpeckleModule
|
||||
public static class ArcGISConnectorModule
|
||||
{
|
||||
public void Load(SpeckleContainerBuilder builder)
|
||||
public static void AddArcGIS(this IServiceCollection serviceCollection)
|
||||
{
|
||||
builder.AddAutofac();
|
||||
builder.AddConnectorUtils();
|
||||
builder.AddDUI();
|
||||
builder.AddDUIView();
|
||||
|
||||
// POC: Overwriting the SyncToMainThread to SyncToCurrentThread for ArcGIS only!
|
||||
// On SendOperation, once we called QueuedTask, it expect to run everything on same thread.
|
||||
builder.AddSingletonInstance<ISyncToThread, SyncToQueuedTask>();
|
||||
|
||||
builder.AddSingleton<DocumentModelStore, ArcGISDocumentStore>();
|
||||
serviceCollection.AddConnectors();
|
||||
serviceCollection.AddDUI<DefaultThreadContext, ArcGISDocumentStore>();
|
||||
serviceCollection.AddDUIView();
|
||||
|
||||
// Register bindings
|
||||
builder.AddSingleton<IBinding, TestBinding>();
|
||||
builder.AddSingleton<IBinding, ConfigBinding>("connectorName", "ArcGIS"); // POC: Easier like this for now, should be cleaned up later
|
||||
builder.AddSingleton<IBinding, AccountBinding>();
|
||||
builder.AddSingleton<IBinding, BasicConnectorBinding>();
|
||||
builder.AddSingleton<IBasicConnectorBinding, BasicConnectorBinding>();
|
||||
builder.AddSingleton<IBinding, ArcGISSelectionBinding>();
|
||||
builder.AddSingleton<IBinding, ArcGISSendBinding>();
|
||||
builder.AddSingleton<IBinding, ArcGISReceiveBinding>();
|
||||
serviceCollection.AddSingleton<IBinding, TestBinding>();
|
||||
serviceCollection.AddSingleton<IBinding, ConfigBinding>();
|
||||
serviceCollection.AddSingleton<IBinding, AccountBinding>();
|
||||
serviceCollection.AddSingleton<IBinding>(sp => sp.GetRequiredService<IBasicConnectorBinding>());
|
||||
serviceCollection.AddSingleton<IBasicConnectorBinding, BasicConnectorBinding>();
|
||||
|
||||
builder.AddTransient<ISendFilter, ArcGISSelectionFilter>();
|
||||
builder.AddScoped<IHostObjectBuilder, ArcGISHostObjectBuilder>();
|
||||
builder.AddSingleton(DefaultTraversal.CreateTraversalFunc());
|
||||
serviceCollection.AddSingleton(DefaultTraversal.CreateTraversalFunc());
|
||||
|
||||
// register send operation and dependencies
|
||||
builder.AddScoped<SendOperation<MapMember>>();
|
||||
builder.AddScoped<ArcGISRootObjectBuilder>();
|
||||
builder.AddScoped<IRootObjectBuilder<MapMember>, ArcGISRootObjectBuilder>();
|
||||
|
||||
serviceCollection.AddSingleton<IBinding, ArcGISSendBinding>();
|
||||
serviceCollection.AddScoped<SendOperation<MapMember>>();
|
||||
serviceCollection.AddSingleton<IBinding, ArcGISSelectionBinding>();
|
||||
serviceCollection.AddTransient<ISendFilter, ArcGISSelectionFilter>();
|
||||
serviceCollection.AddScoped<ArcGISRootObjectBuilder>();
|
||||
serviceCollection.AddScoped<IRootObjectBuilder<MapMember>, ArcGISRootObjectBuilder>();
|
||||
serviceCollection.AddScoped<ArcGISLayerUnpacker>();
|
||||
serviceCollection.AddScoped<ArcGISColorUnpacker>();
|
||||
// register send conversion cache
|
||||
builder.AddSingleton<ISendConversionCache, SendConversionCache>();
|
||||
serviceCollection.AddSingleton<ISendConversionCache, SendConversionCache>();
|
||||
|
||||
// register receive operation and dependencies
|
||||
// serviceCollection.AddSingleton<IBinding, ArcGISReceiveBinding>(); // POC: disabled until receive code is refactored
|
||||
serviceCollection.AddScoped<LocalToGlobalConverterUtils>();
|
||||
serviceCollection.AddScoped<ArcGISColorManager>();
|
||||
serviceCollection.AddScoped<IHostObjectBuilder, ArcGISHostObjectBuilder>();
|
||||
|
||||
serviceCollection.AddScoped<MapMembersUtils>();
|
||||
|
||||
// operation progress manager
|
||||
serviceCollection.AddSingleton<IOperationProgressManager, OperationProgressManager>();
|
||||
}
|
||||
}
|
||||
|
||||
+16
-12
@@ -12,6 +12,9 @@
|
||||
<PackageOutputPath ParameterType="System.String" Output="true"/>
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<!-- <Reference Include="System.IO.Compression.FileSystem"/>-->
|
||||
<!-- <Reference Include="System.Xml.Linq"/>-->
|
||||
<!-- <Reference Include="System.Xml"/>-->
|
||||
<Using Namespace="System"/>
|
||||
<Using Namespace="System.IO"/>
|
||||
<Using Namespace="System.Xml.Linq"/>
|
||||
@@ -151,7 +154,6 @@
|
||||
Log.LogErrorFromException(ex);
|
||||
return false;
|
||||
}
|
||||
return Success;
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
@@ -187,7 +189,7 @@
|
||||
{
|
||||
Log.LogMessage(MessageImportance.Low, "RelativePaths: " + i.ToString());
|
||||
}
|
||||
return true;
|
||||
Success = true;
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
@@ -201,6 +203,8 @@
|
||||
<CleanInfo ParameterType="System.String" Output="true"/>
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<!-- <Reference Include="System.Xml.Linq"/>-->
|
||||
<!-- <Reference Include="System.Xml"/>-->
|
||||
<Using Namespace="System"/>
|
||||
<Using Namespace="System.IO"/>
|
||||
<Using Namespace="System.Xml.Linq"/>
|
||||
@@ -261,7 +265,6 @@
|
||||
CleanInfo = AssemblyName + extension;
|
||||
}
|
||||
Success = true;
|
||||
return Success;
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
@@ -272,8 +275,9 @@
|
||||
<PackageType Condition="'$(PackageType)' == ''">Addin</PackageType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ArcGISFolder>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\ESRI\ArcGISPro', 'InstallDir', null, RegistryView.Registry64))</ArcGISFolder>
|
||||
<ArcGISFolder Condition="'$(ArcGISFolder)' == ''">$(registry:HKEY_CURRENT_USER\SOFTWARE\ESRI\ArcGISPro@InstallDir)</ArcGISFolder>
|
||||
<ArcGISFolder>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\ESRI\ArcGISPro', 'InstallDir', null, RegistryView.Registry64))\bin</ArcGISFolder>
|
||||
<ArcGISFolder Condition="'$(ArcGISFolder)' == ''">$(registry:HKEY_CURRENT_USER\SOFTWARE\ESRI\ArcGISPro@InstallDir)\bin</ArcGISFolder>
|
||||
<ArcGISFolder Condition="'$(ArcGISFolder)' == '' Or !Exists('$(ArcGISFolder)\RegisterAddIn.exe')">$(ProgramData)\EsriProCommon\</ArcGISFolder>
|
||||
</PropertyGroup>
|
||||
<Target Name="ArcGISInstallOutput" AfterTargets="Build">
|
||||
<Message Text="IntermediateOutputPath Name: $(IntermediateOutputPath)..." Importance="High"/>
|
||||
@@ -329,9 +333,9 @@
|
||||
<!-- Shell out to RegisterAddIn.exe to install the package -->
|
||||
<Message Text="Deploying $(PackageType)..." Importance="High"/>
|
||||
<Message Text="ArcGISFolder Name: $(ArcGISFolder)..." Importance="High"/>
|
||||
<Message Text="Unable to execute RegisterAddIn.exe. ArcGIS Pro is not installed." Importance="High" Condition="'$(ArcGISFolder)' == ''"/>
|
||||
<Message Text="Execute RegisterAddIn.exe "$(PackageFile)" /s..." Importance="High" Condition="'$(ArcGISFolder)' != ''"/>
|
||||
<Exec IgnoreExitCode="true" WorkingDirectory="$(ArcGISFolder)bin" Command="RegisterAddIn.exe "$(PackageFile)" /s" Condition="'$(ArcGISFolder)' != '' AND $(PackageFile) != '' ">
|
||||
<Message Text="Unable to execute RegisterAddIn.exe. ArcGIS Pro is not installed." Importance="High" Condition="!Exists('$(ArcGISFolder)')"/>
|
||||
<Message Text="Execute RegisterAddIn.exe "$(PackageFile)" /s..." Importance="High" Condition="Exists('$(ArcGISFolder)')"/>
|
||||
<Exec IgnoreExitCode="true" WorkingDirectory="$(ArcGISFolder)" Command="RegisterAddIn.exe "$(PackageFile)" /s" Condition="Exists('$(ArcGISFolder)') AND $(PackageFile) != '' ">
|
||||
<Output TaskParameter="ExitCode" PropertyName="ESRIRegAddinExitCode" />
|
||||
</Exec>
|
||||
<RemoveDir Condition="Exists('$(ZipIntermediatePath)')" Directories="$(ZipIntermediatePath)" />
|
||||
@@ -342,10 +346,10 @@
|
||||
PackageType="$(PackageType)">
|
||||
<Output TaskParameter="CleanInfo" PropertyName="CleanInfo" />
|
||||
</CleanAddIn>
|
||||
<Message Text="Clean $(PackageType)..." Importance="High"/>
|
||||
<Message Text="Execute RegisterAddIn.exe "$(CleanInfo)" /u..." Importance="High" Condition="'$(ArcGISFolder)' != ''"/>
|
||||
<Message Text="Unable to execute RegisterAddIn.exe. ArcGIS Pro is not installed." Importance="High" Condition="'$(ArcGISFolder)' == ''"/>
|
||||
<Exec IgnoreExitCode="true" WorkingDirectory="$(ArcGISFolder)bin" Command="RegisterAddIn.exe "$(CleanInfo)" /u /s" Condition="'$(ArcGISFolder)' != '' AND $(CleanInfo) != ''">
|
||||
<Message Text="Clean $(PackageType).$(ArcGISFolder).." Importance="High"/>
|
||||
<Message Text="Execute RegisterAddIn.exe "$(CleanInfo)" /u..." Importance="High" Condition="Exists('$(ArcGISFolder)')"/>
|
||||
<Message Text="Unable to execute RegisterAddIn.exe. ArcGIS Pro is not installed." Importance="High" Condition="!Exists('$(ArcGISFolder)')"/>
|
||||
<Exec IgnoreExitCode="true" WorkingDirectory="$(ArcGISFolder)" Command="RegisterAddIn.exe "$(CleanInfo)" /u /s" Condition="Exists('$(ArcGISFolder)') AND $(CleanInfo) != ''">
|
||||
<Output TaskParameter="ExitCode" PropertyName="ESRIRegAddinExitCode" />
|
||||
</Exec>
|
||||
</Target>
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Filters;
|
||||
|
||||
public class ArcGISEverythingFilter : EverythingSendFilter
|
||||
{
|
||||
public override List<string> GetObjectIds() => new(); // TODO
|
||||
|
||||
public override bool CheckExpiry(string[] changedObjectIds) => true;
|
||||
}
|
||||
@@ -4,7 +4,10 @@ namespace Speckle.Connectors.ArcGIS.Filters;
|
||||
|
||||
public class ArcGISSelectionFilter : DirectSelectionSendFilter
|
||||
{
|
||||
public override List<string> GetObjectIds() => SelectedObjectIds;
|
||||
public ArcGISSelectionFilter()
|
||||
{
|
||||
IsDefault = true;
|
||||
}
|
||||
|
||||
public override bool CheckExpiry(string[] changedObjectIds) => SelectedObjectIds.Intersect(changedObjectIds).Any();
|
||||
public override List<string> RefreshObjectIds() => SelectedObjectIds;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
global using AC = ArcGIS.Core;
|
||||
global using ACD = ArcGIS.Core.Data;
|
||||
global using ADM = ArcGIS.Desktop.Mapping;
|
||||
@@ -0,0 +1,265 @@
|
||||
using System.Drawing;
|
||||
using ArcGIS.Core.CIM;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Converters.ArcGIS3.Utils;
|
||||
using Speckle.Objects;
|
||||
using Speckle.Objects.Other;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Extensions;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// TODO: definitely need to refactor this, probably will collect colors during layer iteration in the root object builder.
|
||||
/// </summary>
|
||||
public class ArcGISColorManager
|
||||
{
|
||||
public Dictionary<string, Color> ObjectColorsIdMap { get; set; } = new();
|
||||
public Dictionary<string, Color> ObjectMaterialsIdMap { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Parse Color Proxies and stores in ObjectColorsIdMap the relationship between object ids and colors
|
||||
/// </summary>
|
||||
/// <param name="colorProxies"></param>
|
||||
/// <param name="onOperationProgressed"></param>
|
||||
public void ParseColors(List<ColorProxy> colorProxies, IProgress<CardProgress> onOperationProgressed)
|
||||
{
|
||||
// injected as Singleton, so we need to clean existing proxies first
|
||||
ObjectColorsIdMap = new();
|
||||
var count = 0;
|
||||
foreach (ColorProxy colorProxy in colorProxies)
|
||||
{
|
||||
onOperationProgressed.Report(new("Converting colors", (double)++count / colorProxies.Count));
|
||||
foreach (string objectId in colorProxy.objects)
|
||||
{
|
||||
Color convertedColor = Color.FromArgb(colorProxy.value);
|
||||
ObjectColorsIdMap.TryAdd(objectId, convertedColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse Color renderMaterials and stores in ObjectMaterialsIdMap the relationship between object ids and colors
|
||||
/// </summary>
|
||||
/// <param name="materialProxies"></param>
|
||||
/// <param name="onOperationProgressed"></param>
|
||||
public void ParseMaterials(List<RenderMaterialProxy> materialProxies, IProgress<CardProgress> onOperationProgressed)
|
||||
{
|
||||
// injected as Singleton, so we need to clean existing proxies first
|
||||
ObjectMaterialsIdMap = new();
|
||||
var count = 0;
|
||||
foreach (RenderMaterialProxy colorProxy in materialProxies)
|
||||
{
|
||||
onOperationProgressed.Report(new("Converting materials", (double)++count / materialProxies.Count));
|
||||
foreach (string objectId in colorProxy.objects)
|
||||
{
|
||||
Color convertedColor = Color.FromArgb(colorProxy.value.diffuse);
|
||||
ObjectMaterialsIdMap.TryAdd(objectId, convertedColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int CIMColorToInt(CIMColor color)
|
||||
{
|
||||
return (255 << 24)
|
||||
| ((int)Math.Round(color.Values[0]) << 16)
|
||||
| ((int)Math.Round(color.Values[1]) << 8)
|
||||
| (int)Math.Round(color.Values[2]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new CIMUniqueValueClass for UniqueRenderer per each object ID
|
||||
/// </summary>
|
||||
/// <param name="tc"></param>
|
||||
/// <param name="speckleGeometryType"></param>
|
||||
private CIMUniqueValueClass CreateColorCategory(
|
||||
TraversalContext tc,
|
||||
esriGeometryType speckleGeometryType,
|
||||
string uniqueLabel
|
||||
)
|
||||
{
|
||||
// declare default white color
|
||||
Color color = Color.FromArgb(255, 255, 255, 255);
|
||||
bool colorFound = false;
|
||||
|
||||
// get color moving upwards from the object
|
||||
foreach (var parent in tc.GetAscendants())
|
||||
{
|
||||
if (parent.applicationId is string appId)
|
||||
{
|
||||
if (ObjectMaterialsIdMap.TryGetValue(appId, out Color objColorMaterial))
|
||||
{
|
||||
color = objColorMaterial;
|
||||
colorFound = true;
|
||||
break;
|
||||
}
|
||||
if (ObjectColorsIdMap.TryGetValue(appId, out Color objColor))
|
||||
{
|
||||
color = objColor;
|
||||
colorFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handling Revit case, where child objects have separate colors/materials
|
||||
if (!colorFound && tc.Current is IDataObject)
|
||||
{
|
||||
var displayable = tc.Current.TryGetDisplayValue();
|
||||
if (displayable != null)
|
||||
{
|
||||
foreach (var childObj in displayable)
|
||||
{
|
||||
if (childObj.applicationId is string appId)
|
||||
{
|
||||
if (ObjectMaterialsIdMap.TryGetValue(appId, out Color objColorMaterial))
|
||||
{
|
||||
color = objColorMaterial;
|
||||
break;
|
||||
}
|
||||
if (ObjectColorsIdMap.TryGetValue(appId, out Color objColor))
|
||||
{
|
||||
color = objColor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CIMSymbolReference symbol = CreateSymbol(speckleGeometryType, color);
|
||||
|
||||
// First create a "CIMUniqueValueClass"
|
||||
List<CIMUniqueValue> listUniqueValues = new() { new CIMUniqueValue { FieldValues = new string[] { uniqueLabel } } };
|
||||
|
||||
CIMUniqueValueClass newUniqueValueClass =
|
||||
new()
|
||||
{
|
||||
Editable = true,
|
||||
Label = uniqueLabel,
|
||||
Patch = PatchShape.Default,
|
||||
Symbol = symbol,
|
||||
Visible = true,
|
||||
Values = listUniqueValues.ToArray()
|
||||
};
|
||||
return newUniqueValueClass;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a Symbol from GeometryType and Color
|
||||
/// </summary>
|
||||
/// <param name="speckleGeometryType"></param>
|
||||
/// <param name="color"></param>
|
||||
private CIMSymbolReference CreateSymbol(esriGeometryType speckleGeometryType, Color color)
|
||||
{
|
||||
var symbol = SymbolFactory
|
||||
.Instance.ConstructPointSymbol(ColorFactory.Instance.CreateColor(color))
|
||||
.MakeSymbolReference();
|
||||
|
||||
switch (speckleGeometryType)
|
||||
{
|
||||
case esriGeometryType.esriGeometryLine:
|
||||
case esriGeometryType.esriGeometryPolyline:
|
||||
symbol = SymbolFactory
|
||||
.Instance.ConstructLineSymbol(ColorFactory.Instance.CreateColor(color))
|
||||
.MakeSymbolReference();
|
||||
break;
|
||||
case esriGeometryType.esriGeometryPolygon:
|
||||
case esriGeometryType.esriGeometryMultiPatch:
|
||||
symbol = SymbolFactory
|
||||
.Instance.ConstructPolygonSymbol(ColorFactory.Instance.CreateColor(color))
|
||||
.MakeSymbolReference();
|
||||
break;
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add CIMUniqueValueClass to Layer Renderer (if exists); apply Renderer to Layer (again)
|
||||
/// </summary>
|
||||
/// <param name="tc"></param>
|
||||
/// <param name="trackerItem"></param>
|
||||
public CIMUniqueValueRenderer? CreateOrEditLayerRenderer(
|
||||
TraversalContext tc,
|
||||
ObjectConversionTracker trackerItem,
|
||||
CIMRenderer? existingRenderer
|
||||
)
|
||||
{
|
||||
if (trackerItem.HostAppMapMember is not FeatureLayer fLayer)
|
||||
{
|
||||
// do nothing with non-feature layers
|
||||
return null;
|
||||
}
|
||||
|
||||
// declare default grey color, create default symbol for the given layer geometry type
|
||||
var color = Color.FromArgb(CIMColorToInt(ColorFactory.Instance.GreyRGB));
|
||||
CIMSymbolReference defaultSymbol = CreateSymbol(fLayer.ShapeType, color);
|
||||
|
||||
// get existing renderer classes
|
||||
List<CIMUniqueValueClass> listUniqueValueClasses = new() { };
|
||||
if (existingRenderer is CIMUniqueValueRenderer uniqueRenderer)
|
||||
{
|
||||
if (uniqueRenderer.Groups[0].Classes != null)
|
||||
{
|
||||
listUniqueValueClasses.AddRange(uniqueRenderer.Groups[0].Classes.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
// Add new CIMUniqueValueClass (or multiple, if it's a Collection with elements, e.g. VectorLayer)
|
||||
List<TraversalContext> traversalContexts = new();
|
||||
if (tc.Current is Collection collection)
|
||||
{
|
||||
foreach (var element in collection.elements)
|
||||
{
|
||||
TraversalContext newTc = new(element, "elements", tc);
|
||||
traversalContexts.Add(newTc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
traversalContexts.Add(tc);
|
||||
}
|
||||
|
||||
foreach (var tContext in traversalContexts)
|
||||
{
|
||||
// get unique label
|
||||
string? uniqueLabel = tContext.Current?.id;
|
||||
|
||||
// remove any GIS-specific classes for now
|
||||
/*
|
||||
if (tContext.Current is IGisFeature gisFeat)
|
||||
{
|
||||
var existingLabel = gisFeat.attributes["Speckle_ID"];
|
||||
if (existingLabel is string stringLabel)
|
||||
{
|
||||
uniqueLabel = stringLabel;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (uniqueLabel is not null && !listUniqueValueClasses.Select(x => x.Label).Contains(uniqueLabel))
|
||||
{
|
||||
CIMUniqueValueClass newUniqueValueClass = CreateColorCategory(tContext, fLayer.ShapeType, uniqueLabel);
|
||||
listUniqueValueClasses.Add(newUniqueValueClass);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a list of CIMUniqueValueGroup
|
||||
CIMUniqueValueGroup uvg = new() { Classes = listUniqueValueClasses.ToArray(), Heading = "Speckle_ID" };
|
||||
List<CIMUniqueValueGroup> listUniqueValueGroups = new() { uvg };
|
||||
// Create the CIMUniqueValueRenderer
|
||||
CIMUniqueValueRenderer uvr =
|
||||
new()
|
||||
{
|
||||
UseDefaultSymbol = true,
|
||||
DefaultLabel = "all other values",
|
||||
DefaultSymbol = defaultSymbol,
|
||||
Groups = listUniqueValueGroups.ToArray(),
|
||||
Fields = new string[] { "Speckle_ID" }
|
||||
};
|
||||
return uvr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,461 @@
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.HostApp;
|
||||
|
||||
public class ArcGISColorUnpacker
|
||||
{
|
||||
/// <summary>
|
||||
/// Cache of all color proxies for converted features. Key is the Color proxy argb value.
|
||||
/// </summary>
|
||||
public Dictionary<int, ColorProxy> ColorProxyCache { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Stores the current renderer (determined by mapMember)
|
||||
/// </summary>
|
||||
private AC.CIM.CIMRenderer? StoredRenderer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stores the current renderer (determined by tin mapmember)
|
||||
/// </summary>
|
||||
private AC.CIM.CIMTinRenderer? StoredTinRenderer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stores the used renderer fields from the layer
|
||||
/// </summary>
|
||||
private List<string> StoredRendererFields { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stores an already processed color for current mapMember, to dbe used by all mapMember objects. Only applies to simple type renderers
|
||||
/// </summary>
|
||||
private int? StoredColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stores a feature layer renderer to be used by <see cref="ProcessFeatureLayerColor"/> in <see cref="StoredRenderer"/>, any fields used by the renderer from the layer, and resets the <see cref="StoredColor"/> and <see cref="StoredRendererFields"/>
|
||||
/// </summary>
|
||||
/// <param name="featureLayer"></param>
|
||||
/// <exception cref="AC.CalledOnWrongThreadException">Must be called on MCT.</exception>
|
||||
public void StoreRendererAndFields(ADM.FeatureLayer featureLayer)
|
||||
{
|
||||
// field names are unique, but often their alias is used instead by renderer headings
|
||||
// so we are storing both names and alias in this dictionary for fast lookup
|
||||
// POC: adding aliases are not optimal, because they do not need to be unique && they can be the same as the name of another field
|
||||
Dictionary<string, string> layerFieldDictionary = new();
|
||||
foreach (ADM.FieldDescription field in featureLayer.GetFieldDescriptions())
|
||||
{
|
||||
layerFieldDictionary.TryAdd(field.Name, field.Name);
|
||||
layerFieldDictionary.TryAdd(field.Alias, field.Name);
|
||||
}
|
||||
|
||||
// clear stored values
|
||||
StoredRendererFields = new();
|
||||
StoredColor = null;
|
||||
StoredRenderer = null;
|
||||
|
||||
AC.CIM.CIMRenderer layerRenderer = featureLayer.GetRenderer();
|
||||
List<string> fields = new();
|
||||
bool isSupported = false;
|
||||
switch (layerRenderer)
|
||||
{
|
||||
case AC.CIM.CIMSimpleRenderer:
|
||||
isSupported = true;
|
||||
break;
|
||||
case AC.CIM.CIMUniqueValueRenderer uniqueValueRenderer:
|
||||
isSupported = true;
|
||||
fields = uniqueValueRenderer.Fields.ToList();
|
||||
break;
|
||||
case AC.CIM.CIMClassBreaksRenderer classBreaksRenderer:
|
||||
isSupported = true;
|
||||
fields.Add(classBreaksRenderer.Field);
|
||||
break;
|
||||
default:
|
||||
// TODO: log error here that a renderer is unsupported
|
||||
break;
|
||||
}
|
||||
|
||||
if (isSupported)
|
||||
{
|
||||
StoredRenderer = layerRenderer;
|
||||
foreach (string field in fields)
|
||||
{
|
||||
if (layerFieldDictionary.TryGetValue(field, out string? fieldName))
|
||||
{
|
||||
StoredRendererFields.Add(fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a las layer renderer to be used by <see cref="ProcessLasLayerColor"/> in <see cref="StoredTinRenderer"/>
|
||||
/// </summary>
|
||||
/// <param name="lasLayer"></param>
|
||||
/// <exception cref="AC.CalledOnWrongThreadException">Must be called on MCT.</exception>
|
||||
public void StoreRenderer(ADM.LasDatasetLayer lasLayer)
|
||||
{
|
||||
// clear stored values
|
||||
StoredTinRenderer = null;
|
||||
|
||||
// POC: not sure why we are only using the first renderer here
|
||||
AC.CIM.CIMTinRenderer layerRenderer = lasLayer.GetRenderers()[0];
|
||||
bool isSupported = false;
|
||||
switch (layerRenderer)
|
||||
{
|
||||
case AC.CIM.CIMTinUniqueValueRenderer:
|
||||
isSupported = true;
|
||||
break;
|
||||
default:
|
||||
// TODO: log error here that a renderer is unsupported
|
||||
break;
|
||||
}
|
||||
|
||||
if (isSupported)
|
||||
{
|
||||
StoredTinRenderer = layerRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes a las layer's point color by the stored <see cref="StoredRenderer"/>, and stores the point's id and color proxy to the <see cref="ColorProxyCache"/>.
|
||||
/// POC: logic probably can be combined with ProcessFeatureLayerColor.
|
||||
/// </summary>
|
||||
/// <param name="point"></param>
|
||||
public void ProcessLasLayerColor(ACD.Analyst3D.LasPoint point, string pointApplicationId)
|
||||
{
|
||||
// get the color from the renderer and point
|
||||
AC.CIM.CIMColor? color;
|
||||
switch (StoredTinRenderer)
|
||||
{
|
||||
case AC.CIM.CIMTinUniqueValueRenderer uniqueValueRenderer:
|
||||
color = GetPointColorByUniqueValueRenderer(uniqueValueRenderer, point);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// get or create the color proxy for the point
|
||||
int argb = CIMColorToInt(color ?? point.RGBColor);
|
||||
AddObjectIdToColorProxyCache(pointApplicationId, argb);
|
||||
}
|
||||
|
||||
// Retrieves the las point color from a unique value renderer
|
||||
// unique renderers have groups of conditions that may affect the color of a feature
|
||||
// resulting in a different color than the default renderer symbol color
|
||||
private AC.CIM.CIMColor? GetPointColorByUniqueValueRenderer(
|
||||
AC.CIM.CIMTinUniqueValueRenderer renderer,
|
||||
ACD.Analyst3D.LasPoint point
|
||||
)
|
||||
{
|
||||
foreach (AC.CIM.CIMUniqueValueGroup group in renderer.Groups)
|
||||
{
|
||||
foreach (AC.CIM.CIMUniqueValueClass groupClass in group.Classes)
|
||||
{
|
||||
foreach (AC.CIM.CIMUniqueValue value in groupClass.Values)
|
||||
{
|
||||
// all field values have to match the row values
|
||||
for (int i = 0; i < value.FieldValues.Length; i++)
|
||||
{
|
||||
string groupValue = value.FieldValues[i].Replace("<Null>", "");
|
||||
object? pointValue = point.ClassCode;
|
||||
|
||||
if (ValuesAreEqual(groupValue, pointValue))
|
||||
{
|
||||
return groupClass.Symbol.Symbol.GetColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes a feature layer's row color by the stored <see cref="StoredRenderer"/>, and stores the row's id and color proxy to the <see cref="ColorProxyCache"/>.
|
||||
/// </summary>
|
||||
/// <param name="row"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ACD.Exceptions.GeodatabaseException"></exception>
|
||||
public void ProcessFeatureLayerColor(ACD.Row row, string rowApplicationId)
|
||||
{
|
||||
// if stored color is not null, this means the renderer was a simple renderer that applies to the entire layer, and was already created.
|
||||
// just add the row application id to the color proxy.
|
||||
if (StoredColor is int existingColorProxyId)
|
||||
{
|
||||
AddObjectIdToColorProxyCache(rowApplicationId, existingColorProxyId);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the color from the renderer and row
|
||||
AC.CIM.CIMColor? color = null;
|
||||
switch (StoredRenderer)
|
||||
{
|
||||
// simple renderers do not rely on fields, so the color can be retrieved from the renderer directly
|
||||
case AC.CIM.CIMSimpleRenderer simpleRenderer:
|
||||
color = simpleRenderer.Symbol.Symbol.GetColor();
|
||||
break;
|
||||
|
||||
case AC.CIM.CIMUniqueValueRenderer uniqueValueRenderer:
|
||||
color = GetRowColorByUniqueValueRenderer(uniqueValueRenderer, row);
|
||||
break;
|
||||
|
||||
case AC.CIM.CIMClassBreaksRenderer classBreaksRenderer:
|
||||
color = GetRowColorByClassBreaksRenderer(classBreaksRenderer, row);
|
||||
break;
|
||||
}
|
||||
|
||||
if (color is null)
|
||||
{
|
||||
// TODO: log error or throw exception that color could not be retrieved
|
||||
return;
|
||||
}
|
||||
|
||||
// get or create the color proxy for the row
|
||||
int argb = CIMColorToInt(color);
|
||||
AddObjectIdToColorProxyCache(rowApplicationId, argb);
|
||||
|
||||
// store color if from simple renderer
|
||||
if (StoredRenderer is AC.CIM.CIMSimpleRenderer)
|
||||
{
|
||||
StoredColor = argb;
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieves the row color from a class breaks renderer
|
||||
// unique renderers have groups of conditions that may affect the color of a feature
|
||||
// resulting in a different color than the default renderer symbol color
|
||||
private AC.CIM.CIMColor? GetRowColorByClassBreaksRenderer(AC.CIM.CIMClassBreaksRenderer renderer, ACD.Row row)
|
||||
{
|
||||
AC.CIM.CIMColor? color = null;
|
||||
|
||||
// get the default symbol color
|
||||
if (renderer.DefaultSymbol?.Symbol.GetColor() is AC.CIM.CIMColor defaultColor)
|
||||
{
|
||||
color = defaultColor;
|
||||
}
|
||||
|
||||
// get the first stored field, since this renderer should only have 1 field
|
||||
double storedFieldValue = Convert.ToDouble(row[StoredRendererFields.First()]);
|
||||
|
||||
List<AC.CIM.CIMClassBreak> reversedBreaks = new(renderer.Breaks);
|
||||
reversedBreaks.Reverse();
|
||||
foreach (var rBreak in reversedBreaks)
|
||||
{
|
||||
// keep looping until the last matching condition
|
||||
if (storedFieldValue <= rBreak.UpperBound)
|
||||
{
|
||||
if (rBreak.Symbol.Symbol.GetColor() is AC.CIM.CIMColor breakColor)
|
||||
{
|
||||
color = breakColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: log error here, could not retrieve break color from symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// Retrieves the row color from a unique value renderer
|
||||
// unique renderers have groups of conditions that may affect the color of a feature
|
||||
// resulting in a different color than the default renderer symbol color
|
||||
private AC.CIM.CIMColor? GetRowColorByUniqueValueRenderer(AC.CIM.CIMUniqueValueRenderer renderer, ACD.Row row)
|
||||
{
|
||||
AC.CIM.CIMColor? color = null;
|
||||
|
||||
// get the default symbol color
|
||||
if (renderer.DefaultSymbol?.Symbol.GetColor() is AC.CIM.CIMColor defaultColor)
|
||||
{
|
||||
color = defaultColor;
|
||||
}
|
||||
|
||||
// note: usually there is only 1 group
|
||||
foreach (AC.CIM.CIMUniqueValueGroup group in renderer.Groups)
|
||||
{
|
||||
// loop through all values in groups to see if any have met conditions that result in a different color
|
||||
foreach (AC.CIM.CIMUniqueValueClass groupClass in group.Classes)
|
||||
{
|
||||
bool groupConditionsMet = true;
|
||||
foreach (AC.CIM.CIMUniqueValue value in groupClass.Values)
|
||||
{
|
||||
// all field values have to match the row values
|
||||
for (int i = 0; i < StoredRendererFields.Count; i++)
|
||||
{
|
||||
string groupValue = value.FieldValues[i];
|
||||
object? rowValue = row[StoredRendererFields[i]];
|
||||
|
||||
if (!ValuesAreEqual(groupValue, rowValue))
|
||||
{
|
||||
groupConditionsMet = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set the group color to class symbol color if conditions are met
|
||||
if (groupConditionsMet)
|
||||
{
|
||||
if (groupClass.Symbol.Symbol.GetColor() is AC.CIM.CIMColor groupColor)
|
||||
{
|
||||
color = groupColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: log error here, could not retrieve group color from symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares the label string of a UniqueValueRenderer (groupValue), and an object value (row, las point), to determine if they are equal
|
||||
/// </summary>
|
||||
/// <param name="objectValue"></param>
|
||||
/// <param name="groupValue"></param>
|
||||
private bool ValuesAreEqual(string groupValue, object? objectValue)
|
||||
{
|
||||
switch (objectValue)
|
||||
{
|
||||
case int:
|
||||
case short:
|
||||
case long:
|
||||
case byte:
|
||||
string objectValueString = Convert.ToString(objectValue) ?? "";
|
||||
return groupValue.Equals(objectValueString);
|
||||
|
||||
case string:
|
||||
return groupValue.Equals(objectValue);
|
||||
|
||||
// POC: these are tricky to compare with the label strings accurately, so will trim both values to 5 decimal places.
|
||||
case double d:
|
||||
return double.TryParse(groupValue, out double groupDouble) && groupDouble - d < 0.000001;
|
||||
case float f:
|
||||
return float.TryParse(groupValue, out float groupFloat) && groupFloat - f < 0.000001;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddObjectIdToColorProxyCache(string objectId, int argb)
|
||||
{
|
||||
if (ColorProxyCache.TryGetValue(argb, out ColorProxy? colorProxy))
|
||||
{
|
||||
colorProxy.objects.Add(objectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
ColorProxy newColorProxy =
|
||||
new()
|
||||
{
|
||||
name = argb.ToString(),
|
||||
objects = new() { objectId },
|
||||
value = argb,
|
||||
applicationId = argb.ToString()
|
||||
};
|
||||
|
||||
ColorProxyCache.Add(argb, newColorProxy);
|
||||
}
|
||||
}
|
||||
|
||||
private int ArgbToInt(int a, int r, int g, int b)
|
||||
{
|
||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
// Gets the argb int from a CIMColor
|
||||
// Defaults to assuming CIMColor.Values represent the red, green, and blue channels.
|
||||
private int CIMColorToInt(AC.CIM.CIMColor color)
|
||||
{
|
||||
switch (color)
|
||||
{
|
||||
case AC.CIM.CIMHSVColor hsv:
|
||||
(float hsvR, float hsvG, float hsvB) = RgbFromHsv(hsv.H, hsv.S, hsv.V);
|
||||
return ArgbToInt(
|
||||
(int)Math.Round(hsv.Alpha),
|
||||
(int)Math.Round(hsvR * 255),
|
||||
(int)Math.Round(hsvG * 255),
|
||||
(int)Math.Round(hsvB * 255)
|
||||
);
|
||||
|
||||
case AC.CIM.CIMCMYKColor cmyk:
|
||||
float k = cmyk.K;
|
||||
int cmykR = Convert.ToInt32(255 * (1 - cmyk.C) * (1 - k));
|
||||
int cmykG = Convert.ToInt32(255 * (1 - cmyk.M) * (1 - k));
|
||||
int cmykB = Convert.ToInt32(255 * (1 - cmyk.Y) * (1 - k));
|
||||
return ArgbToInt((int)Math.Round(cmyk.Alpha), cmykR, cmykG, cmykB);
|
||||
|
||||
default:
|
||||
return ArgbToInt(
|
||||
(int)Math.Round(color.Alpha),
|
||||
(int)Math.Round(color.Values[0]),
|
||||
(int)Math.Round(color.Values[1]),
|
||||
(int)Math.Round(color.Values[2])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private (float, float, float) RgbFromHsv(float hue, float saturation, float value)
|
||||
{
|
||||
// Translates HSV color to RGB color
|
||||
// H: 0.0 - 360.0, S: 0.0 - 100.0, V: 0.0 - 100.0
|
||||
// R, G, B: 0.0 - 1.0
|
||||
|
||||
float c = (value / 100) * (saturation / 100);
|
||||
float x = c * (1 - Math.Abs(((hue / 60) % 2) - 1));
|
||||
float m = (value / 100) - c;
|
||||
|
||||
float r = 0;
|
||||
float g = 0;
|
||||
float b = 0;
|
||||
|
||||
if (hue >= 0 && hue < 60)
|
||||
{
|
||||
r = c;
|
||||
g = x;
|
||||
b = 0;
|
||||
}
|
||||
else if (hue >= 60 && hue < 120)
|
||||
{
|
||||
r = x;
|
||||
g = c;
|
||||
b = 0;
|
||||
}
|
||||
else if (hue >= 120 && hue < 180)
|
||||
{
|
||||
r = 0;
|
||||
g = c;
|
||||
b = x;
|
||||
}
|
||||
else if (hue >= 180 && hue < 240)
|
||||
{
|
||||
r = 0;
|
||||
g = x;
|
||||
b = c;
|
||||
}
|
||||
else if (hue >= 240 && hue < 300)
|
||||
{
|
||||
r = x;
|
||||
g = 0;
|
||||
b = c;
|
||||
}
|
||||
else if (hue >= 300 && hue < 360)
|
||||
{
|
||||
r = c;
|
||||
g = 0;
|
||||
b = x;
|
||||
}
|
||||
|
||||
r += m;
|
||||
g += m;
|
||||
b += m;
|
||||
|
||||
return (r, g, b);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using Speckle.Connectors.ArcGIS.HostApp.Extensions;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.HostApp;
|
||||
|
||||
public class ArcGISLayerUnpacker
|
||||
{
|
||||
/// <summary>
|
||||
/// Cache of all collections created by unpacked Layer MapMembers. Key is the Speckle applicationId (Layer URI).
|
||||
/// </summary>
|
||||
public Dictionary<string, Collection> CollectionCache { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Mapmembers can be layers containing objects, or LayerContainers containing other layers.
|
||||
/// Unpacks selected mapMembers and creates their corresponding collection on the root collection.
|
||||
/// </summary>
|
||||
/// <param name="mapMembers"></param>
|
||||
/// <param name="parentCollection"></param>
|
||||
/// <returns>List of layers containing objects.</returns>
|
||||
/// <exception cref="AC.CalledOnWrongThreadException">Thrown when this method is *not* called on the MCT, because this method accesses mapmember fields</exception>
|
||||
public List<ADM.MapMember> UnpackSelection(
|
||||
IEnumerable<ADM.MapMember> mapMembers,
|
||||
Collection parentCollection,
|
||||
List<ADM.MapMember>? objects = null
|
||||
)
|
||||
{
|
||||
if (objects is null)
|
||||
{
|
||||
objects = new();
|
||||
}
|
||||
|
||||
foreach (ADM.MapMember mapMember in mapMembers)
|
||||
{
|
||||
switch (mapMember)
|
||||
{
|
||||
case ADM.ILayerContainer container:
|
||||
Collection containerCollection = CreateAndCacheMapMemberCollection(mapMember, true);
|
||||
parentCollection.elements.Add(containerCollection);
|
||||
|
||||
UnpackSelection(container.Layers, containerCollection, objects);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!(objects.Contains(mapMember)))
|
||||
{
|
||||
Collection collection = CreateAndCacheMapMemberCollection(mapMember);
|
||||
parentCollection.elements.Add(collection);
|
||||
objects.Add(mapMember);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return objects;
|
||||
}
|
||||
|
||||
private Collection CreateAndCacheMapMemberCollection(ADM.MapMember mapMember, bool isLayerContainer = false)
|
||||
{
|
||||
string mapMemberApplicationId = mapMember.GetSpeckleApplicationId();
|
||||
Collection collection =
|
||||
new()
|
||||
{
|
||||
name = mapMember.Name,
|
||||
applicationId = mapMemberApplicationId,
|
||||
["type"] = mapMember.GetType().Name
|
||||
};
|
||||
|
||||
switch (mapMember)
|
||||
{
|
||||
case ADM.IDisplayTable displayTable: // get fields from layers that implement IDisplayTable, eg FeatureLayer or StandaloneTable
|
||||
Dictionary<string, string>? fields = displayTable
|
||||
.GetFieldDescriptions()
|
||||
.ToDictionary(field => field.Name, field => field.Type.ToString());
|
||||
collection["fields"] = fields;
|
||||
if (mapMember is ADM.BasicFeatureLayer basicFeatureLayer)
|
||||
{
|
||||
collection["shapeType"] = basicFeatureLayer.ShapeType.ToString();
|
||||
}
|
||||
break;
|
||||
|
||||
case ADM.Layer layer:
|
||||
collection["mapLayerType"] = layer.MapLayerType.ToString();
|
||||
break;
|
||||
|
||||
case ADM.ILayerContainer:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isLayerContainer) // do not cache layer containers, since these won't contain any objects
|
||||
{
|
||||
CollectionCache.Add(mapMemberApplicationId, collection);
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System.IO;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Core.Kits;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.HostApp;
|
||||
|
||||
//poc: dupe code bewtween connectors
|
||||
public class ArcGISSettings
|
||||
{
|
||||
public ArcGISSettings(HostApplication hostAppInfo, HostAppVersion hostAppVersion)
|
||||
{
|
||||
HostAppInfo = hostAppInfo;
|
||||
HostAppVersion = hostAppVersion;
|
||||
Modules = new[] { new DirectoryInfo(typeof(ArcGISSettings).Assembly.Location).Parent.NotNull().FullName }; //poc: Net6 requires us to use this `location` property rather than ToString, should we use this everywhere?
|
||||
}
|
||||
|
||||
public HostApplication HostAppInfo { get; private set; }
|
||||
public HostAppVersion HostAppVersion { get; private set; }
|
||||
|
||||
public IReadOnlyList<string> Modules { get; private set; }
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
using ArcGIS.Core.Data.Raster;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.HostApp.Extensions;
|
||||
|
||||
public static class SpeckleApplicationIdExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves the Speckle application id for map members
|
||||
/// </summary>
|
||||
public static string GetSpeckleApplicationId(this ADM.MapMember mapMember) => mapMember.URI;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the Speckle application id for Features as a concatenation of the layer URI (applicationId)
|
||||
/// and the row OID (index of row in layer).
|
||||
/// </summary>
|
||||
/// <exception cref="ACD.Exceptions.GeodatabaseException">Throws when this is *not* called on MCT. Use QueuedTask.Run.</exception>
|
||||
public static string GetSpeckleApplicationId(this ACD.Row row, string layerApplicationId) =>
|
||||
$"{layerApplicationId}_{row.GetObjectID()}";
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the Speckle application id for Raster as a concatenation of the layer URI (applicationId) and 0-index
|
||||
/// </summary>
|
||||
public static string GetSpeckleApplicationId(this Raster _, string layerApplicationId) => $"{layerApplicationId}_0";
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the Speckle application id for LasDatasets as a concatenation of the layer URI (applicationId)
|
||||
/// and point OID.
|
||||
/// </summary>
|
||||
public static string GetSpeckleApplicationId(this ACD.Analyst3D.LasPoint point, string layerApplicationId) =>
|
||||
$"{layerApplicationId}_{point.PointID}";
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.HostApp;
|
||||
|
||||
public class SyncToQueuedTask : ISyncToThread
|
||||
{
|
||||
public Task<T> RunOnThread<T>(Func<T> func) => QueuedTask.Run(func);
|
||||
}
|
||||
+411
@@ -0,0 +1,411 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
using ArcGIS.Core.CIM;
|
||||
using ArcGIS.Core.Geometry;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Connectors.ArcGIS.HostApp;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Converters.ArcGIS3;
|
||||
using Speckle.Converters.ArcGIS3.Utils;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Objects.Data;
|
||||
using Speckle.Objects.Other;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Operations.Receive;
|
||||
|
||||
public class ArcGISHostObjectBuilder : IHostObjectBuilder
|
||||
{
|
||||
private readonly IRootToHostConverter _converter;
|
||||
private readonly IFeatureClassUtils _featureClassUtils;
|
||||
private readonly ILocalToGlobalUnpacker _localToGlobalUnpacker;
|
||||
private readonly LocalToGlobalConverterUtils _localToGlobalConverterUtils;
|
||||
|
||||
// POC: figure out the correct scope to only initialize on Receive
|
||||
private readonly IConverterSettingsStore<ArcGISConversionSettings> _settingsStore;
|
||||
private readonly GraphTraversal _traverseFunction;
|
||||
private readonly ArcGISColorManager _colorManager;
|
||||
|
||||
public ArcGISHostObjectBuilder(
|
||||
IRootToHostConverter converter,
|
||||
IConverterSettingsStore<ArcGISConversionSettings> settingsStore,
|
||||
IFeatureClassUtils featureClassUtils,
|
||||
ILocalToGlobalUnpacker localToGlobalUnpacker,
|
||||
LocalToGlobalConverterUtils localToGlobalConverterUtils,
|
||||
GraphTraversal traverseFunction,
|
||||
ArcGISColorManager colorManager
|
||||
)
|
||||
{
|
||||
_converter = converter;
|
||||
_settingsStore = settingsStore;
|
||||
_featureClassUtils = featureClassUtils;
|
||||
_localToGlobalUnpacker = localToGlobalUnpacker;
|
||||
_localToGlobalConverterUtils = localToGlobalConverterUtils;
|
||||
_traverseFunction = traverseFunction;
|
||||
_colorManager = colorManager;
|
||||
}
|
||||
|
||||
public Task<HostObjectBuilderResult> Build(
|
||||
Base rootObject,
|
||||
string projectName,
|
||||
string modelName,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
return QueuedTask.Run(
|
||||
() => BuildInternal(rootObject, projectName, modelName, onOperationProgressed, cancellationToken)
|
||||
);
|
||||
}
|
||||
|
||||
private HostObjectBuilderResult BuildInternal(
|
||||
Base rootObject,
|
||||
string projectName,
|
||||
string modelName,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
// TODO get spatialRef and offsets & rotation from ProjectInfo in CommitObject
|
||||
// ATM, GIS commit CRS is stored per layer (in FeatureClass converter), but should be moved to the Root level too
|
||||
|
||||
// Prompt the UI conversion started. Progress bar will swoosh.
|
||||
onOperationProgressed.Report(new("Converting", null));
|
||||
|
||||
// get materials
|
||||
List<RenderMaterialProxy>? materials = (rootObject[ProxyKeys.RENDER_MATERIAL] as List<object>)
|
||||
?.Cast<RenderMaterialProxy>()
|
||||
.ToList();
|
||||
if (materials != null)
|
||||
{
|
||||
_colorManager.ParseMaterials(materials, onOperationProgressed);
|
||||
}
|
||||
|
||||
// get colors
|
||||
List<ColorProxy>? colors = (rootObject[ProxyKeys.COLOR] as List<object>)?.Cast<ColorProxy>().ToList();
|
||||
if (colors != null)
|
||||
{
|
||||
_colorManager.ParseColors(colors, onOperationProgressed);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
IReadOnlyCollection<LocalToGlobalMap> objectsToConvert = GetObjectsToConvert(rootObject);
|
||||
Dictionary<TraversalContext, ObjectConversionTracker> conversionTracker = new();
|
||||
|
||||
// 1. convert everything
|
||||
List<ReceiveConversionResult> results = new(objectsToConvert.Count);
|
||||
List<string> bakedObjectIds = new();
|
||||
foreach (LocalToGlobalMap objectToConvert in objectsToConvert)
|
||||
{
|
||||
string[] path = GetLayerPath(objectToConvert.TraversalContext);
|
||||
Base obj = objectToConvert.AtomicObject;
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
obj = _localToGlobalConverterUtils.TransformObjects(objectToConvert.AtomicObject, objectToConvert.Matrix);
|
||||
object conversionResult = _converter.Convert(obj);
|
||||
|
||||
string nestedLayerPath = $"{string.Join("\\", path)}";
|
||||
|
||||
if (obj is ArcgisObject gisObj)
|
||||
{
|
||||
nestedLayerPath += $"\\{gisObj.name}";
|
||||
}
|
||||
else
|
||||
{
|
||||
nestedLayerPath += $"\\{obj.speckle_type.Split(".")[^1]}"; // add sub-layer by speckleType, for non-GIS objects
|
||||
}
|
||||
|
||||
conversionTracker[objectToConvert.TraversalContext] = new ObjectConversionTracker(
|
||||
obj,
|
||||
(Geometry?)conversionResult,
|
||||
nestedLayerPath
|
||||
);
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // DO NOT CATCH SPECIFIC STUFF, conversion errors should be recoverable
|
||||
{
|
||||
results.Add(new(Status.ERROR, obj, null, null, ex));
|
||||
}
|
||||
onOperationProgressed.Report(new("Converting", (double)++count / objectsToConvert.Count));
|
||||
}
|
||||
|
||||
// 2.1. Group conversionTrackers (to write into datasets)
|
||||
onOperationProgressed.Report(new("Grouping features into layers", null));
|
||||
Dictionary<string, List<(TraversalContext, ObjectConversionTracker)>> convertedGroups =
|
||||
_featureClassUtils.GroupConversionTrackers(
|
||||
conversionTracker,
|
||||
(s, progres) => onOperationProgressed.Report(new(s, progres))
|
||||
);
|
||||
|
||||
// 2.2. Write groups of objects to Datasets
|
||||
onOperationProgressed.Report(new("Writing to Database", null));
|
||||
|
||||
_featureClassUtils.CreateDatasets(
|
||||
conversionTracker,
|
||||
convertedGroups,
|
||||
(s, progres) => onOperationProgressed.Report(new(s, progres))
|
||||
);
|
||||
|
||||
// 3. add layer and tables to the Map and Table Of Content
|
||||
|
||||
// Create placeholder for GroupLayers
|
||||
Dictionary<string, GroupLayer> createdLayerGroups = new();
|
||||
|
||||
int bakeCount = 0;
|
||||
Dictionary<string, (MapMember, CIMUniqueValueRenderer?)> bakedMapMembers = new();
|
||||
onOperationProgressed.Report(new("Adding to Map", bakeCount));
|
||||
|
||||
foreach (var item in conversionTracker)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var trackerItem = conversionTracker[item.Key]; // updated tracker object
|
||||
|
||||
// BAKE OBJECTS HERE
|
||||
if (trackerItem.Exception != null)
|
||||
{
|
||||
results.Add(new(Status.ERROR, trackerItem.Base, null, null, trackerItem.Exception));
|
||||
}
|
||||
else if (trackerItem.DatasetId == null)
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.ERROR,
|
||||
trackerItem.Base,
|
||||
null,
|
||||
null,
|
||||
new ArgumentException($"Unknown error: Dataset not created for {trackerItem.Base.speckle_type}")
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (bakedMapMembers.TryGetValue(trackerItem.DatasetId, out var value))
|
||||
{
|
||||
// if the layer already created, just add more features to report, and more color categories
|
||||
// add layer and layer URI to tracker
|
||||
trackerItem.AddConvertedMapMember(value.Item1);
|
||||
trackerItem.AddLayerURI(value.Item1.URI);
|
||||
conversionTracker[item.Key] = trackerItem; // not necessary atm, but needed if we use conversionTracker further
|
||||
|
||||
// add color category
|
||||
CIMUniqueValueRenderer? uvr = _colorManager.CreateOrEditLayerRenderer(item.Key, trackerItem, value.Item2);
|
||||
// replace renderer
|
||||
bakedMapMembers[trackerItem.DatasetId] = (value.Item1, uvr);
|
||||
|
||||
// only add a report item
|
||||
AddResultsFromTracker(trackerItem, results);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no layer yet, create and add layer to Map
|
||||
MapMember mapMember = AddDatasetsToMap(trackerItem, createdLayerGroups, projectName, modelName);
|
||||
|
||||
// add layer and layer URI to tracker
|
||||
trackerItem.AddConvertedMapMember(mapMember);
|
||||
trackerItem.AddLayerURI(mapMember.URI);
|
||||
conversionTracker[item.Key] = trackerItem; // not necessary atm, but needed if we use conversionTracker further
|
||||
|
||||
// add layer URI to bakedIds
|
||||
bakedObjectIds.Add(trackerItem.MappedLayerURI == null ? "" : trackerItem.MappedLayerURI);
|
||||
|
||||
// add color category
|
||||
CIMUniqueValueRenderer? uvr = _colorManager.CreateOrEditLayerRenderer(item.Key, trackerItem, null);
|
||||
// mark dataset as already created
|
||||
bakedMapMembers[trackerItem.DatasetId] = (mapMember, uvr);
|
||||
|
||||
// add report item
|
||||
AddResultsFromTracker(trackerItem, results);
|
||||
}
|
||||
|
||||
onOperationProgressed.Report(new("Adding to Map", (double)++bakeCount / conversionTracker.Count));
|
||||
}
|
||||
|
||||
// apply renderers to baked layers
|
||||
foreach (var bakedMember in bakedMapMembers)
|
||||
{
|
||||
if (bakedMember.Value.Item1 is FeatureLayer fLayer)
|
||||
{
|
||||
// Set the feature layer's renderer.
|
||||
fLayer.SetRenderer(bakedMember.Value.Item2);
|
||||
}
|
||||
}
|
||||
bakedObjectIds.AddRange(createdLayerGroups.Values.Select(x => x.URI));
|
||||
|
||||
// TODO: validated a correct set regarding bakedobject ids
|
||||
return new HostObjectBuilderResult(bakedObjectIds, results);
|
||||
}
|
||||
|
||||
private IReadOnlyCollection<LocalToGlobalMap> GetObjectsToConvert(Base rootObject)
|
||||
{
|
||||
// keep GISlayers in the list, because they are still needed to extract CRS of the commit (code below)
|
||||
List<TraversalContext> objectsToConvertTc = _traverseFunction.Traverse(rootObject).ToList();
|
||||
|
||||
// now filter the objects
|
||||
objectsToConvertTc = objectsToConvertTc.Where(ctx => ctx.Current is not Collection).ToList();
|
||||
|
||||
var instanceDefinitionProxies = (rootObject[ProxyKeys.INSTANCE_DEFINITION] as List<object>)
|
||||
?.Cast<InstanceDefinitionProxy>()
|
||||
.ToList();
|
||||
|
||||
return _localToGlobalUnpacker.Unpack(instanceDefinitionProxies, objectsToConvertTc);
|
||||
}
|
||||
|
||||
private void AddResultsFromTracker(ObjectConversionTracker trackerItem, List<ReceiveConversionResult> results)
|
||||
{
|
||||
if (trackerItem.MappedLayerURI == null) // should not happen
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.ERROR,
|
||||
trackerItem.Base,
|
||||
null,
|
||||
null,
|
||||
new ArgumentException($"Created Layer URI not found for {trackerItem.Base.speckle_type}")
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// encode layer ID and ID of its feature in 1 object represented as string
|
||||
ObjectID objectId = new(trackerItem.MappedLayerURI, trackerItem.DatasetRow);
|
||||
if (trackerItem.HostAppGeom != null) // individual hostAppGeometry
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.SUCCESS,
|
||||
trackerItem.Base,
|
||||
objectId.ObjectIdToString(),
|
||||
trackerItem.HostAppGeom.GetType().ToString()
|
||||
)
|
||||
);
|
||||
}
|
||||
else // hostApp Layers
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.SUCCESS,
|
||||
trackerItem.Base,
|
||||
objectId.ObjectIdToString(),
|
||||
trackerItem.HostAppMapMember?.GetType().ToString()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private MapMember AddDatasetsToMap(
|
||||
ObjectConversionTracker trackerItem,
|
||||
Dictionary<string, GroupLayer> createdLayerGroups,
|
||||
string projectName,
|
||||
string modelName
|
||||
)
|
||||
{
|
||||
// get layer details
|
||||
string? datasetId = trackerItem.DatasetId; // should not be null here
|
||||
Uri uri = new($"{_settingsStore.Current.SpeckleDatabasePath.AbsolutePath.Replace('/', '\\')}\\{datasetId}");
|
||||
string nestedLayerName = trackerItem.NestedLayerName;
|
||||
|
||||
// add group for the current layer
|
||||
string shortName = nestedLayerName.Split("\\")[^1];
|
||||
string nestedLayerPath = string.Join("\\", nestedLayerName.Split("\\").SkipLast(1));
|
||||
|
||||
// if no general group layer found
|
||||
if (createdLayerGroups.Count == 0)
|
||||
{
|
||||
Map map = _settingsStore.Current.Map;
|
||||
GroupLayer mainGroupLayer = LayerFactory.Instance.CreateGroupLayer(map, 0, $"{projectName}: {modelName}");
|
||||
mainGroupLayer.SetExpanded(true);
|
||||
createdLayerGroups["Basic Speckle Group"] = mainGroupLayer; // key doesn't really matter here
|
||||
}
|
||||
|
||||
var groupLayer = CreateNestedGroupLayer(nestedLayerPath, createdLayerGroups);
|
||||
|
||||
// Most of the Speckle-written datasets will be containing geometry and added as Layers
|
||||
// although, some datasets might be just tables (e.g. native GIS Tables, in the future maybe Revit schedules etc.
|
||||
// We can create a connection to the dataset in advance and determine its type, but this will be more
|
||||
// expensive, than assuming by default that it's a layer with geometry (which in most cases it's expected to be)
|
||||
try
|
||||
{
|
||||
var layer = LayerFactory.Instance.CreateLayer(uri, groupLayer, layerName: shortName);
|
||||
if (layer == null)
|
||||
{
|
||||
throw new SpeckleException($"Layer '{shortName}' was not created");
|
||||
}
|
||||
layer.SetExpanded(false);
|
||||
|
||||
// if Scene
|
||||
// https://community.esri.com/t5/arcgis-pro-sdk-questions/sdk-equivalent-to-changing-layer-s-elevation/td-p/1346139
|
||||
if (_settingsStore.Current.Map.IsScene)
|
||||
{
|
||||
var groundSurfaceLayer = _settingsStore.Current.Map.GetGroundElevationSurfaceLayer();
|
||||
var layerElevationSurface = new CIMLayerElevationSurface { ElevationSurfaceLayerURI = groundSurfaceLayer.URI, };
|
||||
|
||||
// for Feature Layers
|
||||
if (layer.GetDefinition() is CIMFeatureLayer cimLyr)
|
||||
{
|
||||
cimLyr.LayerElevation = layerElevationSurface;
|
||||
layer.SetDefinition(cimLyr);
|
||||
}
|
||||
}
|
||||
|
||||
return layer;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
StandaloneTable table = StandaloneTableFactory.Instance.CreateStandaloneTable(
|
||||
uri,
|
||||
groupLayer,
|
||||
tableName: shortName
|
||||
);
|
||||
return table;
|
||||
}
|
||||
}
|
||||
|
||||
private GroupLayer CreateNestedGroupLayer(string nestedLayerPath, Dictionary<string, GroupLayer> createdLayerGroups)
|
||||
{
|
||||
GroupLayer lastGroup = createdLayerGroups.FirstOrDefault().Value;
|
||||
if (lastGroup == null) // if layer not found
|
||||
{
|
||||
throw new InvalidOperationException("Speckle Layer Group not found");
|
||||
}
|
||||
|
||||
// iterate through each nested level
|
||||
string createdGroupPath = "";
|
||||
var allPathElements = nestedLayerPath.Split("\\").Where(x => !string.IsNullOrEmpty(x));
|
||||
foreach (string pathElement in allPathElements)
|
||||
{
|
||||
createdGroupPath += "\\" + pathElement;
|
||||
if (createdLayerGroups.TryGetValue(createdGroupPath, out var existingGroupLayer))
|
||||
{
|
||||
lastGroup = existingGroupLayer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// create new GroupLayer under last found Group, named with last pathElement
|
||||
lastGroup = LayerFactory.Instance.CreateGroupLayer(lastGroup, 0, pathElement);
|
||||
lastGroup.SetExpanded(true);
|
||||
}
|
||||
createdLayerGroups[createdGroupPath] = lastGroup;
|
||||
}
|
||||
return lastGroup;
|
||||
}
|
||||
|
||||
[Pure]
|
||||
private static string[] GetLayerPath(TraversalContext context)
|
||||
{
|
||||
string[] collectionBasedPath = context.GetAscendantOfType<Collection>().Select(c => c.name).ToArray();
|
||||
string[] reverseOrderPath =
|
||||
collectionBasedPath.Length != 0 ? collectionBasedPath : context.GetPropertyPath().ToArray();
|
||||
|
||||
var originalPath = reverseOrderPath.Reverse().ToArray();
|
||||
return originalPath.Where(x => !string.IsNullOrEmpty(x)).ToArray();
|
||||
}
|
||||
}
|
||||
@@ -1,293 +0,0 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Connectors.Utils.Builders;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Core.Logging;
|
||||
using Speckle.Core.Models;
|
||||
using Speckle.Converters.ArcGIS3.Utils;
|
||||
using ArcGIS.Core.Geometry;
|
||||
using Objects.GIS;
|
||||
using Speckle.Connectors.Utils.Conversion;
|
||||
using Speckle.Core.Models.GraphTraversal;
|
||||
using Speckle.Converters.ArcGIS3;
|
||||
using RasterLayer = Objects.GIS.RasterLayer;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Operations.Receive;
|
||||
|
||||
public class ArcGISHostObjectBuilder : IHostObjectBuilder
|
||||
{
|
||||
private readonly IRootToHostConverter _converter;
|
||||
private readonly INonNativeFeaturesUtils _nonGisFeaturesUtils;
|
||||
|
||||
// POC: figure out the correct scope to only initialize on Receive
|
||||
private readonly IConversionContextStack<ArcGISDocument, Unit> _contextStack;
|
||||
private readonly GraphTraversal _traverseFunction;
|
||||
|
||||
public ArcGISHostObjectBuilder(
|
||||
IRootToHostConverter converter,
|
||||
IConversionContextStack<ArcGISDocument, Unit> contextStack,
|
||||
INonNativeFeaturesUtils nonGisFeaturesUtils,
|
||||
GraphTraversal traverseFunction
|
||||
)
|
||||
{
|
||||
_converter = converter;
|
||||
_contextStack = contextStack;
|
||||
_nonGisFeaturesUtils = nonGisFeaturesUtils;
|
||||
_traverseFunction = traverseFunction;
|
||||
}
|
||||
|
||||
public HostObjectBuilderResult Build(
|
||||
Base rootObject,
|
||||
string projectName,
|
||||
string modelName,
|
||||
Action<string, double?>? onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
// Prompt the UI conversion started. Progress bar will swoosh.
|
||||
onOperationProgressed?.Invoke("Converting", null);
|
||||
|
||||
var objectsToConvert = _traverseFunction
|
||||
.Traverse(rootObject)
|
||||
.Where(ctx => ctx.Current is not Collection || IsGISType(ctx.Current))
|
||||
.Where(ctx => HasGISParent(ctx) is false)
|
||||
.ToList();
|
||||
|
||||
int allCount = objectsToConvert.Count;
|
||||
int count = 0;
|
||||
Dictionary<TraversalContext, ObjectConversionTracker> conversionTracker = new();
|
||||
|
||||
// 1. convert everything
|
||||
List<ReceiveConversionResult> results = new(objectsToConvert.Count);
|
||||
List<string> bakedObjectIds = new();
|
||||
foreach (TraversalContext ctx in objectsToConvert)
|
||||
{
|
||||
string[] path = GetLayerPath(ctx);
|
||||
Base obj = ctx.Current;
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
if (IsGISType(obj))
|
||||
{
|
||||
string nestedLayerPath = $"{string.Join("\\", path)}";
|
||||
string datasetId = (string)_converter.Convert(obj);
|
||||
conversionTracker[ctx] = new ObjectConversionTracker(obj, nestedLayerPath, datasetId);
|
||||
}
|
||||
else
|
||||
{
|
||||
string nestedLayerPath = $"{string.Join("\\", path)}\\{obj.speckle_type.Split(".")[^1]}";
|
||||
Geometry converted = (Geometry)_converter.Convert(obj);
|
||||
conversionTracker[ctx] = new ObjectConversionTracker(obj, nestedLayerPath, converted);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // DO NOT CATCH SPECIFIC STUFF, conversion errors should be recoverable
|
||||
{
|
||||
results.Add(new(Status.ERROR, obj, null, null, ex));
|
||||
}
|
||||
onOperationProgressed?.Invoke("Converting", (double)++count / allCount);
|
||||
}
|
||||
|
||||
// 2. convert Database entries with non-GIS geometry datasets
|
||||
onOperationProgressed?.Invoke("Writing to Database", null);
|
||||
_nonGisFeaturesUtils.WriteGeometriesToDatasets(conversionTracker);
|
||||
|
||||
// Create main group layer
|
||||
Dictionary<string, GroupLayer> createdLayerGroups = new();
|
||||
Map map = _contextStack.Current.Document.Map;
|
||||
GroupLayer groupLayer = LayerFactory.Instance.CreateGroupLayer(map, 0, $"{projectName}: {modelName}");
|
||||
createdLayerGroups["Basic Speckle Group"] = groupLayer; // key doesn't really matter here
|
||||
|
||||
// 3. add layer and tables to the Table Of Content
|
||||
int bakeCount = 0;
|
||||
Dictionary<string, MapMember> bakedMapMembers = new();
|
||||
onOperationProgressed?.Invoke("Adding to Map", bakeCount);
|
||||
|
||||
foreach (var item in conversionTracker)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var trackerItem = conversionTracker[item.Key]; // updated tracker object
|
||||
|
||||
// BAKE OBJECTS HERE
|
||||
if (trackerItem.Exception != null)
|
||||
{
|
||||
results.Add(new(Status.ERROR, trackerItem.Base, null, null, trackerItem.Exception));
|
||||
}
|
||||
else if (trackerItem.DatasetId == null)
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.ERROR,
|
||||
trackerItem.Base,
|
||||
null,
|
||||
null,
|
||||
new ArgumentException($"Unknown error: Dataset not created for {trackerItem.Base.speckle_type}")
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (bakedMapMembers.TryGetValue(trackerItem.DatasetId, out MapMember? value))
|
||||
{
|
||||
// add layer and layer URI to tracker
|
||||
trackerItem.AddConvertedMapMember(value);
|
||||
trackerItem.AddLayerURI(value.URI);
|
||||
conversionTracker[item.Key] = trackerItem; // not necessary atm, but needed if we use conversionTracker further
|
||||
// only add a report item
|
||||
AddResultsFromTracker(trackerItem, results);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add layer to Map
|
||||
MapMember mapMember = AddDatasetsToMap(trackerItem, createdLayerGroups);
|
||||
|
||||
// add layer and layer URI to tracker
|
||||
trackerItem.AddConvertedMapMember(mapMember);
|
||||
trackerItem.AddLayerURI(mapMember.URI);
|
||||
conversionTracker[item.Key] = trackerItem; // not necessary atm, but needed if we use conversionTracker further
|
||||
|
||||
// add layer URI to bakedIds
|
||||
bakedObjectIds.Add(trackerItem.MappedLayerURI == null ? "" : trackerItem.MappedLayerURI);
|
||||
|
||||
// mark dataset as already created
|
||||
bakedMapMembers[trackerItem.DatasetId] = mapMember;
|
||||
|
||||
// add report item
|
||||
AddResultsFromTracker(trackerItem, results);
|
||||
}
|
||||
onOperationProgressed?.Invoke("Adding to Map", (double)++bakeCount / conversionTracker.Count);
|
||||
}
|
||||
bakedObjectIds.AddRange(createdLayerGroups.Values.Select(x => x.URI));
|
||||
|
||||
// TODO: validated a correct set regarding bakedobject ids
|
||||
return new(bakedObjectIds, results);
|
||||
}
|
||||
|
||||
private void AddResultsFromTracker(ObjectConversionTracker trackerItem, List<ReceiveConversionResult> results)
|
||||
{
|
||||
if (trackerItem.MappedLayerURI == null) // should not happen
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.ERROR,
|
||||
trackerItem.Base,
|
||||
null,
|
||||
null,
|
||||
new ArgumentException($"Created Layer URI not found for {trackerItem.Base.speckle_type}")
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// encode layer ID and ID of its feature in 1 object represented as string
|
||||
ObjectID objectId = new(trackerItem.MappedLayerURI, trackerItem.DatasetRow);
|
||||
if (trackerItem.HostAppGeom != null) // individual hostAppGeometry
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.SUCCESS,
|
||||
trackerItem.Base,
|
||||
objectId.ObjectIdToString(),
|
||||
trackerItem.HostAppGeom.GetType().ToString()
|
||||
)
|
||||
);
|
||||
}
|
||||
else // hostApp Layers
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.SUCCESS,
|
||||
trackerItem.Base,
|
||||
objectId.ObjectIdToString(),
|
||||
trackerItem.HostAppMapMember?.GetType().ToString()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private MapMember AddDatasetsToMap(
|
||||
ObjectConversionTracker trackerItem,
|
||||
Dictionary<string, GroupLayer> createdLayerGroups
|
||||
)
|
||||
{
|
||||
// get layer details
|
||||
string? datasetId = trackerItem.DatasetId; // should not ne null here
|
||||
Uri uri = new($"{_contextStack.Current.Document.SpeckleDatabasePath.AbsolutePath.Replace('/', '\\')}\\{datasetId}");
|
||||
string nestedLayerName = trackerItem.NestedLayerName;
|
||||
|
||||
// add group for the current layer
|
||||
string shortName = nestedLayerName.Split("\\")[^1];
|
||||
string nestedLayerPath = string.Join("\\", nestedLayerName.Split("\\").SkipLast(1));
|
||||
|
||||
GroupLayer groupLayer = CreateNestedGroupLayer(nestedLayerPath, createdLayerGroups);
|
||||
|
||||
// Most of the Speckle-written datasets will be containing geometry and added as Layers
|
||||
// although, some datasets might be just tables (e.g. native GIS Tables, in the future maybe Revit schedules etc.
|
||||
// We can create a connection to the dataset in advance and determine its type, but this will be more
|
||||
// expensive, than assuming by default that it's a layer with geometry (which in most cases it's expected to be)
|
||||
try
|
||||
{
|
||||
var layer = LayerFactory.Instance.CreateLayer(uri, groupLayer, layerName: shortName);
|
||||
layer.SetExpanded(true);
|
||||
return layer;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
var table = StandaloneTableFactory.Instance.CreateStandaloneTable(uri, groupLayer, tableName: shortName);
|
||||
return table;
|
||||
}
|
||||
}
|
||||
|
||||
private GroupLayer CreateNestedGroupLayer(string nestedLayerPath, Dictionary<string, GroupLayer> createdLayerGroups)
|
||||
{
|
||||
GroupLayer lastGroup = createdLayerGroups.FirstOrDefault().Value;
|
||||
if (lastGroup == null) // if layer not found
|
||||
{
|
||||
throw new InvalidOperationException("Speckle Layer Group not found");
|
||||
}
|
||||
|
||||
// iterate through each nested level
|
||||
string createdGroupPath = "";
|
||||
var allPathElements = nestedLayerPath.Split("\\").Where(x => !string.IsNullOrEmpty(x));
|
||||
foreach (string pathElement in allPathElements)
|
||||
{
|
||||
createdGroupPath += "\\" + pathElement;
|
||||
if (createdLayerGroups.TryGetValue(createdGroupPath, out var existingGroupLayer))
|
||||
{
|
||||
lastGroup = existingGroupLayer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// create new GroupLayer under last found Group, named with last pathElement
|
||||
lastGroup = LayerFactory.Instance.CreateGroupLayer(lastGroup, 0, pathElement);
|
||||
lastGroup.SetExpanded(true);
|
||||
}
|
||||
createdLayerGroups[createdGroupPath] = lastGroup;
|
||||
}
|
||||
return lastGroup;
|
||||
}
|
||||
|
||||
[Pure]
|
||||
private static string[] GetLayerPath(TraversalContext context)
|
||||
{
|
||||
string[] collectionBasedPath = context.GetAscendantOfType<Collection>().Select(c => c.name).ToArray();
|
||||
string[] reverseOrderPath =
|
||||
collectionBasedPath.Length != 0 ? collectionBasedPath : context.GetPropertyPath().ToArray();
|
||||
|
||||
var originalPath = reverseOrderPath.Reverse().ToArray();
|
||||
return originalPath.Where(x => !string.IsNullOrEmpty(x)).ToArray();
|
||||
}
|
||||
|
||||
[Pure]
|
||||
private static bool HasGISParent(TraversalContext context)
|
||||
{
|
||||
List<Base> gisLayers = context.GetAscendants().Where(IsGISType).Where(obj => obj != context.Current).ToList();
|
||||
return gisLayers.Count > 0;
|
||||
}
|
||||
|
||||
[Pure]
|
||||
private static bool IsGISType(Base obj)
|
||||
{
|
||||
return obj is RasterLayer or VectorLayer;
|
||||
}
|
||||
}
|
||||
+340
-65
@@ -1,87 +1,362 @@
|
||||
using System.Diagnostics;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.Utils.Builders;
|
||||
using Speckle.Connectors.Utils.Caching;
|
||||
using Speckle.Connectors.Utils.Conversion;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using ArcGIS.Core.Data.Raster;
|
||||
using ArcGIS.Core.Geometry;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.ArcGIS.HostApp;
|
||||
using Speckle.Connectors.ArcGIS.HostApp.Extensions;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Connectors.Common.Extensions;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Converters.ArcGIS3;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Core.Logging;
|
||||
using Speckle.Core.Models;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Logging;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
|
||||
namespace Speckle.Connectors.ArcGis.Operations.Send;
|
||||
|
||||
/// <summary>
|
||||
/// Stateless builder object to turn an ISendFilter into a <see cref="Base"/> object
|
||||
/// </summary>
|
||||
public class ArcGISRootObjectBuilder : IRootObjectBuilder<MapMember>
|
||||
public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
|
||||
{
|
||||
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly IRootToSpeckleConverter _rootToSpeckleConverter;
|
||||
private readonly ArcGISLayerUnpacker _layerUnpacker;
|
||||
private readonly ArcGISColorUnpacker _colorUnpacker;
|
||||
private readonly IConverterSettingsStore<ArcGISConversionSettings> _converterSettings;
|
||||
private readonly ILogger<ArcGISRootObjectBuilder> _logger;
|
||||
private readonly ISdkActivityFactory _activityFactory;
|
||||
private readonly MapMembersUtils _mapMemberUtils;
|
||||
|
||||
public ArcGISRootObjectBuilder(IUnitOfWorkFactory unitOfWorkFactory, ISendConversionCache sendConversionCache)
|
||||
{
|
||||
_unitOfWorkFactory = unitOfWorkFactory;
|
||||
_sendConversionCache = sendConversionCache;
|
||||
}
|
||||
|
||||
public RootObjectBuilderResult Build(
|
||||
IReadOnlyList<MapMember> objects,
|
||||
SendInfo sendInfo,
|
||||
Action<string, double?>? onOperationProgressed = null,
|
||||
CancellationToken ct = default
|
||||
public ArcGISRootObjectBuilder(
|
||||
ArcGISLayerUnpacker layerUnpacker,
|
||||
ArcGISColorUnpacker colorUnpacker,
|
||||
IConverterSettingsStore<ArcGISConversionSettings> converterSettings,
|
||||
IRootToSpeckleConverter rootToSpeckleConverter,
|
||||
ILogger<ArcGISRootObjectBuilder> logger,
|
||||
ISdkActivityFactory activityFactory,
|
||||
MapMembersUtils mapMemberUtils
|
||||
)
|
||||
{
|
||||
// POC: does this feel like the right place? I am wondering if this should be called from within send/rcv?
|
||||
// begin the unit of work
|
||||
using var uow = _unitOfWorkFactory.Resolve<IRootToSpeckleConverter>();
|
||||
var converter = uow.Service;
|
||||
_layerUnpacker = layerUnpacker;
|
||||
_colorUnpacker = colorUnpacker;
|
||||
_converterSettings = converterSettings;
|
||||
_rootToSpeckleConverter = rootToSpeckleConverter;
|
||||
_logger = logger;
|
||||
_activityFactory = activityFactory;
|
||||
_mapMemberUtils = mapMemberUtils;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
public Task<RootObjectBuilderResult> Build(
|
||||
IReadOnlyList<ADM.MapMember> layers,
|
||||
SendInfo __,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
) => QueuedTask.Run(() => BuildInternal(layers, __, onOperationProgressed, cancellationToken));
|
||||
|
||||
Collection rootObjectCollection = new(); //TODO: Collections
|
||||
private async Task<RootObjectBuilderResult> BuildInternal(
|
||||
IReadOnlyList<ADM.MapMember> layers,
|
||||
SendInfo __,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
// TODO: add a warning if Geographic CRS is set
|
||||
// "Data has been sent in the units 'degrees'. It is advisable to set the project CRS to Projected type (e.g. EPSG:32631) to be able to receive geometry correctly in CAD/BIM software"
|
||||
|
||||
List<SendConversionResult> results = new(objects.Count);
|
||||
var cacheHitCount = 0;
|
||||
|
||||
foreach (MapMember mapMember in objects)
|
||||
// 0 - Create Root collection and attach CRS properties
|
||||
// CRS properties are useful for data based workflows coming out of gis applications
|
||||
SpatialReference sr = _converterSettings.Current.ActiveCRSoffsetRotation.SpatialReference;
|
||||
Dictionary<string, object?> spatialReference =
|
||||
new()
|
||||
{
|
||||
["name"] = sr.Name,
|
||||
["unit"] = sr.Unit.Name,
|
||||
["wkid"] = sr.Wkid,
|
||||
["wkt"] = sr.Wkt,
|
||||
};
|
||||
|
||||
Dictionary<string, object?> crs =
|
||||
new()
|
||||
{
|
||||
["trueNorthRadians"] = _converterSettings.Current.ActiveCRSoffsetRotation.TrueNorthRadians,
|
||||
["latOffset"] = _converterSettings.Current.ActiveCRSoffsetRotation.LatOffset,
|
||||
["lonOffset"] = _converterSettings.Current.ActiveCRSoffsetRotation.LonOffset,
|
||||
["spatialReference"] = spatialReference
|
||||
};
|
||||
|
||||
Collection rootCollection =
|
||||
new()
|
||||
{
|
||||
name = ADM.MapView.Active.Map.Name,
|
||||
["units"] = _converterSettings.Current.SpeckleUnits,
|
||||
["crs"] = crs
|
||||
};
|
||||
|
||||
// 1 - Unpack the selected mapmembers
|
||||
// In Arcgis, mapmembers are collections of other mapmember or objects.
|
||||
// We need to unpack the selected mapmembers into all leaf-level mapmembers (containing just objects) and build the root collection structure during unpacking.
|
||||
// Mapmember dynamically attached properties are also added at this step.
|
||||
List<ADM.MapMember> unpackedLayers;
|
||||
Dictionary<ADM.MapMember, long> layersWithFeatureCount;
|
||||
long allFeaturesCount;
|
||||
ADM.Map map = ADM.MapView.Active.Map;
|
||||
IEnumerable<ADM.MapMember> layersOrdered = _mapMemberUtils.GetMapMembersInOrder(map, layers);
|
||||
using (var _ = _activityFactory.Start("Unpacking selection"))
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
var collectionHost = rootObjectCollection;
|
||||
var applicationId = mapMember.URI;
|
||||
unpackedLayers = _layerUnpacker.UnpackSelection(layersOrdered, rootCollection);
|
||||
|
||||
try
|
||||
{
|
||||
Base converted;
|
||||
if (_sendConversionCache.TryGetValue(sendInfo.ProjectId, applicationId, out ObjectReference value))
|
||||
{
|
||||
converted = value;
|
||||
cacheHitCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
converted = converter.Convert(mapMember);
|
||||
converted.applicationId = applicationId;
|
||||
}
|
||||
|
||||
// add to host
|
||||
collectionHost.elements.Add(converted);
|
||||
results.Add(new(Status.SUCCESS, applicationId, mapMember.GetType().Name, converted));
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
results.Add(new(Status.ERROR, applicationId, mapMember.GetType().Name, null, ex));
|
||||
// POC: add logging
|
||||
}
|
||||
|
||||
onOperationProgressed?.Invoke("Converting", (double)++count / objects.Count);
|
||||
// count number of features to convert. Raster layers are counter as 1 feature for now (not ideal)
|
||||
layersWithFeatureCount = CountAllFeaturesInLayers(unpackedLayers);
|
||||
allFeaturesCount = layersWithFeatureCount.Values.Sum();
|
||||
}
|
||||
|
||||
// POC: Log would be nice, or can be removed.
|
||||
Debug.WriteLine(
|
||||
$"Cache hit count {cacheHitCount} out of {objects.Count} ({(double)cacheHitCount / objects.Count})"
|
||||
);
|
||||
List<SendConversionResult> results = new(unpackedLayers.Count);
|
||||
onOperationProgressed.Report(new("Converting", null));
|
||||
using (var convertingActivity = _activityFactory.Start("Converting objects"))
|
||||
{
|
||||
long count = 0;
|
||||
|
||||
return new(rootObjectCollection, results);
|
||||
foreach (var (layer, layerFeatureCount) in layersWithFeatureCount)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
string layerApplicationId = layer.GetSpeckleApplicationId();
|
||||
|
||||
try
|
||||
{
|
||||
// get the corresponding collection for this layer - we'll add all converted objects to the collection
|
||||
if (_layerUnpacker.CollectionCache.TryGetValue(layerApplicationId, out Collection? layerCollection))
|
||||
{
|
||||
var status = Status.SUCCESS;
|
||||
var sdkStatus = SdkActivityStatusCode.Ok;
|
||||
|
||||
// TODO: check cache first to see if this layer was previously converted
|
||||
/*
|
||||
if (_sendConversionCache.TryGetValue(
|
||||
sendInfo.ProjectId,
|
||||
layerApplicationId,
|
||||
out ObjectReference? value
|
||||
))
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
switch (layer)
|
||||
{
|
||||
case ADM.FeatureLayer featureLayer:
|
||||
List<Base> convertedFeatureLayerObjects = ConvertFeatureLayerObjects(
|
||||
featureLayer,
|
||||
count,
|
||||
allFeaturesCount,
|
||||
onOperationProgressed,
|
||||
cancellationToken
|
||||
);
|
||||
layerCollection.elements.AddRange(convertedFeatureLayerObjects);
|
||||
break;
|
||||
case ADM.RasterLayer rasterLayer:
|
||||
List<Base> convertedRasterLayerObjects = ConvertRasterLayerObjects(
|
||||
rasterLayer,
|
||||
count,
|
||||
allFeaturesCount,
|
||||
onOperationProgressed,
|
||||
cancellationToken
|
||||
);
|
||||
layerCollection.elements.AddRange(convertedRasterLayerObjects);
|
||||
break;
|
||||
case ADM.LasDatasetLayer lasDatasetLayer:
|
||||
List<Base> convertedLasDatasetObjects = ConvertLasDatasetLayerObjects(
|
||||
lasDatasetLayer,
|
||||
count,
|
||||
allFeaturesCount,
|
||||
onOperationProgressed,
|
||||
cancellationToken
|
||||
);
|
||||
layerCollection.elements.AddRange(convertedLasDatasetObjects);
|
||||
break;
|
||||
default:
|
||||
status = Status.ERROR;
|
||||
sdkStatus = SdkActivityStatusCode.Error;
|
||||
break;
|
||||
}
|
||||
|
||||
count += layerFeatureCount;
|
||||
results.Add(new(status, layerApplicationId, layer.GetType().Name, layerCollection));
|
||||
convertingActivity?.SetStatus(sdkStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SpeckleException($"No converted Collection found for layer {layerApplicationId}.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogSendConversionError(ex, layer.GetType().Name);
|
||||
results.Add(new(Status.ERROR, layerApplicationId, layer.GetType().Name, null, ex));
|
||||
convertingActivity?.SetStatus(SdkActivityStatusCode.Error);
|
||||
convertingActivity?.RecordException(ex);
|
||||
}
|
||||
|
||||
await Task.Yield();
|
||||
}
|
||||
}
|
||||
|
||||
if (results.All(x => x.Status == Status.ERROR))
|
||||
{
|
||||
throw new SpeckleException("Failed to convert all objects."); // fail fast instead creating empty commit! It will appear as model card error with red color.
|
||||
}
|
||||
|
||||
// 3 - Add Color Proxies
|
||||
rootCollection[ProxyKeys.COLOR] = _colorUnpacker.ColorProxyCache.Values.ToList();
|
||||
|
||||
return new RootObjectBuilderResult(rootCollection, results);
|
||||
}
|
||||
|
||||
private Dictionary<ADM.MapMember, long> CountAllFeaturesInLayers(List<ADM.MapMember> unpackedLayers)
|
||||
{
|
||||
Dictionary<ADM.MapMember, long> layersFeatureCount = new();
|
||||
|
||||
foreach (ADM.MapMember layer in unpackedLayers)
|
||||
{
|
||||
switch (layer)
|
||||
{
|
||||
case ADM.FeatureLayer featureLayer:
|
||||
layersFeatureCount.Add(featureLayer, featureLayer.GetFeatureClass().GetCount());
|
||||
break;
|
||||
case ADM.RasterLayer rasterLayer:
|
||||
// count Raster layer as 1 feature: not optimal but this is the approach for now
|
||||
layersFeatureCount.Add(rasterLayer, 1);
|
||||
break;
|
||||
case ADM.LasDatasetLayer lasDatasetLayer:
|
||||
var dataset = lasDatasetLayer.GetLasDataset();
|
||||
// simple dataset.GetPointCount() keeps returning null, so switched to EstimatePointCount
|
||||
layersFeatureCount.Add(
|
||||
lasDatasetLayer,
|
||||
(long)dataset.EstimatePointCount(dataset.GetDefinition().GetExtent())
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return layersFeatureCount;
|
||||
}
|
||||
|
||||
private List<Base> ConvertFeatureLayerObjects(
|
||||
ADM.FeatureLayer featureLayer,
|
||||
long count,
|
||||
long allFeaturesCount,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
string layerApplicationId = featureLayer.GetSpeckleApplicationId();
|
||||
List<Base> convertedObjects = new();
|
||||
// store the layer renderer for color unpacking
|
||||
_colorUnpacker.StoreRendererAndFields(featureLayer);
|
||||
|
||||
// search the rows of the layer, where each row is treated like an object
|
||||
// RowCursor is IDisposable but is not being correctly picked up by IDE warnings.
|
||||
// This means we need to be carefully adding using statements based on the API documentation coming from each method/class
|
||||
using (ACD.RowCursor rowCursor = featureLayer.Search())
|
||||
{
|
||||
while (rowCursor.MoveNext())
|
||||
{
|
||||
// allow cancellation before every feature
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
// Same IDisposable issue appears to happen on Row class too. Docs say it should always be disposed of manually by the caller.
|
||||
using (ACD.Row row = rowCursor.Current)
|
||||
{
|
||||
// get application id. test for subtypes before defaulting to base type.
|
||||
Base converted = _rootToSpeckleConverter.Convert(row);
|
||||
string applicationId = row.GetSpeckleApplicationId(layerApplicationId);
|
||||
converted.applicationId = applicationId;
|
||||
|
||||
convertedObjects.Add(converted);
|
||||
|
||||
// process the object color
|
||||
_colorUnpacker.ProcessFeatureLayerColor(row, applicationId);
|
||||
}
|
||||
// update report
|
||||
onOperationProgressed.Report(new("Converting", (double)++count / allFeaturesCount));
|
||||
}
|
||||
}
|
||||
|
||||
return convertedObjects;
|
||||
}
|
||||
|
||||
// POC: raster colors are stored as mesh vertex colors in RasterToSpeckleConverter. Should probably move to color unpacker.
|
||||
private List<Base> ConvertRasterLayerObjects(
|
||||
ADM.RasterLayer rasterLayer,
|
||||
long count,
|
||||
long allFeaturesCount,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
string layerApplicationId = rasterLayer.GetSpeckleApplicationId();
|
||||
List<Base> convertedObjects = new();
|
||||
Raster raster = rasterLayer.GetRaster();
|
||||
|
||||
// check cancellation token before conversion
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
Base converted = _rootToSpeckleConverter.Convert(raster);
|
||||
string applicationId = raster.GetSpeckleApplicationId(layerApplicationId);
|
||||
converted.applicationId = applicationId;
|
||||
convertedObjects.Add(converted);
|
||||
|
||||
// update report
|
||||
onOperationProgressed.Report(new("Converting", (double)++count / allFeaturesCount));
|
||||
|
||||
return convertedObjects;
|
||||
}
|
||||
|
||||
private List<Base> ConvertLasDatasetLayerObjects(
|
||||
ADM.LasDatasetLayer lasDatasetLayer,
|
||||
long count,
|
||||
long allFeaturesCount,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
string layerApplicationId = lasDatasetLayer.GetSpeckleApplicationId();
|
||||
List<Base> convertedObjects = new();
|
||||
|
||||
try
|
||||
{
|
||||
// store the layer renderer for color unpacking
|
||||
_colorUnpacker.StoreRenderer(lasDatasetLayer);
|
||||
|
||||
using (ACD.Analyst3D.LasPointCursor ptCursor = lasDatasetLayer.SearchPoints(new ACD.Analyst3D.LasPointFilter()))
|
||||
{
|
||||
while (ptCursor.MoveNext())
|
||||
{
|
||||
// allow cancellation before every point
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
using (ACD.Analyst3D.LasPoint pt = ptCursor.Current)
|
||||
{
|
||||
Base converted = _rootToSpeckleConverter.Convert(pt);
|
||||
string applicationId = pt.GetSpeckleApplicationId(layerApplicationId);
|
||||
converted.applicationId = applicationId;
|
||||
convertedObjects.Add(converted);
|
||||
|
||||
// process the object color
|
||||
_colorUnpacker.ProcessLasLayerColor(pt, applicationId);
|
||||
}
|
||||
// update report
|
||||
onOperationProgressed.Report(new("Converting", (double)++count / allFeaturesCount));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ACD.Exceptions.TinException ex)
|
||||
{
|
||||
throw new SpeckleException("3D analyst extension is not enabled for .las layer operations", ex);
|
||||
}
|
||||
|
||||
return convertedObjects;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Speckle.Connectors.ArcGIS3": {
|
||||
"Speckle.Connectors.ArcGIS3_all_users": {
|
||||
"commandName": "Executable",
|
||||
"executablePath": "C:\\Program Files\\ArcGIS\\Pro\\bin\\ArcGISPro.exe",
|
||||
"commandLineArgs": ""
|
||||
},
|
||||
"Speckle.Connectors.ArcGIS3_user": {
|
||||
"commandName": "Executable",
|
||||
"executablePath": "C:\\Users\\%USERNAME%\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\ArcGISPro.exe",
|
||||
"commandLineArgs": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,29 +9,28 @@
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<EnableWindowsTargeting>true</EnableWindowsTargeting>
|
||||
<DefineConstants>$(DefineConstants);ARCGIS3</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Config.daml"/>
|
||||
<Content Include="Images\s2logo_16.png"/>
|
||||
<Content Include="Images\s2logo_32.png"/>
|
||||
<Content Include="DarkImages\s2logo_16.png"/>
|
||||
<Content Include="DarkImages\s2logo_32.png"/>
|
||||
<Content Include="Config.daml" />
|
||||
<Content Include="Images\s2logo_16.png" />
|
||||
<Content Include="Images\s2logo_32.png" />
|
||||
<Content Include="DarkImages\s2logo_16.png" />
|
||||
<Content Include="DarkImages\s2logo_32.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Esri.ArcGISPro.Extensions30" IncludeAssets="compile"/>
|
||||
<PackageReference Include="Esri.ArcGISPro.Extensions30" IncludeAssets="compile" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference
|
||||
Include="..\..\..\Converters\ArcGIS\Speckle.Converters.ArcGIS3.DependencyInjection\Speckle.Converters.ArcGIS3.DependencyInjection.csproj"/>
|
||||
<ProjectReference
|
||||
Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj"/>
|
||||
<ProjectReference
|
||||
Include="..\..\..\Sdk\Speckle.Connectors.Utils\Speckle.Connectors.Utils.csproj"/>
|
||||
<ProjectReference Include="..\..\..\Converters\ArcGIS\Speckle.Converters.ArcGIS3\Speckle.Converters.ArcGIS3.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Connectors.Common\Speckle.Connectors.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="Esri.ArcGISPro.Extensions30.Speckle.targets"/>
|
||||
<Import Project="Esri.ArcGISPro.Extensions30.Speckle.targets" />
|
||||
</Project>
|
||||
|
||||
@@ -18,7 +18,7 @@ internal sealed class SpeckleDUI3ViewModel : DockPane
|
||||
/// </summary>
|
||||
protected override async Task InitializeAsync()
|
||||
{
|
||||
await base.InitializeAsync().ConfigureAwait(false);
|
||||
await base.InitializeAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -26,7 +26,7 @@ internal sealed class SpeckleDUI3ViewModel : DockPane
|
||||
/// </summary>
|
||||
protected override async Task UninitializeAsync()
|
||||
{
|
||||
await base.UninitializeAsync().ConfigureAwait(false);
|
||||
await base.UninitializeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Windows.Controls;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.DUI.WebView;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS;
|
||||
@@ -12,6 +13,6 @@ public class SpeckleDUI3Wrapper : UserControl
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
Content = SpeckleModule.Current.Container.Resolve<DUI3ControlWebView>();
|
||||
Content = SpeckleModule.Current.Container.GetRequiredService<DUI3ControlWebView>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System.Reflection;
|
||||
using ArcGIS.Desktop.Framework;
|
||||
using Speckle.Autofac;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.ArcGIS.HostApp;
|
||||
using Speckle.Core.Kits;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.ArcGIS.DependencyInjection;
|
||||
using Speckle.Connectors.Common;
|
||||
using Speckle.Connectors.DUI;
|
||||
using Speckle.Converters.ArcGIS3;
|
||||
using Module = ArcGIS.Desktop.Framework.Contracts.Module;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS;
|
||||
@@ -14,6 +14,7 @@ namespace Speckle.Connectors.ArcGIS;
|
||||
internal sealed class SpeckleModule : Module
|
||||
{
|
||||
private static SpeckleModule? s_this;
|
||||
private readonly IDisposable? _disposableLogger;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the singleton instance to this module here
|
||||
@@ -21,21 +22,28 @@ internal sealed class SpeckleModule : Module
|
||||
public static SpeckleModule Current =>
|
||||
s_this ??= (SpeckleModule)FrameworkApplication.FindModule("ConnectorArcGIS_Module");
|
||||
|
||||
public SpeckleContainer Container { get; }
|
||||
public ServiceProvider Container { get; }
|
||||
|
||||
public SpeckleModule()
|
||||
{
|
||||
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolver.OnAssemblyResolve<SpeckleModule>;
|
||||
|
||||
var builder = SpeckleContainerBuilder.CreateInstance();
|
||||
var services = new ServiceCollection();
|
||||
// init DI
|
||||
_disposableLogger = services.Initialize(HostApplications.ArcGIS, GetVersion());
|
||||
services.AddArcGIS();
|
||||
services.AddArcGISConverters();
|
||||
Container = services.BuildServiceProvider();
|
||||
Container.UseDUI();
|
||||
}
|
||||
|
||||
// Register Settings
|
||||
var arcgisSettings = new ArcGISSettings(HostApplications.ArcGIS, HostAppVersion.v3);
|
||||
|
||||
Container = builder
|
||||
.LoadAutofacModules(Assembly.GetExecutingAssembly(), arcgisSettings.Modules)
|
||||
.AddSingleton(arcgisSettings)
|
||||
.Build();
|
||||
private HostAppVersion GetVersion()
|
||||
{
|
||||
#if ARCGIS3
|
||||
return HostAppVersion.v3;
|
||||
#else
|
||||
throw new NotImplementedException();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -46,6 +54,8 @@ internal sealed class SpeckleModule : Module
|
||||
{
|
||||
//TODO - add your business logic
|
||||
//return false to ~cancel~ Application close
|
||||
_disposableLogger?.Dispose();
|
||||
Container.Dispose();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,21 +3,25 @@ using ArcGIS.Desktop.Core.Events;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using ArcGIS.Desktop.Mapping.Events;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Newtonsoft.Json;
|
||||
using Speckle.Connectors.DUI.Utils;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Utils;
|
||||
|
||||
public class ArcGISDocumentStore : DocumentModelStore
|
||||
{
|
||||
private readonly IThreadContext _threadContext;
|
||||
|
||||
public ArcGISDocumentStore(
|
||||
JsonSerializerSettings serializerOption,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
IJsonSerializer jsonSerializer,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler,
|
||||
IThreadContext threadContext
|
||||
)
|
||||
: base(serializerOption, true)
|
||||
: base(jsonSerializer)
|
||||
{
|
||||
_threadContext = threadContext;
|
||||
ActiveMapViewChangedEvent.Subscribe(a => topLevelExceptionHandler.CatchUnhandled(() => OnMapViewChanged(a)), true);
|
||||
ProjectSavingEvent.Subscribe(
|
||||
_ =>
|
||||
@@ -37,10 +41,10 @@ public class ArcGISDocumentStore : DocumentModelStore
|
||||
);
|
||||
|
||||
// in case plugin was loaded into already opened Map, read metadata from the current Map
|
||||
if (IsDocumentInit == false && MapView.Active != null)
|
||||
if (!IsDocumentInit && MapView.Active != null)
|
||||
{
|
||||
IsDocumentInit = true;
|
||||
ReadFromFile();
|
||||
LoadState();
|
||||
OnDocumentChanged();
|
||||
}
|
||||
}
|
||||
@@ -52,14 +56,14 @@ public class ArcGISDocumentStore : DocumentModelStore
|
||||
return;
|
||||
}
|
||||
|
||||
WriteToFile();
|
||||
SaveState();
|
||||
}
|
||||
|
||||
private void OnProjectSaving()
|
||||
{
|
||||
if (MapView.Active is not null)
|
||||
{
|
||||
WriteToFile();
|
||||
SaveState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,58 +78,56 @@ public class ArcGISDocumentStore : DocumentModelStore
|
||||
}
|
||||
|
||||
IsDocumentInit = true;
|
||||
ReadFromFile();
|
||||
LoadState();
|
||||
OnDocumentChanged();
|
||||
}
|
||||
|
||||
public override void WriteToFile()
|
||||
{
|
||||
Map map = MapView.Active.Map;
|
||||
QueuedTask.Run(() =>
|
||||
{
|
||||
// Read existing metadata - To prevent messing existing metadata. 🤞 Hope other add-in developers will do same :D
|
||||
var existingMetadata = map.GetMetadata();
|
||||
|
||||
// Parse existing metadata
|
||||
XDocument existingXmlDocument = !string.IsNullOrEmpty(existingMetadata)
|
||||
? XDocument.Parse(existingMetadata)
|
||||
: new XDocument(new XElement("metadata"));
|
||||
|
||||
string serializedModels = Serialize();
|
||||
|
||||
XElement xmlModelCards = new("SpeckleModelCards", serializedModels);
|
||||
|
||||
// Check if SpeckleModelCards element already exists at root and update it
|
||||
var speckleModelCardsElement = existingXmlDocument.Root?.Element("SpeckleModelCards");
|
||||
if (speckleModelCardsElement != null)
|
||||
protected override void HostAppSaveState(string modelCardState) =>
|
||||
QueuedTask
|
||||
.Run(() =>
|
||||
{
|
||||
speckleModelCardsElement.ReplaceWith(xmlModelCards);
|
||||
}
|
||||
else
|
||||
Map map = MapView.Active.Map;
|
||||
// Read existing metadata - To prevent messing existing metadata. 🤞 Hope other add-in developers will do same :D
|
||||
var existingMetadata = map.GetMetadata();
|
||||
|
||||
// Parse existing metadata
|
||||
XDocument existingXmlDocument = !string.IsNullOrEmpty(existingMetadata)
|
||||
? XDocument.Parse(existingMetadata)
|
||||
: new XDocument(new XElement("metadata"));
|
||||
|
||||
XElement xmlModelCards = new("SpeckleModelCards", modelCardState);
|
||||
|
||||
// Check if SpeckleModelCards element already exists at root and update it
|
||||
var speckleModelCardsElement = existingXmlDocument.Root?.Element("SpeckleModelCards");
|
||||
if (speckleModelCardsElement != null)
|
||||
{
|
||||
speckleModelCardsElement.ReplaceWith(xmlModelCards);
|
||||
}
|
||||
else
|
||||
{
|
||||
existingXmlDocument.Root?.Add(xmlModelCards);
|
||||
}
|
||||
|
||||
map.SetMetadata(existingXmlDocument.ToString());
|
||||
})
|
||||
.FireAndForget();
|
||||
|
||||
protected override void LoadState() =>
|
||||
QueuedTask
|
||||
.Run(() =>
|
||||
{
|
||||
existingXmlDocument.Root?.Add(xmlModelCards);
|
||||
}
|
||||
Map map = MapView.Active.Map;
|
||||
var metadata = map.GetMetadata();
|
||||
var root = XDocument.Parse(metadata).Root;
|
||||
var element = root?.Element("SpeckleModelCards");
|
||||
if (element is null)
|
||||
{
|
||||
ClearAndSave();
|
||||
return;
|
||||
}
|
||||
|
||||
map.SetMetadata(existingXmlDocument.ToString());
|
||||
});
|
||||
}
|
||||
|
||||
public override void ReadFromFile()
|
||||
{
|
||||
Map map = MapView.Active.Map;
|
||||
QueuedTask.Run(() =>
|
||||
{
|
||||
var metadata = map.GetMetadata();
|
||||
var root = XDocument.Parse(metadata).Root;
|
||||
var element = root?.Element("SpeckleModelCards");
|
||||
if (element is null)
|
||||
{
|
||||
Models = new();
|
||||
return;
|
||||
}
|
||||
|
||||
string modelsString = element.Value;
|
||||
Models = Deserialize(modelsString).NotNull();
|
||||
});
|
||||
}
|
||||
string modelsString = element.Value;
|
||||
LoadFromString(modelsString);
|
||||
})
|
||||
.FireAndForget();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Utils;
|
||||
|
||||
public class MapMembersUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns all Layers and Standalone Tables present on the Map
|
||||
/// </summary>
|
||||
/// <param name="map"></param>
|
||||
/// <returns></returns>
|
||||
public List<MapMember> GetAllMapMembers(Map map)
|
||||
{
|
||||
// first get all map layers
|
||||
List<MapMember> mapMembers = new();
|
||||
var layerMapMembers = UnpackMapLayers(map.Layers);
|
||||
mapMembers.AddRange(layerMapMembers);
|
||||
|
||||
// add tables
|
||||
var standaloneTableMapMembers = UnpackMapLayers(map.StandaloneTables);
|
||||
mapMembers.AddRange(standaloneTableMapMembers);
|
||||
return mapMembers;
|
||||
}
|
||||
|
||||
public List<MapMember> UnpackMapLayers(IEnumerable<MapMember> mapMembersToUnpack)
|
||||
{
|
||||
List<MapMember> mapMembers = new();
|
||||
foreach (var layer in mapMembersToUnpack)
|
||||
{
|
||||
mapMembers.Add(layer);
|
||||
switch (layer)
|
||||
{
|
||||
case ILayerContainer subGroup:
|
||||
var subLayerMapMembers = UnpackMapLayers(subGroup.Layers);
|
||||
mapMembers.AddRange(subLayerMapMembers);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mapMembers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sorts the selected mapmembers into the same order as they appear in the Table of Contents (TOC) bar in the file.
|
||||
/// This is a required step before unpacking layers, because depending on the user selection order, some children layers may appear before their container layer if both the container and children layers are selected.
|
||||
/// </summary>
|
||||
public IEnumerable<MapMember> GetMapMembersInOrder(Map map, IReadOnlyList<MapMember> selectedMapMembers)
|
||||
{
|
||||
// first get all map layers
|
||||
List<MapMember> allMapMembers = GetAllMapMembers(map);
|
||||
|
||||
// recalculate selected layer priority from all map layers
|
||||
foreach (MapMember mapMember in allMapMembers)
|
||||
{
|
||||
if (selectedMapMembers.Contains(mapMember))
|
||||
{
|
||||
yield return mapMember;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,18 @@
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "Direct",
|
||||
"requested": "[7.0.0, )",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "kmn78+LPVMOWeITUjIlfxUPDsI0R6G0RkeAMBmQxAJ7vBJn4q2dTva7pWi65ceN5vPGjJ9q/Uae2WKgvfktJAw=="
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
"type": "Direct",
|
||||
@@ -32,9 +41,9 @@
|
||||
},
|
||||
"Speckle.InterfaceGenerator": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.9.5, )",
|
||||
"resolved": "0.9.5",
|
||||
"contentHash": "oU/L7pN1R7q8KkbrpQ3WJnHirPHqn+9DEA7asOcUiggV5dzVg1A/VYs7GOSusD24njxXh03tE3a2oTLOjt3cVg=="
|
||||
"requested": "[0.9.6, )",
|
||||
"resolved": "0.9.6",
|
||||
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
|
||||
},
|
||||
"GraphQL.Client": {
|
||||
"type": "Transitive",
|
||||
@@ -67,43 +76,10 @@
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Http": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.2",
|
||||
"contentHash": "BAibpoItxI5puk7YJbIGj95arZueM8B8M5xT1fXBn3hb3L2G3ucrZcYXv1gXdaroLbntUs8qeV8iuBrpjQsrKw==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Abstractions": "2.2.0",
|
||||
"Microsoft.AspNetCore.WebUtilities": "2.2.0",
|
||||
"Microsoft.Extensions.ObjectPool": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0",
|
||||
"Microsoft.Net.Http.Headers": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Features": "2.2.0",
|
||||
"System.Text.Encodings.Web": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Features": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "ziFz5zH8f33En4dX81LW84I6XrYXKf9jg6aM39cM+LffN9KJahViKZ61dGMSO2gd3e+qe5yBRwsesvyqlZaSMg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.WebUtilities": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "9ErxAAKaDzxXASB/b5uLEkLgUWv1QbeVxyJYEHQwMaxXOeFFVkQxiq8RyfVcifLU7NR0QY0p3acqx4ZpYfhHDg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Net.Http.Headers": "2.2.0",
|
||||
"System.Text.Encodings.Web": "4.5.0"
|
||||
}
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ=="
|
||||
},
|
||||
"Microsoft.Build.Tasks.Git": {
|
||||
"type": "Transitive",
|
||||
@@ -132,172 +108,64 @@
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "elNeOmkeX3eDVG6pYVeV82p29hr+UKDaBhrZyWvWLw/EVZSYEkZlQdkp0V39k/Xehs2Qa0mvoCvkVj3eQxNQ1Q==",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "h3j/QfmFN4S0w4C2A6X7arXij/M/OVw3uQHSOFxnND4DyAzO1F9eMX7Eti7lU/OkSthEE0WzRsfT/Dmx86jzCw=="
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "Nw2muoNrOG5U5qa2ZekXwudUn2BJcD41e65zwmDHb1fQegTX66UokLWZkJRpqSSHXDOWZ5V0iqhbxOEky91atA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "7.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "7.0.0",
|
||||
"Microsoft.Extensions.Options": "7.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.ObjectPool": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "gA8H7uQOnM5gb+L0uTNjViHYr+hRDqCdfugheGo/MxQnuHzmhhzCBTIPm19qL1z1Xe0NEMabfcOBGv9QghlZ8g=="
|
||||
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "lP1yBnTTU42cKpMozuafbvNtQ7QcBjr/CcK3bYOGEMH55Fjt+iecXjT6chR7vbgCMqy3PG3aNQSZgo/EuY/9qQ==",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0",
|
||||
"Microsoft.Extensions.Primitives": "7.0.0"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.ComponentModel.Annotations": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "um1KU5kxcRp3CNuI8o/GrZtD4AIOXDk+RLsytjZ9QPok3ttLUelLKpilVPuaFT3TFjOhSibUAso0odbOaCDj3Q==",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
"System.Memory": "4.5.1",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Net.Http.Headers": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "iZNkjYqlo8sIOI0bQfpsSoMTmB/kyvmV2h225ihyZT33aTp48ZpF6qYnXxzSXmHt8DpBAwBTX+1s1UFLbYfZKg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.Buffers": "4.5.0"
|
||||
}
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Polly": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.2.3",
|
||||
"contentHash": "DeCY0OFbNdNxsjntr1gTXHJ5pKUwYzp04Er2LLeN3g6pWhffsGuKVfMBLe1lw7x76HrPkLxKEFxBlpRxS2nDEQ=="
|
||||
},
|
||||
"Polly.Contrib.WaitAndRetry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.1.1",
|
||||
"contentHash": "1MUQLiSo4KDkQe6nzQRhIU05lm9jlexX5BVsbuw0SL82ynZ+GzAHQxJVDPVBboxV37Po3SG077aX8DuSy8TkaA=="
|
||||
},
|
||||
"Polly.Extensions.Http": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.0",
|
||||
"contentHash": "drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==",
|
||||
"dependencies": {
|
||||
"Polly": "7.1.0"
|
||||
}
|
||||
},
|
||||
"Sentry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.33.0",
|
||||
"contentHash": "8vbD2o6IR2wrRrkSiRbnodWGWUOqIlwYtzpjvPNOb5raJdOf+zxMwfS8f6nx9bmrTTfDj7KrCB8C/5OuicAc8A=="
|
||||
},
|
||||
"Sentry.Serilog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.33.0",
|
||||
"contentHash": "V8BU7QGWg2qLYfNPqtuTBhC1opysny5l+Ifp6J6PhOeAxU0FssR7nYfbJVetrnLIoh2rd3DlJ6hHYYQosQYcUQ==",
|
||||
"dependencies": {
|
||||
"Sentry": "3.33.0",
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"Serilog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.12.0",
|
||||
"contentHash": "xaiJLIdu6rYMKfQMYUZgTy8YK7SMZjB4Yk50C/u//Z4OsvxkUfSPJy4nknfvwAC34yr13q7kcyh4grbwhSxyZg=="
|
||||
},
|
||||
"Serilog.Enrichers.ClientInfo": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.3.0",
|
||||
"contentHash": "mTc7PM+wC9Hr7LWSwqt5mmnlAr7RJs+eTb3PGPRhwdOackk95MkhUZognuxXEdlW19HAFNmEBTSBY5DfLwM8jQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http": "2.2.2",
|
||||
"Serilog": "2.9.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Exceptions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.4.0",
|
||||
"contentHash": "nc/+hUw3lsdo0zCj0KMIybAu7perMx79vu72w0za9Nsi6mWyNkGXxYxakAjWB7nEmYL6zdmhEQRB4oJ2ALUeug==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.8.0",
|
||||
"System.Reflection.TypeExtensions": "4.7.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Formatting.Compact": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.1.0",
|
||||
"contentHash": "pNroKVjo+rDqlxNG5PXkRLpfSCuDOBY0ri6jp9PLe505ljqwhwZz8ospy2vWhQlFu5GkIesh3FcDs4n7sWZODA==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.8.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.Console": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "K6N5q+5fetjnJPvCmkWOpJ/V8IEIoMIB1s86OzBrbxwTyHxdx3pmz4H+8+O/Dc/ftUX12DM1aynx/dDowkwzqg==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.File": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.PeriodicBatching": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "NDWR7m3PalVlGEq3rzoktrXikjFMLmpwF0HI4sowo8YDdU+gqPlTHlDQiOGxHfB0sTfjPA9JjA7ctKG9zqjGkw==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.0.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.Seq": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.2.2",
|
||||
"contentHash": "1Csmo5ua7NKUe0yXUx+zsRefjAniPWcXFhUXxXG8pwo0iMiw2gjn9SOkgYnnxbgWqmlGv236w0N/dHc2v5XwMg==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.12.0",
|
||||
"Serilog.Formatting.Compact": "1.1.0",
|
||||
"Serilog.Sinks.File": "5.0.0",
|
||||
"Serilog.Sinks.PeriodicBatching": "3.1.0"
|
||||
}
|
||||
},
|
||||
"SerilogTimings": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "Zs28eTgszAMwpIrbBnWHBI50yuxL50p/dmAUWmy75+axdZYK/Sjm5/5m1N/CisR8acJUhTVcjPZrsB1P5iv0Uw==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.2",
|
||||
@@ -333,18 +201,10 @@
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"System.Buffers": {
|
||||
"System.ComponentModel.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "pL2ChpaRRWI/p4LXyy4RgeWlYF2sgfj/pnVMvBqwNFr5cXg7CXNnWZWxrOONLg8VGdFB8oB+EG2Qw4MLgTOe+A=="
|
||||
},
|
||||
"System.DoubleNumerics": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.3",
|
||||
"contentHash": "KRKEM/L3KBodjA9VOg3EifFVWUY6EOqaMB05UvPEDm7Zeby/kZW+4kdWUEPzW6xtkwf46p661L9NrbeeQhtLzw==",
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.6.1"
|
||||
}
|
||||
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
@@ -356,141 +216,132 @@
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
|
||||
},
|
||||
"System.Reflection.TypeExtensions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.7.0",
|
||||
"contentHash": "VybpaOQQhqE6siHppMktjfGBw1GCwvCqiufqmP8F1nj7fTUNtW35LOEt3UZTEsECfo+ELAl/9o9nJx3U91i7vA=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "Xg4G4Indi4dqP1iuAiMSwpiWS54ZghzR644OtsRCm/m/lBMG8dUBhLVN7hLm8NNrNTR+iGbshCPTwrvxZPlm4g=="
|
||||
},
|
||||
"speckle.autofac": {
|
||||
"speckle.common.meshtriangulation": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[7.0.0, )"
|
||||
"LibTessDotNet": "[1.1.15, )",
|
||||
"Speckle.DoubleNumerics": "[4.1.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.2.0, )",
|
||||
"Speckle.Sdk": "[3.2.0, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[7.0.0, )",
|
||||
"Speckle.Autofac": "[2.0.999-local, )",
|
||||
"Speckle.Connectors.Utils": "[2.0.999-local, )",
|
||||
"Speckle.Core": "[3.0.1-alpha.14, )",
|
||||
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Connectors.Common": "[1.0.0, )",
|
||||
"Speckle.Sdk": "[3.2.0, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui.webview": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Web.WebView2": "[1.0.1823.32, )",
|
||||
"Speckle.Connectors.DUI": "[2.0.999-local, )"
|
||||
"Microsoft.Web.WebView2": "[1.0.1938.49, )",
|
||||
"Speckle.Connectors.DUI": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.utils": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Serilog.Extensions.Logging": "[7.0.0, )",
|
||||
"Speckle.Autofac": "[2.0.999-local, )",
|
||||
"Speckle.Core": "[3.0.1-alpha.14, )"
|
||||
}
|
||||
"speckle.connectors.logging": {
|
||||
"type": "Project"
|
||||
},
|
||||
"speckle.converters.arcgis3": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Esri.ArcGISPro.Extensions30": "[3.2.0.49743, )",
|
||||
"Speckle.Converters.Common": "[2.0.999-local, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.arcgis3.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Autofac": "[5.2.0, )",
|
||||
"Speckle.Converters.ArcGIS3": "[2.0.999-local, )",
|
||||
"Speckle.Converters.Common.DependencyInjection": "[2.0.999-local, )"
|
||||
"Speckle.Common.MeshTriangulation": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Speckle.Autofac": "[2.0.999-local, )",
|
||||
"Speckle.Objects": "[3.0.1-alpha.14, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Speckle.Autofac": "[2.0.999-local, )",
|
||||
"Speckle.Converters.Common": "[2.0.999-local, )"
|
||||
}
|
||||
},
|
||||
"Autofac": {
|
||||
"LibTessDotNet": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[5.2.0, )",
|
||||
"resolved": "5.2.0",
|
||||
"contentHash": "V8dBH0dsv75uDzl7Sw+HkhKDPUw2eXnlMjcSVMH+tLo2s67MpTKGyDj1pDcpR+IF2u4YRs0s3/x7R88YJzIWvg=="
|
||||
"requested": "[1.1.15, )",
|
||||
"resolved": "1.1.15",
|
||||
"contentHash": "KuA7N3Nv/lIeawJdQBQJR6oqWD9KETHLbWzBqapwFs+Tby+R5I4crkKujKMm5bXcSuFZ8LNtflFQVadsWCbBjg=="
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1823.32, )",
|
||||
"resolved": "1.0.1823.32",
|
||||
"contentHash": "ppRcWBUNggFIqyJp7PfgS4Oe8/7yli/mHcTNDOaqo3ZzJWnv9AOr0WE9ceEP5SPs1M7CQ3QvdGMR7KNz0v09EA=="
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
},
|
||||
"Serilog.Extensions.Logging": {
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[7.0.0, )",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "9faU0zNQqU7I6soVhLUMYaGNpgWv6cKlKb2S5AnS8gXxzW/em5Ladm/6FMrWTnX41cdbdGPOWNAo6adi4WaJ6A==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging": "7.0.0",
|
||||
"Serilog": "2.12.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Core": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.0.1-alpha.14, )",
|
||||
"resolved": "3.0.1-alpha.14",
|
||||
"contentHash": "RzQPVIGFFkKvG56YLr8ACtiwdWJE6IJ9vCQ4qHa0PIsUEpfzAIAi59jnzqtByOFC0FiFrFPow9bkfzylaZorAA==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Polly": "7.2.3",
|
||||
"Polly.Contrib.WaitAndRetry": "1.1.1",
|
||||
"Polly.Extensions.Http": "3.0.0",
|
||||
"Sentry": "3.33.0",
|
||||
"Sentry.Serilog": "3.33.0",
|
||||
"Serilog": "2.12.0",
|
||||
"Serilog.Enrichers.ClientInfo": "1.3.0",
|
||||
"Serilog.Exceptions": "8.4.0",
|
||||
"Serilog.Sinks.Console": "4.1.0",
|
||||
"Serilog.Sinks.Seq": "5.2.2",
|
||||
"SerilogTimings": "3.0.1",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"System.DoubleNumerics": "3.1.3"
|
||||
}
|
||||
"requested": "[4.1.0, )",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.0.1-alpha.14, )",
|
||||
"resolved": "3.0.1-alpha.14",
|
||||
"contentHash": "z38LGryMvh7iU1uBW+4uo5DwsB3CwRgLt2uFexWFx3mPSid+A0l5XcJzOgLwgFhNl6B42Ryz4ezBsddTp1Uc/g==",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
|
||||
"dependencies": {
|
||||
"Speckle.Core": "3.0.1-alpha.14"
|
||||
"Speckle.Sdk": "3.2.0"
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks.Dataflow": {
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[6.0.0, )",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.2.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
|
||||
}
|
||||
},
|
||||
"net6.0-windows7.0/win-x64": {
|
||||
@@ -501,9 +352,9 @@
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1823.32, )",
|
||||
"resolved": "1.0.1823.32",
|
||||
"contentHash": "ppRcWBUNggFIqyJp7PfgS4Oe8/7yli/mHcTNDOaqo3ZzJWnv9AOr0WE9ceEP5SPs1M7CQ3QvdGMR7KNz0v09EA=="
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<Target AfterTargets="Clean" Name="CleanAddinAutocad" Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<RemoveDir Directories="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Autocad$(AutoCADVersion);" />
|
||||
</Target>
|
||||
|
||||
<Target AfterTargets="Build" Name="AfterBuildAutoCAD" Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<ItemGroup>
|
||||
<AutoCADDLLs Include="$(TargetDir)\**\*.*" />
|
||||
</ItemGroup>
|
||||
<Message Text="AutoCAD Version $(AutoCADVersion)" Importance="high"/>
|
||||
<Copy DestinationFolder="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Autocad$(AutoCADVersion)\%(RecursiveDir)" SourceFiles="@(AutoCADDLLs)" />
|
||||
</Target>
|
||||
|
||||
<Target AfterTargets="Clean" Name="CleanAddinCivil3D" Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<RemoveDir Directories="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Civil3d$(Civil3DVersion);" />
|
||||
</Target>
|
||||
|
||||
<Target AfterTargets="Build" Name="AfterBuildCivil3D" Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<ItemGroup>
|
||||
<Civil3DDLLs Include="$(TargetDir)\**\*.*" />
|
||||
</ItemGroup>
|
||||
<Message Text="Civil3D Version $(Civil3DVersion)" Importance="high"/>
|
||||
<Copy DestinationFolder="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Civil3d$(Civil3DVersion)\%(RecursiveDir)" SourceFiles="@(Civil3DDLLs)" />
|
||||
</Target>
|
||||
|
||||
<PropertyGroup Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<StartAction>Program</StartAction>
|
||||
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(AutoCADVersion)\acad.exe</StartProgram>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<StartAction>Program</StartAction>
|
||||
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(Civil3DVersion)\acad.exe</StartProgram>
|
||||
<StartArguments>/product C3D</StartArguments>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<UseWpf>true</UseWpf>
|
||||
<AutoCADVersion>2022</AutoCADVersion>
|
||||
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2022;AUTOCAD2022_OR_GREATER</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2022.0.2" ExcludeAssets="runtime"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2022\Speckle.Converters.Autocad2022.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Converters.Common\Speckle.Converters.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems" Label="Shared" />
|
||||
</Project>
|
||||
@@ -0,0 +1,373 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dependencies": {
|
||||
".NETFramework,Version=v4.8": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net48": "1.0.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Build.Tasks.Git": "8.0.0",
|
||||
"Microsoft.SourceLink.Common": "8.0.0"
|
||||
}
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.14.1, )",
|
||||
"resolved": "1.14.1",
|
||||
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
|
||||
},
|
||||
"Speckle.AutoCAD.API": {
|
||||
"type": "Direct",
|
||||
"requested": "[2022.0.2, )",
|
||||
"resolved": "2022.0.2",
|
||||
"contentHash": "NFHXnlkBjzM8Bau52d6eF6m0+etHddGx7qlWN8YyrfTtGyz+AmPvF8fgxcLgyjAcB3W4Wim11JeYuEoTNH1X0w=="
|
||||
},
|
||||
"Speckle.InterfaceGenerator": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.9.6, )",
|
||||
"resolved": "0.9.6",
|
||||
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
|
||||
},
|
||||
"GraphQL.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client.Abstractions": "6.0.0",
|
||||
"GraphQL.Client.Abstractions.Websocket": "6.0.0",
|
||||
"System.Net.WebSockets.Client.Managed": "1.0.22",
|
||||
"System.Reactive": "5.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Client.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
|
||||
"dependencies": {
|
||||
"GraphQL.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Client.Abstractions.Websocket": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==",
|
||||
"dependencies": {
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Build.Tasks.Git": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
|
||||
},
|
||||
"Microsoft.CSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.7.0",
|
||||
"contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA=="
|
||||
},
|
||||
"Microsoft.Data.Sqlite": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.5",
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Data.Sqlite.Core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.ComponentModel.Annotations": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.1",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net48": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "zMk4D+9zyiEWByyQ7oPImPN/Jhpj166Ky0Nlla4eXlNL8hI/BtSJsgR8Inldd4NNpIAH3oh8yym0W2DrhXdSLQ=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Speckle.Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.2",
|
||||
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
|
||||
},
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
|
||||
"SQLitePCLRaw.provider.dynamic_cdecl": "2.1.4"
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.3"
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.lib.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
|
||||
},
|
||||
"SQLitePCLRaw.provider.dynamic_cdecl": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "ZsaKKhgYF9B1fvcnOGKl3EycNAwd9CRWX7v0rEfuPWhQQ5Jjpvf2VEHahiLIGHio3hxi3EIKFJw9KvyowWOUAw==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"System.Buffers": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "AwarXzzoDwX6BgrhjoJsk6tUezZEozOT5Y9QKF94Gl4JK91I4PIIBkBco9068Y9/Dra8Dkbie99kXB8+1BaYKw=="
|
||||
},
|
||||
"System.ComponentModel.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.4.0",
|
||||
"System.Numerics.Vectors": "4.4.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.2"
|
||||
}
|
||||
},
|
||||
"System.Net.WebSockets.Client.Managed": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.22",
|
||||
"contentHash": "WqEOxPlXjuZrIjUtXNE9NxEfU/n5E35iV2PtoZdJSUC4tlrqwHnTee+wvMIM4OUaJWmwrymeqcgYrE0IkGAgLA==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.4.0",
|
||||
"System.Numerics.Vectors": "4.4.0"
|
||||
}
|
||||
},
|
||||
"System.Numerics.Vectors": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
|
||||
},
|
||||
"System.Reactive": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
|
||||
"dependencies": {
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3TIsJhD1EiiT0w2CcDMN/iSSwnNnsrnbzeVHSKkaEgV85txMprmuO+Yq2AdSbeVGcg28pdNDTPK87tJhX7VFHw=="
|
||||
},
|
||||
"System.Threading.Tasks.Extensions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.4",
|
||||
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.2.0, )",
|
||||
"Speckle.Sdk": "[3.2.0, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Connectors.Common": "[1.0.0, )",
|
||||
"Speckle.Sdk": "[3.2.0, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui.webview": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Web.WebView2": "[1.0.1938.49, )",
|
||||
"Speckle.Connectors.DUI": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
"type": "Project"
|
||||
},
|
||||
"speckle.converters.autocad2022": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Speckle.AutoCAD.API": "[2022.0.2, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[4.1.0, )",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.2.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.2.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-12
@@ -1,25 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<RootNamespace>Speckle.Connectors.Autocad</RootNamespace>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<UseWpf>true</UseWpf>
|
||||
<StartAction>Program</StartAction>
|
||||
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD 2023\acad.exe</StartProgram>
|
||||
<DefineConstants>$(DefineConstants);AUTOCAD2023;AUTOCAD</DefineConstants>
|
||||
<AutoCADVersion>2023</AutoCADVersion>
|
||||
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2023;AUTOCAD2022_OR_GREATER;AUTOCAD2023_OR_GREATER</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\2023\Speckle.Converters.Autocad2023.DependencyInjection\Speckle.Converters.Autocad2023.DependencyInjection.csproj" />
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2023.0.0" ExcludeAssets="runtime"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2023\Speckle.Converters.Autocad2023.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Autofac\Speckle.Autofac.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Connectors.Utils\Speckle.Connectors.Utils.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Converters.Common.DependencyInjection\Speckle.Converters.Common.DependencyInjection.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Converters.Common\Speckle.Converters.Common.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2023.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems" Label="Shared" />
|
||||
</Project>
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
"version": 2,
|
||||
"dependencies": {
|
||||
".NETFramework,Version=v4.8": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[7.0.0, )",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "kmn78+LPVMOWeITUjIlfxUPDsI0R6G0RkeAMBmQxAJ7vBJn4q2dTva7pWi65ceN5vPGjJ9q/Uae2WKgvfktJAw==",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.5"
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net48": "1.0.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
@@ -36,9 +35,9 @@
|
||||
},
|
||||
"Speckle.InterfaceGenerator": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.9.5, )",
|
||||
"resolved": "0.9.5",
|
||||
"contentHash": "oU/L7pN1R7q8KkbrpQ3WJnHirPHqn+9DEA7asOcUiggV5dzVg1A/VYs7GOSusD24njxXh03tE3a2oTLOjt3cVg=="
|
||||
"requested": "[0.9.6, )",
|
||||
"resolved": "0.9.6",
|
||||
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
|
||||
},
|
||||
"GraphQL.Client": {
|
||||
"type": "Transitive",
|
||||
@@ -74,8 +73,8 @@
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "3aeMZ1N0lJoSyzqiP03hqemtb1BijhsJADdobn/4nsMJ8V1H+CrpuduUe4hlRdx+ikBQju1VGjMD1GJ3Sk05Eg==",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==",
|
||||
"dependencies": {
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
@@ -107,171 +106,64 @@
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "elNeOmkeX3eDVG6pYVeV82p29hr+UKDaBhrZyWvWLw/EVZSYEkZlQdkp0V39k/Xehs2Qa0mvoCvkVj3eQxNQ1Q==",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "7.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0",
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "h3j/QfmFN4S0w4C2A6X7arXij/M/OVw3uQHSOFxnND4DyAzO1F9eMX7Eti7lU/OkSthEE0WzRsfT/Dmx86jzCw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "7.0.0",
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "Nw2muoNrOG5U5qa2ZekXwudUn2BJcD41e65zwmDHb1fQegTX66UokLWZkJRpqSSHXDOWZ5V0iqhbxOEky91atA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "7.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection": "7.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "7.0.0",
|
||||
"Microsoft.Extensions.Options": "7.0.0",
|
||||
"System.Diagnostics.DiagnosticSource": "7.0.0",
|
||||
"System.ValueTuple": "4.5.0"
|
||||
}
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "lP1yBnTTU42cKpMozuafbvNtQ7QcBjr/CcK3bYOGEMH55Fjt+iecXjT6chR7vbgCMqy3PG3aNQSZgo/EuY/9qQ==",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0",
|
||||
"Microsoft.Extensions.Primitives": "7.0.0"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.ComponentModel.Annotations": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "um1KU5kxcRp3CNuI8o/GrZtD4AIOXDk+RLsytjZ9QPok3ttLUelLKpilVPuaFT3TFjOhSibUAso0odbOaCDj3Q==",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.5",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
"System.Memory": "4.5.1",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net48": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "zMk4D+9zyiEWByyQ7oPImPN/Jhpj166Ky0Nlla4eXlNL8hI/BtSJsgR8Inldd4NNpIAH3oh8yym0W2DrhXdSLQ=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Polly": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.2.3",
|
||||
"contentHash": "DeCY0OFbNdNxsjntr1gTXHJ5pKUwYzp04Er2LLeN3g6pWhffsGuKVfMBLe1lw7x76HrPkLxKEFxBlpRxS2nDEQ=="
|
||||
},
|
||||
"Polly.Contrib.WaitAndRetry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.1.1",
|
||||
"contentHash": "1MUQLiSo4KDkQe6nzQRhIU05lm9jlexX5BVsbuw0SL82ynZ+GzAHQxJVDPVBboxV37Po3SG077aX8DuSy8TkaA=="
|
||||
},
|
||||
"Polly.Extensions.Http": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.0",
|
||||
"contentHash": "drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==",
|
||||
"dependencies": {
|
||||
"Polly": "7.1.0"
|
||||
}
|
||||
},
|
||||
"Sentry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.33.0",
|
||||
"contentHash": "8vbD2o6IR2wrRrkSiRbnodWGWUOqIlwYtzpjvPNOb5raJdOf+zxMwfS8f6nx9bmrTTfDj7KrCB8C/5OuicAc8A==",
|
||||
"dependencies": {
|
||||
"System.Reflection.Metadata": "5.0.0",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
|
||||
"System.Text.Json": "5.0.2"
|
||||
}
|
||||
},
|
||||
"Sentry.Serilog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.33.0",
|
||||
"contentHash": "V8BU7QGWg2qLYfNPqtuTBhC1opysny5l+Ifp6J6PhOeAxU0FssR7nYfbJVetrnLIoh2rd3DlJ6hHYYQosQYcUQ==",
|
||||
"dependencies": {
|
||||
"Sentry": "3.33.0",
|
||||
"Serilog": "2.7.1"
|
||||
}
|
||||
},
|
||||
"Serilog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.12.0",
|
||||
"contentHash": "xaiJLIdu6rYMKfQMYUZgTy8YK7SMZjB4Yk50C/u//Z4OsvxkUfSPJy4nknfvwAC34yr13q7kcyh4grbwhSxyZg=="
|
||||
},
|
||||
"Serilog.Enrichers.ClientInfo": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.3.0",
|
||||
"contentHash": "mTc7PM+wC9Hr7LWSwqt5mmnlAr7RJs+eTb3PGPRhwdOackk95MkhUZognuxXEdlW19HAFNmEBTSBY5DfLwM8jQ==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.4.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Exceptions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.4.0",
|
||||
"contentHash": "nc/+hUw3lsdo0zCj0KMIybAu7perMx79vu72w0za9Nsi6mWyNkGXxYxakAjWB7nEmYL6zdmhEQRB4oJ2ALUeug==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.8.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Formatting.Compact": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.1.0",
|
||||
"contentHash": "pNroKVjo+rDqlxNG5PXkRLpfSCuDOBY0ri6jp9PLe505ljqwhwZz8ospy2vWhQlFu5GkIesh3FcDs4n7sWZODA==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.8.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.Console": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "K6N5q+5fetjnJPvCmkWOpJ/V8IEIoMIB1s86OzBrbxwTyHxdx3pmz4H+8+O/Dc/ftUX12DM1aynx/dDowkwzqg==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.File": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.PeriodicBatching": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "NDWR7m3PalVlGEq3rzoktrXikjFMLmpwF0HI4sowo8YDdU+gqPlTHlDQiOGxHfB0sTfjPA9JjA7ctKG9zqjGkw==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.0.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.Seq": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.2.2",
|
||||
"contentHash": "1Csmo5ua7NKUe0yXUx+zsRefjAniPWcXFhUXxXG8pwo0iMiw2gjn9SOkgYnnxbgWqmlGv236w0N/dHc2v5XwMg==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.12.0",
|
||||
"Serilog.Formatting.Compact": "1.1.0",
|
||||
"Serilog.Sinks.File": "5.0.0",
|
||||
"Serilog.Sinks.PeriodicBatching": "3.1.0"
|
||||
}
|
||||
},
|
||||
"SerilogTimings": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "Zs28eTgszAMwpIrbBnWHBI50yuxL50p/dmAUWmy75+axdZYK/Sjm5/5m1N/CisR8acJUhTVcjPZrsB1P5iv0Uw==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.2",
|
||||
@@ -309,42 +201,22 @@
|
||||
},
|
||||
"System.Buffers": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "AwarXzzoDwX6BgrhjoJsk6tUezZEozOT5Y9QKF94Gl4JK91I4PIIBkBco9068Y9/Dra8Dkbie99kXB8+1BaYKw=="
|
||||
},
|
||||
"System.Collections.Immutable": {
|
||||
"System.ComponentModel.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.4"
|
||||
}
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "9W0ewWDuAyDqS2PigdTxk6jDKonfgscY/hP8hm7VpxYhNHZHKvZTdRckberlFk3VnCmr3xBUyMBut12Q+T2aOw==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.5",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.DoubleNumerics": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.3",
|
||||
"contentHash": "KRKEM/L3KBodjA9VOg3EifFVWUY6EOqaMB05UvPEDm7Zeby/kZW+4kdWUEPzW6xtkwf46p661L9NrbeeQhtLzw==",
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.6.1"
|
||||
}
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.5",
|
||||
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Numerics.Vectors": "4.5.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
|
||||
"System.Buffers": "4.4.0",
|
||||
"System.Numerics.Vectors": "4.4.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.2"
|
||||
}
|
||||
},
|
||||
"System.Net.WebSockets.Client.Managed": {
|
||||
@@ -358,8 +230,8 @@
|
||||
},
|
||||
"System.Numerics.Vectors": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
|
||||
},
|
||||
"System.Reactive": {
|
||||
"type": "Transitive",
|
||||
@@ -369,47 +241,10 @@
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
},
|
||||
"System.Reflection.Metadata": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==",
|
||||
"dependencies": {
|
||||
"System.Collections.Immutable": "5.0.0"
|
||||
}
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
|
||||
},
|
||||
"System.Runtime.InteropServices.RuntimeInformation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.3.0",
|
||||
"contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.1",
|
||||
"contentHash": "KmJ+CJXizDofbq6mpqDoRRLcxgOd2z9X3XoFNULSbvbqVRZkFX3istvr+MUjL6Zw1RT+RNdoI4GYidIINtgvqQ==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.4"
|
||||
}
|
||||
},
|
||||
"System.Text.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.2",
|
||||
"contentHash": "I47dVIGiV6SfAyppphxqupertT/5oZkYLDCX6vC3HpOI4ZLjyoKAreUoem2ie6G0RbRuFrlqz/PcTQjfb2DOfQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Numerics.Vectors": "4.5.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "5.0.0",
|
||||
"System.Text.Encodings.Web": "5.0.1",
|
||||
"System.Threading.Tasks.Extensions": "4.5.4",
|
||||
"System.ValueTuple": "4.5.0"
|
||||
}
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3TIsJhD1EiiT0w2CcDMN/iSSwnNnsrnbzeVHSKkaEgV85txMprmuO+Yq2AdSbeVGcg28pdNDTPK87tJhX7VFHw=="
|
||||
},
|
||||
"System.Threading.Tasks.Extensions": {
|
||||
"type": "Transitive",
|
||||
@@ -419,134 +254,119 @@
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
|
||||
}
|
||||
},
|
||||
"System.ValueTuple": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
|
||||
},
|
||||
"speckle.autofac": {
|
||||
"speckle.connectors.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[7.0.0, )"
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.2.0, )",
|
||||
"Speckle.Sdk": "[3.2.0, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[7.0.0, )",
|
||||
"Speckle.Autofac": "[2.0.999-local, )",
|
||||
"Speckle.Connectors.Utils": "[2.0.999-local, )",
|
||||
"Speckle.Core": "[3.0.1-alpha.14, )",
|
||||
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Connectors.Common": "[1.0.0, )",
|
||||
"Speckle.Sdk": "[3.2.0, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui.webview": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Web.WebView2": "[1.0.1823.32, )",
|
||||
"Speckle.Connectors.DUI": "[2.0.999-local, )"
|
||||
"Microsoft.Web.WebView2": "[1.0.1938.49, )",
|
||||
"Speckle.Connectors.DUI": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.utils": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Serilog.Extensions.Logging": "[7.0.0, )",
|
||||
"Speckle.Autofac": "[2.0.999-local, )",
|
||||
"Speckle.Core": "[3.0.1-alpha.14, )"
|
||||
}
|
||||
"speckle.connectors.logging": {
|
||||
"type": "Project"
|
||||
},
|
||||
"speckle.converters.autocad2023": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Speckle.AutoCAD.API": "[2023.0.0, )",
|
||||
"Speckle.Converters.Common": "[2.0.999-local, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.autocad2023.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Autofac": "[5.2.0, )",
|
||||
"Speckle.Converters.Autocad2023": "[2.0.999-local, )",
|
||||
"Speckle.Converters.Common.DependencyInjection": "[2.0.999-local, )"
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Speckle.Autofac": "[2.0.999-local, )",
|
||||
"Speckle.Objects": "[3.0.1-alpha.14, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Speckle.Autofac": "[2.0.999-local, )",
|
||||
"Speckle.Converters.Common": "[2.0.999-local, )"
|
||||
}
|
||||
},
|
||||
"Autofac": {
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[5.2.0, )",
|
||||
"resolved": "5.2.0",
|
||||
"contentHash": "V8dBH0dsv75uDzl7Sw+HkhKDPUw2eXnlMjcSVMH+tLo2s67MpTKGyDj1pDcpR+IF2u4YRs0s3/x7R88YJzIWvg==",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "1.1.0"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1823.32, )",
|
||||
"resolved": "1.0.1823.32",
|
||||
"contentHash": "ppRcWBUNggFIqyJp7PfgS4Oe8/7yli/mHcTNDOaqo3ZzJWnv9AOr0WE9ceEP5SPs1M7CQ3QvdGMR7KNz0v09EA=="
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
},
|
||||
"Serilog.Extensions.Logging": {
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[7.0.0, )",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "9faU0zNQqU7I6soVhLUMYaGNpgWv6cKlKb2S5AnS8gXxzW/em5Ladm/6FMrWTnX41cdbdGPOWNAo6adi4WaJ6A==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging": "7.0.0",
|
||||
"Serilog": "2.12.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Core": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.0.1-alpha.14, )",
|
||||
"resolved": "3.0.1-alpha.14",
|
||||
"contentHash": "RzQPVIGFFkKvG56YLr8ACtiwdWJE6IJ9vCQ4qHa0PIsUEpfzAIAi59jnzqtByOFC0FiFrFPow9bkfzylaZorAA==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Polly": "7.2.3",
|
||||
"Polly.Contrib.WaitAndRetry": "1.1.1",
|
||||
"Polly.Extensions.Http": "3.0.0",
|
||||
"Sentry": "3.33.0",
|
||||
"Sentry.Serilog": "3.33.0",
|
||||
"Serilog": "2.12.0",
|
||||
"Serilog.Enrichers.ClientInfo": "1.3.0",
|
||||
"Serilog.Exceptions": "8.4.0",
|
||||
"Serilog.Sinks.Console": "4.1.0",
|
||||
"Serilog.Sinks.Seq": "5.2.2",
|
||||
"SerilogTimings": "3.0.1",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"System.DoubleNumerics": "3.1.3"
|
||||
}
|
||||
"requested": "[4.1.0, )",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.0.1-alpha.14, )",
|
||||
"resolved": "3.0.1-alpha.14",
|
||||
"contentHash": "z38LGryMvh7iU1uBW+4uo5DwsB3CwRgLt2uFexWFx3mPSid+A0l5XcJzOgLwgFhNl6B42Ryz4ezBsddTp1Uc/g==",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
|
||||
"dependencies": {
|
||||
"Speckle.Core": "3.0.1-alpha.14"
|
||||
"Speckle.Sdk": "3.2.0"
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks.Dataflow": {
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[6.0.0, )",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.2.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<AutoCADVersion>2024</AutoCADVersion>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<UseWpf>true</UseWpf>
|
||||
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2024;AUTOCAD2022_OR_GREATER;AUTOCAD2023_OR_GREATER;AUTOCAD2024_OR_GREATER</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2024.0.0" ExcludeAssets="runtime"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2024\Speckle.Converters.Autocad2024.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Converters.Common\Speckle.Converters.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems" Label="Shared" />
|
||||
</Project>
|
||||
+175
-216
@@ -2,6 +2,15 @@
|
||||
"version": 2,
|
||||
"dependencies": {
|
||||
".NETFramework,Version=v4.8": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net48": "1.0.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
@@ -26,9 +35,9 @@
|
||||
},
|
||||
"Speckle.InterfaceGenerator": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.9.5, )",
|
||||
"resolved": "0.9.5",
|
||||
"contentHash": "oU/L7pN1R7q8KkbrpQ3WJnHirPHqn+9DEA7asOcUiggV5dzVg1A/VYs7GOSusD24njxXh03tE3a2oTLOjt3cVg=="
|
||||
"requested": "[0.9.6, )",
|
||||
"resolved": "0.9.6",
|
||||
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
|
||||
},
|
||||
"GraphQL.Client": {
|
||||
"type": "Transitive",
|
||||
@@ -97,120 +106,64 @@
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.ComponentModel.Annotations": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.1",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net48": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "zMk4D+9zyiEWByyQ7oPImPN/Jhpj166Ky0Nlla4eXlNL8hI/BtSJsgR8Inldd4NNpIAH3oh8yym0W2DrhXdSLQ=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Polly": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.2.3",
|
||||
"contentHash": "DeCY0OFbNdNxsjntr1gTXHJ5pKUwYzp04Er2LLeN3g6pWhffsGuKVfMBLe1lw7x76HrPkLxKEFxBlpRxS2nDEQ=="
|
||||
},
|
||||
"Polly.Contrib.WaitAndRetry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.1.1",
|
||||
"contentHash": "1MUQLiSo4KDkQe6nzQRhIU05lm9jlexX5BVsbuw0SL82ynZ+GzAHQxJVDPVBboxV37Po3SG077aX8DuSy8TkaA=="
|
||||
},
|
||||
"Polly.Extensions.Http": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.0",
|
||||
"contentHash": "drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==",
|
||||
"dependencies": {
|
||||
"Polly": "7.1.0"
|
||||
}
|
||||
},
|
||||
"Sentry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.33.0",
|
||||
"contentHash": "8vbD2o6IR2wrRrkSiRbnodWGWUOqIlwYtzpjvPNOb5raJdOf+zxMwfS8f6nx9bmrTTfDj7KrCB8C/5OuicAc8A==",
|
||||
"dependencies": {
|
||||
"System.Reflection.Metadata": "5.0.0",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
|
||||
"System.Text.Json": "5.0.2"
|
||||
}
|
||||
},
|
||||
"Sentry.Serilog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.33.0",
|
||||
"contentHash": "V8BU7QGWg2qLYfNPqtuTBhC1opysny5l+Ifp6J6PhOeAxU0FssR7nYfbJVetrnLIoh2rd3DlJ6hHYYQosQYcUQ==",
|
||||
"dependencies": {
|
||||
"Sentry": "3.33.0",
|
||||
"Serilog": "2.7.1"
|
||||
}
|
||||
},
|
||||
"Serilog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.12.0",
|
||||
"contentHash": "xaiJLIdu6rYMKfQMYUZgTy8YK7SMZjB4Yk50C/u//Z4OsvxkUfSPJy4nknfvwAC34yr13q7kcyh4grbwhSxyZg=="
|
||||
},
|
||||
"Serilog.Enrichers.ClientInfo": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.3.0",
|
||||
"contentHash": "mTc7PM+wC9Hr7LWSwqt5mmnlAr7RJs+eTb3PGPRhwdOackk95MkhUZognuxXEdlW19HAFNmEBTSBY5DfLwM8jQ==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.4.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Exceptions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.4.0",
|
||||
"contentHash": "nc/+hUw3lsdo0zCj0KMIybAu7perMx79vu72w0za9Nsi6mWyNkGXxYxakAjWB7nEmYL6zdmhEQRB4oJ2ALUeug==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.8.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Formatting.Compact": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.1.0",
|
||||
"contentHash": "pNroKVjo+rDqlxNG5PXkRLpfSCuDOBY0ri6jp9PLe505ljqwhwZz8ospy2vWhQlFu5GkIesh3FcDs4n7sWZODA==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.8.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.Console": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "K6N5q+5fetjnJPvCmkWOpJ/V8IEIoMIB1s86OzBrbxwTyHxdx3pmz4H+8+O/Dc/ftUX12DM1aynx/dDowkwzqg==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.File": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.PeriodicBatching": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "NDWR7m3PalVlGEq3rzoktrXikjFMLmpwF0HI4sowo8YDdU+gqPlTHlDQiOGxHfB0sTfjPA9JjA7ctKG9zqjGkw==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.0.0"
|
||||
}
|
||||
},
|
||||
"Serilog.Sinks.Seq": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.2.2",
|
||||
"contentHash": "1Csmo5ua7NKUe0yXUx+zsRefjAniPWcXFhUXxXG8pwo0iMiw2gjn9SOkgYnnxbgWqmlGv236w0N/dHc2v5XwMg==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.12.0",
|
||||
"Serilog.Formatting.Compact": "1.1.0",
|
||||
"Serilog.Sinks.File": "5.0.0",
|
||||
"Serilog.Sinks.PeriodicBatching": "3.1.0"
|
||||
}
|
||||
},
|
||||
"SerilogTimings": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "Zs28eTgszAMwpIrbBnWHBI50yuxL50p/dmAUWmy75+axdZYK/Sjm5/5m1N/CisR8acJUhTVcjPZrsB1P5iv0Uw==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.2",
|
||||
@@ -248,33 +201,22 @@
|
||||
},
|
||||
"System.Buffers": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "AwarXzzoDwX6BgrhjoJsk6tUezZEozOT5Y9QKF94Gl4JK91I4PIIBkBco9068Y9/Dra8Dkbie99kXB8+1BaYKw=="
|
||||
},
|
||||
"System.Collections.Immutable": {
|
||||
"System.ComponentModel.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.4"
|
||||
}
|
||||
},
|
||||
"System.DoubleNumerics": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.3",
|
||||
"contentHash": "KRKEM/L3KBodjA9VOg3EifFVWUY6EOqaMB05UvPEDm7Zeby/kZW+4kdWUEPzW6xtkwf46p661L9NrbeeQhtLzw==",
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.6.1"
|
||||
}
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.5",
|
||||
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Numerics.Vectors": "4.5.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
|
||||
"System.Buffers": "4.4.0",
|
||||
"System.Numerics.Vectors": "4.4.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.2"
|
||||
}
|
||||
},
|
||||
"System.Net.WebSockets.Client.Managed": {
|
||||
@@ -288,8 +230,8 @@
|
||||
},
|
||||
"System.Numerics.Vectors": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
|
||||
},
|
||||
"System.Reactive": {
|
||||
"type": "Transitive",
|
||||
@@ -299,47 +241,10 @@
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
},
|
||||
"System.Reflection.Metadata": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==",
|
||||
"dependencies": {
|
||||
"System.Collections.Immutable": "5.0.0"
|
||||
}
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "ZD9TMpsmYJLrxbbmdvhwt9YEgG5WntEnZ/d1eH8JBX9LBp+Ju8BSBhUGbZMNVHHomWo2KVImJhTDl2hIgw/6MA=="
|
||||
},
|
||||
"System.Runtime.InteropServices.RuntimeInformation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.3.0",
|
||||
"contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.1",
|
||||
"contentHash": "KmJ+CJXizDofbq6mpqDoRRLcxgOd2z9X3XoFNULSbvbqVRZkFX3istvr+MUjL6Zw1RT+RNdoI4GYidIINtgvqQ==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.4"
|
||||
}
|
||||
},
|
||||
"System.Text.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.2",
|
||||
"contentHash": "I47dVIGiV6SfAyppphxqupertT/5oZkYLDCX6vC3HpOI4ZLjyoKAreUoem2ie6G0RbRuFrlqz/PcTQjfb2DOfQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Numerics.Vectors": "4.5.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "5.0.0",
|
||||
"System.Text.Encodings.Web": "5.0.1",
|
||||
"System.Threading.Tasks.Extensions": "4.5.4",
|
||||
"System.ValueTuple": "4.5.0"
|
||||
}
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3TIsJhD1EiiT0w2CcDMN/iSSwnNnsrnbzeVHSKkaEgV85txMprmuO+Yq2AdSbeVGcg28pdNDTPK87tJhX7VFHw=="
|
||||
},
|
||||
"System.Threading.Tasks.Extensions": {
|
||||
"type": "Transitive",
|
||||
@@ -349,66 +254,120 @@
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
|
||||
}
|
||||
},
|
||||
"System.ValueTuple": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
|
||||
},
|
||||
"speckle.autofac": {
|
||||
"speckle.connectors.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[7.0.0, )"
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.2.0, )",
|
||||
"Speckle.Sdk": "[3.2.0, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Connectors.Common": "[1.0.0, )",
|
||||
"Speckle.Sdk": "[3.2.0, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui.webview": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Web.WebView2": "[1.0.1938.49, )",
|
||||
"Speckle.Connectors.DUI": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
"type": "Project"
|
||||
},
|
||||
"speckle.converters.autocad2024": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Speckle.AutoCAD.API": "[2024.0.0, )",
|
||||
"Speckle.Connectors.DUI.WebView": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Speckle.Autofac": "[2.0.999-local, )",
|
||||
"Speckle.Objects": "[3.0.1-alpha.14, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[7.0.0, )",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "kmn78+LPVMOWeITUjIlfxUPDsI0R6G0RkeAMBmQxAJ7vBJn4q2dTva7pWi65ceN5vPGjJ9q/Uae2WKgvfktJAw==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.5"
|
||||
}
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
|
||||
},
|
||||
"Speckle.Core": {
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.0.1-alpha.14, )",
|
||||
"resolved": "3.0.1-alpha.14",
|
||||
"contentHash": "RzQPVIGFFkKvG56YLr8ACtiwdWJE6IJ9vCQ4qHa0PIsUEpfzAIAi59jnzqtByOFC0FiFrFPow9bkfzylaZorAA==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Polly": "7.2.3",
|
||||
"Polly.Contrib.WaitAndRetry": "1.1.1",
|
||||
"Polly.Extensions.Http": "3.0.0",
|
||||
"Sentry": "3.33.0",
|
||||
"Sentry.Serilog": "3.33.0",
|
||||
"Serilog": "2.12.0",
|
||||
"Serilog.Enrichers.ClientInfo": "1.3.0",
|
||||
"Serilog.Exceptions": "8.4.0",
|
||||
"Serilog.Sinks.Console": "4.1.0",
|
||||
"Serilog.Sinks.Seq": "5.2.2",
|
||||
"SerilogTimings": "3.0.1",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"System.DoubleNumerics": "3.1.3"
|
||||
}
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[4.1.0, )",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.0.1-alpha.14, )",
|
||||
"resolved": "3.0.1-alpha.14",
|
||||
"contentHash": "z38LGryMvh7iU1uBW+4uo5DwsB3CwRgLt2uFexWFx3mPSid+A0l5XcJzOgLwgFhNl6B42Ryz4ezBsddTp1Uc/g==",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
|
||||
"dependencies": {
|
||||
"Speckle.Core": "3.0.1-alpha.14"
|
||||
"Speckle.Sdk": "3.2.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.2.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<AutoCADVersion>2025</AutoCADVersion>
|
||||
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2025;AUTOCAD2022_OR_GREATER;AUTOCAD2023_OR_GREATER;AUTOCAD2024_OR_GREATER;AUTOCAD2025_OR_GREATER</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <!-- .NET Core uses this to move native dependencies into a root for runtime selection and usage for non-windows development https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#enablewindowstargeting -->
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2025.0.0" ExcludeAssets="runtime"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2025\Speckle.Converters.Autocad2025.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Converters.Common\Speckle.Converters.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems" Label="Shared" />
|
||||
</Project>
|
||||
@@ -0,0 +1,342 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dependencies": {
|
||||
"net8.0-windows7.0": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Build.Tasks.Git": "8.0.0",
|
||||
"Microsoft.SourceLink.Common": "8.0.0"
|
||||
}
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.14.1, )",
|
||||
"resolved": "1.14.1",
|
||||
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
|
||||
},
|
||||
"Speckle.AutoCAD.API": {
|
||||
"type": "Direct",
|
||||
"requested": "[2025.0.0, )",
|
||||
"resolved": "2025.0.0",
|
||||
"contentHash": "dqEgZ+bTqAG0tx0WwdnTZcbNKH2igzhOr3SMXtRYai7yIqXiz5btZ4Mf2bmfxbmxLucww3GKVpdZoI+PSZlMuQ=="
|
||||
},
|
||||
"Speckle.InterfaceGenerator": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.9.6, )",
|
||||
"resolved": "0.9.6",
|
||||
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
|
||||
},
|
||||
"GraphQL.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client.Abstractions": "6.0.0",
|
||||
"GraphQL.Client.Abstractions.Websocket": "6.0.0",
|
||||
"System.Reactive": "5.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Client.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
|
||||
"dependencies": {
|
||||
"GraphQL.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Client.Abstractions.Websocket": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
|
||||
},
|
||||
"Microsoft.Build.Tasks.Git": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
|
||||
},
|
||||
"Microsoft.CSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.7.0",
|
||||
"contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA=="
|
||||
},
|
||||
"Microsoft.Data.Sqlite": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.5",
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Data.Sqlite.Core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.ComponentModel.Annotations": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.1",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Speckle.Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.2",
|
||||
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
|
||||
},
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
|
||||
"SQLitePCLRaw.provider.e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.3"
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.lib.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
|
||||
},
|
||||
"SQLitePCLRaw.provider.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"System.ComponentModel.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA=="
|
||||
},
|
||||
"System.Reactive": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
|
||||
},
|
||||
"speckle.connectors.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.2.0, )",
|
||||
"Speckle.Sdk": "[3.2.0, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Connectors.Common": "[1.0.0, )",
|
||||
"Speckle.Sdk": "[3.2.0, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui.webview": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Web.WebView2": "[1.0.1938.49, )",
|
||||
"Speckle.Connectors.DUI": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
"type": "Project"
|
||||
},
|
||||
"speckle.converters.autocad2025": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Speckle.AutoCAD.API": "[2025.0.0, )",
|
||||
"Speckle.Connectors.DUI.WebView": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[4.1.0, )",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.2.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.2.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
"SQLitePCLRaw.lib.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<AutoCADVersion>2026</AutoCADVersion>
|
||||
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2026;AUTOCAD2022_OR_GREATER;AUTOCAD2023_OR_GREATER;AUTOCAD2024_OR_GREATER;AUTOCAD2025_OR_GREATER;AUTOCAD2026_OR_GREATER</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <!-- .NET Core uses this to move native dependencies into a root for runtime selection and usage for non-windows development https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#enablewindowstargeting -->
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2026.0.0" ExcludeAssets="runtime"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2026\Speckle.Converters.Autocad2026.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Converters.Common\Speckle.Converters.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems" Label="Shared" />
|
||||
</Project>
|
||||
@@ -0,0 +1,342 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dependencies": {
|
||||
"net8.0-windows7.0": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Build.Tasks.Git": "8.0.0",
|
||||
"Microsoft.SourceLink.Common": "8.0.0"
|
||||
}
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.14.1, )",
|
||||
"resolved": "1.14.1",
|
||||
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
|
||||
},
|
||||
"Speckle.AutoCAD.API": {
|
||||
"type": "Direct",
|
||||
"requested": "[2026.0.0, )",
|
||||
"resolved": "2026.0.0",
|
||||
"contentHash": "WlkV81PmbK/ftoM7aGpU6LGosKbePBQej9MO/m63rFMozX89tsitEhE12o58wu7K/4FmRUdAMolYtdK20EDBnw=="
|
||||
},
|
||||
"Speckle.InterfaceGenerator": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.9.6, )",
|
||||
"resolved": "0.9.6",
|
||||
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
|
||||
},
|
||||
"GraphQL.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client.Abstractions": "6.0.0",
|
||||
"GraphQL.Client.Abstractions.Websocket": "6.0.0",
|
||||
"System.Reactive": "5.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Client.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
|
||||
"dependencies": {
|
||||
"GraphQL.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Client.Abstractions.Websocket": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
|
||||
},
|
||||
"Microsoft.Build.Tasks.Git": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
|
||||
},
|
||||
"Microsoft.CSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.7.0",
|
||||
"contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA=="
|
||||
},
|
||||
"Microsoft.Data.Sqlite": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.5",
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Data.Sqlite.Core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.ComponentModel.Annotations": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.1",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Speckle.Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.2",
|
||||
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
|
||||
},
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
|
||||
"SQLitePCLRaw.provider.e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.3"
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.lib.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
|
||||
},
|
||||
"SQLitePCLRaw.provider.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"System.ComponentModel.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA=="
|
||||
},
|
||||
"System.Reactive": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
|
||||
},
|
||||
"speckle.connectors.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.2.0, )",
|
||||
"Speckle.Sdk": "[3.2.0, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Connectors.Common": "[1.0.0, )",
|
||||
"Speckle.Sdk": "[3.2.0, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui.webview": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Web.WebView2": "[1.0.1938.49, )",
|
||||
"Speckle.Connectors.DUI": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
"type": "Project"
|
||||
},
|
||||
"speckle.converters.autocad2026": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Speckle.AutoCAD.API": "[2026.0.0, )",
|
||||
"Speckle.Connectors.DUI.WebView": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.2.0, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[4.1.0, )",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.2.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.2.0"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.2.0, )",
|
||||
"resolved": "3.2.0",
|
||||
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
"SQLitePCLRaw.lib.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+72
-33
@@ -1,47 +1,63 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Sentry.Reflection;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Core.Credentials;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Core.Logging;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Credentials;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Bindings;
|
||||
|
||||
public class AutocadBasicConnectorBinding : IBasicConnectorBinding
|
||||
{
|
||||
private readonly IAccountManager _accountManager;
|
||||
public string Name { get; set; } = "baseBinding";
|
||||
public IBridge Parent { get; }
|
||||
public IBrowserBridge Parent { get; }
|
||||
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly AutocadSettings _settings;
|
||||
private readonly ISpeckleApplication _speckleApplication;
|
||||
private readonly IThreadContext _threadContext;
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
private readonly ILogger<AutocadBasicConnectorBinding> _logger;
|
||||
|
||||
public BasicConnectorBindingCommands Commands { get; }
|
||||
|
||||
public AutocadBasicConnectorBinding(DocumentModelStore store, AutocadSettings settings, IBridge parent)
|
||||
public AutocadBasicConnectorBinding(
|
||||
DocumentModelStore store,
|
||||
IBrowserBridge parent,
|
||||
IAccountManager accountManager,
|
||||
ISpeckleApplication speckleApplication,
|
||||
ILogger<AutocadBasicConnectorBinding> logger,
|
||||
IThreadContext threadContext,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_settings = settings;
|
||||
Parent = parent;
|
||||
_accountManager = accountManager;
|
||||
_speckleApplication = speckleApplication;
|
||||
Commands = new BasicConnectorBindingCommands(parent);
|
||||
_logger = logger;
|
||||
_threadContext = threadContext;
|
||||
_topLevelExceptionHandler = topLevelExceptionHandler;
|
||||
_store.DocumentChanged += (_, _) =>
|
||||
{
|
||||
Commands.NotifyDocumentChanged();
|
||||
};
|
||||
_topLevelExceptionHandler.FireAndForget(async () =>
|
||||
{
|
||||
await Commands.NotifyDocumentChanged();
|
||||
});
|
||||
}
|
||||
|
||||
public string GetConnectorVersion() =>
|
||||
typeof(AutocadBasicConnectorBinding).Assembly.GetNameAndVersion().Version ?? "No version";
|
||||
public string GetConnectorVersion() => _speckleApplication.SpeckleVersion;
|
||||
|
||||
public string GetSourceApplicationName() => _settings.HostAppInfo.Slug;
|
||||
public string GetSourceApplicationName() => _speckleApplication.Slug;
|
||||
|
||||
public string GetSourceApplicationVersion() => _settings.HostAppVersion.ToString();
|
||||
public string GetSourceApplicationVersion() => _speckleApplication.HostApplicationVersion;
|
||||
|
||||
public Account[] GetAccounts() => AccountManager.GetAccounts().ToArray();
|
||||
public Account[] GetAccounts() => _accountManager.GetAccounts().ToArray();
|
||||
|
||||
public DocumentInfo? GetDocumentInfo()
|
||||
{
|
||||
@@ -57,23 +73,25 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
|
||||
|
||||
public DocumentModelStore GetDocumentState() => _store;
|
||||
|
||||
public void AddModel(ModelCard model) => _store.Models.Add(model);
|
||||
public void AddModel(ModelCard model) => _store.AddModel(model);
|
||||
|
||||
public void UpdateModel(ModelCard model) => _store.UpdateModel(model);
|
||||
|
||||
public void RemoveModel(ModelCard model) => _store.RemoveModel(model);
|
||||
|
||||
public void HighlightObjects(List<string> objectIds)
|
||||
public void RemoveModels(List<ModelCard> models) => _store.RemoveModels(models);
|
||||
|
||||
public async Task HighlightObjects(IReadOnlyList<string> objectIds)
|
||||
{
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
var doc = Application.DocumentManager.MdiActiveDocument;
|
||||
|
||||
var dbObjects = doc.GetObjects(objectIds);
|
||||
var acadObjectIds = dbObjects.Select(tuple => tuple.Root.Id).ToArray();
|
||||
HighlightObjectsOnView(acadObjectIds);
|
||||
await HighlightObjectsOnView(acadObjectIds);
|
||||
}
|
||||
|
||||
public void HighlightModel(string modelCardId)
|
||||
public async Task HighlightModel(string modelCardId)
|
||||
{
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
var doc = Application.DocumentManager.MdiActiveDocument;
|
||||
@@ -86,14 +104,16 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
|
||||
var objectIds = Array.Empty<ObjectId>();
|
||||
|
||||
var model = _store.GetModelById(modelCardId);
|
||||
|
||||
if (model == null)
|
||||
{
|
||||
_logger.LogError("Model was null when highlighting received model");
|
||||
return;
|
||||
}
|
||||
|
||||
if (model is SenderModelCard senderModelCard)
|
||||
{
|
||||
var dbObjects = doc.GetObjects(senderModelCard.SendFilter.NotNull().GetObjectIds());
|
||||
var dbObjects = doc.GetObjects(senderModelCard.SendFilter.NotNull().RefreshObjectIds());
|
||||
objectIds = dbObjects.Select(tuple => tuple.Root.Id).ToArray();
|
||||
}
|
||||
|
||||
@@ -105,23 +125,33 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
|
||||
|
||||
if (objectIds.Length == 0)
|
||||
{
|
||||
Commands.SetModelError(modelCardId, new OperationCanceledException("No objects found to highlight."));
|
||||
await Commands.SetModelError(modelCardId, new OperationCanceledException("No objects found to highlight."));
|
||||
return;
|
||||
}
|
||||
|
||||
HighlightObjectsOnView(objectIds, modelCardId);
|
||||
await HighlightObjectsOnView(objectIds, modelCardId);
|
||||
}
|
||||
|
||||
private void HighlightObjectsOnView(ObjectId[] objectIds, string? modelCardId = null)
|
||||
private async Task HighlightObjectsOnView(ObjectId[] objectIds, string? modelCardId = null)
|
||||
{
|
||||
var doc = Application.DocumentManager.MdiActiveDocument;
|
||||
|
||||
Parent.RunOnMainThread(() =>
|
||||
await _threadContext.RunOnMainAsync(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
doc.Editor.SetImpliedSelection(Array.Empty<ObjectId>()); // Deselects
|
||||
doc.Editor.SetImpliedSelection(objectIds); // Selects
|
||||
doc.Editor.SetImpliedSelection([]); // Deselects
|
||||
try
|
||||
{
|
||||
doc.Editor.SetImpliedSelection(objectIds);
|
||||
}
|
||||
catch (Exception e) when (!e.IsFatal())
|
||||
{
|
||||
// SWALLOW REASON:
|
||||
// If the objects under the blocks, it won't be able to select them.
|
||||
// If we try, API will throw the invalid input error, because we request something from API that Autocad doesn't
|
||||
// handle it on its current canvas. Block elements only selectable when in its scope.
|
||||
}
|
||||
doc.Editor.UpdateScreen();
|
||||
|
||||
Extents3d selectedExtents = new();
|
||||
@@ -129,10 +159,19 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
|
||||
var tr = doc.TransactionManager.StartTransaction();
|
||||
foreach (ObjectId objectId in objectIds)
|
||||
{
|
||||
var entity = (Entity)tr.GetObject(objectId, OpenMode.ForRead);
|
||||
if (entity != null)
|
||||
try
|
||||
{
|
||||
selectedExtents.AddExtents(entity.GeometricExtents);
|
||||
var entity = (Entity?)tr.GetObject(objectId, OpenMode.ForRead);
|
||||
if (entity?.GeometricExtents != null)
|
||||
{
|
||||
selectedExtents.AddExtents(entity.GeometricExtents);
|
||||
}
|
||||
}
|
||||
catch (Exception e) when (!e.IsFatal())
|
||||
{
|
||||
// Note: we're swallowing exeptions here because of a weird case when receiving blocks, we would have
|
||||
// acad api throw an error on accessing entity.GeometricExtents.
|
||||
// may also throw Autodesk.AutoCAD.Runtime.Exception for invalid extents on objects like rays and xlines
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +183,7 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
|
||||
{
|
||||
if (modelCardId != null)
|
||||
{
|
||||
Commands.SetModelError(modelCardId, new OperationCanceledException("Failed to highlight objects."));
|
||||
await Commands.SetModelError(modelCardId, new OperationCanceledException("Failed to highlight objects."));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Logging;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Sdk;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Bindings;
|
||||
|
||||
public abstract class AutocadReceiveBaseBinding : IReceiveBinding
|
||||
{
|
||||
public string Name => "receiveBinding";
|
||||
public IBrowserBridge Parent { get; }
|
||||
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly ICancellationManager _cancellationManager;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IOperationProgressManager _operationProgressManager;
|
||||
private readonly ILogger<AutocadReceiveBinding> _logger;
|
||||
private readonly ISpeckleApplication _speckleApplication;
|
||||
private readonly IThreadContext _threadContext;
|
||||
|
||||
private ReceiveBindingUICommands Commands { get; }
|
||||
|
||||
protected AutocadReceiveBaseBinding(
|
||||
DocumentModelStore store,
|
||||
IBrowserBridge parent,
|
||||
ICancellationManager cancellationManager,
|
||||
IServiceProvider serviceProvider,
|
||||
IOperationProgressManager operationProgressManager,
|
||||
ILogger<AutocadReceiveBinding> logger,
|
||||
ISpeckleApplication speckleApplication,
|
||||
IThreadContext threadContext
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_cancellationManager = cancellationManager;
|
||||
_serviceProvider = serviceProvider;
|
||||
_operationProgressManager = operationProgressManager;
|
||||
_logger = logger;
|
||||
_speckleApplication = speckleApplication;
|
||||
_threadContext = threadContext;
|
||||
Parent = parent;
|
||||
Commands = new ReceiveBindingUICommands(parent);
|
||||
}
|
||||
|
||||
protected abstract void InitializeSettings(IServiceProvider serviceProvider);
|
||||
|
||||
public void CancelReceive(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
|
||||
public async Task Receive(string modelCardId) =>
|
||||
await _threadContext.RunOnMainAsync(async () => await ReceiveInternal(modelCardId));
|
||||
|
||||
private async Task ReceiveInternal(string modelCardId)
|
||||
{
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
InitializeSettings(scope.ServiceProvider);
|
||||
|
||||
try
|
||||
{
|
||||
// Get receiver card
|
||||
if (_store.GetModelById(modelCardId) is not ReceiverModelCard modelCard)
|
||||
{
|
||||
// Handle as GLOBAL ERROR at BrowserBridge
|
||||
throw new InvalidOperationException("No download model card was found.");
|
||||
}
|
||||
|
||||
using var cancellationItem = _cancellationManager.GetCancellationItem(modelCardId);
|
||||
|
||||
// Disable document activation (document creation and document switch)
|
||||
// Not disabling results in DUI model card being out of sync with the active document
|
||||
// The DocumentActivated event isn't usable probably because it is pushed to back of main thread queue
|
||||
Application.DocumentManager.DocumentActivationEnabled = false;
|
||||
|
||||
// Receive host objects
|
||||
var operationResults = await scope
|
||||
.ServiceProvider.GetRequiredService<ReceiveOperation>()
|
||||
.Execute(
|
||||
modelCard.GetReceiveInfo(_speckleApplication.Slug),
|
||||
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationItem.Token),
|
||||
cancellationItem.Token
|
||||
);
|
||||
|
||||
await Commands.SetModelReceiveResult(
|
||||
modelCardId,
|
||||
operationResults.BakedObjectIds,
|
||||
operationResults.ConversionResults
|
||||
);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything for now!
|
||||
// Idea for later -> when cancel called, create promise from UI to solve it later with this catch block.
|
||||
// So have 3 state on UI -> Cancellation clicked -> Cancelling -> Cancelled
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // UX reasons - we will report operation exceptions as model card error. We may change this later when we have more exception documentation
|
||||
{
|
||||
_logger.LogModelCardHandledError(ex);
|
||||
await Commands.SetModelError(modelCardId, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// reenable document activation
|
||||
Application.DocumentManager.DocumentActivationEnabled = true;
|
||||
|
||||
// regenerate doc to flush graphics, sometimes some objects (ellipses, nurbs curves) do not appear fully visible after receive.
|
||||
// Adding a regen (must be run on main thread) here, but it doesn't seem to work:
|
||||
// it's run on main thread, tried sending the "regen" string to execute, also tried regen after every object bake, but still can't fix.
|
||||
// the objects should appear visible if you manually call the "regen" command after the operation finishes, or click on a view on the view cube which also calls regen.
|
||||
Application.DocumentManager.CurrentDocument.Editor.Regen();
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
-70
@@ -1,87 +1,49 @@
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.Utils.Cancellation;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Converters.Autocad;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Bindings;
|
||||
|
||||
public sealed class AutocadReceiveBinding : IReceiveBinding
|
||||
public sealed class AutocadReceiveBinding : AutocadReceiveBaseBinding
|
||||
{
|
||||
public string Name => "receiveBinding";
|
||||
public IBridge Parent { get; }
|
||||
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly CancellationManager _cancellationManager;
|
||||
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
|
||||
|
||||
public ReceiveBindingUICommands Commands { get; }
|
||||
private readonly IAutocadConversionSettingsFactory _autocadConversionSettingsFactory;
|
||||
|
||||
public AutocadReceiveBinding(
|
||||
DocumentModelStore store,
|
||||
IBridge parent,
|
||||
CancellationManager cancellationManager,
|
||||
IUnitOfWorkFactory unitOfWorkFactory
|
||||
IBrowserBridge parent,
|
||||
ICancellationManager cancellationManager,
|
||||
IServiceProvider serviceProvider,
|
||||
IOperationProgressManager operationProgressManager,
|
||||
ILogger<AutocadReceiveBinding> logger,
|
||||
IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
|
||||
ISpeckleApplication speckleApplication,
|
||||
IThreadContext threadContext
|
||||
)
|
||||
: base(
|
||||
store,
|
||||
parent,
|
||||
cancellationManager,
|
||||
serviceProvider,
|
||||
operationProgressManager,
|
||||
logger,
|
||||
speckleApplication,
|
||||
threadContext
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_cancellationManager = cancellationManager;
|
||||
_unitOfWorkFactory = unitOfWorkFactory;
|
||||
Parent = parent;
|
||||
Commands = new ReceiveBindingUICommands(parent);
|
||||
_autocadConversionSettingsFactory = autocadConversionSettingsFactory;
|
||||
}
|
||||
|
||||
public void CancelReceive(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
|
||||
public async Task Receive(string modelCardId)
|
||||
protected override void InitializeSettings(IServiceProvider serviceProvider)
|
||||
{
|
||||
using var unitOfWork = _unitOfWorkFactory.Resolve<ReceiveOperation>();
|
||||
try
|
||||
{
|
||||
// Get receiver card
|
||||
if (_store.GetModelById(modelCardId) is not ReceiverModelCard modelCard)
|
||||
{
|
||||
// Handle as GLOBAL ERROR at BrowserBridge
|
||||
throw new InvalidOperationException("No download model card was found.");
|
||||
}
|
||||
|
||||
// Init cancellation token source -> Manager also cancel it if exist before
|
||||
CancellationTokenSource cts = _cancellationManager.InitCancellationTokenSource(modelCardId);
|
||||
|
||||
// Disable document activation (document creation and document switch)
|
||||
// Not disabling results in DUI model card being out of sync with the active document
|
||||
// The DocumentActivated event isn't usable probably because it is pushed to back of main thread queue
|
||||
Application.DocumentManager.DocumentActivationEnabled = false;
|
||||
|
||||
// Receive host objects
|
||||
var operationResults = await unitOfWork.Service
|
||||
.Execute(
|
||||
modelCard.AccountId.NotNull(), // POC: I hear -you are saying why we're passing them separately. Not sure pass the DUI3-> Connectors.DUI project dependency to the SDK-> Connector.Utils
|
||||
modelCard.ProjectId.NotNull(),
|
||||
modelCard.ProjectName.NotNull(),
|
||||
modelCard.ModelName.NotNull(),
|
||||
modelCard.SelectedVersionId.NotNull(),
|
||||
cts.Token,
|
||||
(status, progress) =>
|
||||
Commands.SetModelProgress(modelCardId, new ModelCardProgress(modelCardId, status, progress), cts)
|
||||
)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
Commands.SetModelReceiveResult(modelCardId, operationResults.BakedObjectIds, operationResults.ConversionResults);
|
||||
}
|
||||
// Catch here specific exceptions if they related to model card.
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// renable document activation
|
||||
Application.DocumentManager.DocumentActivationEnabled = true;
|
||||
}
|
||||
serviceProvider
|
||||
.GetRequiredService<IConverterSettingsStore<AutocadConversionSettings>>()
|
||||
.Initialize(_autocadConversionSettingsFactory.Create(Application.DocumentManager.CurrentDocument));
|
||||
}
|
||||
}
|
||||
|
||||
+26
-12
@@ -1,23 +1,31 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.EditorInput;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Autodesk.AutoCAD.EditorInput;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Bindings;
|
||||
|
||||
public class AutocadSelectionBinding : ISelectionBinding
|
||||
{
|
||||
private const string SELECTION_EVENT = "setSelection";
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
private readonly IThreadContext _threadContext;
|
||||
private const string SELECTION_EVENT = "setSelection";
|
||||
private readonly HashSet<Document> _visitedDocuments = new();
|
||||
|
||||
public string Name => "selectionBinding";
|
||||
|
||||
public IBridge Parent { get; }
|
||||
public IBrowserBridge Parent { get; }
|
||||
|
||||
public AutocadSelectionBinding(IBridge parent, ITopLevelExceptionHandler topLevelExceptionHandler)
|
||||
public AutocadSelectionBinding(
|
||||
IBrowserBridge parent,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler,
|
||||
IThreadContext threadContext
|
||||
)
|
||||
{
|
||||
_topLevelExceptionHandler = topLevelExceptionHandler;
|
||||
_threadContext = threadContext;
|
||||
Parent = parent;
|
||||
|
||||
// POC: Use here Context for doc. In converters it's OK but we are still lacking to use context into bindings.
|
||||
@@ -40,19 +48,26 @@ public class AutocadSelectionBinding : ISelectionBinding
|
||||
if (!_visitedDocuments.Contains(document))
|
||||
{
|
||||
document.ImpliedSelectionChanged += (_, _) =>
|
||||
_topLevelExceptionHandler.CatchUnhandled(() => Parent.RunOnMainThread(OnSelectionChanged));
|
||||
_topLevelExceptionHandler.FireAndForget(async () => await _threadContext.RunOnMainAsync(OnSelectionChanged));
|
||||
|
||||
_visitedDocuments.Add(document);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSelectionChanged()
|
||||
// NOTE: Autocad 2022 caused problems, so we need to refactor things a bit in here to always store
|
||||
// selection info locally (and get it updated by the event, which we can control to run on the main thread).
|
||||
// Ui requests to GetSelection() should just return this local copy that is kept up to date by the event handler.
|
||||
private SelectionInfo _selectionInfo;
|
||||
|
||||
private async Task OnSelectionChanged()
|
||||
{
|
||||
SelectionInfo selInfo = GetSelection();
|
||||
Parent.Send(SELECTION_EVENT, selInfo);
|
||||
_selectionInfo = GetSelectionInternal();
|
||||
await Parent.Send(SELECTION_EVENT, _selectionInfo);
|
||||
}
|
||||
|
||||
public SelectionInfo GetSelection()
|
||||
public SelectionInfo GetSelection() => _selectionInfo;
|
||||
|
||||
private SelectionInfo GetSelectionInternal()
|
||||
{
|
||||
// POC: Will be addressed to move it into AutocadContext! https://spockle.atlassian.net/browse/CNX-9319
|
||||
Document? doc = Application.DocumentManager.MdiActiveDocument;
|
||||
@@ -60,10 +75,10 @@ public class AutocadSelectionBinding : ISelectionBinding
|
||||
List<string> objectTypes = new();
|
||||
if (doc != null)
|
||||
{
|
||||
using var tr = doc.TransactionManager.StartTransaction();
|
||||
PromptSelectionResult selection = doc.Editor.SelectImplied();
|
||||
if (selection.Status == PromptStatus.OK)
|
||||
{
|
||||
using var tr = doc.TransactionManager.StartTransaction();
|
||||
foreach (SelectedObject obj in selection.Value)
|
||||
{
|
||||
var dbObject = tr.GetObject(obj.ObjectId, OpenMode.ForRead);
|
||||
@@ -72,9 +87,8 @@ public class AutocadSelectionBinding : ISelectionBinding
|
||||
continue;
|
||||
}
|
||||
|
||||
var handleString = dbObject.Handle.Value.ToString();
|
||||
objectTypes.Add(dbObject.GetType().Name);
|
||||
objs.Add(handleString);
|
||||
objs.Add(dbObject.GetSpeckleApplicationId());
|
||||
}
|
||||
|
||||
tr.Commit();
|
||||
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Exceptions;
|
||||
using Speckle.Connectors.DUI.Logging;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Connectors.DUI.Settings;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Bindings;
|
||||
|
||||
[SuppressMessage("ReSharper", "AsyncVoidMethod")]
|
||||
public abstract class AutocadSendBaseBinding : ISendBinding
|
||||
{
|
||||
public string Name => "sendBinding";
|
||||
public SendBindingUICommands Commands { get; }
|
||||
private OperationProgressManager OperationProgressManager { get; }
|
||||
public IBrowserBridge Parent { get; }
|
||||
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly List<ISendFilter> _sendFilters;
|
||||
private readonly ICancellationManager _cancellationManager;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly IOperationProgressManager _operationProgressManager;
|
||||
private readonly ILogger<AutocadSendBinding> _logger;
|
||||
private readonly ISpeckleApplication _speckleApplication;
|
||||
private readonly IThreadContext _threadContext;
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
private readonly IAppIdleManager _idleManager;
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to aggregate the changed objects' id. Note we're using a concurrent dictionary here as the expiry check method is not thread safe, and this was causing problems. See:
|
||||
/// [CNX-202: Unhandled Exception Occurred when receiving in Rhino](https://linear.app/speckle/issue/CNX-202/unhandled-exception-occurred-when-receiving-in-rhino)
|
||||
/// As to why a concurrent dictionary, it's because it's the cheapest/easiest way to do so.
|
||||
/// https://stackoverflow.com/questions/18922985/concurrent-hashsett-in-net-framework
|
||||
/// </summary>
|
||||
private ConcurrentBag<string> ChangedObjectIds { get; set; } = new();
|
||||
|
||||
protected AutocadSendBaseBinding(
|
||||
DocumentModelStore store,
|
||||
IBrowserBridge parent,
|
||||
IEnumerable<ISendFilter> sendFilters,
|
||||
ICancellationManager cancellationManager,
|
||||
IServiceProvider serviceProvider,
|
||||
ISendConversionCache sendConversionCache,
|
||||
IOperationProgressManager operationProgressManager,
|
||||
ILogger<AutocadSendBinding> logger,
|
||||
ISpeckleApplication speckleApplication,
|
||||
IThreadContext threadContext,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler,
|
||||
IAppIdleManager idleManager
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_serviceProvider = serviceProvider;
|
||||
_cancellationManager = cancellationManager;
|
||||
_sendFilters = sendFilters.ToList();
|
||||
_sendConversionCache = sendConversionCache;
|
||||
_operationProgressManager = operationProgressManager;
|
||||
_logger = logger;
|
||||
_speckleApplication = speckleApplication;
|
||||
_threadContext = threadContext;
|
||||
_topLevelExceptionHandler = topLevelExceptionHandler;
|
||||
_idleManager = idleManager;
|
||||
Parent = parent;
|
||||
Commands = new SendBindingUICommands(parent);
|
||||
|
||||
Application.DocumentManager.DocumentActivated += (_, args) =>
|
||||
_topLevelExceptionHandler.CatchUnhandled(() => SubscribeToObjectChanges(args.Document));
|
||||
|
||||
if (Application.DocumentManager.CurrentDocument != null)
|
||||
{
|
||||
// catches the case when autocad just opens up with a blank new doc
|
||||
SubscribeToObjectChanges(Application.DocumentManager.CurrentDocument);
|
||||
}
|
||||
// Since ids of the objects generates from same seed, we should clear the cache always whenever doc swapped.
|
||||
_store.DocumentChanged += (_, _) =>
|
||||
{
|
||||
_sendConversionCache.ClearCache();
|
||||
};
|
||||
}
|
||||
|
||||
private readonly List<string> _docSubsTracker = new();
|
||||
|
||||
private void SubscribeToObjectChanges(Document doc)
|
||||
{
|
||||
if (doc == null || doc.Database == null || _docSubsTracker.Contains(doc.Name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_docSubsTracker.Add(doc.Name);
|
||||
doc.Database.ObjectAppended += (_, e) => OnObjectChanged(e.DBObject);
|
||||
doc.Database.ObjectErased += (_, e) => OnObjectChanged(e.DBObject);
|
||||
doc.Database.ObjectModified += (_, e) => OnObjectChanged(e.DBObject);
|
||||
}
|
||||
|
||||
private void OnObjectChanged(DBObject dbObject) =>
|
||||
_topLevelExceptionHandler.CatchUnhandled(() => OnChangeChangedObjectIds(dbObject));
|
||||
|
||||
private void OnChangeChangedObjectIds(DBObject dBObject)
|
||||
{
|
||||
ChangedObjectIds.Add(dBObject.GetSpeckleApplicationId());
|
||||
_idleManager.SubscribeToIdle(nameof(RunExpirationChecks), async () => await RunExpirationChecks());
|
||||
}
|
||||
|
||||
private async Task RunExpirationChecks()
|
||||
{
|
||||
var senders = _store.GetSenders();
|
||||
List<string> expiredSenderIds = new();
|
||||
|
||||
_sendConversionCache.EvictObjects(ChangedObjectIds);
|
||||
|
||||
foreach (SenderModelCard modelCard in senders)
|
||||
{
|
||||
var intersection = modelCard.SendFilter.NotNull().RefreshObjectIds().Intersect(ChangedObjectIds).ToList();
|
||||
bool isExpired = intersection.Count != 0;
|
||||
if (isExpired)
|
||||
{
|
||||
expiredSenderIds.Add(modelCard.ModelCardId.NotNull());
|
||||
}
|
||||
}
|
||||
|
||||
await Commands.SetModelsExpired(expiredSenderIds);
|
||||
ChangedObjectIds = new();
|
||||
}
|
||||
|
||||
public List<ISendFilter> GetSendFilters() => _sendFilters;
|
||||
|
||||
public List<ICardSetting> GetSendSettings() => [];
|
||||
|
||||
public async Task Send(string modelCardId) =>
|
||||
await _threadContext.RunOnMainAsync(async () => await SendInternal(modelCardId));
|
||||
|
||||
protected abstract void InitializeSettings(IServiceProvider serviceProvider);
|
||||
|
||||
private async Task SendInternal(string modelCardId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_store.GetModelById(modelCardId) is not SenderModelCard modelCard)
|
||||
{
|
||||
// Handle as GLOBAL ERROR at BrowserBridge
|
||||
throw new InvalidOperationException("No publish model card was found.");
|
||||
}
|
||||
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
InitializeSettings(scope.ServiceProvider);
|
||||
|
||||
using var cancellationItem = _cancellationManager.GetCancellationItem(modelCardId);
|
||||
|
||||
// Disable document activation (document creation and document switch)
|
||||
// Not disabling results in DUI model card being out of sync with the active document
|
||||
// The DocumentActivated event isn't usable probably because it is pushed to back of main thread queue
|
||||
Application.DocumentManager.DocumentActivationEnabled = false;
|
||||
|
||||
// Get elements to convert
|
||||
List<AutocadRootObject> autocadObjects = Application.DocumentManager.CurrentDocument.GetObjects(
|
||||
modelCard.SendFilter.NotNull().RefreshObjectIds()
|
||||
);
|
||||
|
||||
if (autocadObjects.Count == 0)
|
||||
{
|
||||
// Handle as CARD ERROR in this function
|
||||
throw new SpeckleSendFilterException("No objects were found to convert. Please update your publish filter!");
|
||||
}
|
||||
|
||||
var sendResult = await scope
|
||||
.ServiceProvider.GetRequiredService<SendOperation<AutocadRootObject>>()
|
||||
.Execute(
|
||||
autocadObjects,
|
||||
modelCard.GetSendInfo(_speckleApplication.ApplicationAndVersion),
|
||||
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationItem.Token),
|
||||
cancellationItem.Token
|
||||
);
|
||||
|
||||
await Commands.SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything for now!
|
||||
// Idea for later -> when cancel called, create promise from UI to solve it later with this catch block.
|
||||
// So have 3 state on UI -> Cancellation clicked -> Cancelling -> Cancelled
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // UX reasons - we will report operation exceptions as model card error. We may change this later when we have more exception documentation
|
||||
{
|
||||
_logger.LogModelCardHandledError(ex);
|
||||
await Commands.SetModelError(modelCardId, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// renable document activation
|
||||
Application.DocumentManager.DocumentActivationEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelSend(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
}
|
||||
+39
-176
@@ -1,196 +1,59 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Connectors.Utils.Cancellation;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.DUI.Exceptions;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Connectors.Utils.Caching;
|
||||
using Speckle.Converters.Autocad;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Bindings;
|
||||
|
||||
public sealed class AutocadSendBinding : ISendBinding
|
||||
public sealed class AutocadSendBinding : AutocadSendBaseBinding
|
||||
{
|
||||
public string Name => "sendBinding";
|
||||
public SendBindingUICommands Commands { get; }
|
||||
public IBridge Parent { get; }
|
||||
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly AutocadIdleManager _idleManager;
|
||||
private readonly List<ISendFilter> _sendFilters;
|
||||
private readonly CancellationManager _cancellationManager;
|
||||
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
|
||||
private readonly AutocadSettings _autocadSettings;
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to aggregate the changed objects' id.
|
||||
/// </summary>
|
||||
private HashSet<string> ChangedObjectIds { get; set; } = new();
|
||||
private readonly IAutocadConversionSettingsFactory _autocadConversionSettingsFactory;
|
||||
|
||||
public AutocadSendBinding(
|
||||
DocumentModelStore store,
|
||||
AutocadIdleManager idleManager,
|
||||
IBridge parent,
|
||||
IBrowserBridge parent,
|
||||
IEnumerable<ISendFilter> sendFilters,
|
||||
CancellationManager cancellationManager,
|
||||
AutocadSettings autocadSettings,
|
||||
IUnitOfWorkFactory unitOfWorkFactory,
|
||||
ICancellationManager cancellationManager,
|
||||
IServiceProvider serviceProvider,
|
||||
ISendConversionCache sendConversionCache,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
IOperationProgressManager operationProgressManager,
|
||||
ILogger<AutocadSendBinding> logger,
|
||||
IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
|
||||
ISpeckleApplication speckleApplication,
|
||||
IThreadContext threadContext,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler,
|
||||
IAppIdleManager appIdleManager
|
||||
)
|
||||
: base(
|
||||
store,
|
||||
parent,
|
||||
sendFilters,
|
||||
cancellationManager,
|
||||
serviceProvider,
|
||||
sendConversionCache,
|
||||
operationProgressManager,
|
||||
logger,
|
||||
speckleApplication,
|
||||
threadContext,
|
||||
topLevelExceptionHandler,
|
||||
appIdleManager
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_idleManager = idleManager;
|
||||
_unitOfWorkFactory = unitOfWorkFactory;
|
||||
_autocadSettings = autocadSettings;
|
||||
_cancellationManager = cancellationManager;
|
||||
_sendFilters = sendFilters.ToList();
|
||||
_sendConversionCache = sendConversionCache;
|
||||
_topLevelExceptionHandler = topLevelExceptionHandler;
|
||||
Parent = parent;
|
||||
Commands = new SendBindingUICommands(parent);
|
||||
|
||||
Application.DocumentManager.DocumentActivated += (_, args) =>
|
||||
topLevelExceptionHandler.CatchUnhandled(() => SubscribeToObjectChanges(args.Document));
|
||||
|
||||
if (Application.DocumentManager.CurrentDocument != null)
|
||||
{
|
||||
// catches the case when autocad just opens up with a blank new doc
|
||||
SubscribeToObjectChanges(Application.DocumentManager.CurrentDocument);
|
||||
}
|
||||
_autocadConversionSettingsFactory = autocadConversionSettingsFactory;
|
||||
}
|
||||
|
||||
private readonly List<string> _docSubsTracker = new();
|
||||
|
||||
private void SubscribeToObjectChanges(Document doc)
|
||||
protected override void InitializeSettings(IServiceProvider serviceProvider)
|
||||
{
|
||||
if (doc == null || doc.Database == null || _docSubsTracker.Contains(doc.Name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_docSubsTracker.Add(doc.Name);
|
||||
doc.Database.ObjectAppended += (_, e) => OnObjectChanged(e.DBObject);
|
||||
doc.Database.ObjectErased += (_, e) => OnObjectChanged(e.DBObject);
|
||||
doc.Database.ObjectModified += (_, e) => OnObjectChanged(e.DBObject);
|
||||
serviceProvider
|
||||
.GetRequiredService<IConverterSettingsStore<AutocadConversionSettings>>()
|
||||
.Initialize(_autocadConversionSettingsFactory.Create(Application.DocumentManager.CurrentDocument));
|
||||
}
|
||||
|
||||
void OnObjectChanged(DBObject dbObject)
|
||||
{
|
||||
_topLevelExceptionHandler.CatchUnhandled(() => OnChangeChangedObjectIds(dbObject));
|
||||
}
|
||||
|
||||
private void OnChangeChangedObjectIds(DBObject dBObject)
|
||||
{
|
||||
ChangedObjectIds.Add(dBObject.Handle.Value.ToString());
|
||||
_idleManager.SubscribeToIdle(RunExpirationChecks);
|
||||
}
|
||||
|
||||
private void RunExpirationChecks()
|
||||
{
|
||||
var senders = _store.GetSenders();
|
||||
string[] objectIdsList = ChangedObjectIds.ToArray();
|
||||
List<string> expiredSenderIds = new();
|
||||
|
||||
_sendConversionCache.EvictObjects(objectIdsList);
|
||||
|
||||
foreach (SenderModelCard modelCard in senders)
|
||||
{
|
||||
var intersection = modelCard.SendFilter.NotNull().GetObjectIds().Intersect(objectIdsList).ToList();
|
||||
bool isExpired = intersection.Count != 0;
|
||||
if (isExpired)
|
||||
{
|
||||
expiredSenderIds.Add(modelCard.ModelCardId.NotNull());
|
||||
}
|
||||
}
|
||||
|
||||
Commands.SetModelsExpired(expiredSenderIds);
|
||||
ChangedObjectIds = new HashSet<string>();
|
||||
}
|
||||
|
||||
public List<ISendFilter> GetSendFilters() => _sendFilters;
|
||||
|
||||
public Task Send(string modelCardId)
|
||||
{
|
||||
Parent.RunOnMainThread(async () => await SendInternal(modelCardId).ConfigureAwait(false));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task SendInternal(string modelCardId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_store.GetModelById(modelCardId) is not SenderModelCard modelCard)
|
||||
{
|
||||
// Handle as GLOBAL ERROR at BrowserBridge
|
||||
throw new InvalidOperationException("No publish model card was found.");
|
||||
}
|
||||
|
||||
using var uow = _unitOfWorkFactory.Resolve<SendOperation<AutocadRootObject>>();
|
||||
|
||||
// Init cancellation token source -> Manager also cancel it if exist before
|
||||
CancellationTokenSource cts = _cancellationManager.InitCancellationTokenSource(modelCardId);
|
||||
|
||||
// Disable document activation (document creation and document switch)
|
||||
// Not disabling results in DUI model card being out of sync with the active document
|
||||
// The DocumentActivated event isn't usable probably because it is pushed to back of main thread queue
|
||||
Application.DocumentManager.DocumentActivationEnabled = false;
|
||||
|
||||
// Get elements to convert
|
||||
List<AutocadRootObject> autocadObjects = Application.DocumentManager.CurrentDocument.GetObjects(
|
||||
modelCard.SendFilter.NotNull().GetObjectIds()
|
||||
);
|
||||
|
||||
if (autocadObjects.Count == 0)
|
||||
{
|
||||
// Handle as CARD ERROR in this function
|
||||
throw new SpeckleSendFilterException("No objects were found to convert. Please update your publish filter!");
|
||||
}
|
||||
|
||||
var sendInfo = new SendInfo(
|
||||
modelCard.AccountId.NotNull(),
|
||||
modelCard.ProjectId.NotNull(),
|
||||
modelCard.ModelId.NotNull(),
|
||||
_autocadSettings.HostAppInfo.Name
|
||||
);
|
||||
|
||||
var sendResult = await uow.Service
|
||||
.Execute(
|
||||
autocadObjects,
|
||||
sendInfo,
|
||||
(status, progress) =>
|
||||
Commands.SetModelProgress(modelCardId, new ModelCardProgress(modelCardId, status, progress), cts),
|
||||
cts.Token
|
||||
)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
Commands.SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults);
|
||||
}
|
||||
// Catch here specific exceptions if they related to model card.
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything
|
||||
return;
|
||||
}
|
||||
catch (SpeckleSendFilterException e)
|
||||
{
|
||||
Commands.SetModelError(modelCardId, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// renable document activation
|
||||
Application.DocumentManager.DocumentActivationEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelSend(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
}
|
||||
|
||||
+15
-54
@@ -1,69 +1,30 @@
|
||||
#if AUTOCAD
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Speckle.Autofac;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.Autocad.Bindings;
|
||||
using Speckle.Connectors.Autocad.Filters;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Autocad.Interfaces;
|
||||
using Speckle.Connectors.Autocad.Operations.Receive;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.Autocad.Plugin;
|
||||
using Speckle.Connectors.DUI;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Connectors.DUI.WebView;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Connectors.Utils.Builders;
|
||||
using Speckle.Connectors.Utils.Caching;
|
||||
using Speckle.Connectors.Utils.Instances;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Core.Models.GraphTraversal;
|
||||
using Speckle.Sdk;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.DependencyInjection;
|
||||
|
||||
public class AutocadConnectorModule : ISpeckleModule
|
||||
public static class AutocadConnectorModule
|
||||
{
|
||||
public void Load(SpeckleContainerBuilder builder)
|
||||
public static void AddAutocad(this IServiceCollection serviceCollection)
|
||||
{
|
||||
builder.AddAutofac();
|
||||
builder.AddConnectorUtils();
|
||||
builder.AddDUI();
|
||||
builder.AddDUIView();
|
||||
serviceCollection.AddAutocadBase();
|
||||
|
||||
// Register other connector specific types
|
||||
builder.AddSingleton<IAutocadPlugin, AutocadPlugin>();
|
||||
builder.AddTransient<TransactionContext>();
|
||||
builder.AddSingleton(new AutocadDocumentManager()); // TODO: Dependent to TransactionContext, can be moved to AutocadContext
|
||||
builder.AddSingleton<DocumentModelStore, AutocadDocumentStore>();
|
||||
builder.AddSingleton<AutocadContext>();
|
||||
builder.AddSingleton<AutocadIdleManager>();
|
||||
// Send
|
||||
serviceCollection.LoadSend();
|
||||
serviceCollection.AddScoped<IRootObjectBuilder<AutocadRootObject>, AutocadRootObjectBuilder>();
|
||||
|
||||
SharedConnectorModule.LoadShared(builder);
|
||||
// Receive
|
||||
serviceCollection.LoadReceive();
|
||||
|
||||
|
||||
builder.AddScoped<AutocadLayerManager>();
|
||||
|
||||
// Operations
|
||||
builder.AddScoped<SendOperation<AutocadRootObject>>();
|
||||
builder.AddSingleton(DefaultTraversal.CreateTraversalFunc());
|
||||
|
||||
// Object Builders
|
||||
builder.AddScoped<IHostObjectBuilder, AutocadHostObjectBuilder>();
|
||||
builder.AddScoped<IRootObjectBuilder<AutocadRootObject>, AutocadRootObjectBuilder>();
|
||||
|
||||
// Register bindings
|
||||
builder.AddSingleton<IBinding, ConfigBinding>("connectorName", "Autocad"); // POC: Easier like this for now, should be cleaned up later
|
||||
builder.AddSingleton<IBinding, AutocadSendBinding>();
|
||||
builder.AddSingleton<IBinding, AutocadReceiveBinding>();
|
||||
|
||||
// register send filters
|
||||
builder.AddTransient<ISendFilter, AutocadSelectionFilter>();
|
||||
|
||||
// register send conversion cache
|
||||
builder.AddSingleton<ISendConversionCache, SendConversionCache>();
|
||||
builder.AddScoped<IInstanceObjectsManager<AutocadRootObject, List<Entity>>, AutocadInstanceObjectManager>();
|
||||
// Register vertical specific bindings
|
||||
serviceCollection.AddSingleton<IBinding, AutocadSendBinding>();
|
||||
serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetExecutingAssembly());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+8
-26
@@ -1,37 +1,19 @@
|
||||
#if CIVIL3D
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.Autocad.Bindings;
|
||||
using Speckle.Connectors.Autocad.Filters;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Connectors.Utils.Builders;
|
||||
using Speckle.Connectors.Utils.Caching;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.DependencyInjection;
|
||||
|
||||
public class Civil3dConnectorModule : ISpeckleModule
|
||||
public static class Civil3dConnectorModule
|
||||
{
|
||||
public void Load(SpeckleContainerBuilder builder)
|
||||
public static void AddCivil3d(this IServiceCollection serviceCollection)
|
||||
{
|
||||
SharedConnectorModule.LoadShared(builder);
|
||||
serviceCollection.AddAutocadBase();
|
||||
|
||||
// Operations
|
||||
builder.AddScoped<SendOperation<AutocadRootObject>>();
|
||||
|
||||
// Object Builders
|
||||
builder.AddScoped<IRootObjectBuilder<AutocadRootObject>, AutocadRootObjectBuilder>();
|
||||
|
||||
// Register bindings
|
||||
builder.AddSingleton<IBinding, ConfigBinding>("connectorName", "Civil3d"); // POC: Easier like this for now, should be cleaned up later
|
||||
builder.AddSingleton<IBinding, AutocadSendBinding>();
|
||||
|
||||
// register send filters
|
||||
builder.AddTransient<ISendFilter, AutocadSelectionFilter>();
|
||||
|
||||
// register send conversion cache
|
||||
builder.AddSingleton<ISendConversionCache, SendConversionCache>();
|
||||
// send
|
||||
serviceCollection.LoadSend();
|
||||
serviceCollection.AddScoped<IRootObjectBuilder<AutocadRootObject>, Civil3dRootObjectBuilder>();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.Autocad.Bindings;
|
||||
using Speckle.Connectors.Autocad.Filters;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Autocad.Operations.Receive;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.Common;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Connectors.DUI.WebView;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.DependencyInjection;
|
||||
|
||||
public static class SharedRegistration
|
||||
{
|
||||
public static void AddAutocadBase(this IServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddConnectors();
|
||||
serviceCollection.AddDUI<DefaultThreadContext, AutocadDocumentStore>();
|
||||
serviceCollection.AddDUIView();
|
||||
|
||||
// Register other connector specific types
|
||||
serviceCollection.AddTransient<TransactionContext>();
|
||||
serviceCollection.AddSingleton(new AutocadDocumentManager()); // TODO: Dependent to TransactionContext, can be moved to AutocadContext
|
||||
serviceCollection.AddSingleton<AutocadContext>();
|
||||
|
||||
// Unpackers and builders
|
||||
serviceCollection.AddScoped<AutocadLayerUnpacker>();
|
||||
serviceCollection.AddScoped<AutocadLayerBaker>();
|
||||
|
||||
serviceCollection.AddScoped<AutocadInstanceUnpacker>();
|
||||
serviceCollection.AddScoped<AutocadInstanceBaker>();
|
||||
|
||||
serviceCollection.AddScoped<AutocadGroupUnpacker>();
|
||||
serviceCollection.AddScoped<AutocadGroupBaker>();
|
||||
|
||||
serviceCollection.AddScoped<AutocadColorUnpacker>();
|
||||
serviceCollection.AddScoped<IAutocadColorBaker, AutocadColorBaker>();
|
||||
|
||||
serviceCollection.AddScoped<AutocadMaterialUnpacker>();
|
||||
serviceCollection.AddScoped<IAutocadMaterialBaker, AutocadMaterialBaker>();
|
||||
|
||||
serviceCollection.AddSingleton<IAppIdleManager, AutocadIdleManager>();
|
||||
|
||||
// operation progress manager
|
||||
serviceCollection.AddSingleton<IOperationProgressManager, OperationProgressManager>();
|
||||
|
||||
// Register bindings
|
||||
serviceCollection.AddSingleton<IBinding, TestBinding>();
|
||||
serviceCollection.AddSingleton<IBinding, AccountBinding>();
|
||||
serviceCollection.AddSingleton<IBinding, AutocadSelectionBinding>();
|
||||
serviceCollection.AddSingleton<IBinding>(sp => sp.GetRequiredService<IBasicConnectorBinding>());
|
||||
serviceCollection.AddSingleton<IBasicConnectorBinding, AutocadBasicConnectorBinding>();
|
||||
serviceCollection.AddSingleton<IBinding, ConfigBinding>();
|
||||
}
|
||||
|
||||
public static void LoadSend(this IServiceCollection serviceCollection)
|
||||
{
|
||||
// Operations
|
||||
serviceCollection.AddScoped<SendOperation<AutocadRootObject>>();
|
||||
|
||||
// register send filters
|
||||
serviceCollection.AddTransient<ISendFilter, AutocadSelectionFilter>();
|
||||
|
||||
// register send conversion cache
|
||||
serviceCollection.AddSingleton<ISendConversionCache, SendConversionCache>();
|
||||
serviceCollection.AddScoped<
|
||||
IInstanceObjectsManager<AutocadRootObject, List<Entity>>,
|
||||
InstanceObjectsManager<AutocadRootObject, List<Entity>>
|
||||
>();
|
||||
}
|
||||
|
||||
public static void LoadReceive(this IServiceCollection serviceCollection)
|
||||
{
|
||||
// traversal
|
||||
serviceCollection.AddSingleton(DefaultTraversal.CreateTraversalFunc());
|
||||
|
||||
// Object Builders
|
||||
serviceCollection.AddScoped<IHostObjectBuilder, AutocadHostObjectBuilder>();
|
||||
|
||||
// Register bindings
|
||||
serviceCollection.AddSingleton<IBinding, AutocadReceiveBinding>();
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -4,7 +4,10 @@ namespace Speckle.Connectors.Autocad.Filters;
|
||||
|
||||
public class AutocadSelectionFilter : DirectSelectionSendFilter
|
||||
{
|
||||
public override List<string> GetObjectIds() => SelectedObjectIds;
|
||||
public AutocadSelectionFilter()
|
||||
{
|
||||
IsDefault = true;
|
||||
}
|
||||
|
||||
public override bool CheckExpiry(string[] changedObjectIds) => SelectedObjectIds.Intersect(changedObjectIds).Any();
|
||||
public override List<string> RefreshObjectIds() => SelectedObjectIds;
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
global using Document = Autodesk.AutoCAD.ApplicationServices.Document;
|
||||
global using Application = Autodesk.AutoCAD.ApplicationServices.Core.Application;
|
||||
global using Document = Autodesk.AutoCAD.ApplicationServices.Document;
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
using Autodesk.AutoCAD.Colors;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.InterfaceGenerator;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency for a given operation and helps with layer creation and cleanup.
|
||||
/// </summary>
|
||||
[GenerateAutoInterface]
|
||||
public class AutocadColorBaker(ILogger<AutocadColorBaker> logger) : IAutocadColorBaker
|
||||
{
|
||||
/// <summary>
|
||||
/// For receive operations
|
||||
/// </summary>
|
||||
public Dictionary<string, AutocadColor> ObjectColorsIdMap { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Parse Color Proxies and stores in ObjectColorIdMap the relationship between object ids and colors
|
||||
/// </summary>
|
||||
/// <param name="colorProxies"></param>
|
||||
/// <param name="onOperationProgressed"></param>
|
||||
public void ParseColors(IReadOnlyCollection<ColorProxy> colorProxies, IProgress<CardProgress> onOperationProgressed)
|
||||
{
|
||||
var count = 0;
|
||||
foreach (ColorProxy colorProxy in colorProxies)
|
||||
{
|
||||
try
|
||||
{
|
||||
onOperationProgressed.Report(new("Converting colors", (double)++count / colorProxies.Count));
|
||||
|
||||
// skip any colors with source = layer, since object color default source is by layer
|
||||
if (colorProxy["source"] is string source && source == "layer")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (string objectId in colorProxy.objects)
|
||||
{
|
||||
AutocadColor convertedColor = ConvertColorProxyToColor(colorProxy);
|
||||
#if NET8_0
|
||||
ObjectColorsIdMap.TryAdd(objectId, convertedColor);
|
||||
#else
|
||||
if (!ObjectColorsIdMap.ContainsKey(objectId))
|
||||
{
|
||||
ObjectColorsIdMap.Add(objectId, convertedColor);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
logger.LogError(ex, "Failed parsing color proxy");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AutocadColor ConvertColorProxyToColor(ColorProxy colorProxy)
|
||||
{
|
||||
// if source = block, return a default ByBlock color
|
||||
if (colorProxy["source"] is string source && source == "block")
|
||||
{
|
||||
return AutocadColor.FromColorIndex(ColorMethod.ByBlock, 0);
|
||||
}
|
||||
|
||||
return colorProxy["autocadColorIndex"] is long index
|
||||
? AutocadColor.FromColorIndex(ColorMethod.ByAci, (short)index)
|
||||
: AutocadColor.FromColor(System.Drawing.Color.FromArgb(colorProxy.value));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
using Autodesk.AutoCAD.Colors;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency for a given operation and helps with layer creation and cleanup.
|
||||
/// </summary>
|
||||
public class AutocadColorUnpacker
|
||||
{
|
||||
private readonly ILogger<AutocadColorUnpacker> _logger;
|
||||
|
||||
public AutocadColorUnpacker(ILogger<AutocadColorUnpacker> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For send operations
|
||||
/// </summary>
|
||||
private Dictionary<string, ColorProxy> ColorProxies { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Iterates through a given set of autocad objects and layers to collect colors.
|
||||
/// </summary>
|
||||
/// <param name="unpackedAutocadRootObjects">atomic root objects, including instance objects</param>
|
||||
/// <param name="layers">layers used by atomic objects</param>
|
||||
/// <returns></returns>
|
||||
public List<ColorProxy> UnpackColors(
|
||||
List<AutocadRootObject> unpackedAutocadRootObjects,
|
||||
List<LayerTableRecord> layers
|
||||
)
|
||||
{
|
||||
// Stage 1: unpack colors from objects
|
||||
foreach (AutocadRootObject rootObj in unpackedAutocadRootObjects)
|
||||
{
|
||||
try
|
||||
{
|
||||
Entity entity = rootObj.Root;
|
||||
ProcessObjectColor(rootObj.ApplicationId, entity.Color);
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to unpack colors from Autocad Entity");
|
||||
}
|
||||
}
|
||||
|
||||
// Stage 2: make sure we collect layer colors as well
|
||||
foreach (LayerTableRecord layer in layers)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessObjectColor(layer.GetSpeckleApplicationId(), layer.Color);
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to unpack colors from Autocad Layer");
|
||||
}
|
||||
}
|
||||
|
||||
return ColorProxies.Values.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes an object's color and adds the object id to a color proxy in <see cref="ColorProxies"/> if object color is set ByAci, ByColor, or ByBlock.
|
||||
/// Skips processing ByPen for now, because I don't understand what this means.
|
||||
/// </summary>
|
||||
/// <param name="objectId"></param>
|
||||
/// <param name="color"></param>
|
||||
/// <remarks>Skips processing object colors if it is "ByLayer" since autocad commits are structured by layer and by default sets the color by layer on receive. If this ever changes, then we do need to start processing object colors by layer.</remarks>
|
||||
private void ProcessObjectColor(string objectId, AutocadColor color)
|
||||
{
|
||||
switch (color.ColorMethod)
|
||||
{
|
||||
case ColorMethod.ByAci:
|
||||
case ColorMethod.ByColor:
|
||||
case ColorMethod.ByBlock:
|
||||
AddObjectIdToColorProxy(objectId, color);
|
||||
break;
|
||||
case ColorMethod.ByLayer: // skipping these since autocad commits are structured by layer. Will need to be updated if this ever changes!!
|
||||
case ColorMethod.ByPen: // POC: no idea what this means
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddObjectIdToColorProxy(string objectId, AutocadColor color)
|
||||
{
|
||||
string colorId = color.GetSpeckleApplicationId();
|
||||
if (ColorProxies.TryGetValue(colorId, out ColorProxy? proxy))
|
||||
{
|
||||
proxy.objects.Add(objectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
ColorProxy newColor = ConvertColorToColorProxy(color);
|
||||
newColor.objects.Add(objectId);
|
||||
ColorProxies[colorId] = newColor;
|
||||
}
|
||||
}
|
||||
|
||||
private ColorProxy ConvertColorToColorProxy(AutocadColor color)
|
||||
{
|
||||
int argb = color.ColorValue.ToArgb();
|
||||
string name = color.ColorNameForDisplay;
|
||||
string id = color.GetSpeckleApplicationId();
|
||||
|
||||
ColorProxy colorProxy =
|
||||
new()
|
||||
{
|
||||
value = argb,
|
||||
applicationId = id,
|
||||
name = name,
|
||||
objects = new()
|
||||
};
|
||||
|
||||
// add the color source as well for receiving in other apps
|
||||
// POC: in order to support full fidelity color support across autocad and rhino, we need to keep track of the color source property. Not sure if this is the best place to keep track of the source, vs on a ColorSourceProxy or as a property on the atomic object.
|
||||
colorProxy["source"] = color.IsByBlock
|
||||
? "block"
|
||||
: color.IsByLayer
|
||||
? "layer"
|
||||
: "object";
|
||||
|
||||
// set additional properties if by aci or by block
|
||||
// ByBlock colors for some reason do not have their color value set to the correct color (white): instead it's a near-black
|
||||
// ByACI is an Autocad internal index for set rgb values, which effects name presentation, see: https://gohtx.com/acadcolors.php
|
||||
if (color.IsByAci)
|
||||
{
|
||||
colorProxy["autocadColorIndex"] = (int)color.ColorIndex;
|
||||
}
|
||||
else if (color.IsByBlock)
|
||||
{
|
||||
colorProxy.value = -1;
|
||||
}
|
||||
|
||||
return colorProxy;
|
||||
}
|
||||
}
|
||||
+15
-16
@@ -1,25 +1,26 @@
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Newtonsoft.Json;
|
||||
using Speckle.Connectors.DUI.Utils;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
public class AutocadDocumentStore : DocumentModelStore
|
||||
{
|
||||
private readonly string _nullDocumentName = "Null Doc";
|
||||
private const string NULL_DOCUMENT_NAME = "Null Doc";
|
||||
private string _previousDocName;
|
||||
private readonly AutocadDocumentManager _autocadDocumentManager;
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
|
||||
public AutocadDocumentStore(
|
||||
JsonSerializerSettings jsonSerializerSettings,
|
||||
IJsonSerializer jsonSerializer,
|
||||
AutocadDocumentManager autocadDocumentManager,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
)
|
||||
: base(jsonSerializerSettings, true)
|
||||
: base(jsonSerializer)
|
||||
{
|
||||
_autocadDocumentManager = autocadDocumentManager;
|
||||
_previousDocName = _nullDocumentName;
|
||||
_topLevelExceptionHandler = topLevelExceptionHandler;
|
||||
_previousDocName = NULL_DOCUMENT_NAME;
|
||||
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
if (Application.DocumentManager.MdiActiveDocument != null)
|
||||
@@ -41,39 +42,38 @@ public class AutocadDocumentStore : DocumentModelStore
|
||||
|
||||
private void OnDocChangeInternal(Document? doc)
|
||||
{
|
||||
var currentDocName = doc != null ? doc.Name : _nullDocumentName;
|
||||
var currentDocName = doc != null ? doc.Name : NULL_DOCUMENT_NAME;
|
||||
if (_previousDocName == currentDocName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_previousDocName = currentDocName;
|
||||
ReadFromFile();
|
||||
LoadState();
|
||||
OnDocumentChanged();
|
||||
}
|
||||
|
||||
public override void ReadFromFile()
|
||||
protected override void LoadState()
|
||||
{
|
||||
Models = new();
|
||||
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
Document? doc = Application.DocumentManager.MdiActiveDocument;
|
||||
|
||||
if (doc == null)
|
||||
{
|
||||
ClearAndSave();
|
||||
return;
|
||||
}
|
||||
|
||||
string? serializedModelCards = _autocadDocumentManager.ReadModelCards(doc);
|
||||
if (serializedModelCards == null)
|
||||
{
|
||||
ClearAndSave();
|
||||
return;
|
||||
}
|
||||
|
||||
Models = Deserialize(serializedModelCards).NotNull();
|
||||
LoadFromString(serializedModelCards);
|
||||
}
|
||||
|
||||
public override void WriteToFile()
|
||||
protected override void HostAppSaveState(string modelCardState)
|
||||
{
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
Document doc = Application.DocumentManager.MdiActiveDocument;
|
||||
@@ -83,7 +83,6 @@ public class AutocadDocumentStore : DocumentModelStore
|
||||
return;
|
||||
}
|
||||
|
||||
string modelCardsString = Serialize();
|
||||
_autocadDocumentManager.WriteModelCards(doc, modelCardsString);
|
||||
_autocadDocumentManager.WriteModelCards(doc, modelCardState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Dependencies;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// This resource expects to be injected "fresh" in each receive operation (scoped lifetime).
|
||||
/// Extracts group information from a set of objects into proxies in send operations; also creates groups from a set of proxies in receive operations.
|
||||
/// TODO: Oguzhan! Check whats happening on second receive unless purge groups? naming etc..
|
||||
/// </summary>
|
||||
public class AutocadGroupBaker
|
||||
{
|
||||
private readonly ILogger<AutocadGroupBaker> _logger;
|
||||
private readonly AutocadContext _autocadContext;
|
||||
|
||||
public AutocadGroupBaker(AutocadContext autocadContext, ILogger<AutocadGroupBaker> logger)
|
||||
{
|
||||
_autocadContext = autocadContext;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates groups in the host app from a set of group proxies. Can be called after the bake operation of all atomic objects (including instances) is complete.
|
||||
/// </summary>
|
||||
/// <param name="groupProxies"></param>
|
||||
/// <param name="applicationIdMap"></param>
|
||||
/// <returns></returns>
|
||||
// TODO: Oguzhan! Do not report here too! But this is TBD that we don't know the shape of the report yet.
|
||||
public IReadOnlyCollection<ReceiveConversionResult> CreateGroups(
|
||||
IEnumerable<GroupProxy> groupProxies,
|
||||
Dictionary<string, IReadOnlyCollection<Entity>> applicationIdMap
|
||||
)
|
||||
{
|
||||
HashSet<ReceiveConversionResult> results = new();
|
||||
|
||||
using var groupCreationTransaction =
|
||||
Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
var groupDictionary = (DBDictionary)
|
||||
groupCreationTransaction.GetObject(
|
||||
Application.DocumentManager.CurrentDocument.Database.GroupDictionaryId,
|
||||
OpenMode.ForWrite
|
||||
);
|
||||
|
||||
foreach (var gp in groupProxies.OrderBy(group => group.objects.Count))
|
||||
{
|
||||
try
|
||||
{
|
||||
var entities = gp.objects.SelectMany(oldObjId => applicationIdMap[oldObjId]);
|
||||
var ids = new ObjectIdCollection();
|
||||
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
ids.Add(entity.ObjectId);
|
||||
}
|
||||
|
||||
var groupName = _autocadContext.RemoveInvalidChars(gp.name);
|
||||
var newGroup = new Group(groupName, true); // NOTE: this constructor sets both the description (as it says) but also the name at the same time
|
||||
newGroup.Append(ids);
|
||||
|
||||
groupDictionary.UpgradeOpen();
|
||||
groupDictionary.SetAt(groupName, newGroup);
|
||||
|
||||
groupCreationTransaction.AddNewlyCreatedDBObject(newGroup, true);
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
results.Add(new ReceiveConversionResult(Status.ERROR, gp, null, null, ex));
|
||||
_logger.LogError(ex, "Failed to bake Autocad Group");
|
||||
}
|
||||
}
|
||||
|
||||
groupCreationTransaction.Commit();
|
||||
|
||||
return results.Freeze();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// This resource expects to be injected "fresh" in each send/receive operation (scoped lifetime). Extracts group information from a set of objects into proxies in send operations; also creates groups from a set of proxies in receive operations.
|
||||
/// </summary>
|
||||
public class AutocadGroupUnpacker
|
||||
{
|
||||
private readonly ILogger<AutocadGroupUnpacker> _logger;
|
||||
|
||||
public AutocadGroupUnpacker(ILogger<AutocadGroupUnpacker> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpacks a selection of atomic objects into their groups
|
||||
/// </summary>
|
||||
/// <param name="autocadObjects"></param>
|
||||
/// <returns></returns>
|
||||
public List<GroupProxy> UnpackGroups(IEnumerable<AutocadRootObject> autocadObjects)
|
||||
{
|
||||
var groupProxies = new Dictionary<string, GroupProxy>();
|
||||
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
foreach (var (dbObject, applicationId) in autocadObjects)
|
||||
{
|
||||
try
|
||||
{
|
||||
var persistentReactorIds = dbObject.GetPersistentReactorIds();
|
||||
foreach (ObjectId oReactorId in persistentReactorIds)
|
||||
{
|
||||
var obj = transaction.GetObject(oReactorId, OpenMode.ForRead);
|
||||
if (obj is not Group group)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var groupAppId = group.GetSpeckleApplicationId();
|
||||
if (groupProxies.TryGetValue(groupAppId, out GroupProxy? groupProxy))
|
||||
{
|
||||
groupProxy.objects.Add(applicationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
groupProxies[groupAppId] = new()
|
||||
{
|
||||
applicationId = groupAppId,
|
||||
name = group.Name,
|
||||
objects = [applicationId]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed on unpacking Autocad group");
|
||||
}
|
||||
}
|
||||
|
||||
return groupProxies.Values.ToList();
|
||||
}
|
||||
}
|
||||
@@ -1,38 +1,19 @@
|
||||
using System.Collections.Concurrent;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.InterfaceGenerator;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
public class AutocadIdleManager
|
||||
public partial interface IAutocadIdleManager : IAppIdleManager;
|
||||
|
||||
[GenerateAutoInterface]
|
||||
public sealed class AutocadIdleManager(IIdleCallManager idleCallManager)
|
||||
: AppIdleManager(idleCallManager),
|
||||
IAutocadIdleManager
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, Action> _sCalls = new();
|
||||
private bool _hasSubscribed;
|
||||
private readonly IIdleCallManager _idleCallManager = idleCallManager;
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe deferred action to AutocadIdle event to run it whenever Autocad become idle.
|
||||
/// </summary>
|
||||
/// <param name="action"> Action to call whenever Autocad become Idle.</param>
|
||||
public void SubscribeToIdle(Action action)
|
||||
{
|
||||
_sCalls[action.Method.Name] = action;
|
||||
protected override void AddEvent() => Application.Idle += AutocadAppOnIdle;
|
||||
|
||||
if (_hasSubscribed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_hasSubscribed = true;
|
||||
Application.Idle += OnIdleHandler;
|
||||
}
|
||||
|
||||
private void OnIdleHandler(object sender, EventArgs e)
|
||||
{
|
||||
foreach (var kvp in _sCalls)
|
||||
{
|
||||
kvp.Value();
|
||||
}
|
||||
|
||||
_sCalls.Clear();
|
||||
_hasSubscribed = false;
|
||||
Application.Idle -= OnIdleHandler;
|
||||
}
|
||||
private void AutocadAppOnIdle(object? sender, EventArgs e) =>
|
||||
_idleCallManager.AppOnIdle(() => Application.Idle -= AutocadAppOnIdle);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.Geometry;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Converters.Autocad;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.DoubleNumerics;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Common.Exceptions;
|
||||
using Speckle.Sdk.Dependencies;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency receive operation.
|
||||
/// </summary>
|
||||
public class AutocadInstanceBaker : IInstanceBaker<IReadOnlyCollection<Entity>>
|
||||
{
|
||||
private readonly AutocadLayerBaker _layerBaker;
|
||||
private readonly IAutocadColorBaker _colorBaker;
|
||||
private readonly IAutocadMaterialBaker _materialBaker;
|
||||
private readonly AutocadContext _autocadContext;
|
||||
private readonly ILogger<AutocadInstanceBaker> _logger;
|
||||
private readonly IConverterSettingsStore<AutocadConversionSettings> _converterSettings;
|
||||
|
||||
public AutocadInstanceBaker(
|
||||
AutocadLayerBaker layerBaker,
|
||||
IAutocadColorBaker colorBaker,
|
||||
IAutocadMaterialBaker materialBaker,
|
||||
AutocadContext autocadContext,
|
||||
ILogger<AutocadInstanceBaker> logger,
|
||||
IConverterSettingsStore<AutocadConversionSettings> converterSettings
|
||||
)
|
||||
{
|
||||
_layerBaker = layerBaker;
|
||||
_colorBaker = colorBaker;
|
||||
_materialBaker = materialBaker;
|
||||
_autocadContext = autocadContext;
|
||||
_logger = logger;
|
||||
_converterSettings = converterSettings;
|
||||
}
|
||||
|
||||
[SuppressMessage("Maintainability", "CA1506:Avoid excessive class coupling")]
|
||||
public BakeResult BakeInstances(
|
||||
ICollection<(Collection[] collectionPath, IInstanceComponent obj)> instanceComponents,
|
||||
Dictionary<string, IReadOnlyCollection<Entity>> applicationIdMap,
|
||||
string baseLayerName,
|
||||
IProgress<CardProgress> onOperationProgressed
|
||||
)
|
||||
{
|
||||
var sortedInstanceComponents = instanceComponents
|
||||
.OrderByDescending(x => x.obj.maxDepth) // Sort by max depth, so we start baking from the deepest element first
|
||||
.ThenBy(x => x.obj is InstanceDefinitionProxy ? 0 : 1) // Ensure we bake the deepest definition first, then any instances that depend on it
|
||||
.ToList();
|
||||
|
||||
var definitionIdAndApplicationIdMap = new Dictionary<string, ObjectId>();
|
||||
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
var conversionResults = new HashSet<ReceiveConversionResult>();
|
||||
var createdObjectIds = new HashSet<string>();
|
||||
var consumedObjectIds = new HashSet<string>();
|
||||
var count = 0;
|
||||
|
||||
foreach (var (collectionPath, instanceOrDefinition) in sortedInstanceComponents)
|
||||
{
|
||||
try
|
||||
{
|
||||
onOperationProgressed.Report(new("Converting blocks", (double)++count / sortedInstanceComponents.Count));
|
||||
|
||||
if (instanceOrDefinition is InstanceDefinitionProxy { applicationId: not null } definitionProxy)
|
||||
{
|
||||
// TODO: create definition (block table record)
|
||||
var constituentEntities = definitionProxy
|
||||
.objects.Select(id =>
|
||||
applicationIdMap.TryGetValue(id, out IReadOnlyCollection<Entity>? value) ? value : null
|
||||
)
|
||||
.Where(x => x is not null)
|
||||
.SelectMany(ent => ent!)
|
||||
.ToList();
|
||||
|
||||
var record = new BlockTableRecord();
|
||||
var objectIds = new ObjectIdCollection();
|
||||
// We're expecting to have Name prop always for definitions. If there is an edge case, ask to Dim or Ogu
|
||||
record.Name = _autocadContext.RemoveInvalidChars(
|
||||
$"{definitionProxy.name}-({definitionProxy.applicationId})-{baseLayerName}"
|
||||
);
|
||||
|
||||
foreach (var entity in constituentEntities)
|
||||
{
|
||||
objectIds.Add(entity.ObjectId);
|
||||
}
|
||||
|
||||
if (constituentEntities.Count == 0)
|
||||
{
|
||||
throw new ConversionException("No objects found to create instance definition.");
|
||||
}
|
||||
|
||||
using var blockTable = (BlockTable)
|
||||
transaction.GetObject(Application.DocumentManager.CurrentDocument.Database.BlockTableId, OpenMode.ForWrite);
|
||||
var id = blockTable.Add(record);
|
||||
record.AssumeOwnershipOf(objectIds);
|
||||
|
||||
definitionIdAndApplicationIdMap[definitionProxy.applicationId] = id;
|
||||
transaction.AddNewlyCreatedDBObject(record, true);
|
||||
var consumedEntitiesHandleValues = constituentEntities.Select(ent => ent.GetSpeckleApplicationId()).ToArray();
|
||||
consumedObjectIds.UnionWith(consumedEntitiesHandleValues);
|
||||
createdObjectIds.RemoveWhere(newId => consumedEntitiesHandleValues.Contains(newId));
|
||||
}
|
||||
else if (
|
||||
instanceOrDefinition is InstanceProxy instanceProxy
|
||||
&& definitionIdAndApplicationIdMap.TryGetValue(instanceProxy.definitionId, out ObjectId definitionId)
|
||||
)
|
||||
{
|
||||
var matrix3d = GetMatrix3d(instanceProxy.transform, instanceProxy.units);
|
||||
var insertionPoint = Point3d.Origin.TransformBy(matrix3d);
|
||||
|
||||
var modelSpaceBlockTableRecord = Application.DocumentManager.CurrentDocument.Database.GetModelSpace(
|
||||
OpenMode.ForWrite
|
||||
);
|
||||
|
||||
// POC: collectionPath for instances should be an array of size 1, because we are flattening collections on traversal
|
||||
string layerName = _layerBaker.CreateLayerForReceive(collectionPath, baseLayerName);
|
||||
|
||||
// get color and material if any
|
||||
string instanceId = instanceProxy.applicationId ?? instanceProxy.id.NotNull();
|
||||
AutocadColor? objColor = _colorBaker.ObjectColorsIdMap.TryGetValue(instanceId, out AutocadColor? color)
|
||||
? color
|
||||
: null;
|
||||
ObjectId objMaterial = _materialBaker.ObjectMaterialsIdMap.TryGetValue(instanceId, out ObjectId matId)
|
||||
? matId
|
||||
: ObjectId.Null;
|
||||
|
||||
BlockReference blockRef = new(insertionPoint, definitionId) { BlockTransform = matrix3d, Layer = layerName, };
|
||||
|
||||
if (objColor is not null)
|
||||
{
|
||||
blockRef.Color = objColor;
|
||||
}
|
||||
|
||||
if (objMaterial != ObjectId.Null)
|
||||
{
|
||||
blockRef.MaterialId = objMaterial;
|
||||
}
|
||||
|
||||
modelSpaceBlockTableRecord.AppendEntity(blockRef);
|
||||
|
||||
applicationIdMap[instanceId] = new List<Entity> { blockRef };
|
||||
|
||||
transaction.AddNewlyCreatedDBObject(blockRef, true);
|
||||
conversionResults.Add(
|
||||
new(Status.SUCCESS, instanceProxy, blockRef.GetSpeckleApplicationId(), "Instance (Block)")
|
||||
);
|
||||
createdObjectIds.Add(blockRef.GetSpeckleApplicationId());
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to create an instance from proxy");
|
||||
conversionResults.Add(new(Status.ERROR, instanceOrDefinition as Base ?? new Base(), null, null, ex));
|
||||
}
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
return new(createdObjectIds.Freeze(), consumedObjectIds.Freeze(), conversionResults.Freeze());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans up any previously created instances.
|
||||
/// POC: This function will not be able to delete block definitions if the user creates a new one composed out of received definitions.
|
||||
/// </summary>
|
||||
/// <param name="namePrefix"></param>
|
||||
public void PurgeInstances(string namePrefix)
|
||||
{
|
||||
namePrefix = _autocadContext.RemoveInvalidChars(namePrefix);
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
var instanceDefinitionsToDelete = new Dictionary<string, BlockTableRecord>();
|
||||
|
||||
// Helper function that recurses through a given block table record's constituent objects and purges inner instances as required.
|
||||
void TraverseAndClean(BlockTableRecord btr)
|
||||
{
|
||||
foreach (var objectId in btr)
|
||||
{
|
||||
var obj = transaction.GetObject(objectId, OpenMode.ForRead) as BlockReference;
|
||||
if (obj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var definition = (BlockTableRecord)transaction.GetObject(obj.BlockTableRecord, OpenMode.ForRead);
|
||||
if (obj.IsErased)
|
||||
{
|
||||
TraverseAndClean(definition);
|
||||
continue;
|
||||
}
|
||||
|
||||
obj.UpgradeOpen();
|
||||
obj.Erase();
|
||||
TraverseAndClean(definition);
|
||||
instanceDefinitionsToDelete[obj.BlockTableRecord.ToString()] = definition;
|
||||
}
|
||||
}
|
||||
|
||||
using var blockTable = (BlockTable)
|
||||
transaction.GetObject(Application.DocumentManager.CurrentDocument.Database.BlockTableId, OpenMode.ForRead);
|
||||
|
||||
// deep clean definitions
|
||||
foreach (var btrId in blockTable)
|
||||
{
|
||||
var btr = (BlockTableRecord)transaction.GetObject(btrId, OpenMode.ForRead);
|
||||
if (btr.Name.Contains(namePrefix)) // POC: this is tightly coupled with a naming convention for definitions in the instance object manager
|
||||
{
|
||||
TraverseAndClean(btr);
|
||||
instanceDefinitionsToDelete[btr.Name] = btr;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var def in instanceDefinitionsToDelete.Values)
|
||||
{
|
||||
def.UpgradeOpen();
|
||||
def.Erase();
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
private Matrix3d GetMatrix3d(Matrix4x4 matrix, string units)
|
||||
{
|
||||
var sf = Units.GetConversionFactor(units, _converterSettings.Current.SpeckleUnits);
|
||||
|
||||
var scaledTransform = new[]
|
||||
{
|
||||
matrix.M11,
|
||||
matrix.M12,
|
||||
matrix.M13,
|
||||
matrix.M14 * sf,
|
||||
matrix.M21,
|
||||
matrix.M22,
|
||||
matrix.M23,
|
||||
matrix.M24 * sf,
|
||||
matrix.M31,
|
||||
matrix.M32,
|
||||
matrix.M33,
|
||||
matrix.M34 * sf,
|
||||
matrix.M41,
|
||||
matrix.M42,
|
||||
matrix.M43,
|
||||
matrix.M44
|
||||
};
|
||||
|
||||
var m3d = new Matrix3d(scaledTransform);
|
||||
if (!m3d.IsScaledOrtho())
|
||||
{
|
||||
m3d = new Matrix3d(MakePerpendicular(m3d));
|
||||
}
|
||||
|
||||
return m3d;
|
||||
}
|
||||
|
||||
// https://forums.autodesk.com/t5/net/set-blocktransform-values/m-p/6452121#M49479
|
||||
private double[] MakePerpendicular(Matrix3d matrix)
|
||||
{
|
||||
// Get the basis vectors of the matrix
|
||||
Vector3d right = new(matrix[0, 0], matrix[1, 0], matrix[2, 0]);
|
||||
Vector3d up = new(matrix[0, 1], matrix[1, 1], matrix[2, 1]);
|
||||
|
||||
Vector3d newForward = right.CrossProduct(up).GetNormal();
|
||||
Vector3d newUp = newForward.CrossProduct(right).GetNormal();
|
||||
|
||||
return
|
||||
[
|
||||
right.X,
|
||||
newUp.X,
|
||||
newForward.X,
|
||||
matrix[0, 3],
|
||||
right.Y,
|
||||
newUp.Y,
|
||||
newForward.Y,
|
||||
matrix[1, 3],
|
||||
right.Z,
|
||||
newUp.Z,
|
||||
newForward.Z,
|
||||
matrix[2, 3],
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
matrix[3, 3]
|
||||
];
|
||||
}
|
||||
}
|
||||
-368
@@ -1,368 +0,0 @@
|
||||
using System.DoubleNumerics;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.Geometry;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.Utils.Conversion;
|
||||
using Speckle.Connectors.Utils.Instances;
|
||||
using Speckle.Core.Kits;
|
||||
using Speckle.Core.Logging;
|
||||
using Speckle.Core.Models;
|
||||
using Speckle.Core.Models.Instances;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// Expects to be a scoped dependency per send or receive operation.
|
||||
/// </summary>
|
||||
public class AutocadInstanceObjectManager : IInstanceObjectsManager<AutocadRootObject, List<Entity>>
|
||||
{
|
||||
private readonly AutocadLayerManager _autocadLayerManager;
|
||||
private Dictionary<string, InstanceProxy> InstanceProxies { get; set; } = new();
|
||||
private Dictionary<string, List<InstanceProxy>> InstanceProxiesByDefinitionId { get; set; } = new();
|
||||
private Dictionary<string, InstanceDefinitionProxy> DefinitionProxies { get; set; } = new();
|
||||
private Dictionary<string, AutocadRootObject> FlatAtomicObjects { get; set; } = new();
|
||||
|
||||
public AutocadInstanceObjectManager(AutocadLayerManager autocadLayerManager)
|
||||
{
|
||||
_autocadLayerManager = autocadLayerManager;
|
||||
}
|
||||
|
||||
public UnpackResult<AutocadRootObject> UnpackSelection(IEnumerable<AutocadRootObject> objects)
|
||||
{
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
if (obj.Root is BlockReference blockReference && !blockReference.IsDynamicBlock)
|
||||
{
|
||||
UnpackInstance(blockReference, 0, transaction);
|
||||
}
|
||||
|
||||
FlatAtomicObjects[obj.ApplicationId] = obj;
|
||||
}
|
||||
return new(FlatAtomicObjects.Values.ToList(), InstanceProxies, DefinitionProxies.Values.ToList());
|
||||
}
|
||||
|
||||
private void UnpackInstance(BlockReference instance, int depth, Transaction transaction)
|
||||
{
|
||||
var instanceIdString = instance.Handle.Value.ToString();
|
||||
var definitionId = instance.BlockTableRecord;
|
||||
|
||||
InstanceProxies[instanceIdString] = new InstanceProxy()
|
||||
{
|
||||
applicationId = instanceIdString,
|
||||
DefinitionId = definitionId.ToString(),
|
||||
MaxDepth = depth,
|
||||
Transform = GetMatrix(instance.BlockTransform.ToArray()),
|
||||
Units = Application.DocumentManager.CurrentDocument.Database.Insunits.ToSpeckleString()
|
||||
};
|
||||
|
||||
// For each block instance that has the same definition, we need to keep track of the "maximum depth" at which is found.
|
||||
// This will enable on receive to create them in the correct order (descending by max depth, interleaved definitions and instances).
|
||||
// We need to interleave the creation of definitions and instances, as some definitions may depend on instances.
|
||||
if (
|
||||
!InstanceProxiesByDefinitionId.TryGetValue(
|
||||
definitionId.ToString(),
|
||||
out List<InstanceProxy> instanceProxiesWithSameDefinition
|
||||
)
|
||||
)
|
||||
{
|
||||
instanceProxiesWithSameDefinition = new List<InstanceProxy>();
|
||||
InstanceProxiesByDefinitionId[definitionId.ToString()] = instanceProxiesWithSameDefinition;
|
||||
}
|
||||
|
||||
// We ensure that all previous instance proxies that have the same definition are at this max depth. I kind of have a feeling this can be done more elegantly, but YOLO
|
||||
foreach (var instanceProxy in instanceProxiesWithSameDefinition)
|
||||
{
|
||||
instanceProxy.MaxDepth = depth;
|
||||
}
|
||||
|
||||
instanceProxiesWithSameDefinition.Add(InstanceProxies[instanceIdString]);
|
||||
|
||||
if (DefinitionProxies.TryGetValue(definitionId.ToString(), out InstanceDefinitionProxy value))
|
||||
{
|
||||
value.MaxDepth = depth;
|
||||
return; // exit fast - we've parsed this one so no need to go further
|
||||
}
|
||||
|
||||
var definition = (BlockTableRecord)transaction.GetObject(definitionId, OpenMode.ForRead);
|
||||
// definition.Origin
|
||||
var definitionProxy = new InstanceDefinitionProxy()
|
||||
{
|
||||
applicationId = definitionId.ToString(),
|
||||
Objects = new(),
|
||||
MaxDepth = depth,
|
||||
["name"] = definition.Name,
|
||||
["comments"] = definition.Comments,
|
||||
["units"] = definition.Units // ? not sure needed?
|
||||
};
|
||||
|
||||
// Go through each definition object
|
||||
foreach (ObjectId id in definition)
|
||||
{
|
||||
var obj = transaction.GetObject(id, OpenMode.ForRead);
|
||||
var handleIdString = obj.Handle.Value.ToString();
|
||||
definitionProxy.Objects.Add(handleIdString);
|
||||
|
||||
if (obj is BlockReference blockReference && !blockReference.IsDynamicBlock)
|
||||
{
|
||||
UnpackInstance(blockReference, depth + 1, transaction);
|
||||
}
|
||||
FlatAtomicObjects[handleIdString] = new(obj, handleIdString);
|
||||
}
|
||||
|
||||
DefinitionProxies[definitionId.ToString()] = definitionProxy;
|
||||
}
|
||||
|
||||
public BakeResult BakeInstances(
|
||||
List<(string[] layerPath, IInstanceComponent obj)> instanceComponents,
|
||||
Dictionary<string, List<Entity>> applicationIdMap,
|
||||
string baseLayerName,
|
||||
Action<string, double?>? onOperationProgressed
|
||||
)
|
||||
{
|
||||
var sortedInstanceComponents = instanceComponents
|
||||
.OrderByDescending(x => x.obj.MaxDepth) // Sort by max depth, so we start baking from the deepest element first
|
||||
.ThenBy(x => x.obj is InstanceDefinitionProxy ? 0 : 1) // Ensure we bake the deepest definition first, then any instances that depend on it
|
||||
.ToList();
|
||||
|
||||
var definitionIdAndApplicationIdMap = new Dictionary<string, ObjectId>();
|
||||
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
var conversionResults = new List<ReceiveConversionResult>();
|
||||
var createdObjectIds = new List<string>();
|
||||
var consumedObjectIds = new List<string>();
|
||||
var count = 0;
|
||||
|
||||
foreach (var (path, instanceOrDefinition) in sortedInstanceComponents)
|
||||
{
|
||||
try
|
||||
{
|
||||
onOperationProgressed?.Invoke("Converting blocks", (double)++count / sortedInstanceComponents.Count);
|
||||
if (instanceOrDefinition is InstanceDefinitionProxy { applicationId: not null } definitionProxy)
|
||||
{
|
||||
// TODO: create definition (block table record)
|
||||
var constituentEntities = definitionProxy.Objects
|
||||
.Select(id => applicationIdMap.TryGetValue(id, out List<Entity> value) ? value : null)
|
||||
.Where(x => x is not null)
|
||||
.SelectMany(ent => ent)
|
||||
.ToList();
|
||||
|
||||
var record = new BlockTableRecord();
|
||||
var objectIds = new ObjectIdCollection();
|
||||
record.Name = baseLayerName;
|
||||
if (definitionProxy["name"] is string name)
|
||||
{
|
||||
record.Name += name;
|
||||
}
|
||||
else
|
||||
{
|
||||
record.Name += definitionProxy.applicationId;
|
||||
}
|
||||
|
||||
foreach (var entity in constituentEntities)
|
||||
{
|
||||
// record.AppendEntity(entity);
|
||||
objectIds.Add(entity.ObjectId);
|
||||
}
|
||||
|
||||
using var blockTable = (BlockTable)
|
||||
transaction.GetObject(Application.DocumentManager.CurrentDocument.Database.BlockTableId, OpenMode.ForWrite);
|
||||
var id = blockTable.Add(record);
|
||||
record.AssumeOwnershipOf(objectIds);
|
||||
|
||||
definitionIdAndApplicationIdMap[definitionProxy.applicationId] = id;
|
||||
transaction.AddNewlyCreatedDBObject(record, true);
|
||||
var consumedEntitiesHandleValues = constituentEntities.Select(ent => ent.Handle.Value.ToString()).ToArray();
|
||||
consumedObjectIds.AddRange(consumedEntitiesHandleValues);
|
||||
createdObjectIds.RemoveAll(newId => consumedEntitiesHandleValues.Contains(newId));
|
||||
}
|
||||
else if (
|
||||
instanceOrDefinition is InstanceProxy instanceProxy
|
||||
&& definitionIdAndApplicationIdMap.TryGetValue(instanceProxy.DefinitionId, out ObjectId definitionId)
|
||||
)
|
||||
{
|
||||
var matrix3d = GetMatrix3d(instanceProxy.Transform, instanceProxy.Units);
|
||||
var insertionPoint = Point3d.Origin.TransformBy(matrix3d);
|
||||
|
||||
var modelSpaceBlockTableRecord = Application.DocumentManager.CurrentDocument.Database.GetModelSpace(
|
||||
OpenMode.ForWrite
|
||||
);
|
||||
_autocadLayerManager.CreateLayerForReceive(path[0]);
|
||||
var blockRef = new BlockReference(insertionPoint, definitionId)
|
||||
{
|
||||
BlockTransform = matrix3d,
|
||||
Layer = path[0],
|
||||
};
|
||||
|
||||
modelSpaceBlockTableRecord.AppendEntity(blockRef);
|
||||
|
||||
if (instanceProxy.applicationId != null)
|
||||
{
|
||||
applicationIdMap[instanceProxy.applicationId] = new List<Entity> { blockRef };
|
||||
}
|
||||
|
||||
transaction.AddNewlyCreatedDBObject(blockRef, true);
|
||||
conversionResults.Add(
|
||||
new(Status.SUCCESS, instanceProxy, blockRef.Handle.Value.ToString(), "Instance (Block)")
|
||||
);
|
||||
createdObjectIds.Add(blockRef.Handle.Value.ToString());
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
conversionResults.Add(new(Status.ERROR, instanceOrDefinition as Base ?? new Base(), null, null, ex));
|
||||
}
|
||||
}
|
||||
transaction.Commit();
|
||||
return new(createdObjectIds, consumedObjectIds, conversionResults);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans up any previously created instances.
|
||||
/// POC: This function will not be able to delete block definitions if the user creates a new one composed out of received definitions.
|
||||
/// </summary>
|
||||
/// <param name="namePrefix"></param>
|
||||
public void PurgeInstances(string namePrefix)
|
||||
{
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
var instanceDefinitionsToDelete = new Dictionary<string, BlockTableRecord>();
|
||||
|
||||
// Helper function that recurses through a given block table record's constituent objects and purges inner instances as required.
|
||||
void TraverseAndClean(BlockTableRecord btr)
|
||||
{
|
||||
foreach (var objectId in btr)
|
||||
{
|
||||
var obj = transaction.GetObject(objectId, OpenMode.ForRead) as BlockReference;
|
||||
if (obj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var definition = (BlockTableRecord)transaction.GetObject(obj.BlockTableRecord, OpenMode.ForRead);
|
||||
if (obj.IsErased)
|
||||
{
|
||||
TraverseAndClean(definition);
|
||||
continue;
|
||||
}
|
||||
|
||||
obj.UpgradeOpen();
|
||||
obj.Erase();
|
||||
TraverseAndClean(definition);
|
||||
instanceDefinitionsToDelete[obj.BlockTableRecord.ToString()] = definition;
|
||||
}
|
||||
}
|
||||
|
||||
using var blockTable = (BlockTable)
|
||||
transaction.GetObject(Application.DocumentManager.CurrentDocument.Database.BlockTableId, OpenMode.ForRead);
|
||||
|
||||
// deep clean definitions
|
||||
foreach (var btrId in blockTable)
|
||||
{
|
||||
var btr = (BlockTableRecord)transaction.GetObject(btrId, OpenMode.ForRead);
|
||||
if (btr.Name.Contains(namePrefix)) // POC: this is tightly coupled with a naming convention for definitions in the instance object manager
|
||||
{
|
||||
TraverseAndClean(btr);
|
||||
instanceDefinitionsToDelete[btr.Name] = btr;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var def in instanceDefinitionsToDelete.Values)
|
||||
{
|
||||
def.UpgradeOpen();
|
||||
def.Erase();
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
private Matrix4x4 GetMatrix(double[] t)
|
||||
{
|
||||
return new Matrix4x4(
|
||||
t[0],
|
||||
t[1],
|
||||
t[2],
|
||||
t[3],
|
||||
t[4],
|
||||
t[5],
|
||||
t[6],
|
||||
t[7],
|
||||
t[8],
|
||||
t[9],
|
||||
t[10],
|
||||
t[11],
|
||||
t[12],
|
||||
t[13],
|
||||
t[14],
|
||||
t[15]
|
||||
);
|
||||
}
|
||||
|
||||
private Matrix3d GetMatrix3d(Matrix4x4 matrix, string units)
|
||||
{
|
||||
var sf = Units.GetConversionFactor(
|
||||
units,
|
||||
Application.DocumentManager.CurrentDocument.Database.Insunits.ToSpeckleString()
|
||||
);
|
||||
|
||||
var scaledTransform = new[]
|
||||
{
|
||||
matrix.M11,
|
||||
matrix.M12,
|
||||
matrix.M13,
|
||||
matrix.M14 * sf,
|
||||
matrix.M21,
|
||||
matrix.M22,
|
||||
matrix.M23,
|
||||
matrix.M24 * sf,
|
||||
matrix.M31,
|
||||
matrix.M32,
|
||||
matrix.M33,
|
||||
matrix.M34 * sf,
|
||||
matrix.M41,
|
||||
matrix.M42,
|
||||
matrix.M43,
|
||||
matrix.M44
|
||||
};
|
||||
|
||||
var m3d = new Matrix3d(scaledTransform);
|
||||
if (!m3d.IsScaledOrtho())
|
||||
{
|
||||
m3d = new Matrix3d(MakePerpendicular(m3d));
|
||||
}
|
||||
|
||||
return m3d;
|
||||
}
|
||||
|
||||
// https://forums.autodesk.com/t5/net/set-blocktransform-values/m-p/6452121#M49479
|
||||
private static double[] MakePerpendicular(Matrix3d matrix)
|
||||
{
|
||||
// Get the basis vectors of the matrix
|
||||
Vector3d right = new(matrix[0, 0], matrix[1, 0], matrix[2, 0]);
|
||||
Vector3d up = new(matrix[0, 1], matrix[1, 1], matrix[2, 1]);
|
||||
|
||||
Vector3d newForward = right.CrossProduct(up).GetNormal();
|
||||
Vector3d newUp = newForward.CrossProduct(right).GetNormal();
|
||||
|
||||
return new[]
|
||||
{
|
||||
right.X,
|
||||
newUp.X,
|
||||
newForward.X,
|
||||
matrix[0, 3],
|
||||
right.Y,
|
||||
newUp.Y,
|
||||
newForward.Y,
|
||||
matrix[1, 3],
|
||||
right.Z,
|
||||
newUp.Z,
|
||||
newForward.Z,
|
||||
matrix[2, 3],
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
matrix[3, 3],
|
||||
};
|
||||
}
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.DoubleNumerics;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency per send operation.
|
||||
/// </summary>
|
||||
public class AutocadInstanceUnpacker : IInstanceUnpacker<AutocadRootObject>
|
||||
{
|
||||
private readonly IHostToSpeckleUnitConverter<UnitsValue> _unitsConverter;
|
||||
private readonly IInstanceObjectsManager<AutocadRootObject, List<Entity>> _instanceObjectsManager;
|
||||
private readonly ILogger<AutocadInstanceUnpacker> _logger;
|
||||
|
||||
public AutocadInstanceUnpacker(
|
||||
IHostToSpeckleUnitConverter<UnitsValue> unitsConverter,
|
||||
IInstanceObjectsManager<AutocadRootObject, List<Entity>> instanceObjectsManager,
|
||||
ILogger<AutocadInstanceUnpacker> logger
|
||||
)
|
||||
{
|
||||
_unitsConverter = unitsConverter;
|
||||
_instanceObjectsManager = instanceObjectsManager;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public UnpackResult<AutocadRootObject> UnpackSelection(IEnumerable<AutocadRootObject> objects)
|
||||
{
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
// Note: isDynamicBlock always returns false for a selection of doc objects. Instances of dynamic blocks are represented in the document as blocks that have
|
||||
// a definition reference to the anonymous block table record.
|
||||
if (obj.Root is BlockReference blockReference && !blockReference.IsDynamicBlock)
|
||||
{
|
||||
UnpackInstance(blockReference, 0, transaction);
|
||||
}
|
||||
_instanceObjectsManager.AddAtomicObject(obj.ApplicationId, obj);
|
||||
}
|
||||
return _instanceObjectsManager.GetUnpackResult();
|
||||
}
|
||||
|
||||
private void UnpackInstance(BlockReference instance, int depth, Transaction transaction)
|
||||
{
|
||||
try
|
||||
{
|
||||
string instanceId = instance.GetSpeckleApplicationId();
|
||||
|
||||
// If this instance has a reference to an anonymous block, it means it's spawned from a dynamic block. Anonymous blocks are
|
||||
// used to represent specific "instances" of dynamic ones.
|
||||
// We do not want to send the full dynamic block definition, but its current "instance", as such here we're making sure we
|
||||
// take up the anon block table reference definition (if it exists). If it's not an instance of a dynamic block, we're
|
||||
// using the normal def reference.
|
||||
ObjectId definitionId = !instance.AnonymousBlockTableRecord.IsNull
|
||||
? instance.AnonymousBlockTableRecord
|
||||
: instance.BlockTableRecord;
|
||||
|
||||
InstanceProxy instanceProxy =
|
||||
new()
|
||||
{
|
||||
applicationId = instanceId,
|
||||
definitionId = definitionId.ToString(),
|
||||
maxDepth = depth,
|
||||
transform = GetMatrix(instance.BlockTransform.ToArray()),
|
||||
units = _unitsConverter.ConvertOrThrow(Application.DocumentManager.CurrentDocument.Database.Insunits)
|
||||
};
|
||||
_instanceObjectsManager.AddInstanceProxy(instanceId, instanceProxy);
|
||||
|
||||
// For each block instance that has the same definition, we need to keep track of the "maximum depth" at which is found.
|
||||
// This will enable on receive to create them in the correct order (descending by max depth, interleaved definitions and instances).
|
||||
// We need to interleave the creation of definitions and instances, as some definitions may depend on instances.
|
||||
if (
|
||||
!_instanceObjectsManager.TryGetInstanceProxiesFromDefinitionId(
|
||||
definitionId.ToString(),
|
||||
out List<InstanceProxy>? instanceProxiesWithSameDefinition
|
||||
)
|
||||
)
|
||||
{
|
||||
instanceProxiesWithSameDefinition = new List<InstanceProxy>();
|
||||
_instanceObjectsManager.AddInstanceProxiesByDefinitionId(
|
||||
definitionId.ToString(),
|
||||
instanceProxiesWithSameDefinition
|
||||
);
|
||||
}
|
||||
|
||||
// We ensure that all previous instance proxies that have the same definition are at this max depth. I kind of have a feeling this can be done more elegantly, but YOLO
|
||||
foreach (var instanceProxyWithSameDefinition in instanceProxiesWithSameDefinition)
|
||||
{
|
||||
if (instanceProxyWithSameDefinition.maxDepth < depth)
|
||||
{
|
||||
instanceProxyWithSameDefinition.maxDepth = depth;
|
||||
}
|
||||
}
|
||||
|
||||
instanceProxiesWithSameDefinition.Add(_instanceObjectsManager.GetInstanceProxy(instanceId));
|
||||
|
||||
if (
|
||||
_instanceObjectsManager.TryGetInstanceDefinitionProxy(
|
||||
definitionId.ToString(),
|
||||
out InstanceDefinitionProxy? value
|
||||
)
|
||||
)
|
||||
{
|
||||
int depthDifference = depth - value.maxDepth;
|
||||
if (depthDifference > 0)
|
||||
{
|
||||
// all MaxDepth of children definitions and its instances should be increased with difference of depth
|
||||
_instanceObjectsManager.UpdateChildrenMaxDepth(value, depthDifference);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var definition = (BlockTableRecord)transaction.GetObject(definitionId, OpenMode.ForRead);
|
||||
var definitionProxy = new InstanceDefinitionProxy()
|
||||
{
|
||||
applicationId = definitionId.ToString(),
|
||||
objects = new(),
|
||||
maxDepth = depth,
|
||||
name = !instance.AnonymousBlockTableRecord.IsNull ? "Dynamic instance " + definitionId : definition.Name
|
||||
};
|
||||
|
||||
// Go through each definition object
|
||||
foreach (ObjectId id in definition)
|
||||
{
|
||||
Entity obj = (Entity)transaction.GetObject(id, OpenMode.ForRead);
|
||||
|
||||
// In the case of dynamic blocks, this prevents sending objects that are not visibile in its current state.
|
||||
if (!obj.Visible)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string appId = obj.GetSpeckleApplicationId();
|
||||
definitionProxy.objects.Add(appId);
|
||||
|
||||
if (obj is BlockReference blockReference)
|
||||
{
|
||||
UnpackInstance(blockReference, depth + 1, transaction);
|
||||
}
|
||||
|
||||
_instanceObjectsManager.AddAtomicObject(appId, new(obj, appId));
|
||||
}
|
||||
|
||||
_instanceObjectsManager.AddDefinitionProxy(definitionId.ToString(), definitionProxy);
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed unpacking Autocad instance");
|
||||
}
|
||||
}
|
||||
|
||||
private Matrix4x4 GetMatrix(double[] t) =>
|
||||
new(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9], t[10], t[11], t[12], t[13], t[14], t[15]);
|
||||
}
|
||||
+76
-34
@@ -1,38 +1,75 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.EditorInput;
|
||||
using Autodesk.AutoCAD.LayerManager;
|
||||
using Speckle.Core.Models;
|
||||
using Speckle.Core.Models.GraphTraversal;
|
||||
using Speckle.Connectors.Common.Operations.Receive;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency for a given operation and helps with layer creation and cleanup.
|
||||
/// </summary>
|
||||
public class AutocadLayerManager
|
||||
public class AutocadLayerBaker : TraversalContextUnpacker
|
||||
{
|
||||
private readonly AutocadContext _autocadContext;
|
||||
private readonly string _layerFilterName = "Speckle";
|
||||
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
private readonly AutocadContext _autocadContext;
|
||||
private readonly IAutocadMaterialBaker _materialBaker;
|
||||
private readonly IAutocadColorBaker _colorBaker;
|
||||
private Document Doc => Application.DocumentManager.MdiActiveDocument;
|
||||
private readonly HashSet<string> _uniqueLayerNames = new();
|
||||
|
||||
public AutocadLayerManager(AutocadContext autocadContext)
|
||||
public AutocadLayerBaker(
|
||||
AutocadContext autocadContext,
|
||||
IAutocadMaterialBaker materialBaker,
|
||||
IAutocadColorBaker colorBaker
|
||||
)
|
||||
{
|
||||
_autocadContext = autocadContext;
|
||||
_materialBaker = materialBaker;
|
||||
_colorBaker = colorBaker;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will create a layer with the provided name, or, if it finds an existing one, will "purge" all objects from it.
|
||||
/// This ensures we're creating the new objects we've just received rather than overlaying them.
|
||||
/// </summary>
|
||||
/// <param name="layerName">Name to search layer for purge and create.</param>
|
||||
public void CreateLayerForReceive(string layerName)
|
||||
/// <returns>The name of the existing or created layer</returns>
|
||||
public string CreateLayerForReceive(Collection[] layerPath, string baseLayerPrefix)
|
||||
{
|
||||
string[] namePath = layerPath.Select(c => c.name).ToArray();
|
||||
string layerName = _autocadContext.RemoveInvalidChars(baseLayerPrefix + string.Join("-", namePath));
|
||||
if (!_uniqueLayerNames.Add(layerName))
|
||||
{
|
||||
return;
|
||||
return layerName;
|
||||
}
|
||||
|
||||
// get the color and material if any, of the leaf collection with a color
|
||||
AutocadColor? layerColor = null;
|
||||
ObjectId layerMaterial = ObjectId.Null;
|
||||
if (_colorBaker.ObjectColorsIdMap.Count > 0 || _materialBaker.ObjectMaterialsIdMap.Count > 0)
|
||||
{
|
||||
bool foundColor = false;
|
||||
bool foundMaterial = false;
|
||||
|
||||
// Goes up the tree to find any potential parent layer that has a material/color
|
||||
for (int j = layerPath.Length - 1; j >= 0; j--)
|
||||
{
|
||||
string layerId = layerPath[j].applicationId ?? layerPath[j].id.NotNull();
|
||||
|
||||
if (!foundColor)
|
||||
{
|
||||
foundColor = _colorBaker.ObjectColorsIdMap.TryGetValue(layerId, out layerColor);
|
||||
}
|
||||
|
||||
if (!foundMaterial)
|
||||
{
|
||||
foundMaterial = _materialBaker.ObjectMaterialsIdMap.TryGetValue(layerId, out layerMaterial);
|
||||
}
|
||||
|
||||
if (foundColor && foundMaterial)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Doc.LockDocument();
|
||||
@@ -42,28 +79,41 @@ public class AutocadLayerManager
|
||||
transaction.TransactionManager.GetObject(Doc.Database.LayerTableId, OpenMode.ForRead) as LayerTable;
|
||||
LayerTableRecord layerTableRecord = new() { Name = layerName };
|
||||
|
||||
if (layerColor is not null)
|
||||
{
|
||||
layerTableRecord.Color = layerColor;
|
||||
}
|
||||
|
||||
if (layerMaterial != ObjectId.Null)
|
||||
{
|
||||
layerTableRecord.MaterialId = layerMaterial;
|
||||
}
|
||||
|
||||
bool hasLayer = layerTable != null && layerTable.Has(layerName);
|
||||
if (hasLayer)
|
||||
{
|
||||
TypedValue[] tvs = { new((int)DxfCode.LayerName, layerName) };
|
||||
TypedValue[] tvs = [new((int)DxfCode.LayerName, layerName)];
|
||||
SelectionFilter selectionFilter = new(tvs);
|
||||
SelectionSet selectionResult = Doc.Editor.SelectAll(selectionFilter).Value;
|
||||
if (selectionResult == null)
|
||||
{
|
||||
return;
|
||||
return layerName;
|
||||
}
|
||||
|
||||
foreach (SelectedObject selectedObject in selectionResult)
|
||||
{
|
||||
transaction.GetObject(selectedObject.ObjectId, OpenMode.ForWrite).Erase();
|
||||
}
|
||||
|
||||
return;
|
||||
return layerName;
|
||||
}
|
||||
|
||||
layerTable?.UpgradeOpen();
|
||||
layerTable?.Add(layerTableRecord);
|
||||
transaction.AddNewlyCreatedDBObject(layerTableRecord, true);
|
||||
transaction.Commit();
|
||||
|
||||
return layerName;
|
||||
}
|
||||
|
||||
public void DeleteAllLayersByPrefix(string prefix)
|
||||
@@ -72,19 +122,26 @@ public class AutocadLayerManager
|
||||
using Transaction transaction = Doc.TransactionManager.StartTransaction();
|
||||
|
||||
var layerTable = (LayerTable)transaction.TransactionManager.GetObject(Doc.Database.LayerTableId, OpenMode.ForRead);
|
||||
var activeLayer = (LayerTableRecord)transaction.GetObject(Doc.Database.Clayer, OpenMode.ForRead);
|
||||
foreach (var layerId in layerTable)
|
||||
{
|
||||
var layer = (LayerTableRecord)transaction.GetObject(layerId, OpenMode.ForRead);
|
||||
var layerName = layer.Name;
|
||||
if (layer.Name.Contains(prefix))
|
||||
{
|
||||
if (activeLayer.Name == layerName)
|
||||
{
|
||||
// Layer `0` cannot be deleted or renamed in Autocad, so it is safe to get zero layer id.
|
||||
ObjectId zeroLayerId = layerTable["0"];
|
||||
Doc.Database.Clayer = zeroLayerId;
|
||||
}
|
||||
// Delete objects from this layer
|
||||
TypedValue[] tvs = { new((int)DxfCode.LayerName, layerName) };
|
||||
TypedValue[] tvs = [new((int)DxfCode.LayerName, layerName)];
|
||||
SelectionFilter selectionFilter = new(tvs);
|
||||
SelectionSet selectionResult = Doc.Editor.SelectAll(selectionFilter).Value;
|
||||
if (selectionResult == null)
|
||||
{
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
foreach (SelectedObject selectedObject in selectionResult)
|
||||
{
|
||||
@@ -142,19 +199,4 @@ public class AutocadLayerManager
|
||||
groupFilter.NestedFilters.Add(layerFilter);
|
||||
Doc.Database.LayerFilters = layerFilterTree;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a valid layer name for a given context.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="baseLayerPrefix"></param>
|
||||
/// <returns></returns>
|
||||
public string GetLayerPath(TraversalContext context, string baseLayerPrefix)
|
||||
{
|
||||
string[] collectionBasedPath = context.GetAscendantOfType<Collection>().Select(c => c.name).Reverse().ToArray();
|
||||
string[] path = collectionBasedPath.Length != 0 ? collectionBasedPath : context.GetPropertyPath().ToArray();
|
||||
|
||||
var name = baseLayerPrefix + string.Join("-", path);
|
||||
return _autocadContext.RemoveInvalidChars(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
public class AutocadLayerUnpacker
|
||||
{
|
||||
private readonly Dictionary<string, Layer> _layerCollectionCache = new();
|
||||
|
||||
public Layer GetOrCreateSpeckleLayer(Entity entity, Transaction tr, out LayerTableRecord? layer)
|
||||
{
|
||||
string layerName = entity.Layer;
|
||||
layer = null;
|
||||
if (_layerCollectionCache.TryGetValue(layerName, out Layer? speckleLayer))
|
||||
{
|
||||
return speckleLayer;
|
||||
}
|
||||
if (tr.GetObject(entity.LayerId, OpenMode.ForRead) is LayerTableRecord autocadLayer)
|
||||
{
|
||||
speckleLayer = new Layer(layerName) { applicationId = autocadLayer.GetSpeckleApplicationId() }; // Do not use handle directly, see note in the 'GetSpeckleApplicationId' method
|
||||
_layerCollectionCache[layerName] = speckleLayer;
|
||||
layer = autocadLayer;
|
||||
return speckleLayer;
|
||||
}
|
||||
|
||||
throw new SpeckleException("Unexpected condition in GetOrCreateSpeckleLayer");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
using Autodesk.AutoCAD.Colors;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.GraphicsInterface;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.InterfaceGenerator;
|
||||
using Speckle.Objects.Other;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Models;
|
||||
using Material = Autodesk.AutoCAD.DatabaseServices.Material;
|
||||
using RenderMaterial = Speckle.Objects.Other.RenderMaterial;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency for a given operation and helps with layer creation and cleanup.
|
||||
/// </summary>
|
||||
[GenerateAutoInterface]
|
||||
public class AutocadMaterialBaker : IAutocadMaterialBaker
|
||||
{
|
||||
private readonly ILogger<AutocadMaterialBaker> _logger;
|
||||
private readonly AutocadContext _autocadContext;
|
||||
private Document Doc => Application.DocumentManager.MdiActiveDocument;
|
||||
public Dictionary<string, ObjectId> ObjectMaterialsIdMap { get; } = new();
|
||||
|
||||
public AutocadMaterialBaker(AutocadContext autocadContext, ILogger<AutocadMaterialBaker> logger)
|
||||
{
|
||||
_autocadContext = autocadContext;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to get material id from original object or its parent (if provided) as fallback).
|
||||
/// It covers one-to-many problem, i.e.
|
||||
/// - rhino: Brep (material id is extracted into render material proxy objects) -> [Mesh, Mesh, ...] (child objects application ids ARE NOT EXIST in render material proxy objects)
|
||||
/// - revit : RevitElement (material IS NOT extracted into render material proxy objects) -> [Mesh, Mesh...] (child objects application ids EXIST in render material proxy objects)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a question that we need to answer where to handle these cases.
|
||||
/// We alsa do reverse search for layer render materials on Revit Receive, and mutating the proxy list accordingly.
|
||||
/// These cases are increasing, and need some ideation around it before going more messy.
|
||||
/// </remarks>
|
||||
public bool TryGetMaterialId(Base originalObject, Base? parentObject, out ObjectId materialId)
|
||||
{
|
||||
materialId = ObjectId.Null;
|
||||
var originalObjectId = originalObject.applicationId ?? originalObject.id.NotNull();
|
||||
if (ObjectMaterialsIdMap.TryGetValue(originalObjectId, out ObjectId originalObjectMaterialId))
|
||||
{
|
||||
materialId = originalObjectMaterialId;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (parentObject is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var subObjectId = parentObject.applicationId ?? parentObject.id.NotNull();
|
||||
if (ObjectMaterialsIdMap.TryGetValue(subObjectId, out ObjectId subObjectMaterialId))
|
||||
{
|
||||
materialId = subObjectMaterialId;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all materials with a name starting with <paramref name="namePrefix"/> from the active document
|
||||
/// </summary>
|
||||
/// <param name="namePrefix"></param>
|
||||
public void PurgeMaterials(string namePrefix)
|
||||
{
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
if (transaction.GetObject(Doc.Database.MaterialDictionaryId, OpenMode.ForWrite) is DBDictionary materialDict)
|
||||
{
|
||||
foreach (var entry in materialDict)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (entry.Key.Contains(namePrefix))
|
||||
{
|
||||
materialDict.Remove(entry.Value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to purge a material from the document");
|
||||
}
|
||||
}
|
||||
}
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
public void ParseAndBakeRenderMaterials(
|
||||
IReadOnlyCollection<RenderMaterialProxy> materialProxies,
|
||||
string baseLayerPrefix,
|
||||
IProgress<CardProgress> onOperationProgressed
|
||||
)
|
||||
{
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
var materialDict = transaction.GetObject(Doc.Database.MaterialDictionaryId, OpenMode.ForWrite) as DBDictionary;
|
||||
|
||||
if (materialDict == null)
|
||||
{
|
||||
// POC: we should report failed conversion here if material dict is not accessible, but it is not linked to a Base source
|
||||
transaction.Commit();
|
||||
return;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
foreach (RenderMaterialProxy materialProxy in materialProxies)
|
||||
{
|
||||
onOperationProgressed.Report(new("Converting render materials", (double)++count / materialProxies.Count));
|
||||
|
||||
// bake render material
|
||||
RenderMaterial renderMaterial = materialProxy.value;
|
||||
string renderMaterialId = renderMaterial.applicationId ?? renderMaterial.id.NotNull();
|
||||
ObjectId materialId = ObjectId.Null;
|
||||
|
||||
if (!ObjectMaterialsIdMap.TryGetValue(renderMaterialId, out materialId))
|
||||
{
|
||||
(materialId, ReceiveConversionResult result) = BakeMaterial(
|
||||
renderMaterial,
|
||||
baseLayerPrefix,
|
||||
materialDict,
|
||||
transaction
|
||||
);
|
||||
}
|
||||
|
||||
if (materialId == ObjectId.Null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// parse render material object ids
|
||||
foreach (string objectId in materialProxy.objects)
|
||||
{
|
||||
ObjectMaterialsIdMap[objectId] = materialId;
|
||||
}
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
private (ObjectId, ReceiveConversionResult) BakeMaterial(
|
||||
RenderMaterial renderMaterial,
|
||||
string baseLayerPrefix,
|
||||
DBDictionary materialDict,
|
||||
Transaction tr
|
||||
)
|
||||
{
|
||||
ObjectId materialId = ObjectId.Null;
|
||||
|
||||
try
|
||||
{
|
||||
// POC: Currently we're relying on the render material name for identification if it's coming from speckle and from which model; could we do something else?
|
||||
// POC: we should assume render materials all have application ids?
|
||||
string renderMaterialId = renderMaterial.applicationId ?? renderMaterial.id.NotNull();
|
||||
string matName = _autocadContext.RemoveInvalidChars(
|
||||
$"{renderMaterial.name}-({renderMaterialId})-{baseLayerPrefix}"
|
||||
);
|
||||
|
||||
MaterialMap map = new();
|
||||
MaterialOpacityComponent opacity = new(renderMaterial.opacity, map);
|
||||
var systemDiffuse = System.Drawing.Color.FromArgb(renderMaterial.diffuse);
|
||||
EntityColor entityDiffuseColor = new(systemDiffuse.R, systemDiffuse.G, systemDiffuse.B);
|
||||
MaterialColor diffuseColor = new(Method.Override, 1, entityDiffuseColor);
|
||||
MaterialDiffuseComponent diffuse = new(diffuseColor, map);
|
||||
|
||||
Material mat =
|
||||
new()
|
||||
{
|
||||
Name = matName,
|
||||
Opacity = opacity,
|
||||
Diffuse = diffuse
|
||||
};
|
||||
|
||||
if (renderMaterial["reflectivity"] is double reflectivity)
|
||||
{
|
||||
mat.Reflectivity = reflectivity;
|
||||
}
|
||||
|
||||
if (renderMaterial["ior"] is double ior)
|
||||
{
|
||||
mat.Refraction = new(ior, map);
|
||||
}
|
||||
|
||||
// POC: assumes all materials with this prefix has already been purged from doc
|
||||
materialId = materialDict.SetAt(matName, mat);
|
||||
tr.AddNewlyCreatedDBObject(mat, true);
|
||||
|
||||
return (materialId, new(Status.SUCCESS, renderMaterial, matName, "Material"));
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to add a material to the document");
|
||||
return (materialId, new(Status.ERROR, renderMaterial, null, null, ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
using Autodesk.AutoCAD.Colors;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Objects.Other;
|
||||
using Speckle.Sdk;
|
||||
using Material = Autodesk.AutoCAD.DatabaseServices.Material;
|
||||
using RenderMaterial = Speckle.Objects.Other.RenderMaterial;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency for a given operation and helps with layer creation and cleanup.
|
||||
/// </summary>
|
||||
public class AutocadMaterialUnpacker
|
||||
{
|
||||
private readonly ILogger<AutocadMaterialUnpacker> _logger;
|
||||
|
||||
public AutocadMaterialUnpacker(ILogger<AutocadMaterialUnpacker> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates through a given set of autocad objects and collects their materials. Note: expects objects to be "atomic", and extracted out of their instances already.
|
||||
/// </summary>
|
||||
/// <param name="unpackedAutocadObjects"></param>
|
||||
/// <param name="layers"></param>
|
||||
/// <returns></returns>
|
||||
public List<RenderMaterialProxy> UnpackMaterials(
|
||||
List<AutocadRootObject> unpackedAutocadObjects,
|
||||
List<LayerTableRecord> layers
|
||||
)
|
||||
{
|
||||
Dictionary<string, RenderMaterialProxy> materialProxies = new();
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
// Stage 1: unpack materials from objects
|
||||
foreach (AutocadRootObject rootObj in unpackedAutocadObjects)
|
||||
{
|
||||
try
|
||||
{
|
||||
Entity entity = rootObj.Root;
|
||||
|
||||
// skip inherited materials
|
||||
if (entity.Material == "ByLayer" || entity.Material == "ByBlock")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (transaction.GetObject(entity.MaterialId, OpenMode.ForRead) is Material material)
|
||||
{
|
||||
string materialId = material.GetSpeckleApplicationId();
|
||||
if (materialProxies.TryGetValue(materialId, out RenderMaterialProxy? value))
|
||||
{
|
||||
value.objects.Add(rootObj.ApplicationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderMaterialProxy materialProxy = ConvertMaterialToRenderMaterialProxy(material, materialId);
|
||||
materialProxy.objects.Add(rootObj.ApplicationId);
|
||||
materialProxies[materialId] = materialProxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to unpack render material from Autocad Entity");
|
||||
}
|
||||
}
|
||||
|
||||
// Stage 2: make sure we collect layer materials as well
|
||||
foreach (LayerTableRecord layer in layers)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (transaction.GetObject(layer.MaterialId, OpenMode.ForRead) is Material material)
|
||||
{
|
||||
string materialId = material.GetSpeckleApplicationId();
|
||||
string layerId = layer.GetSpeckleApplicationId(); // Do not use handle directly, see note in the 'GetSpeckleApplicationId' method
|
||||
if (materialProxies.TryGetValue(materialId, out RenderMaterialProxy? value))
|
||||
{
|
||||
value.objects.Add(layerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderMaterialProxy materialProxy = ConvertMaterialToRenderMaterialProxy(material, materialId);
|
||||
materialProxy.objects.Add(layerId);
|
||||
materialProxies[materialId] = materialProxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to unpack render material from Autocad Layer");
|
||||
}
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
return materialProxies.Values.ToList();
|
||||
}
|
||||
|
||||
private RenderMaterialProxy ConvertMaterialToRenderMaterialProxy(Material material, string id)
|
||||
{
|
||||
EntityColor diffuseColor = material.Diffuse.Color.Color;
|
||||
System.Drawing.Color diffuse = System.Drawing.Color.FromArgb(
|
||||
diffuseColor.Red,
|
||||
diffuseColor.Green,
|
||||
diffuseColor.Blue
|
||||
);
|
||||
|
||||
RenderMaterial renderMaterial =
|
||||
new()
|
||||
{
|
||||
name = material.Name,
|
||||
opacity = material.Opacity.Percentage,
|
||||
diffuse = diffuse.ToArgb(),
|
||||
applicationId = id
|
||||
};
|
||||
|
||||
// Add additional properties
|
||||
renderMaterial["ior"] = material.Refraction.Index;
|
||||
renderMaterial["reflectivity"] = material.Reflectivity;
|
||||
|
||||
return new RenderMaterialProxy()
|
||||
{
|
||||
value = renderMaterial,
|
||||
objects = new(),
|
||||
applicationId = id
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System.IO;
|
||||
using Speckle.Core.Kits; // POC: Must go https://spockle.atlassian.net/browse/CNX-9325
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
public class AutocadSettings
|
||||
{
|
||||
public AutocadSettings(HostApplication hostAppInfo, HostAppVersion hostAppVersion)
|
||||
{
|
||||
HostAppInfo = hostAppInfo;
|
||||
HostAppVersion = hostAppVersion;
|
||||
Modules = new[] { new DirectoryInfo(typeof(AutocadSettings).Assembly.Location).Parent.FullName };
|
||||
}
|
||||
|
||||
public HostApplication HostAppInfo { get; private set; }
|
||||
public HostAppVersion HostAppVersion { get; private set; }
|
||||
|
||||
public IReadOnlyList<string> Modules { get; private set; }
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Speckle.Core.Kits;
|
||||
using Speckle.Core.Logging;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
|
||||
public static class AcadUnitsExtension
|
||||
{
|
||||
public static string ToSpeckleString(this UnitsValue units)
|
||||
{
|
||||
switch (units)
|
||||
{
|
||||
case UnitsValue.Millimeters:
|
||||
return Units.Millimeters;
|
||||
case UnitsValue.Centimeters:
|
||||
return Units.Centimeters;
|
||||
case UnitsValue.Meters:
|
||||
return Units.Meters;
|
||||
case UnitsValue.Kilometers:
|
||||
return Units.Kilometers;
|
||||
case UnitsValue.Inches:
|
||||
case UnitsValue.USSurveyInch:
|
||||
return Units.Inches;
|
||||
case UnitsValue.Feet:
|
||||
case UnitsValue.USSurveyFeet:
|
||||
return Units.Feet;
|
||||
case UnitsValue.Yards:
|
||||
case UnitsValue.USSurveyYard:
|
||||
return Units.Yards;
|
||||
case UnitsValue.Miles:
|
||||
case UnitsValue.USSurveyMile:
|
||||
return Units.Miles;
|
||||
case UnitsValue.Undefined:
|
||||
return Units.None;
|
||||
default:
|
||||
throw new SpeckleException($"The Unit System \"{units}\" is unsupported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.Runtime;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
|
||||
@@ -25,7 +25,7 @@ public static class DocumentExtensions
|
||||
{
|
||||
if (tr.GetObject(myObjectId, OpenMode.ForRead) is DBObject dbObject)
|
||||
{
|
||||
objects.Add(new(dbObject, objectIdHandle));
|
||||
objects.Add(new((Entity)dbObject, objectIdHandle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -6,12 +6,16 @@ namespace Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
|
||||
public static class EditorExtensions
|
||||
{
|
||||
public static void Zoom(this Editor editor, Extents3d ext)
|
||||
public static void Zoom(this Editor? editor, Extents3d ext)
|
||||
{
|
||||
#if NET8_0
|
||||
ArgumentNullException.ThrowIfNull(editor);
|
||||
#else
|
||||
if (editor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(editor));
|
||||
}
|
||||
#endif
|
||||
|
||||
using ViewTableRecord view = editor.GetCurrentView();
|
||||
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
|
||||
public static class SpeckleApplicationIdExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves the Speckle object application id
|
||||
/// </summary>
|
||||
public static string GetSpeckleApplicationId(this Entity entity) => entity.Handle.Value.ToString();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the Speckle object application id
|
||||
/// </summary>
|
||||
public static string GetSpeckleApplicationId(this DBObject dbObj) => dbObj.Handle.Value.ToString();
|
||||
|
||||
/// <summary>
|
||||
/// Layers and geometries can have same application ids.....
|
||||
/// We should prevent it for sketchup converter. Because when it happens "objects_to_bake" definition
|
||||
/// is changing on the way if it happens.
|
||||
/// </summary>
|
||||
public static string GetSpeckleApplicationId(this LayerTableRecord layerTableRecord) =>
|
||||
$"layer_{layerTableRecord.Handle.Value}";
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a unique material Speckle object application id.
|
||||
/// </summary>
|
||||
/// <remarks> Unconfirmed, but materials and geometries may have same application ids.</remarks>
|
||||
public static string GetSpeckleApplicationId(this Material material) => $"material_{material.Handle.Value}";
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a unique color Speckle object application id from the rgb value and color source.
|
||||
/// </summary>
|
||||
/// <remarks> Uses the rgb value since color names are not unique </remarks>
|
||||
public static string GetSpeckleApplicationId(this AutocadColor color) =>
|
||||
$"color_{color.ColorValue}_{(color.IsByBlock ? "block" : color.IsByLayer ? "layer" : "object")}";
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a unique group Speckle object application id.
|
||||
/// </summary>
|
||||
/// <remarks>Unconfirmed, but groups and geometries may have same application ids.</remarks>
|
||||
public static string GetSpeckleApplicationId(this Group group) => $"group_{group.Handle.Value}";
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Speckle.Connectors.Autocad.Interfaces;
|
||||
|
||||
internal interface IAutocadPlugin
|
||||
{
|
||||
void Initialise();
|
||||
void Shutdown();
|
||||
}
|
||||
+173
-116
@@ -1,125 +1,114 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Core.Models;
|
||||
using Speckle.Connectors.Utils.Builders;
|
||||
using Speckle.Connectors.Utils.Conversion;
|
||||
using Speckle.Connectors.Utils.Instances;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Connectors.Common.Extensions;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Common.Operations.Receive;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Core.Logging;
|
||||
using Speckle.Core.Models.GraphTraversal;
|
||||
using Speckle.Core.Models.Instances;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Dependencies;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Operations.Receive;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Expects to be a scoped dependency per receive operation.</para>
|
||||
/// </summary>
|
||||
public class AutocadHostObjectBuilder : IHostObjectBuilder
|
||||
public class AutocadHostObjectBuilder(
|
||||
IRootToHostConverter converter,
|
||||
AutocadLayerBaker layerBaker,
|
||||
AutocadGroupBaker groupBaker,
|
||||
AutocadInstanceBaker instanceBaker,
|
||||
IAutocadMaterialBaker materialBaker,
|
||||
IAutocadColorBaker colorBaker,
|
||||
AutocadContext autocadContext,
|
||||
RootObjectUnpacker rootObjectUnpacker
|
||||
) : IHostObjectBuilder
|
||||
{
|
||||
private readonly AutocadLayerManager _autocadLayerManager;
|
||||
private readonly IRootToHostConverter _converter;
|
||||
private readonly GraphTraversal _traversalFunction;
|
||||
|
||||
// private readonly HashSet<string> _uniqueLayerNames = new();
|
||||
private readonly IInstanceObjectsManager<AutocadRootObject, List<Entity>> _instanceObjectsManager;
|
||||
|
||||
public AutocadHostObjectBuilder(
|
||||
IRootToHostConverter converter,
|
||||
GraphTraversal traversalFunction,
|
||||
AutocadLayerManager autocadLayerManager,
|
||||
IInstanceObjectsManager<AutocadRootObject, List<Entity>> instanceObjectsManager
|
||||
)
|
||||
{
|
||||
_converter = converter;
|
||||
_traversalFunction = traversalFunction;
|
||||
_autocadLayerManager = autocadLayerManager;
|
||||
_instanceObjectsManager = instanceObjectsManager;
|
||||
}
|
||||
|
||||
public HostObjectBuilderResult Build(
|
||||
public Task<HostObjectBuilderResult> Build(
|
||||
Base rootObject,
|
||||
string projectName,
|
||||
string modelName,
|
||||
Action<string, double?>? onOperationProgressed,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
// Prompt the UI conversion started. Progress bar will swoosh.
|
||||
onOperationProgressed?.Invoke("Converting", null);
|
||||
onOperationProgressed.Report(new("Converting", null));
|
||||
|
||||
// Layer filter for received commit with project and model name
|
||||
_autocadLayerManager.CreateLayerFilter(projectName, modelName);
|
||||
|
||||
//TODO: make the layerManager handle \/ ?
|
||||
string baseLayerPrefix = $"SPK-{projectName}-{modelName}-";
|
||||
layerBaker.CreateLayerFilter(projectName, modelName);
|
||||
|
||||
// 0 - Clean then Rock n Roll!
|
||||
string baseLayerPrefix = autocadContext.RemoveInvalidChars($"SPK-{projectName}-{modelName}-");
|
||||
PreReceiveDeepClean(baseLayerPrefix);
|
||||
|
||||
List<ReceiveConversionResult> results = new();
|
||||
List<string> bakedObjectIds = new();
|
||||
// 1 - Unpack objects and proxies from root commit object
|
||||
var unpackedRoot = rootObjectUnpacker.Unpack(rootObject);
|
||||
|
||||
// return new(bakedObjectIds, results);
|
||||
|
||||
var objectGraph = _traversalFunction.Traverse(rootObject).Where(obj => obj.Current is not Collection);
|
||||
// 2 - Split atomic objects and instance components with their path
|
||||
var (atomicObjects, instanceComponents) = rootObjectUnpacker.SplitAtomicObjectsAndInstances(
|
||||
unpackedRoot.ObjectsToConvert
|
||||
);
|
||||
var atomicObjectsWithPath = layerBaker.GetAtomicObjectsWithPath(atomicObjects);
|
||||
var instanceComponentsWithPath = layerBaker.GetInstanceComponentsWithPath(instanceComponents);
|
||||
|
||||
// POC: these are not captured by traversal, so we need to re-add them here
|
||||
var instanceDefinitionProxies = (rootObject["instanceDefinitionProxies"] as List<object>)
|
||||
?.Cast<InstanceDefinitionProxy>()
|
||||
.ToList();
|
||||
|
||||
var instanceComponents = new List<(string[] path, IInstanceComponent obj)>();
|
||||
// POC: these are not captured by traversal, so we need to re-add them here
|
||||
if (instanceDefinitionProxies != null && instanceDefinitionProxies.Count > 0)
|
||||
if (unpackedRoot.DefinitionProxies != null && unpackedRoot.DefinitionProxies.Count > 0)
|
||||
{
|
||||
var transformed = instanceDefinitionProxies.Select(proxy => (Array.Empty<string>(), proxy as IInstanceComponent));
|
||||
instanceComponents.AddRange(transformed);
|
||||
var transformed = unpackedRoot.DefinitionProxies.Select(proxy =>
|
||||
(Array.Empty<Collection>(), proxy as IInstanceComponent)
|
||||
);
|
||||
instanceComponentsWithPath.AddRange(transformed);
|
||||
}
|
||||
|
||||
var atomicObjects = new List<(string layerName, Base obj)>();
|
||||
|
||||
foreach (TraversalContext tc in objectGraph)
|
||||
// 3 - Bake materials and colors, as they are used later down the line by layers and objects
|
||||
if (unpackedRoot.RenderMaterialProxies != null)
|
||||
{
|
||||
var layerName = _autocadLayerManager.GetLayerPath(tc, baseLayerPrefix);
|
||||
if (tc.Current is IInstanceComponent instanceComponent)
|
||||
{
|
||||
instanceComponents.Add((new string[] { layerName }, instanceComponent));
|
||||
}
|
||||
else
|
||||
{
|
||||
atomicObjects.Add((layerName, tc.Current));
|
||||
}
|
||||
materialBaker.ParseAndBakeRenderMaterials(
|
||||
unpackedRoot.RenderMaterialProxies,
|
||||
baseLayerPrefix,
|
||||
onOperationProgressed
|
||||
);
|
||||
}
|
||||
|
||||
// Stage 1: Convert atomic objects
|
||||
Dictionary<string, List<Entity>> applicationIdMap = new();
|
||||
if (unpackedRoot.ColorProxies != null)
|
||||
{
|
||||
colorBaker.ParseColors(unpackedRoot.ColorProxies, onOperationProgressed);
|
||||
}
|
||||
|
||||
// 4 - Convert atomic objects
|
||||
HashSet<ReceiveConversionResult> results = new();
|
||||
HashSet<string> bakedObjectIds = new();
|
||||
Dictionary<string, IReadOnlyCollection<Entity>> applicationIdMap = new();
|
||||
var count = 0;
|
||||
foreach (var (layerName, atomicObject) in atomicObjects)
|
||||
foreach (var (layerPath, atomicObject) in atomicObjectsWithPath)
|
||||
{
|
||||
onOperationProgressed?.Invoke("Converting objects", (double)++count / atomicObjects.Count);
|
||||
string objectId = atomicObject.applicationId ?? atomicObject.id.NotNull();
|
||||
onOperationProgressed.Report(new("Converting objects", (double)++count / atomicObjects.Count));
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
var convertedObjects = ConvertObject(atomicObject, layerName).ToList();
|
||||
IReadOnlyCollection<Entity> convertedObjects = ConvertObject(atomicObject, layerPath, baseLayerPrefix);
|
||||
|
||||
if (atomicObject.applicationId != null)
|
||||
{
|
||||
applicationIdMap[atomicObject.applicationId] = convertedObjects;
|
||||
}
|
||||
applicationIdMap[objectId] = convertedObjects;
|
||||
|
||||
results.AddRange(
|
||||
convertedObjects.Select(
|
||||
e =>
|
||||
new ReceiveConversionResult(
|
||||
Status.SUCCESS,
|
||||
atomicObject,
|
||||
e.Handle.Value.ToString(),
|
||||
e.GetType().ToString()
|
||||
)
|
||||
)
|
||||
results.UnionWith(
|
||||
convertedObjects.Select(e => new ReceiveConversionResult(
|
||||
Status.SUCCESS,
|
||||
atomicObject,
|
||||
e.GetSpeckleApplicationId(),
|
||||
e.GetType().ToString()
|
||||
))
|
||||
);
|
||||
|
||||
bakedObjectIds.AddRange(convertedObjects.Select(e => e.Handle.Value.ToString()));
|
||||
bakedObjectIds.UnionWith(convertedObjects.Select(e => e.GetSpeckleApplicationId()));
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
@@ -127,55 +116,123 @@ public class AutocadHostObjectBuilder : IHostObjectBuilder
|
||||
}
|
||||
}
|
||||
|
||||
// Stage 2: Convert instances
|
||||
var (createdInstanceIds, consumedObjectIds, instanceConversionResults) = _instanceObjectsManager.BakeInstances(
|
||||
instanceComponents,
|
||||
// 5 - Convert instances
|
||||
var (createdInstanceIds, consumedObjectIds, instanceConversionResults) = instanceBaker.BakeInstances(
|
||||
instanceComponentsWithPath,
|
||||
applicationIdMap,
|
||||
baseLayerPrefix,
|
||||
onOperationProgressed
|
||||
);
|
||||
|
||||
bakedObjectIds.RemoveAll(id => consumedObjectIds.Contains(id));
|
||||
bakedObjectIds.AddRange(createdInstanceIds);
|
||||
results.RemoveAll(result => result.ResultId != null && consumedObjectIds.Contains(result.ResultId));
|
||||
results.AddRange(instanceConversionResults);
|
||||
bakedObjectIds.RemoveWhere(id => consumedObjectIds.Contains(id));
|
||||
bakedObjectIds.UnionWith(createdInstanceIds);
|
||||
results.RemoveWhere(result => result.ResultId != null && consumedObjectIds.Contains(result.ResultId));
|
||||
results.UnionWith(instanceConversionResults);
|
||||
|
||||
return new(bakedObjectIds, results);
|
||||
// 6 - Create groups
|
||||
if (unpackedRoot.GroupProxies != null)
|
||||
{
|
||||
IReadOnlyCollection<ReceiveConversionResult> groupResults = groupBaker.CreateGroups(
|
||||
unpackedRoot.GroupProxies,
|
||||
applicationIdMap
|
||||
);
|
||||
results.UnionWith(groupResults);
|
||||
}
|
||||
|
||||
return Task.FromResult(new HostObjectBuilderResult(bakedObjectIds, results));
|
||||
}
|
||||
|
||||
private void PreReceiveDeepClean(string baseLayerPrefix)
|
||||
{
|
||||
_autocadLayerManager.DeleteAllLayersByPrefix(baseLayerPrefix);
|
||||
_instanceObjectsManager.PurgeInstances(baseLayerPrefix);
|
||||
layerBaker.DeleteAllLayersByPrefix(baseLayerPrefix);
|
||||
instanceBaker.PurgeInstances(baseLayerPrefix);
|
||||
materialBaker.PurgeMaterials(baseLayerPrefix);
|
||||
}
|
||||
|
||||
private IEnumerable<Entity> ConvertObject(Base obj, string layerName)
|
||||
private IReadOnlyCollection<Entity> ConvertObject(Base obj, Collection[] layerPath, string baseLayerNamePrefix)
|
||||
{
|
||||
using TransactionContext transactionContext = TransactionContext.StartTransaction(
|
||||
Application.DocumentManager.MdiActiveDocument
|
||||
string layerName = layerBaker.CreateLayerForReceive(layerPath, baseLayerNamePrefix);
|
||||
var convertedEntities = new HashSet<Entity>();
|
||||
|
||||
using var tr = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
// 1: convert
|
||||
var converted = converter.Convert(obj);
|
||||
|
||||
// 2: handle result
|
||||
switch (converted)
|
||||
{
|
||||
case Entity entity:
|
||||
var bakedEntity = BakeObject(entity, obj, layerName);
|
||||
convertedEntities.Add(bakedEntity);
|
||||
break;
|
||||
|
||||
case List<(Entity, Base)> listConversionResult: // this is from fallback conversion for brep/brepx/subdx/extrusionx/polycurve
|
||||
var bakedFallbackEntities = BakeObjectsAsGroup(listConversionResult, obj, layerName, baseLayerNamePrefix);
|
||||
convertedEntities.UnionWith(bakedFallbackEntities);
|
||||
break;
|
||||
|
||||
default:
|
||||
// TODO: capture defualt case with report object here? Same as in Rhino
|
||||
break;
|
||||
}
|
||||
|
||||
tr.Commit();
|
||||
return convertedEntities.Freeze();
|
||||
}
|
||||
|
||||
private Entity BakeObject(Entity entity, Base originalObject, string layerName, Base? parentObject = null)
|
||||
{
|
||||
var objId = originalObject.applicationId ?? originalObject.id.NotNull();
|
||||
if (colorBaker.ObjectColorsIdMap.TryGetValue(objId, out AutocadColor? color))
|
||||
{
|
||||
entity.Color = color;
|
||||
}
|
||||
|
||||
if (materialBaker.TryGetMaterialId(originalObject, parentObject, out ObjectId matId))
|
||||
{
|
||||
entity.MaterialId = matId;
|
||||
}
|
||||
|
||||
entity.AppendToDb(layerName);
|
||||
return entity;
|
||||
}
|
||||
|
||||
private List<Entity> BakeObjectsAsGroup(
|
||||
List<(Entity, Base)> fallbackConversionResult,
|
||||
Base parentObject,
|
||||
string layerName,
|
||||
string baseLayerName
|
||||
)
|
||||
{
|
||||
var ids = new ObjectIdCollection();
|
||||
var entities = new List<Entity>();
|
||||
foreach (var (conversionResult, originalObject) in fallbackConversionResult)
|
||||
{
|
||||
BakeObject(conversionResult, originalObject, layerName, parentObject);
|
||||
ids.Add(conversionResult.ObjectId);
|
||||
entities.Add(conversionResult);
|
||||
}
|
||||
|
||||
if (entities.Count <= 1) // return if empty list or only one, because we don't want to create empty or single item groups.
|
||||
{
|
||||
return entities;
|
||||
}
|
||||
|
||||
var tr = Application.DocumentManager.CurrentDocument.Database.TransactionManager.TopTransaction;
|
||||
var groupDictionary = (DBDictionary)
|
||||
tr.GetObject(Application.DocumentManager.CurrentDocument.Database.GroupDictionaryId, OpenMode.ForWrite);
|
||||
|
||||
var groupName = autocadContext.RemoveInvalidChars(
|
||||
$@"{parentObject.speckle_type.Split('.').Last()} - {parentObject.applicationId ?? parentObject.id} ({baseLayerName})"
|
||||
);
|
||||
|
||||
_autocadLayerManager.CreateLayerForReceive(layerName);
|
||||
var newGroup = new Group(groupName, true);
|
||||
newGroup.Append(ids);
|
||||
groupDictionary.UpgradeOpen();
|
||||
groupDictionary.SetAt(groupName, newGroup);
|
||||
tr.AddNewlyCreatedDBObject(newGroup, true);
|
||||
|
||||
object converted;
|
||||
using (var tr = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction())
|
||||
{
|
||||
converted = _converter.Convert(obj);
|
||||
tr.Commit();
|
||||
}
|
||||
|
||||
IEnumerable<Entity?> flattened = Utilities.FlattenToHostConversionResult(converted).Cast<Entity>();
|
||||
|
||||
foreach (Entity? conversionResult in flattened)
|
||||
{
|
||||
if (conversionResult == null)
|
||||
{
|
||||
// POC: This needed to be double checked why we check null and continue
|
||||
continue;
|
||||
}
|
||||
|
||||
conversionResult.AppendToDb(layerName);
|
||||
yield return conversionResult;
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Operations.Send;
|
||||
|
||||
// Note: naming is a bit confusing, Root is similar to base commit object, or root commit object, etc. It might be just in my head (dim)
|
||||
public record AutocadRootObject(DBObject Root, string ApplicationId);
|
||||
public record AutocadRootObject(Entity Root, string ApplicationId);
|
||||
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Connectors.Common.Extensions;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Logging;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Operations.Send;
|
||||
|
||||
public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder<AutocadRootObject>
|
||||
{
|
||||
private readonly IRootToSpeckleConverter _converter;
|
||||
private readonly string[] _documentPathSeparator = ["\\"];
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly AutocadInstanceUnpacker _instanceUnpacker;
|
||||
private readonly AutocadMaterialUnpacker _materialUnpacker;
|
||||
private readonly AutocadColorUnpacker _colorUnpacker;
|
||||
private readonly AutocadGroupUnpacker _groupUnpacker;
|
||||
private readonly ILogger<AutocadRootObjectBuilder> _logger;
|
||||
private readonly ISdkActivityFactory _activityFactory;
|
||||
|
||||
protected AutocadRootObjectBaseBuilder(
|
||||
IRootToSpeckleConverter converter,
|
||||
ISendConversionCache sendConversionCache,
|
||||
AutocadInstanceUnpacker instanceObjectManager,
|
||||
AutocadMaterialUnpacker materialUnpacker,
|
||||
AutocadColorUnpacker colorUnpacker,
|
||||
AutocadGroupUnpacker groupUnpacker,
|
||||
ILogger<AutocadRootObjectBuilder> logger,
|
||||
ISdkActivityFactory activityFactory
|
||||
)
|
||||
{
|
||||
_converter = converter;
|
||||
_sendConversionCache = sendConversionCache;
|
||||
_instanceUnpacker = instanceObjectManager;
|
||||
_materialUnpacker = materialUnpacker;
|
||||
_colorUnpacker = colorUnpacker;
|
||||
_groupUnpacker = groupUnpacker;
|
||||
_logger = logger;
|
||||
_activityFactory = activityFactory;
|
||||
}
|
||||
|
||||
[SuppressMessage(
|
||||
"Maintainability",
|
||||
"CA1506:Avoid excessive class coupling",
|
||||
Justification = """
|
||||
It is already simplified but has many different references since it is a builder. Do not know can we simplify it now.
|
||||
Later we might consider to refactor proxies from one proxy manager? but we do not know the shape of it all potential
|
||||
proxy classes yet. So I'm supressing this one now!!!
|
||||
"""
|
||||
)]
|
||||
public Task<RootObjectBuilderResult> Build(
|
||||
IReadOnlyList<AutocadRootObject> objects,
|
||||
SendInfo sendInfo,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
// 0 - Init the root
|
||||
Collection root =
|
||||
new()
|
||||
{
|
||||
name = Application
|
||||
.DocumentManager.CurrentDocument.Name // POC: https://spockle.atlassian.net/browse/CNX-9319
|
||||
.Split(_documentPathSeparator, StringSplitOptions.None)
|
||||
.Reverse()
|
||||
.First()
|
||||
};
|
||||
|
||||
// TODO: better handling for document and transactions!!
|
||||
Document doc = Application.DocumentManager.CurrentDocument;
|
||||
using Transaction tr = doc.Database.TransactionManager.StartTransaction();
|
||||
|
||||
// 1 - Unpack the instances
|
||||
var (atomicObjects, instanceProxies, instanceDefinitionProxies) = _instanceUnpacker.UnpackSelection(objects);
|
||||
root[ProxyKeys.INSTANCE_DEFINITION] = instanceDefinitionProxies;
|
||||
|
||||
// 2 - Unpack the groups
|
||||
root[ProxyKeys.GROUP] = _groupUnpacker.UnpackGroups(atomicObjects);
|
||||
using (var _ = _activityFactory.Start("Converting objects"))
|
||||
{
|
||||
// 3 - Convert atomic objects
|
||||
List<LayerTableRecord> usedAcadLayers = new(); // Keeps track of autocad layers used, so we can pass them on later to the material and color unpacker.
|
||||
List<SendConversionResult> results = new();
|
||||
int count = 0;
|
||||
foreach (var (entity, applicationId) in atomicObjects)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
using (var convertActivity = _activityFactory.Start("Converting object"))
|
||||
{
|
||||
// Create and add a collection for this entity if not done so already.
|
||||
(Collection objectCollection, LayerTableRecord? autocadLayer) = CreateObjectCollection(entity, tr);
|
||||
|
||||
if (autocadLayer is not null)
|
||||
{
|
||||
usedAcadLayers.Add(autocadLayer);
|
||||
root.elements.Add(objectCollection);
|
||||
}
|
||||
|
||||
var result = ConvertAutocadEntity(
|
||||
entity,
|
||||
applicationId,
|
||||
objectCollection,
|
||||
instanceProxies,
|
||||
sendInfo.ProjectId
|
||||
);
|
||||
results.Add(result);
|
||||
|
||||
onOperationProgressed.Report(new("Converting", (double)++count / atomicObjects.Count));
|
||||
}
|
||||
}
|
||||
|
||||
if (results.All(x => x.Status == Status.ERROR))
|
||||
{
|
||||
throw new SpeckleException("Failed to convert all objects."); // fail fast instead creating empty commit! It will appear as model card error with red color.
|
||||
}
|
||||
|
||||
// 4 - Unpack the render material proxies
|
||||
root[ProxyKeys.RENDER_MATERIAL] = _materialUnpacker.UnpackMaterials(atomicObjects, usedAcadLayers);
|
||||
|
||||
// 5 - Unpack the color proxies
|
||||
root[ProxyKeys.COLOR] = _colorUnpacker.UnpackColors(atomicObjects, usedAcadLayers);
|
||||
|
||||
// add any additional properties (most likely from verticals)
|
||||
AddAdditionalProxiesToRoot(root);
|
||||
|
||||
return Task.FromResult(new RootObjectBuilderResult(root, results));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual (Collection, LayerTableRecord?) CreateObjectCollection(Entity entity, Transaction tr)
|
||||
{
|
||||
return (new(), null);
|
||||
}
|
||||
|
||||
public virtual void AddAdditionalProxiesToRoot(Collection rootCollection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
private SendConversionResult ConvertAutocadEntity(
|
||||
Entity entity,
|
||||
string applicationId,
|
||||
Collection collectionHost,
|
||||
IReadOnlyDictionary<string, InstanceProxy> instanceProxies,
|
||||
string projectId
|
||||
)
|
||||
{
|
||||
string sourceType = entity.GetType().ToString();
|
||||
try
|
||||
{
|
||||
Base converted;
|
||||
if (entity is BlockReference && instanceProxies.TryGetValue(applicationId, out InstanceProxy? instanceProxy))
|
||||
{
|
||||
converted = instanceProxy;
|
||||
}
|
||||
else if (_sendConversionCache.TryGetValue(projectId, applicationId, out ObjectReference? value))
|
||||
{
|
||||
converted = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
converted = _converter.Convert(entity);
|
||||
converted.applicationId = applicationId;
|
||||
}
|
||||
|
||||
collectionHost.elements.Add(converted);
|
||||
return new(Status.SUCCESS, applicationId, sourceType, converted);
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogSendConversionError(ex, sourceType);
|
||||
return new(Status.ERROR, applicationId, sourceType, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
-95
@@ -1,113 +1,46 @@
|
||||
using System.Diagnostics;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Speckle.Connectors.Utils.Builders;
|
||||
using Speckle.Connectors.Utils.Caching;
|
||||
using Speckle.Connectors.Utils.Conversion;
|
||||
using Speckle.Connectors.Utils.Instances;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Core.Logging;
|
||||
using Speckle.Core.Models;
|
||||
using Speckle.Core.Models.Instances;
|
||||
using Speckle.Sdk.Logging;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Operations.Send;
|
||||
|
||||
public class AutocadRootObjectBuilder : IRootObjectBuilder<AutocadRootObject>
|
||||
public sealed class AutocadRootObjectBuilder : AutocadRootObjectBaseBuilder
|
||||
{
|
||||
private readonly IRootToSpeckleConverter _converter;
|
||||
private readonly string[] _documentPathSeparator = { "\\" };
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly IInstanceObjectsManager<AutocadRootObject, List<Entity>> _instanceObjectsManager;
|
||||
private readonly AutocadLayerUnpacker _layerUnpacker;
|
||||
|
||||
public AutocadRootObjectBuilder(
|
||||
AutocadLayerUnpacker layerUnpacker,
|
||||
IRootToSpeckleConverter converter,
|
||||
ISendConversionCache sendConversionCache,
|
||||
IInstanceObjectsManager<AutocadRootObject, List<Entity>> instanceObjectManager
|
||||
AutocadInstanceUnpacker instanceObjectManager,
|
||||
AutocadMaterialUnpacker materialUnpacker,
|
||||
AutocadColorUnpacker colorUnpacker,
|
||||
AutocadGroupUnpacker groupUnpacker,
|
||||
ILogger<AutocadRootObjectBuilder> logger,
|
||||
ISdkActivityFactory activityFactory
|
||||
)
|
||||
: base(
|
||||
converter,
|
||||
sendConversionCache,
|
||||
instanceObjectManager,
|
||||
materialUnpacker,
|
||||
colorUnpacker,
|
||||
groupUnpacker,
|
||||
logger,
|
||||
activityFactory
|
||||
)
|
||||
{
|
||||
_converter = converter;
|
||||
_sendConversionCache = sendConversionCache;
|
||||
_instanceObjectsManager = instanceObjectManager;
|
||||
_layerUnpacker = layerUnpacker;
|
||||
}
|
||||
|
||||
public RootObjectBuilderResult Build(
|
||||
IReadOnlyList<AutocadRootObject> objects,
|
||||
SendInfo sendInfo,
|
||||
Action<string, double?>? onOperationProgressed = null,
|
||||
CancellationToken ct = default
|
||||
)
|
||||
public override (Collection, LayerTableRecord?) CreateObjectCollection(Entity entity, Transaction tr)
|
||||
{
|
||||
Collection modelWithLayers =
|
||||
new()
|
||||
{
|
||||
name = Application.DocumentManager.CurrentDocument.Name // POC: https://spockle.atlassian.net/browse/CNX-9319
|
||||
.Split(_documentPathSeparator, StringSplitOptions.None)
|
||||
.Reverse()
|
||||
.First(),
|
||||
collectionType = "root"
|
||||
};
|
||||
Layer layer = _layerUnpacker.GetOrCreateSpeckleLayer(entity, tr, out LayerTableRecord? autocadLayer);
|
||||
|
||||
// Cached dictionary to create Collection for autocad entity layers. We first look if collection exists. If so use it otherwise create new one for that layer.
|
||||
Dictionary<string, Collection> collectionCache = new();
|
||||
int count = 0;
|
||||
|
||||
var (atomicObjects, instanceProxies, instanceDefinitionProxies) = _instanceObjectsManager.UnpackSelection(objects);
|
||||
// POC: until we formalise a bit more the root object
|
||||
modelWithLayers["instanceDefinitionProxies"] = instanceDefinitionProxies;
|
||||
|
||||
List<SendConversionResult> results = new();
|
||||
var cacheHitCount = 0;
|
||||
|
||||
foreach (var (dbObject, applicationId) in atomicObjects)
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
Base converted;
|
||||
if (dbObject is BlockReference && instanceProxies.TryGetValue(applicationId, out InstanceProxy instanceProxy))
|
||||
{
|
||||
converted = instanceProxy;
|
||||
}
|
||||
else if (_sendConversionCache.TryGetValue(sendInfo.ProjectId, applicationId, out ObjectReference value))
|
||||
{
|
||||
converted = value;
|
||||
cacheHitCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
converted = _converter.Convert(dbObject);
|
||||
converted.applicationId = applicationId;
|
||||
}
|
||||
|
||||
// Create and add a collection for each layer if not done so already.
|
||||
if ((dbObject as Entity)?.Layer is string layer)
|
||||
{
|
||||
if (!collectionCache.TryGetValue(layer, out Collection? collection))
|
||||
{
|
||||
collection = new Collection() { name = layer, collectionType = "layer" };
|
||||
collectionCache[layer] = collection;
|
||||
modelWithLayers.elements.Add(collectionCache[layer]);
|
||||
}
|
||||
|
||||
collection.elements.Add(converted);
|
||||
}
|
||||
|
||||
results.Add(new(Status.SUCCESS, applicationId, dbObject.GetType().ToString(), converted));
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
results.Add(new(Status.ERROR, applicationId, dbObject.GetType().ToString(), null, ex));
|
||||
// POC: add logging
|
||||
}
|
||||
|
||||
onOperationProgressed?.Invoke("Converting", (double)++count / atomicObjects.Count);
|
||||
}
|
||||
|
||||
// POC: Log would be nice, or can be removed.
|
||||
Debug.WriteLine(
|
||||
$"Cache hit count {cacheHitCount} out of {objects.Count} ({(double)cacheHitCount / objects.Count})"
|
||||
);
|
||||
|
||||
return new(modelWithLayers, results);
|
||||
return (layer, autocadLayer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
using Speckle.Connectors.Common;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Plugin;
|
||||
|
||||
public static class AppUtils
|
||||
{
|
||||
public static Speckle.Sdk.Application App =>
|
||||
#if CIVIL3D
|
||||
HostApplications.Civil3D;
|
||||
#elif AUTOCAD
|
||||
HostApplications.AutoCAD;
|
||||
#else
|
||||
throw new NotSupportedException();
|
||||
#endif
|
||||
|
||||
public static HostAppVersion Version =>
|
||||
#if AUTOCAD2026 || CIVIL3D2026
|
||||
HostAppVersion.v2026;
|
||||
#elif AUTOCAD2025 || CIVIL3D2025
|
||||
HostAppVersion.v2025;
|
||||
#elif AUTOCAD2024 || CIVIL3D2024
|
||||
HostAppVersion.v2024;
|
||||
#elif AUTOCAD2023|| CIVIL3D2023
|
||||
HostAppVersion.v2023;
|
||||
#elif AUTOCAD2022 || CIVIL3D2022
|
||||
HostAppVersion.v2022;
|
||||
#else
|
||||
throw new NotSupportedException();
|
||||
#endif
|
||||
}
|
||||
@@ -1,24 +1,28 @@
|
||||
using System.Drawing;
|
||||
using System.Reflection;
|
||||
using Autodesk.AutoCAD.Runtime;
|
||||
using Autodesk.AutoCAD.Windows;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Core.Kits;
|
||||
using Speckle.Connectors.Autocad.Interfaces;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.Common;
|
||||
using Speckle.Connectors.DUI;
|
||||
using Speckle.Connectors.DUI.WebView;
|
||||
|
||||
#if AUTOCAD
|
||||
using Speckle.Connectors.Autocad.DependencyInjection;
|
||||
using Speckle.Converters.Autocad;
|
||||
#elif CIVIL3D
|
||||
using Speckle.Converters.Civil3dShared;
|
||||
using Speckle.Connectors.Civil3dShared.DependencyInjection;
|
||||
#endif
|
||||
namespace Speckle.Connectors.Autocad.Plugin;
|
||||
|
||||
public class AutocadCommand
|
||||
{
|
||||
private static PaletteSet? PaletteSet { get; set; }
|
||||
private static readonly Guid s_id = new("3223E594-1B09-4E54-B3DD-8EA0BECE7BA5");
|
||||
private IAutocadPlugin? _autocadPlugin;
|
||||
public ServiceProvider? Container { get; private set; }
|
||||
private IDisposable? _disposableLogger;
|
||||
public const string COMMAND_STRING = "SpeckleBeta";
|
||||
|
||||
public SpeckleContainer? Container { get; private set; }
|
||||
|
||||
[CommandMethod("SpeckleNewUI")]
|
||||
[CommandMethod(COMMAND_STRING)]
|
||||
public void Command()
|
||||
{
|
||||
if (PaletteSet != null)
|
||||
@@ -27,33 +31,28 @@ public class AutocadCommand
|
||||
return;
|
||||
}
|
||||
|
||||
PaletteSet = new PaletteSet("Speckle DUI3", s_id)
|
||||
PaletteSet = new PaletteSet($"Speckle (Beta)", s_id)
|
||||
{
|
||||
Size = new Size(400, 500),
|
||||
DockEnabled = (DockSides)((int)DockSides.Left + (int)DockSides.Right)
|
||||
};
|
||||
|
||||
var builder = SpeckleContainerBuilder.CreateInstance();
|
||||
|
||||
#if CIVIL3D2024
|
||||
AutocadSettings autocadSettings = new (HostApplications.Civil3D, HostAppVersion.v2024);
|
||||
#elif AUTOCAD2023
|
||||
AutocadSettings autocadSettings = new(HostApplications.AutoCAD, HostAppVersion.v2023);
|
||||
#else
|
||||
AutocadSettings autocadSettings = new(HostApplications.AutoCAD, HostAppVersion.v2023);
|
||||
// init DI
|
||||
var services = new ServiceCollection();
|
||||
_disposableLogger = services.Initialize(AppUtils.App, AppUtils.Version);
|
||||
#if AUTOCAD
|
||||
services.AddAutocad();
|
||||
services.AddAutocadConverters();
|
||||
#elif CIVIL3D
|
||||
services.AddCivil3d();
|
||||
services.AddCivil3dConverters();
|
||||
#endif
|
||||
Container = builder
|
||||
.LoadAutofacModules(Assembly.GetExecutingAssembly(), autocadSettings.Modules)
|
||||
.AddSingleton(autocadSettings)
|
||||
.Build();
|
||||
Container = services.BuildServiceProvider();
|
||||
Container.UseDUI();
|
||||
|
||||
// Resolve root plugin object and initialise.
|
||||
_autocadPlugin = Container.Resolve<IAutocadPlugin>();
|
||||
_autocadPlugin.Initialise();
|
||||
var panelWebView = Container.GetRequiredService<DUI3ControlWebView>();
|
||||
|
||||
var panelWebView = Container.Resolve<DUI3ControlWebView>();
|
||||
|
||||
PaletteSet.AddVisual("Speckle DUI3 WebView", panelWebView);
|
||||
PaletteSet.AddVisual("Speckle (Beta)", panelWebView);
|
||||
|
||||
FocusPalette();
|
||||
}
|
||||
|
||||
+8
-2
@@ -1,12 +1,18 @@
|
||||
using Autodesk.AutoCAD.Runtime;
|
||||
using Speckle.Autofac;
|
||||
using Speckle.Connectors.Common;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Plugin;
|
||||
|
||||
public class AutocadExtensionApplication : IExtensionApplication
|
||||
{
|
||||
public void Initialize() =>
|
||||
public void Initialize()
|
||||
{
|
||||
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolver.OnAssemblyResolve<AutocadExtensionApplication>;
|
||||
|
||||
AutocadCommand autocadCommand = new();
|
||||
AutocadRibbon ribbon = new(autocadCommand);
|
||||
ribbon.CreateRibbon();
|
||||
}
|
||||
|
||||
public void Terminate() { }
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Autocad.Interfaces;
|
||||
using Speckle.Connectors.DUI.WebView;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Plugin;
|
||||
|
||||
public class AutocadPlugin : IAutocadPlugin
|
||||
{
|
||||
private readonly AutocadIdleManager _idleManager;
|
||||
private readonly DUI3ControlWebView _panel;
|
||||
private readonly AutocadSettings _settings;
|
||||
|
||||
public AutocadPlugin(DUI3ControlWebView panel, AutocadSettings settings, AutocadIdleManager idleManager)
|
||||
{
|
||||
_panel = panel;
|
||||
_settings = settings;
|
||||
_idleManager = idleManager;
|
||||
}
|
||||
|
||||
public void Initialise() { }
|
||||
|
||||
public void Shutdown() { }
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
using System.Reflection;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Autodesk.Windows;
|
||||
using Speckle.Sdk;
|
||||
#if !AUTOCAD2025_OR_GREATER && !CIVIL3D2025_OR_GREATER
|
||||
using System.IO;
|
||||
#endif
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Plugin;
|
||||
|
||||
public class AutocadRibbon
|
||||
{
|
||||
private RibbonControl? _ribbon;
|
||||
private readonly AutocadCommand _command;
|
||||
|
||||
public AutocadRibbon(AutocadCommand command)
|
||||
{
|
||||
_command = command;
|
||||
}
|
||||
|
||||
public bool CreateRibbon()
|
||||
{
|
||||
_ribbon = ComponentManager.Ribbon;
|
||||
try
|
||||
{
|
||||
if (_ribbon != null) //the assembly was loaded using netload
|
||||
{
|
||||
Create();
|
||||
}
|
||||
else
|
||||
{
|
||||
// load the custom ribbon on startup, but wait for ribbon control to be created
|
||||
ComponentManager.ItemInitialized += new System.EventHandler<RibbonItemEventArgs>(
|
||||
ComponentManager_ItemInitialized
|
||||
);
|
||||
Application.SystemVariableChanged += TrapWSCurrentChange;
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
return false;
|
||||
// todo: report error
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void Create()
|
||||
{
|
||||
RibbonTab tab = FindOrMakeTab("Speckle");
|
||||
RibbonPanelSource source = new() { Title = "Speckle (Beta)" };
|
||||
RibbonPanel panel = new() { Source = source };
|
||||
tab.Panels.Add(panel);
|
||||
|
||||
RibbonToolTip speckleToolTip =
|
||||
new()
|
||||
{
|
||||
Title = "Speckle (Beta)",
|
||||
Content = $"Next Gen Speckle Connector (Beta) for {AppUtils.App.Name}",
|
||||
IsHelpEnabled = true // Without this "Press F1 for help" does not appear in the tooltip
|
||||
};
|
||||
|
||||
_ = CreateSpeckleButton("Speckle (Beta)", source, null, speckleToolTip, "logo");
|
||||
}
|
||||
|
||||
private void ComponentManager_ItemInitialized(object? sender, RibbonItemEventArgs e)
|
||||
{
|
||||
// one Ribbon item is initialized, check for Ribbon control
|
||||
_ribbon = ComponentManager.Ribbon;
|
||||
if (_ribbon != null)
|
||||
{
|
||||
Create();
|
||||
// remove the event handler
|
||||
ComponentManager.ItemInitialized -= new System.EventHandler<RibbonItemEventArgs>(
|
||||
ComponentManager_ItemInitialized
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// solving workspace changing
|
||||
private void TrapWSCurrentChange(object sender, Autodesk.AutoCAD.ApplicationServices.SystemVariableChangedEventArgs e)
|
||||
{
|
||||
if (e.Name.Equals("WSCURRENT"))
|
||||
{
|
||||
Create();
|
||||
}
|
||||
}
|
||||
|
||||
private RibbonTab FindOrMakeTab(string name)
|
||||
{
|
||||
if (_ribbon is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Ribbon control was null, could not create tab {name}");
|
||||
}
|
||||
|
||||
RibbonTab? tab = _ribbon.Tabs.FirstOrDefault(o => o.Title.Equals(name)); // check to see if tab exists
|
||||
if (tab is null) // if not, create a new one
|
||||
{
|
||||
tab = new RibbonTab { Title = name, Id = name };
|
||||
_ribbon.Tabs.Add(tab);
|
||||
}
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
private RibbonButton CreateSpeckleButton(
|
||||
string name,
|
||||
RibbonPanelSource? sourcePanel = null,
|
||||
RibbonSplitButton? sourceButton = null,
|
||||
RibbonToolTip? tooltip = null,
|
||||
string imageName = ""
|
||||
)
|
||||
{
|
||||
var button = new RibbonButton
|
||||
{
|
||||
// ribbon panel source info assignment
|
||||
Text = name,
|
||||
Id = name,
|
||||
ShowImage = true,
|
||||
ShowText = true,
|
||||
ToolTip = tooltip,
|
||||
HelpSource = new System.Uri("https://speckle.guide/user/autocadcivil.html"),
|
||||
Size = RibbonItemSize.Large
|
||||
};
|
||||
|
||||
if (TryLoadPngImgSource(imageName + "16.png", out ImageSource? imageSource))
|
||||
{
|
||||
button.Image = imageSource;
|
||||
}
|
||||
|
||||
if (TryLoadPngImgSource(imageName + "32.png", out ImageSource? largeImageSource))
|
||||
{
|
||||
button.LargeImage = largeImageSource;
|
||||
}
|
||||
|
||||
// add ribbon button panel to the ribbon panel source
|
||||
if (sourcePanel != null)
|
||||
{
|
||||
button.Orientation = System.Windows.Controls.Orientation.Vertical;
|
||||
button.CommandParameter = AutocadCommand.COMMAND_STRING;
|
||||
button.CommandHandler = new SpeckleButtonCommandHandler(_command);
|
||||
sourcePanel.Items.Add(button);
|
||||
}
|
||||
else if (sourceButton != null)
|
||||
{
|
||||
button.Orientation = System.Windows.Controls.Orientation.Horizontal;
|
||||
button.CommandParameter = AutocadCommand.COMMAND_STRING;
|
||||
button.CommandHandler = new SpeckleButtonCommandHandler(_command);
|
||||
sourceButton.Items.Add(button);
|
||||
}
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the png image source
|
||||
/// </summary>
|
||||
/// <param name="sourceName"></param>
|
||||
/// <returns></returns>
|
||||
private bool TryLoadPngImgSource(string sourceName, out System.Windows.Media.ImageSource? source)
|
||||
{
|
||||
source = null;
|
||||
if (string.IsNullOrEmpty(sourceName) || !sourceName.ToLower().EndsWith(".png"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
string[] assemblyResources = GetType().Assembly.GetManifestResourceNames();
|
||||
string? resource = assemblyResources.Where(o => o.EndsWith(sourceName)).FirstOrDefault();
|
||||
if (string.IsNullOrEmpty(resource))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Stream? stream = null;
|
||||
try
|
||||
{
|
||||
stream = assembly.GetManifestResourceStream(resource);
|
||||
}
|
||||
catch (FileLoadException) { }
|
||||
catch (FileNotFoundException) { }
|
||||
catch (NotImplementedException) { }
|
||||
|
||||
if (stream is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PngBitmapDecoder decoder = new(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
|
||||
if (decoder.Frames.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
source = decoder.Frames[0];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class SpeckleButtonCommandHandler : System.Windows.Input.ICommand
|
||||
{
|
||||
private readonly AutocadCommand _autocadCommand;
|
||||
|
||||
public SpeckleButtonCommandHandler(AutocadCommand autocadCommand)
|
||||
{
|
||||
_autocadCommand = autocadCommand;
|
||||
}
|
||||
|
||||
#pragma warning disable 67
|
||||
// Disabling warning for `event never used` since this is required by autocad
|
||||
public event System.EventHandler? CanExecuteChanged;
|
||||
#pragma warning restore 67
|
||||
|
||||
public void Execute(object? parameter)
|
||||
{
|
||||
if (parameter is RibbonButton)
|
||||
{
|
||||
_autocadCommand.Command();
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanExecute(object? parameter) => true;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 714 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
+20
-10
@@ -9,37 +9,47 @@
|
||||
<Import_RootNamespace>Speckle.Connectors.AutocadShared</Import_RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bindings\AutocadReceiveBaseBinding.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bindings\AutocadSelectionBinding.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bindings\AutocadReceiveBinding.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bindings\AutocadSendBinding.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bindings\AutocadBasicConnectorBinding.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)DependencyInjection\SharedConnectorModule.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bindings\AutocadSendBaseBinding.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)DependencyInjection\SharedRegistration.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)DependencyInjection\AutocadConnectorModule.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)DependencyInjection\Civil3dConnectorModule.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Filters\AutocadSelectionFilter.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadInstanceObjectManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadColorBaker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadColorUnpacker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadGroupBaker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadGroupUnpacker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadIdleManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadInstanceBaker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadInstanceUnpacker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadLayerBaker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadLayerUnpacker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadMaterialBaker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadContext.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadDocumentManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadDocumentModelStore.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadIdleManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadLayerManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadSettings.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Extensions\AcadUnitsExtension.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadMaterialUnpacker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Extensions\DatabaseExtensions.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Extensions\DocumentExtensions.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Extensions\EditorExtensions.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Extensions\EntityExtensions.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Extensions\SpeckleApplicationIdExtensions.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\TransactionContext.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Operations\Receive\AutocadHostObjectBuilder.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\AutocadRootObject.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\AutocadRootObjectBaseBuilder.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\AutocadRootObjectBuilder.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Plugin\AutocadRibbon.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Plugin\AutocadExtensionApplication.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Plugin\AutocadPlugin.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Interfaces\IAutocadPlugin.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Plugin\AutocadCommand.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)GlobalUsings.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Plugin\AppUtils.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="$(MSBuildThisFileDirectory)Interfaces\" />
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Resources\s2logo16.png" />
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Resources\s2logo32.png" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<UseWpf>true</UseWpf>
|
||||
<Civil3DVersion>2022</Civil3DVersion>
|
||||
<DefineConstants>$(DefineConstants);CIVIL3D;CIVIL3D2022;CIVIL3D2022_OR_GREATER</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2022.0.2" ExcludeAssets="runtime"/>
|
||||
<PackageReference Include="Speckle.Civil3D.API" VersionOverride="2022.0.2" ExcludeAssets="runtime"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Civil3d\Speckle.Converters.Civil3d2022\Speckle.Converters.Civil3d2022.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Converters.Common\Speckle.Converters.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\..\Autocad\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems" Label="Shared" />
|
||||
<Import Project="..\..\Autocad\Speckle.Connectors.Civil3dShared\Speckle.Connectors.Civil3dShared.projitems" Label="Shared" />
|
||||
</Project>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user