mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-06 07:51:47 +00:00
Compare commits
950 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2531a58083 | |||
| 70ae0fd850 | |||
| 174749caf7 | |||
| dd8ec95fad | |||
| 0a791a3b85 | |||
| 1c91b966b5 | |||
| db6cda2816 | |||
| d6dab75653 | |||
| 0dc084d785 | |||
| 3bafea62f4 | |||
| 69b7658196 | |||
| 9e93f22e53 | |||
| 94bcb8d266 | |||
| bbd4e00972 | |||
| 16e8c504f3 | |||
| 95c457f53d | |||
| 38f5b77f92 | |||
| 4f1a36753c | |||
| 565a0edb73 | |||
| 54a65abd76 | |||
| 5b16699eb4 | |||
| b4482780cf | |||
| 589b9d4a79 | |||
| 04365053a8 | |||
| c79e490d6d | |||
| b674b8ca58 | |||
| f56bae141b | |||
| 8579c61ab6 | |||
| 5440445cbc | |||
| e28b4d40ab | |||
| a6940d2cba | |||
| 9f14769cba | |||
| 585eeb283a | |||
| 3a6c3a8312 | |||
| 86fa24aba3 | |||
| 474d8381ab | |||
| feea42f988 | |||
| 88d3152f04 | |||
| 515bfd1beb | |||
| 472e2f8e59 | |||
| 83a0d7a63c | |||
| 4e78de6ce9 | |||
| 670bf9d4a6 | |||
| ad1183dab8 | |||
| a1568641b0 | |||
| 76a6ad6596 | |||
| 355cca3679 | |||
| 7e1eadf54c | |||
| a2dead2dd7 | |||
| 220fb13eec | |||
| 7c1c139074 | |||
| 3a3421897c | |||
| b34d10bd35 | |||
| 8e86b3d1d8 | |||
| acf135a6ed | |||
| 7c1459b83e | |||
| dd561d3703 | |||
| 24c4858570 | |||
| 9690bfb1ed | |||
| fd48f70ef1 | |||
| c33c19c483 | |||
| c9989c5f8f | |||
| d996811306 | |||
| 10b5910654 | |||
| ee5b3d1775 | |||
| b45a995bb3 | |||
| fc45e587c0 | |||
| c18e4ea6ce | |||
| ff662fdfcf | |||
| f075b0ca52 | |||
| a3844fe098 | |||
| d00e60369b | |||
| 22b7027746 | |||
| 410fff6ee9 | |||
| 9d11f8a25b | |||
| 95f71a2e2f | |||
| accb1890dc | |||
| 2a808318bf | |||
| 24d1a2ee64 | |||
| 1d59edcbe8 | |||
| 8a9ca9ac60 | |||
| 7a89d8f5ed | |||
| a6951d1a6d | |||
| 1cdd4c27fc | |||
| 7acea25fdf | |||
| 2510e4e6c4 | |||
| d0f4c25c9f | |||
| 0557ff810a | |||
| fdaf059c60 | |||
| 79f96d22a5 | |||
| 31e7cd7a8c | |||
| 6b274535c6 | |||
| 410767921d | |||
| 78dd4856eb | |||
| 166e75db3f | |||
| 01c7be2b48 | |||
| d05e30b4c5 | |||
| 4f44bde9e9 | |||
| bd50276e7d | |||
| 58b132136d | |||
| bd8988a474 | |||
| c0216efffe | |||
| 25e964788c | |||
| 52d9cbff28 | |||
| 1eb9537d58 | |||
| 24c753a09d | |||
| b5a130263a | |||
| 13a1252c77 | |||
| f338f66b4b | |||
| a782812911 | |||
| 10f96d873a | |||
| 09a2494967 | |||
| 84d58cc572 | |||
| 74e27a27b5 | |||
| f5b71543af | |||
| ef39acfb05 | |||
| 8abb8d1102 | |||
| 4db3c60ccf | |||
| baec208303 | |||
| dda4dd3ab5 | |||
| 2ddbf57597 | |||
| f1290ef061 | |||
| cf3d050423 | |||
| a4532cc722 | |||
| 813a8e12ed | |||
| 10059a722b | |||
| 4211e7a936 | |||
| 33785620d5 | |||
| 5a0df870f5 | |||
| f9aba58342 | |||
| 788fb62f25 | |||
| cc6d254698 | |||
| 3f2703ca21 | |||
| e72f2758c6 | |||
| 2feae06ebd | |||
| fccf56d5fd | |||
| 6e9309aefc | |||
| fbe60c85a1 | |||
| 8f92877fb4 | |||
| 5d1b2e4651 | |||
| 10c3893b79 | |||
| e2198c3ba7 | |||
| 752a64bf3e | |||
| 71ef1bf056 | |||
| d4efcd40f9 | |||
| 9485190604 | |||
| d1523eaeac | |||
| 1af8e7d0ef | |||
| 19b89a3b1f | |||
| b73da046ee | |||
| 675e1982ee | |||
| 0357d15ce4 | |||
| 22cd1e8b9e | |||
| 0f8f6419e9 | |||
| bd7ee0a1c6 | |||
| 4463548740 | |||
| 5655df2081 | |||
| deb0b3482b | |||
| ae2a299616 | |||
| 375deaad1e | |||
| f692e943c9 | |||
| 8538a916a3 | |||
| a8b2997e58 | |||
| 5c151c6b57 | |||
| 8c12da13e6 | |||
| 20f8181ac3 | |||
| 656a519126 | |||
| 71869b65f3 | |||
| fe8d42c27c | |||
| 688c841a8e | |||
| 989219e1e2 | |||
| f2c3e62ba1 | |||
| 73f546aab1 | |||
| c4b3e57677 | |||
| 4e9f2ea4b2 | |||
| 2efeb6edb3 | |||
| c68dcba087 | |||
| a92d51aeb1 | |||
| 0544bbc886 | |||
| 9a871f1459 | |||
| 0d401c9272 | |||
| 2129350ab7 | |||
| 43bc979114 | |||
| a0458eeb91 | |||
| c7232a780a | |||
| e96b4c11a2 | |||
| fecca6a8b2 | |||
| 1fc56585dd | |||
| d1be0e8c1c | |||
| dcc568f5a3 | |||
| 2e4a2712e9 | |||
| d4b055aeb2 | |||
| 0e2cc463c8 | |||
| c3930a6573 | |||
| 3c094b7bd2 | |||
| f8dffa1a9b | |||
| 03b6c08c50 | |||
| 42b96d6290 | |||
| c240f0582a | |||
| 76b7748be1 | |||
| a2334f4ce0 | |||
| db50c87bf4 | |||
| dc8766cf0a | |||
| 158f3d2962 | |||
| 008fa70345 | |||
| e59cd80868 | |||
| f0d7965d49 | |||
| b616cafa49 | |||
| 70bb0e5481 | |||
| 07060fc769 | |||
| b5d613989e | |||
| f604aa8b6b | |||
| dc8912c128 | |||
| 07a0b4fe2d | |||
| eb67ffcbec | |||
| 4ec8345716 | |||
| 56d3b2ca36 | |||
| dd06b1a6c4 | |||
| 3469a9caad | |||
| 599ca56496 | |||
| 14dbe121f6 | |||
| dee936b2c3 | |||
| a98cddf676 | |||
| 48d058a32a | |||
| 98afb72ba3 | |||
| 2d5be6cf89 | |||
| 1299a8f512 | |||
| eccbdfa76e | |||
| 24e16d97f3 | |||
| 13d61f0135 | |||
| c56a4a6c9d | |||
| 832dce462e | |||
| 6f45373edd | |||
| d5613e0e26 | |||
| d0ec4fe345 | |||
| 665bf00f8b | |||
| 2d2ca64a72 | |||
| 60cb41a428 | |||
| a69f3e8da9 | |||
| 2f81cab5f1 | |||
| 78e81542d9 | |||
| 7bbc81b7c3 | |||
| 6e6b256c22 | |||
| d23eba9343 | |||
| e899104d56 | |||
| de00429df6 | |||
| 3aba82f608 | |||
| cb85b690e7 | |||
| 527742ca93 | |||
| b85dcdb437 | |||
| f740ca3cf1 | |||
| b9269b5a11 | |||
| 16e98e1400 | |||
| 4976074b18 | |||
| e670a7ca71 | |||
| d892ad956c | |||
| ac42ed7bab | |||
| bf677b839d | |||
| 464815b045 | |||
| ae91c2b9f0 | |||
| 39cd980008 | |||
| f364643d7e | |||
| ef9bbd8de6 | |||
| 8172096a5b | |||
| 46d3d3afe1 | |||
| 39cd4187ea | |||
| d6a3bc3556 | |||
| ce9e4f2854 | |||
| 7700e8016b | |||
| 6e1ebb02ac | |||
| d2e7e3daaf | |||
| 5d6215d889 | |||
| 17eb45fb4e | |||
| 0a06d58c42 | |||
| a65c6b6d3f | |||
| c5262274eb | |||
| 65f94bcc0c | |||
| 804bbc47c3 | |||
| a967665cbd | |||
| cbd017aceb | |||
| 8d9d142bc2 | |||
| f6c30f2ddf | |||
| d2a27999ba | |||
| 2738b280a1 | |||
| c8946a19f2 | |||
| 6b1932c8d9 | |||
| a133b51dcc | |||
| 6155edef0d | |||
| 439595f04c | |||
| c1fa9fe28e | |||
| 54a0a5b454 | |||
| bace73f854 | |||
| 8da68f599b | |||
| 278524ee3e | |||
| a9912f351f | |||
| 1e5c51e5b2 | |||
| 44100f3c46 | |||
| 713e9c8e14 | |||
| e6238a1f75 | |||
| cfd440dae9 | |||
| a0e5d350bd | |||
| c37240cf96 | |||
| 115844279f | |||
| cbb7c5620d | |||
| 6d5d15793b | |||
| 8ac6f59394 | |||
| 5d8addf1f8 | |||
| 9b9301cbb0 | |||
| 4d9b461776 | |||
| 36f7cdacbd | |||
| feb0e46257 | |||
| 0b901bff5f | |||
| b45b0f2c81 | |||
| 7a36c05c30 | |||
| ac58e6b8b2 | |||
| 68d3771a83 | |||
| 80349d70d8 | |||
| e295d596fe | |||
| 013b138e5c | |||
| 95d2d0af83 | |||
| 03ee826e67 | |||
| 9f31815d9e | |||
| 1e9bfec655 | |||
| fd8cb7e8ed | |||
| 4ef237e0f7 | |||
| 3c48cfbc19 | |||
| 177d43c30e | |||
| a6c3ae8446 | |||
| d0373da0ad | |||
| 7bb3de8371 | |||
| 45e0045820 | |||
| 347b2b783d | |||
| 2fc7cc7de2 | |||
| 4d39804045 | |||
| 746051815d | |||
| 4385bf0bcc | |||
| 1e092c140f | |||
| c4ae9578e9 | |||
| a834e5b4cd | |||
| e329b18e33 | |||
| 5731c4036a | |||
| a594a6cfe2 | |||
| 8b6235f42f | |||
| d443c5e2a6 | |||
| 68d3539a86 | |||
| 301cdf6504 | |||
| 882e0a4ae9 | |||
| f921b65953 | |||
| 1e26587bd3 | |||
| bce6485b91 | |||
| a0cb980a8f | |||
| fc0e9e900f | |||
| d700262e7f | |||
| d92679223e | |||
| 7ac117cd8d | |||
| b87a6bc15c | |||
| fbefe8c555 | |||
| 030119fd0e | |||
| fcf2c37432 | |||
| fab3ee70dd | |||
| 4738528e69 | |||
| 88c8bcf119 | |||
| 3c3e4dd047 | |||
| b44b1cb8b0 | |||
| 6ad2bef05c | |||
| 8e0c92d5eb | |||
| 6bafbd92f3 | |||
| 03663eec3f | |||
| a3d4642ea9 | |||
| 0e42130e9d | |||
| 691fe549d7 | |||
| f5979be4d5 | |||
| 9fe40c3137 | |||
| 82496e8126 | |||
| 9c22e6ecc8 | |||
| 17a433a97b | |||
| b90c1ee7c9 | |||
| bd30f73b3a | |||
| 0aad3d99b5 | |||
| f7d55a4a4a | |||
| df2655e7ae | |||
| 9ec51e040e | |||
| 467602aec3 | |||
| 88610e23b2 | |||
| 89fb59307c | |||
| 65a1fbea78 | |||
| 78bc8fe977 | |||
| 6ab08a2f49 | |||
| de7d315eb3 | |||
| 24662d75e4 | |||
| 76e6697bbc | |||
| 3c2fcffd0d | |||
| 0188757197 | |||
| 444554a12d | |||
| ba42f01db2 | |||
| 5d91766f07 | |||
| c4cbc577d8 | |||
| bfd9cc0cf0 | |||
| ac0b5abfc5 | |||
| ad61cc3c92 | |||
| 6fa586a1b6 | |||
| 4c09773211 | |||
| 2300411ce4 | |||
| 9c61a9eed7 | |||
| 743a197542 | |||
| 99f329c13d | |||
| 623d487df7 | |||
| 348ef4023f | |||
| b253b74e88 | |||
| a3b6a6ea39 | |||
| 8246d2c593 | |||
| 3a6cf0e5ae | |||
| 1db26aab15 | |||
| a23e6dcd66 | |||
| 9331292dd1 | |||
| cad7db0162 | |||
| 9f356542bc | |||
| 1f7d80e6f1 | |||
| f3f1e8721c | |||
| 114fca8be5 | |||
| 52167a47b9 | |||
| d4ff2c8dda | |||
| 75f8e75a8e | |||
| d0f612afc2 | |||
| b6b681c244 | |||
| 5911a602b9 | |||
| 453ef437d3 | |||
| 88494d3379 | |||
| 1b41440aba | |||
| 105434fe68 | |||
| a0a505d64b | |||
| 3a4bdd623d | |||
| 99338187de | |||
| 9d7ef6ff47 | |||
| ffd944f4f9 | |||
| ecef745c3b | |||
| 44507785ac | |||
| 79c0246e6a | |||
| 3c659a342f | |||
| d192217e78 | |||
| 6474552649 | |||
| 4b454dd646 | |||
| 85e1786ce5 | |||
| 45b81ab814 | |||
| 8241b557fe | |||
| 1312a8e704 | |||
| 2a5e42e359 | |||
| dae7d86dad | |||
| 9906149b0d | |||
| 2e2c116180 | |||
| 13c6b9d673 | |||
| 2fbac57faf | |||
| f803447651 | |||
| bec834c651 | |||
| 3df75e9af3 | |||
| 6630db21ee | |||
| f54f45a051 | |||
| acd4274136 | |||
| d400a48a9d | |||
| 4331f4f785 | |||
| 95e36979d5 | |||
| 07827940cc | |||
| c2efcda7bb | |||
| aa0fbd434e | |||
| 8cff046a46 | |||
| ff4154c2bd | |||
| d7e497727c | |||
| d4dc9af1be | |||
| fbe25b314b | |||
| bfe36dddb7 | |||
| dea2b6e367 | |||
| 5e6fe5e3cf | |||
| b009913cf4 | |||
| 783675f78c | |||
| 6fb05fa743 | |||
| 2ccc598270 | |||
| d125699ca6 | |||
| 593fba98c1 | |||
| 74a42ba006 | |||
| 19933e0102 | |||
| c01263d721 | |||
| f2074d95fd | |||
| 83a929604c | |||
| d8c5414ed1 | |||
| ab31f9ae85 | |||
| 293cee414a | |||
| 8067d0c4f6 | |||
| a70b7e319b | |||
| de80e416c3 | |||
| 51f859d8e4 | |||
| 6552463ed9 | |||
| d56da70cae | |||
| 6cab7d964e | |||
| 1343741cfd | |||
| 7c713eee65 | |||
| 277e53d5ac | |||
| 1b63d9e88f | |||
| e520c2ce8a | |||
| 94f54fd4cb | |||
| e6ac012f57 | |||
| 72998b4eac | |||
| 177b8218ee | |||
| 6e0665bd31 | |||
| cdce612566 | |||
| 52f9db4522 | |||
| 1e1066da3b | |||
| 072b9fd147 | |||
| 3a1f1af803 | |||
| 03b277626f | |||
| cd2e33721e | |||
| 2d7a7a8bc3 | |||
| b1d9c2df64 | |||
| c4dfbdbe2e | |||
| e3cb811225 | |||
| db98f13982 | |||
| 61c2a2c6c6 | |||
| 5c41baeaf1 | |||
| f8a5ce34a8 | |||
| 4078140079 | |||
| c9d724fe18 | |||
| 03b2afbb31 | |||
| f0a19cb054 | |||
| f565b4e8f0 | |||
| af5838cba6 | |||
| d0058a1bde | |||
| 698c648413 | |||
| 8f64ef4465 | |||
| a16c159b7f | |||
| 04b641c49c | |||
| 84d475cfd3 | |||
| afe7d526a5 | |||
| 98ec3e2301 | |||
| cfd0ed60cf | |||
| 802e1966fd | |||
| b57a1e5ea8 | |||
| b92e78b137 | |||
| 8b69ea464f | |||
| 1565575e8b | |||
| 18b68353b1 | |||
| 9699eb38c5 | |||
| d294be3433 | |||
| 60ae4e80ce | |||
| 05ec36a37d | |||
| dc8ea31138 | |||
| faaea7db49 | |||
| b14ff94303 | |||
| b3dcfbf0dc | |||
| b68109d32b | |||
| 2ea3fe4ab9 | |||
| 94c159ccd0 | |||
| e4eead6662 | |||
| ee4e92dfa3 | |||
| f4ce2965f9 | |||
| 5fb7e6e375 | |||
| c399eb259a | |||
| 5ccdf187d5 | |||
| d53351d218 | |||
| 08a82c7b57 | |||
| 499cdbb9b8 | |||
| 4a5d1eba0b | |||
| 70091aa28b | |||
| 3d566cc401 | |||
| 6eb3c48144 | |||
| 44d180007e | |||
| 7e8060b224 | |||
| d408568d01 | |||
| 47704b1625 | |||
| 23fee9c8c8 | |||
| c5d1801e1e | |||
| e2dc5f4a48 | |||
| d28f62d327 | |||
| 70064359c3 | |||
| d8b74cf125 | |||
| 00c13c5ea4 | |||
| e26dae67aa | |||
| 6e30cd2ba7 | |||
| 0f9ea1e1e7 | |||
| 128ffc8fd7 | |||
| f67911902f | |||
| 64a1a3eb29 | |||
| fcf70ad160 | |||
| 116c9a5fd9 | |||
| 61b10a19c7 | |||
| 666f8e2459 | |||
| c303f216ad | |||
| 162e66b775 | |||
| c05abc4d5b | |||
| dacb3b101c | |||
| 696c6b09b0 | |||
| 6e738a0e3a | |||
| ba6cdc967c | |||
| 468baef5c8 | |||
| bda9dfd4cc | |||
| 930feb1d52 | |||
| e0b11aa66e | |||
| b2e7044373 | |||
| 77abe9a0a5 | |||
| e2c67c2f37 | |||
| a5d123fe83 | |||
| b7b99b6db7 | |||
| 2be0cc697a | |||
| dc92b973a0 | |||
| 5466be9b7b | |||
| b86dab2a76 | |||
| a57e063c14 | |||
| c7830e9e5b | |||
| d533ba1e6b | |||
| 45a1655485 | |||
| 3679fccfbd | |||
| cf9f792a3b | |||
| d87665de7e | |||
| 95daf7efa3 | |||
| 435ce8d58a | |||
| f92a2b3c8e | |||
| 5ea1c94822 | |||
| ab1bf7592e | |||
| f4247c3527 | |||
| 8c3d10a2bd | |||
| 1bda47f76e | |||
| 9001aa6383 | |||
| 097c5cee3c | |||
| 9d789425ce | |||
| c0b86ea016 | |||
| 6806eb0a05 | |||
| ce26d931c1 | |||
| eeaa0a5530 | |||
| a09cb5dee4 | |||
| 6035683492 | |||
| f27dbacd28 | |||
| 8817a7e6d5 | |||
| 80c4c13998 | |||
| 5159e2daee | |||
| 54951d2102 | |||
| 8403c32e76 | |||
| 316934de97 | |||
| dd48fbcb0f | |||
| 54978a9868 | |||
| 02fd78df14 | |||
| ed1202e1f2 | |||
| d9de967197 | |||
| e57076c84f | |||
| 75e6495999 | |||
| fcf07bebfb | |||
| f190ddcd92 | |||
| 39a841fb4e | |||
| bdfd0c4aa7 | |||
| 37b14f2a3d | |||
| 70a4af2605 | |||
| 7142f3856c | |||
| f2ca030fab | |||
| 37cacfcd06 | |||
| 3e31309384 | |||
| a19b7614fa | |||
| 763ee9198d | |||
| 9ec8035a8d | |||
| 687bb32e37 | |||
| 4279b769aa | |||
| 9a59b8cdae | |||
| b9b0e81d25 | |||
| 80d31b4e1a | |||
| dac9bfe3d4 | |||
| 58a7ef62d7 | |||
| d2198568b2 | |||
| b087aa09d9 | |||
| fd62ba63a5 | |||
| 16c5fd56ca | |||
| d85f9af790 | |||
| 2f071bd809 | |||
| 7a44f9e8a7 | |||
| 59a19a1a70 | |||
| 6a8b59f2cf | |||
| ec28d3d0af | |||
| f576aadee1 | |||
| fffd7360cb | |||
| 64ea455c01 | |||
| cf635986a6 | |||
| ac8040008a | |||
| df15a37127 | |||
| 6d887d593e | |||
| fa87092fe0 | |||
| 1a4e4678d0 | |||
| 7f2c7eb467 | |||
| c70745826a | |||
| 291bffca95 | |||
| e5a316e509 | |||
| e4aa97091e | |||
| b4f0a346c1 | |||
| 073e471305 | |||
| 4d9f47b3a7 | |||
| 96088c1d08 | |||
| c405ff1adf | |||
| 02cae9c7c2 | |||
| 3c42962635 | |||
| 90ae709156 | |||
| 0336dbabf7 | |||
| a8729933af | |||
| 993ce46fcc | |||
| edfd446833 | |||
| 87c184ef8a | |||
| 579768c35f | |||
| e9b9113df8 | |||
| f772a53dd5 | |||
| 85c6b6c4da | |||
| 1aaccba803 | |||
| f2eb08a066 | |||
| f460676e54 | |||
| 382e028b90 | |||
| 53d02446bf | |||
| 5a82d7a9d4 | |||
| a976e63def | |||
| 69c197c1a4 | |||
| 4027f28c85 | |||
| 3a1154c4ba | |||
| aeb1e4bf49 | |||
| 4fb34c0816 | |||
| 9b562669d2 | |||
| 295d0a677e | |||
| 9aacafd575 | |||
| ce6ce1b975 | |||
| d064ef1237 | |||
| 2db9bd9c39 | |||
| 7622504d68 | |||
| 221dd9a7a2 | |||
| 1b74a99667 | |||
| a45f6f980f | |||
| 9122f006c7 | |||
| 678dbaa66a | |||
| fb88499197 | |||
| f84adf67cd | |||
| cacb38a251 | |||
| 7c6c01e6b9 | |||
| 4e462a3cf7 | |||
| e7f4c6c9cc | |||
| 7bf8c0bbfb | |||
| c4157673f5 | |||
| 16285e0625 | |||
| a07d3b9669 | |||
| 2d0b356203 | |||
| f666053b63 | |||
| 3bdc969efb | |||
| 932817877c | |||
| cb255a18b9 | |||
| 183028570e | |||
| 341cdd4ef7 | |||
| fe68e16ca3 | |||
| a8f0c90d47 | |||
| 39f550529b | |||
| 25c1a14e64 | |||
| 9f7d710119 | |||
| ea592775e4 | |||
| 42be4eb064 | |||
| 8662e20c58 | |||
| da4ce3773f | |||
| 87c9bbe2a7 | |||
| a66ee06e3d | |||
| 9969de58cb | |||
| 6995cafe63 | |||
| eaa80ad08a | |||
| d001180082 | |||
| 3884403231 | |||
| 8d4b5d83e1 | |||
| e1250f2177 | |||
| a2ee920a5f | |||
| fdbe74a432 | |||
| 4e39fb3edd | |||
| c2049246cd | |||
| 335e2b7a78 | |||
| bb8e84e5ec | |||
| 2fa30be0d0 | |||
| c50149ad87 | |||
| da1bdc802d | |||
| a9cba30da6 | |||
| 3665dda87c | |||
| f2696d5352 | |||
| 5e394e1576 | |||
| ebd03e9290 | |||
| c3bfd7354f | |||
| 1d046eaadf | |||
| 2f554db54b | |||
| 54b4cef25e | |||
| c6106e6636 | |||
| 865dbab3ec | |||
| 76e6c63a01 | |||
| 3320accc7a | |||
| ac686db298 | |||
| aca26c7597 | |||
| b7737cb6d3 | |||
| 55026ca996 | |||
| 3fa573e3c1 | |||
| 00ae6809a9 | |||
| c3fbb11093 | |||
| a0d27c3f1c | |||
| 811a908cc3 | |||
| 94e5baf48a | |||
| cd2570cdbb | |||
| 6df6553935 | |||
| 8e6c372a4f | |||
| 371e11de9b | |||
| d2a708fcc4 | |||
| 845d772a08 | |||
| 1e630ede08 | |||
| c50d1ea2fe | |||
| e7eb00eaa3 | |||
| cd6eac3c8f | |||
| 69e21da60c | |||
| 57b905862a | |||
| 51d3a2b77b | |||
| b2920996be | |||
| bdc5a7a01b | |||
| 1c6a9e2c49 | |||
| 8ffb77551f | |||
| 2d35869c41 | |||
| 359dab573b | |||
| 6e2edbf101 | |||
| 4c8f93d737 | |||
| 2789bc565a | |||
| a1e0b8858e | |||
| f075a6178b | |||
| 5fa385e1e0 | |||
| b57141a80c | |||
| d453adb7cf | |||
| c5a7a8680e | |||
| d4ccadb832 | |||
| cbf04546b8 | |||
| 37c0084874 | |||
| 875afd69d5 | |||
| 67f4ed00d0 | |||
| 10d30b0de7 | |||
| 1110f0cffb | |||
| 66e829a8aa | |||
| 984b1212a6 | |||
| bc72c927c1 | |||
| b8275f2802 | |||
| 267527f3fc | |||
| c5b4513f65 | |||
| 5da4fbb39c | |||
| 93639e9e50 | |||
| d76462ca42 | |||
| 722201a1af | |||
| 0a3dddef2f | |||
| 26434f0331 | |||
| f6c2e2c20d | |||
| 424a06f6c8 | |||
| 89c4cbeb05 | |||
| 7e13ed746e | |||
| 28d205b4a3 | |||
| dcc52fc4e4 | |||
| a9d785c28f | |||
| 54a3730c20 | |||
| 31d322a28c | |||
| 3b90086109 | |||
| 30b870b98d | |||
| b3e7975b83 | |||
| 8f7f6223de | |||
| 6c313dd25c | |||
| b718bd19bd | |||
| ab5ea4c853 | |||
| d11ec67129 | |||
| 10f894e2ea | |||
| 34bbc8f1ea | |||
| a213ab6760 | |||
| d694d8fcc2 | |||
| 5f2d451c5e | |||
| ab696b980a | |||
| 9f2df7fb9d | |||
| 9e5c3ff675 | |||
| a67108e6c1 | |||
| b1706f2eac | |||
| ac29e152bb | |||
| de690a385c | |||
| a973b62918 | |||
| 92426a640a | |||
| 93f8638a94 | |||
| 16b0b1c3a5 | |||
| 25fff3fdd0 | |||
| 0384de46a4 | |||
| 080f325557 | |||
| 86cc2bf39a | |||
| c7effa3f25 | |||
| be262eaef2 | |||
| 523e51c775 | |||
| 5410f14aa1 | |||
| 45b2411c2b | |||
| 9f12091c7f | |||
| bef5d3cca5 | |||
| 0f548eb93e | |||
| 374348bb81 | |||
| b42f6b1827 | |||
| addcf531f0 | |||
| 0ef683013a | |||
| 137a306269 | |||
| fc0ffd1c02 | |||
| 04172a87cb | |||
| 97e0c43702 | |||
| 8dde98f543 | |||
| 9962a0c905 | |||
| 4b56b34124 | |||
| f857c513c5 | |||
| 41df6410bd | |||
| dcbd6a925d | |||
| 3848a21136 | |||
| 8af37cb4ec | |||
| 44c28e9a4c | |||
| 677324927c | |||
| d212344c54 | |||
| 74da327803 | |||
| f021041b31 | |||
| c05d2df116 | |||
| 2b926f7906 | |||
| 3ac69043d6 | |||
| f726708815 | |||
| 21e153087a | |||
| 31d85b715a | |||
| 344cc1fb7d | |||
| 1cea3d21e8 | |||
| 640320f70d | |||
| 29352092aa | |||
| 5b877b549a | |||
| 721466c429 | |||
| cce2fee1fa | |||
| 087d55f02a | |||
| f1037de14d | |||
| 4711672170 | |||
| c0b4e099af | |||
| f41fbf24c3 | |||
| e14d96e6ee | |||
| 716a33f347 | |||
| c5f084a4af | |||
| 606a0b46f2 | |||
| 1c729a74d1 | |||
| db31574103 | |||
| d03b47e1e6 | |||
| ae62ac2777 | |||
| 998f9c6a1e | |||
| 3ff31b577c | |||
| cd013079f4 | |||
| b8a9674483 | |||
| 8beb1bef98 | |||
| 377676f881 | |||
| 4efe284338 | |||
| 34a4e3f37a | |||
| 889c9a9e9f | |||
| 9e79499532 | |||
| 589b98053e | |||
| fc5bb230a9 | |||
| 01361cc8f2 | |||
| e6bef16c45 | |||
| 4829c4c02b | |||
| 3bf4a8ef52 | |||
| c95a47ca97 |
@@ -1,24 +1,8 @@
|
||||
name: ci-bcf-pypi
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# ┌───────────── minute (0 - 59)
|
||||
# │ ┌───────────── hour (0 - 23)
|
||||
# │ │ ┌───────────── day of the month (1 - 31)
|
||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
||||
# * * * * *
|
||||
- cron: "0 0 18 * *"
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/ci-bcf-pypi.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
major: 0
|
||||
minor: 0
|
||||
name: ifcopenshell
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -54,4 +38,4 @@ jobs:
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
packages_dir: src/bcf/dist
|
||||
packages_dir: src/bcf/dist
|
||||
|
||||
@@ -28,65 +28,18 @@ jobs:
|
||||
|
||||
build:
|
||||
needs: activate
|
||||
name: ${{ matrix.config.name }}-${{ matrix.pyver }}
|
||||
name: "choco_release"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pyver: [py310]
|
||||
config:
|
||||
- {
|
||||
name: "Windows Build",
|
||||
short_name: win,
|
||||
}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
python-version: '3.10.9' # Version range or exact version of a Python version to use, using SemVer's version range syntax
|
||||
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
|
||||
fetch-tags: true
|
||||
fetch-depth: 0
|
||||
- run: echo ${{ env.DATE }}
|
||||
|
||||
- name: Check in published releases if we should do a choco release
|
||||
id: do_choco
|
||||
- name: Check in release tags if we should do a choco release and perform the release if needed
|
||||
id: do_choco_release
|
||||
run: |
|
||||
echo "::set-output name=choco_release::$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --do_choco_release?)"
|
||||
|
||||
- name: Fill chocolatey scripts on win with latest blender python
|
||||
if: ${{steps.do_choco.outputs.choco_release}} == 'do_choco_release'
|
||||
run: |
|
||||
yesterday_non_iso="$(date --date='yesterday' +'%y%m%d' | tr -d '\n')" &&
|
||||
target_os=${{ matrix.config.short_name }} &&
|
||||
latest_blender_python_version_maj_min=$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --latest_blender_python_version_maj_min?) &&
|
||||
echo "latest_blender_python_version_maj_min?: $latest_blender_python_version_maj_min" &&
|
||||
pyver=$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --pyver?) &&
|
||||
export latest_blender_version_maj_min=$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --latest_blender_release_maj_min?) &&
|
||||
export latest_blender_version_maj_min_pat=$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --latest_blender_release_maj_min_pat?) &&
|
||||
echo latest_blender_version_maj_min_pat?: $latest_blender_version_maj_min_pat &&
|
||||
export blenderbim_build_version="${{ env.major }}.${{ env.minor }}.$yesterday_non_iso" &&
|
||||
export url_blenderbim_py310_win_zip="https://github.com/IfcOpenShell/IfcOpenShell/releases/download/blenderbim-$yesterday_non_iso/blenderbim-$yesterday_non_iso-$pyver-$target_os.zip" &&
|
||||
wget $url_blenderbim_py310_win_zip --no-verbose &&
|
||||
export sha256sum_blenderbim_py310_win_zip=$( sha256sum blenderbim-$yesterday_non_iso-$pyver-$target_os.zip --tag | cut -d ' ' -f 4 | tr -d '\n') &&
|
||||
echo sha256sum_blenderbim_py310_win_zip: $sha256sum_blenderbim_py310_win_zip &&
|
||||
python3 choco/blenderbim/fill_dynamic_parameters.py &&
|
||||
echo __build choco with mono &&
|
||||
wget "https://github.com/chocolatey/choco/archive/refs/tags/$choco_version.tar.gz" --quiet &&
|
||||
tar -xzf "$choco_version.tar.gz" &&
|
||||
cd choco-$choco_version &&
|
||||
chmod +x build.sh zip.sh &&
|
||||
./build.sh &&
|
||||
cp -r build_output/chocolatey /opt/chocolatey &&
|
||||
cd /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/ &&
|
||||
echo __choco pack &&
|
||||
mono /opt/chocolatey/choco.exe --version &&
|
||||
mono /opt/chocolatey/choco.exe pack --allow-unofficial &&
|
||||
echo __choco set apiKey &&
|
||||
mono /opt/chocolatey/choco.exe setapikey --key="$CHOCO_TOKEN" --source="https://push.chocolatey.org/" --allow-unofficial # &&
|
||||
echo __choco push &&
|
||||
mono /opt/chocolatey/choco.exe push --source="https://push.chocolatey.org/" --key="$CHOCO_TOKEN" --allow-unofficial --verbose
|
||||
|
||||
- name: Inform user about not packaging
|
||||
if: ${{steps.do_choco.outputs.choco_release}} != 'do_choco_release'
|
||||
run: |
|
||||
echo "no releases found today ${{ env.DATE }}, therefore choco packaging is skipped."
|
||||
|
||||
python3 choco_release.py
|
||||
|
||||
+13
-15
@@ -1,4 +1,4 @@
|
||||
name: Publish-blenderbim-multiplatform
|
||||
name: ci-blenderbim-daily
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -16,12 +16,8 @@ on:
|
||||
- 'src/ifc5d/ifc5d/**'
|
||||
- 'src/ifccityjson/**'
|
||||
branches:
|
||||
- v0.7.0
|
||||
|
||||
env:
|
||||
major: 0
|
||||
minor: 0
|
||||
name: blenderbim
|
||||
- v0.8.0
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
@@ -39,7 +35,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pyver: [py39, py310, py311]
|
||||
pyver: [py39, py310, py311, py312]
|
||||
config:
|
||||
- {
|
||||
name: "Windows Build",
|
||||
@@ -63,21 +59,23 @@ jobs:
|
||||
with:
|
||||
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
|
||||
python-version: '3.11'
|
||||
- run: echo ${{ env.DATE }}
|
||||
- name: Get current version
|
||||
id: version
|
||||
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "::set-output name=date::$(date +'%y%m%d')"
|
||||
run: echo "date=$(date +'%y%m%d')" >> $GITHUB_OUTPUT
|
||||
- name: Compile
|
||||
run: |
|
||||
cp -r src/blenderbim src/blenderbim_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
|
||||
cd src/blenderbim_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
|
||||
make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }}
|
||||
- name: Upload Zip file to release
|
||||
- name: Upload zip file to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: src/blenderbim_${{ matrix.config.short_name }}_${{ matrix.pyver }}/dist/blenderbim-${{steps.date.outputs.date}}-${{ matrix.pyver }}-${{ matrix.config.short_name }}.zip
|
||||
asset_name: blenderbim-${{steps.date.outputs.date}}-${{ matrix.pyver }}-${{ matrix.config.short_name }}.zip
|
||||
tag: "blenderbim-${{steps.date.outputs.date}}"
|
||||
file: src/blenderbim_${{ matrix.config.short_name }}_${{ matrix.pyver }}/dist/blenderbim-${{steps.version.outputs.version}}.${{steps.date.outputs.date}}-${{ matrix.pyver }}-${{ matrix.config.short_name }}.zip
|
||||
asset_name: blenderbim-${{steps.version.outputs.version}}.${{steps.date.outputs.date}}-${{ matrix.pyver }}-${{ matrix.config.short_name }}.zip
|
||||
release_name: "blenderbim-${{steps.version.outputs.version}}.${{steps.date.outputs.date}} (unstable)"
|
||||
tag: "blenderbim-${{steps.version.outputs.version}}.${{steps.date.outputs.date}}"
|
||||
overwrite: true
|
||||
body: "Daily developer testing build blenderbim-${{steps.date.outputs.date}}"
|
||||
@@ -0,0 +1,62 @@
|
||||
name: ci-blenderbim
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
build:
|
||||
needs: activate
|
||||
name: ${{ matrix.config.name }}-${{ matrix.pyver }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pyver: [py39, py310, py311, py312]
|
||||
config:
|
||||
- {
|
||||
name: "Windows Build",
|
||||
short_name: win,
|
||||
}
|
||||
- {
|
||||
name: "Linux Build",
|
||||
short_name: linux
|
||||
}
|
||||
- {
|
||||
name: "MacOS Build",
|
||||
short_name: macos
|
||||
}
|
||||
- {
|
||||
name: "MacOS ARM Build",
|
||||
short_name: macosm1
|
||||
}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
|
||||
python-version: '3.11'
|
||||
- name: Get current version
|
||||
id: version
|
||||
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
||||
- name: Compile
|
||||
run: |
|
||||
cp -r src/blenderbim src/blenderbim_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
|
||||
cd src/blenderbim_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
|
||||
make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }} IS_STABLE=TRUE
|
||||
- name: Upload zip file to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: src/blenderbim_${{ matrix.config.short_name }}_${{ matrix.pyver }}/dist/blenderbim-${{steps.version.outputs.version}}-${{ matrix.pyver }}-${{ matrix.config.short_name }}.zip
|
||||
asset_name: blenderbim-${{steps.version.outputs.version}}-${{ matrix.pyver }}-${{ matrix.config.short_name }}.zip
|
||||
release_name: "blenderbim-${{steps.version.outputs.version}}"
|
||||
tag: "blenderbim-${{steps.version.outputs.version}}"
|
||||
overwrite: true
|
||||
@@ -1,21 +1,8 @@
|
||||
name: ci-bsdd-pypi
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# ┌───────────── minute (0 - 59)
|
||||
# │ ┌───────────── hour (0 - 23)
|
||||
# │ │ ┌───────────── day of the month (1 - 31)
|
||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
||||
# * * * * *
|
||||
- cron: "0 0 18 * *"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
major: 0
|
||||
minor: 0
|
||||
name: ifcopenshell
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
name: ci-ifc4d-pypi
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
build:
|
||||
needs: activate
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
|
||||
- name: Compile
|
||||
run: |
|
||||
pip install build
|
||||
cd src/ifc4d &&
|
||||
make dist
|
||||
- name: Publish a Python distribution to PyPI
|
||||
uses: ortega2247/pypi-upload-action@master
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
packages_dir: src/ifc4d/dist
|
||||
@@ -0,0 +1,35 @@
|
||||
name: ci-ifc5d-pypi
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
build:
|
||||
needs: activate
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
|
||||
- name: Compile
|
||||
run: |
|
||||
pip install build
|
||||
cd src/ifc5d &&
|
||||
make dist
|
||||
- name: Publish a Python distribution to PyPI
|
||||
uses: ortega2247/pypi-upload-action@master
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
packages_dir: src/ifc5d/dist
|
||||
@@ -0,0 +1,35 @@
|
||||
name: ci-ifccityjson-pypi
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
build:
|
||||
needs: activate
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
|
||||
- name: Compile
|
||||
run: |
|
||||
pip install build
|
||||
cd src/ifccityjson &&
|
||||
make dist
|
||||
- name: Publish a Python distribution to PyPI
|
||||
uses: ortega2247/pypi-upload-action@master
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
packages_dir: src/ifccityjson/dist
|
||||
@@ -1,21 +1,8 @@
|
||||
name: ci-ifcclash-pypi
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# ┌───────────── minute (0 - 59)
|
||||
# │ ┌───────────── hour (0 - 23)
|
||||
# │ │ ┌───────────── day of the month (1 - 31)
|
||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
||||
# * * * * *
|
||||
- cron: "0 0 18 * *"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
major: 0
|
||||
minor: 0
|
||||
name: ifcopenshell
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -1,21 +1,8 @@
|
||||
name: ci-ifccsv-pypi
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# ┌───────────── minute (0 - 59)
|
||||
# │ ┌───────────── hour (0 - 23)
|
||||
# │ │ ┌───────────── day of the month (1 - 31)
|
||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
||||
# * * * * *
|
||||
- cron: "0 0 18 * *"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
major: 0
|
||||
minor: 0
|
||||
name: ifcopenshell
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
name: ci-ifcdiff-pypi
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
build:
|
||||
needs: activate
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
|
||||
- name: Compile
|
||||
run: |
|
||||
pip install build
|
||||
cd src/ifcdiff &&
|
||||
make dist
|
||||
- name: Publish a Python distribution to PyPI
|
||||
uses: ortega2247/pypi-upload-action@master
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
packages_dir: src/ifcdiff/dist
|
||||
@@ -0,0 +1,35 @@
|
||||
name: ci-ifcfm-pypi
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
build:
|
||||
needs: activate
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
|
||||
- name: Compile
|
||||
run: |
|
||||
pip install build
|
||||
cd src/ifcfm &&
|
||||
make dist
|
||||
- name: Publish a Python distribution to PyPI
|
||||
uses: ortega2247/pypi-upload-action@master
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
packages_dir: src/ifcfm/dist
|
||||
@@ -0,0 +1,101 @@
|
||||
name: ci-ifcopenshell-conda-daily-cleaner
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# ┌───────────── minute (0 - 59)
|
||||
# │ ┌───────────── hour (0 - 23)
|
||||
# │ │ ┌───────────── day of the month (1 - 31)
|
||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
||||
# * * * * *
|
||||
- cron: "00 23 * * *" # 11min before utc midnight every day
|
||||
|
||||
env:
|
||||
ANACONDA_TOKEN: ${{ secrets.ANACONDA_TOKEN }}
|
||||
NUM_SUPPORTED_VERSIONS: 5
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: bash -l {0}
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- uses: mamba-org/setup-micromamba@v1 # https://github.com/mamba-org/setup-micromamba
|
||||
with:
|
||||
environment-name: test-env
|
||||
create-args: >-
|
||||
python=3.11
|
||||
anaconda-client=1.12.3
|
||||
|
||||
- name: Run conda cleaner
|
||||
run: |
|
||||
python - << EOF
|
||||
|
||||
import os
|
||||
from datetime import datetime, timedelta
|
||||
from binstar_client.utils import get_server_api
|
||||
from binstar_client.errors import BinstarError
|
||||
|
||||
# Configuration
|
||||
api_token = os.environ.get('ANACONDA_TOKEN')
|
||||
pkg_name = 'ifcopenshell'
|
||||
channel_name = 'ifcopenshell'
|
||||
|
||||
# Authenticate with Anaconda
|
||||
aserver_api = get_server_api(token=api_token)
|
||||
|
||||
|
||||
# Get the list of packages in the channel
|
||||
def get_package(filter_package_name: str = None):
|
||||
try:
|
||||
user_packages = aserver_api.user_packages(channel_name)
|
||||
if filter_package_name:
|
||||
user_packages = [pkg for pkg in user_packages if pkg['name'] == filter_package_name]
|
||||
if len(user_packages) == 0:
|
||||
print(f"No packages found for {filter_package_name}.")
|
||||
if len(user_packages) > 1:
|
||||
raise ValueError(f"Found {len(user_packages)} package for {filter_package_name}. Will only support 1 package.")
|
||||
|
||||
return user_packages[0]
|
||||
except BinstarError as err:
|
||||
raise ValueError(f"Failed to fetch packages: {err}")
|
||||
|
||||
|
||||
# Delete a package version
|
||||
def delete_package(package_name, version):
|
||||
try:
|
||||
aserver_api.remove_release(channel_name, package_name, version)
|
||||
print(f"Deleted {package_name} version {version}")
|
||||
except BinstarError as err:
|
||||
print(f"Failed to delete {package_name} version {version}: {err}")
|
||||
|
||||
|
||||
# Main logic
|
||||
def main():
|
||||
package = get_package(pkg_name)
|
||||
if not package:
|
||||
print("No packages found.")
|
||||
return
|
||||
|
||||
number_of_supported_versions = ${{ env.NUM_SUPPORTED_VERSIONS }}
|
||||
|
||||
package_name = package['name']
|
||||
versions = package["versions"]
|
||||
if len(versions) <= number_of_supported_versions:
|
||||
print(f"Number of versions {len(versions)} is less than or equal to {number_of_supported_versions}.")
|
||||
return
|
||||
|
||||
# sort the versions in descending order
|
||||
versions = sorted(versions, reverse=True)
|
||||
releases = versions[number_of_supported_versions:]
|
||||
|
||||
for release in releases:
|
||||
delete_package(package_name, release)
|
||||
|
||||
main()
|
||||
|
||||
EOF
|
||||
@@ -2,21 +2,44 @@ name: ci-ifcopenshell-conda-daily-v0.8.0
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- v0.8.0
|
||||
schedule:
|
||||
# ┌───────────── minute (0 - 59)
|
||||
# │ ┌───────────── hour (0 - 23)
|
||||
# │ │ ┌───────────── day of the month (1 - 31)
|
||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
||||
# * * * * *
|
||||
- cron: "49 23 * * *" # 11min before utc midnight every day
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
date: ${{ steps.date.outputs.date }}
|
||||
verdate: ${{ steps.verdate.outputs.verdate }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
- name: Get current version
|
||||
id: version
|
||||
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "date=$(date +'%y%m%d')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Version + date str
|
||||
id: verdate
|
||||
run: echo "verdate='${{ steps.version.outputs.version }}.${{ steps.date.outputs.date }}'" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
test:
|
||||
name: ${{ matrix.platform.distver }}-${{ matrix.pyver.name }}
|
||||
name: ${{ matrix.platform.distver }}-${{ matrix.pyver.name }}-${{ matrix.variant }}
|
||||
needs: activate
|
||||
runs-on: ${{ matrix.platform.distver }}
|
||||
defaults:
|
||||
@@ -25,8 +48,9 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
variant: [novtk, all]
|
||||
pyver: [
|
||||
{ name: py311, distver: '3.11'},
|
||||
# { name: py311, distver: '3.11'},
|
||||
{ name: py312, distver: '3.12'}
|
||||
]
|
||||
platform: [
|
||||
@@ -35,24 +59,28 @@ jobs:
|
||||
{ name: macOS, distver: macos-latest, pkg_dir: 'osx-64' }
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up swap space
|
||||
if: runner.os == 'Linux'
|
||||
uses: pierotofy/set-swap-space@v1.0
|
||||
with:
|
||||
swap-size-gb: 10
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Download and extract MacOSX SDK
|
||||
if: ${{ matrix.platform.name == 'macOS' }}
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
run: |
|
||||
curl -o MacOSX10.13.sdk.tar.xz -L https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX10.13.sdk.tar.xz && \
|
||||
tar xf MacOSX10.13.sdk.tar.xz && \
|
||||
sudo mv -v MacOSX10.13.sdk /opt/ && \
|
||||
ls /opt/
|
||||
- uses: seanmiddleditch/gha-setup-ninja@master
|
||||
curl -L https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX10.13.sdk.tar.xz | tar -xvJf - -C /Users/runner/work/
|
||||
|
||||
- uses: mamba-org/setup-micromamba@v1 # https://github.com/mamba-org/setup-micromamba
|
||||
with:
|
||||
environment-file: conda/environment.build.yml
|
||||
environment-name: test-env
|
||||
create-args: >-
|
||||
python=${{ matrix.pyver.distver }}
|
||||
python=3.11
|
||||
anaconda-client
|
||||
boa
|
||||
|
||||
- name: create conda package dist dir
|
||||
run: |
|
||||
@@ -60,8 +88,10 @@ jobs:
|
||||
|
||||
- name: build & test ifcopenshell
|
||||
run: |
|
||||
boa build . --python ${{ matrix.pyver.distver }} --no-remove-work-dir --output-folder '${{ github.workspace }}/dist'
|
||||
conda mambabuild . --python ${{ matrix.pyver.distver }} --no-remove-work-dir --output-folder '${{ github.workspace }}/dist' --variants='{variant: ${{ matrix.variant }}}'
|
||||
working-directory: ./conda
|
||||
env:
|
||||
VERSION_OVERRIDE: ${{ needs.activate.outputs.verdate }}
|
||||
|
||||
- name: upload to anaconda
|
||||
if: ${{ matrix.platform.name == 'win' }}
|
||||
@@ -71,4 +101,4 @@ jobs:
|
||||
- name: upload to anaconda
|
||||
if: ${{ matrix.platform.name != 'win' }}
|
||||
run: |
|
||||
anaconda -t ${{ secrets.ANACONDA_TOKEN }} upload --force --user ifcopenshell ${{ github.workspace }}/dist/${{ matrix.platform.pkg_dir }}/*.tar.bz2
|
||||
anaconda -t ${{ secrets.ANACONDA_TOKEN }} upload --force --user ifcopenshell ${{ github.workspace }}/dist/${{ matrix.platform.pkg_dir }}/*.tar.bz2
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
name: CD
|
||||
name: ci-ifcopenshell-docker
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
|
||||
tags:
|
||||
- v0.**
|
||||
|
||||
jobs:
|
||||
|
||||
+9
-21
@@ -1,19 +1,7 @@
|
||||
name: ci-ifcopenshell-pypi
|
||||
name: ci-ifcopenshell-python-pypi
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# ┌───────────── minute (0 - 59)
|
||||
# │ ┌───────────── hour (0 - 23)
|
||||
# │ │ ┌───────────── day of the month (1 - 31)
|
||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
||||
# * * * * *
|
||||
- cron: "0 0 18 * *"
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/ci-ifcopenshell-pypi.yml'
|
||||
|
||||
|
||||
env:
|
||||
major: 0
|
||||
@@ -39,20 +27,20 @@ jobs:
|
||||
pyver: [py39, py310, py311, py312]
|
||||
config:
|
||||
- {
|
||||
name: "Windows Build",
|
||||
short_name: win,
|
||||
name: "Windows 64bit",
|
||||
short_name: win64,
|
||||
}
|
||||
- {
|
||||
name: "Linux Build",
|
||||
short_name: linux
|
||||
name: "Linux 64bit",
|
||||
short_name: linux64
|
||||
}
|
||||
- {
|
||||
name: "MacOS Build",
|
||||
short_name: macos
|
||||
name: "MacOS Intel 64bit",
|
||||
short_name: macos64
|
||||
}
|
||||
- {
|
||||
name: "MacOS ARM Build",
|
||||
short_name: macosm1
|
||||
name: "MacOS Silicon 64bit",
|
||||
short_name: macosm164
|
||||
}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -0,0 +1,67 @@
|
||||
name: ci-ifcopenshell-python
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
build:
|
||||
needs: activate
|
||||
name: ${{ matrix.config.name }}-${{ matrix.pyver }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pyver: [py39, py310, py311, py312]
|
||||
config:
|
||||
- {
|
||||
name: "Windows 64bit",
|
||||
short_name: win64,
|
||||
}
|
||||
- {
|
||||
name: "Windows 32bit",
|
||||
short_name: win32,
|
||||
}
|
||||
- {
|
||||
name: "Linux 64bit",
|
||||
short_name: linux64
|
||||
}
|
||||
- {
|
||||
name: "MacOS Intel 64bit",
|
||||
short_name: macos64
|
||||
}
|
||||
- {
|
||||
name: "MacOS Silicon 64bit",
|
||||
short_name: macosm164
|
||||
}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
|
||||
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
|
||||
- run: echo ${{ env.DATE }}
|
||||
- name: Get current version
|
||||
id: version
|
||||
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
||||
- name: Compile
|
||||
run: |
|
||||
cp -r src/ifcopenshell-python src/ifcopenshell_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
|
||||
cd src/ifcopenshell_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
|
||||
make zip PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }}
|
||||
- name: Upload zip file to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: src/ifcopenshell_${{ matrix.config.short_name }}_${{ matrix.pyver }}/dist/ifcopenshell-python-${{ steps.version.outputs.version }}-${{ matrix.pyver }}-${{ matrix.config.short_name }}.zip
|
||||
asset_name: ifcopenshell-python-${{ steps.version.outputs.version }}-${{ matrix.pyver }}-${{ matrix.config.short_name }}.zip
|
||||
release_name: "ifcopenshell-python-${{steps.version.outputs.version}}"
|
||||
tag: "ifcopenshell-python-${{steps.version.outputs.version}}"
|
||||
overwrite: true
|
||||
@@ -1,21 +1,8 @@
|
||||
name: ci-ifcpatch-pypi
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# ┌───────────── minute (0 - 59)
|
||||
# │ ┌───────────── hour (0 - 23)
|
||||
# │ │ ┌───────────── day of the month (1 - 31)
|
||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
||||
# * * * * *
|
||||
- cron: "0 0 18 * *"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
major: 0
|
||||
minor: 0
|
||||
name: ifcopenshell
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
+12
-14
@@ -1,17 +1,13 @@
|
||||
name: Publish-ifcsverchok
|
||||
name: ci-ifcsverchok-daily
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/ci-ifcsverchok-build.yml'
|
||||
- 'src/ifcsverchok/*'
|
||||
branches:
|
||||
- v0.7.0
|
||||
|
||||
env:
|
||||
major: 0
|
||||
minor: 0
|
||||
name: ifcsverchok
|
||||
- v0.8.0
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
@@ -34,20 +30,22 @@ jobs:
|
||||
with:
|
||||
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
|
||||
python-version: '3.11'
|
||||
- run: echo ${{ env.DATE }}
|
||||
- name: Get current version
|
||||
id: version
|
||||
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "::set-output name=date::$(date +'%y%m%d')"
|
||||
run: echo "date=$(date +'%y%m%d')" >> $GITHUB_OUTPUT
|
||||
- name: Compile
|
||||
run: |
|
||||
cd src/ifcsverchok
|
||||
make dist
|
||||
- name: Upload Zip file to release
|
||||
- name: Upload zip file to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: src/ifcsverchok/dist/ifcsverchok-${{steps.date.outputs.date}}.zip
|
||||
asset_name: ifcsverchok-${{steps.date.outputs.date}}.zip
|
||||
tag: "ifcsverchok-${{steps.date.outputs.date}}"
|
||||
file: src/ifcsverchok/dist/ifcsverchok-${{steps.version.outputs.version}}.${{steps.date.outputs.date}}.zip
|
||||
asset_name: ifcsverchok-${{steps.version.outputs.version}}.${{steps.date.outputs.date}}.zip
|
||||
release_name: "ifcsverchok-${{steps.version.outputs.version}}.${{steps.date.outputs.date}} (unstable)"
|
||||
tag: "ifcsverchok-${{steps.version.outputs.version}}.${{steps.date.outputs.date}}"
|
||||
overwrite: true
|
||||
body: "ifcsverchok build for ${{steps.date.outputs.date}}"
|
||||
@@ -0,0 +1,42 @@
|
||||
name: ci-ifcsverchok
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
build:
|
||||
needs: activate
|
||||
name: ifcsverchok
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
|
||||
python-version: '3.11'
|
||||
- name: Get current version
|
||||
id: version
|
||||
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
||||
- name: Compile
|
||||
run: |
|
||||
cd src/ifcsverchok
|
||||
make dist IS_STABLE=TRUE
|
||||
- name: Upload zip file to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: src/ifcsverchok/dist/ifcsverchok-${{steps.version.outputs.version}}.zip
|
||||
asset_name: ifcsverchok-${{steps.version.outputs.version}}.zip
|
||||
release_name: "ifcsverchok-${{steps.version.outputs.version}}"
|
||||
tag: "ifcsverchok-${{steps.version.outputs.version}}"
|
||||
overwrite: true
|
||||
@@ -1,21 +1,8 @@
|
||||
name: ci-ifctester-pypi
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# ┌───────────── minute (0 - 59)
|
||||
# │ ┌───────────── hour (0 - 23)
|
||||
# │ │ ┌───────────── day of the month (1 - 31)
|
||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
||||
# * * * * *
|
||||
- cron: "0 0 18 * *"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
major: 0
|
||||
minor: 0
|
||||
name: ifcopenshell
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
name: Restart failed daily conda builds
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [ ci-ifcopenshell-conda-daily ]
|
||||
types:
|
||||
- completed
|
||||
|
||||
env:
|
||||
REPO_OWNER: IfcOpenShell/IfcOpenShell
|
||||
MY_WORKFLOW: ci-ifcopenshell-conda-daily
|
||||
|
||||
jobs:
|
||||
restart-failed-runs:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Use python 3.11
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.11
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install requests
|
||||
- name: Check for failed runs
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }}
|
||||
run: |
|
||||
python check_repo_ci_jobs.py
|
||||
working-directory: .github/workflows
|
||||
@@ -46,7 +46,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install xmlschema xsdata numpy lxml pytest isodate lark networkx tabulate python-dateutil
|
||||
pip install xmlschema xsdata numpy lxml pytest isodate lark networkx tabulate python-dateutil shapely
|
||||
pip install src/bcf --no-deps
|
||||
pip install https://github.com/Andrej730/aud/archive/refs/heads/master-reduced-size.zip
|
||||
|
||||
|
||||
@@ -26,49 +26,45 @@ For more information, see:
|
||||
* [BlenderBIM Add-on Documentation](https://docs.blenderbim.org/index.html)
|
||||
* [Add-on Installation](https://docs.blenderbim.org/users/installation.html)
|
||||
* [Exploring an IFC model](https://docs.blenderbim.org/users/exploring_an_ifc_model.html)
|
||||
|
||||
Development is sponsored through your generous donations!
|
||||
|
||||
| Service | Status |
|
||||
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Anaconda Daily Build | [](https://anaconda.org/ifcopenshell/ifcopenshell) |
|
||||
| Anaconda v0.7.0 Stable | [](https://anaconda.org/conda-forge/ifcopenshell) |
|
||||
| PyPi Daily Build | [](https://pypi.org/project/ifcopenshell/) |
|
||||
| ArchLinux AUR Package Stable | [](https://aur.archlinux.org/packages/ifcopenshell) |
|
||||
| ArchLinux AUR Package git | [](https://aur.archlinux.org/packages/ifcopenshell-git) |
|
||||
| BlenderBIM Add-on Chocolatey (under moderation) | [](https://community.chocolatey.org/packages/blenderbim-nightly/) |
|
||||
| Sponsor development on OpenCollective | [](https://opencollective.com/opensourcebim/) |
|
||||
| Docker hub | [](https://hub.docker.com/r/aecgeeks/ifcopenshell) |
|
||||
[](https://opencollective.com/opensourcebim/)
|
||||
|
||||
Contents
|
||||
--------
|
||||
|
||||
Those marked with an asterisk are part of IfcOpenShell.
|
||||
| Name | Description | License | Service |
|
||||
| ------------------------- | --------------------------------------------------------------------- | ------------------- | ------- |
|
||||
| bcf | Library to read and write BCF-XML and query OpenCDE BCF-API modules | LGPL-3.0-or-later | [](https://pypi.org/project/bcf-client/) |
|
||||
| blenderbim | Add-on to Blender providing a graphical native IFC authoring platform | GPL-3.0-or-later | [](https://blenderbim.org/download.html) [](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=blenderbim&expanded=true) [](https://community.chocolatey.org/packages/blenderbim-nightly/) |
|
||||
| bsdd | Library to query the bSDD API | LGPL-3.0-or-later | [](https://pypi.org/project/bsdd/) |
|
||||
| ifc2ca | Utility to convert IFC structural analysis models to Code_Aster | LGPL-3.0-or-later |
|
||||
| ifc4d | Convert to and from IFC and project management software | LGPL-3.0-or-later | [](https://pypi.org/project/ifc4d/) |
|
||||
| ifc5d | Report and optimise cost information from IFC | LGPL-3.0-or-later | [](https://pypi.org/project/ifc5d/) |
|
||||
| ifcbimtester | Wrapper for Gherkin based unit testing for IFC models | LGPL-3.0-or-later |
|
||||
| ifcblender | Historic Blender IFC import add-on | LGPL-3.0-or-later\* |
|
||||
| ifccityjson | Convert CityJSON to IFC | LGPL-3.0-or-later | [](https://pypi.org/project/ifccityjson/) |
|
||||
| ifcclash | Clash detection library and CLI app | LGPL-3.0-or-later | [](https://pypi.org/project/ifcclash/) |
|
||||
| ifcconvert | CLI app to convert IFC to many other formats | LGPL-3.0-or-later\* | [](https://docs.ifcopenshell.org/ifcconvert/installation.html)
|
||||
| ifccsv | Library and CLI app to export and import schedules from IFC | LGPL-3.0-or-later | [](https://pypi.org/project/ifccsv/) |
|
||||
| ifcdiff | Compare changes between IFC models | LGPL-3.0-or-later | [](https://pypi.org/project/ifcdiff/) |
|
||||
| ifcfm | Extract IFC data for FM handover requirements | LGPL-3.0-or-later | [](https://pypi.org/project/ifcfm/) |
|
||||
| ifcmax | Historic extension for IFC support in 3DS Max | LGPL-3.0-or-later\* | [](https://docs.ifcopenshell.org/ifcmax.html)
|
||||
| ifcopenshell-python | Python library for IFC manipulation | LGPL-3.0-or-later\* | [](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcopenshell-python&expanded=true) [](https://pypi.org/project/ifcopenshell/) [](https://anaconda.org/conda-forge/ifcopenshell) [](https://anaconda.org/ifcopenshell/ifcopenshell) [](https://hub.docker.com/r/aecgeeks/ifcopenshell) [](https://aur.archlinux.org/packages/ifcopenshell) [](https://aur.archlinux.org/packages/ifcopenshell-git) |
|
||||
| ifcpatch | Utility to run pre-packaged scripts to manipulate IFCs | LGPL-3.0-or-later | [](https://pypi.org/project/ifcpatch/) |
|
||||
| ifcsverchok | Blender Add-on for visual node programming with IFC | GPL-3.0-or-later | [](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcsverchok&expanded=true)
|
||||
| ifctester | Library, CLI and webapp for IDS model auditing | LGPL-3.0-or-later | [](https://pypi.org/project/ifctester/) |
|
||||
|
||||
The IfcOpenShell C++ codebase is split into multiple interal libraries:
|
||||
|
||||
| Name | Description | License |
|
||||
| ------------------------- | --------------------------------------------------------------------- | ------------------- |
|
||||
| bcf | Library to read and write BCF-XML and query OpenCDE BCF-API modules | LGPL-3.0-or-later |
|
||||
| blenderbim | Add-on to Blender providing a graphical native IFC authoring platform | GPL-3.0-or-later |
|
||||
| bsdd | Library to query the bSDD API | LGPL-3.0-or-later |
|
||||
| ifc2ca | Utility to convert IFC structural analysis models to Code_Aster | LGPL-3.0-or-later |
|
||||
| ifc4d | Convert to and from IFC and project management software | LGPL-3.0-or-later |
|
||||
| ifc5d | Report and optimise cost information from IFC | LGPL-3.0-or-later |
|
||||
| ifcbimtester | Wrapper for Gherkin based unit testing for IFC models | LGPL-3.0-or-later |
|
||||
| ifcblender | Historic Blender IFC import add-on | LGPL-3.0-or-later\* |
|
||||
| ifccityjson | Convert CityJSON to IFC | LGPL-3.0-or-later |
|
||||
| ifcclash | Clash detection library and CLI app | LGPL-3.0-or-later |
|
||||
| ifcconvert | CLI app to convert IFC to many other formats | LGPL-3.0-or-later\* |
|
||||
| ifccsv | Library and CLI app to export and import schedules from IFC | LGPL-3.0-or-later |
|
||||
| ifcdiff | Compare changes between IFC models | LGPL-3.0-or-later |
|
||||
| ifcfm | Extract IFC data for FM handover requirements | LGPL-3.0-or-later |
|
||||
| ifcgeom | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| ifcgeom\_schema\_agnostic | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| ifcgeomserver | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| ifcjni | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| ifcmax | Historic extension for IFC support in 3DS Max | LGPL-3.0-or-later\* |
|
||||
| ifcopenshell-python | Python library for IFC manipulation | LGPL-3.0-or-later\* |
|
||||
| ifcparse | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| ifcpatch | Utility to run pre-packaged scripts to manipulate IFCs | LGPL-3.0-or-later |
|
||||
| ifcsverchok | Blender Add-on for visual node programming with IFC | GPL-3.0-or-later |
|
||||
| ifctester | Library, CLI and webapp for IDS model auditing | LGPL-3.0-or-later |
|
||||
| ifcwrap | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| qtviewer | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| serializers | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<projectUrl>https://github.com/IfcOpenShell/IfcOpenShell</projectUrl>
|
||||
<iconUrl>https://rawcdn.githack.com/IfcOpenShell/IfcOpenShell/c6ee1d1679d1298de0d7447ff108c22709c68e54/choco/blenderbim/blenderbim.png</iconUrl>
|
||||
<!-- <copyright>Year Software Vendor</copyright> -->
|
||||
<licenseUrl>https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.7.0/COPYING</licenseUrl>
|
||||
<licenseUrl>https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.8.0/COPYING</licenseUrl>
|
||||
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||
<projectSourceUrl>https://github.com/IfcOpenShell/IfcOpenShell</projectSourceUrl>
|
||||
<docsUrl>https://docs.blenderbim.org/</docsUrl>
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
import datetime
|
||||
import re
|
||||
import sys
|
||||
from urllib import request
|
||||
|
||||
|
||||
def request_repo_info(url: str):
|
||||
req = request.Request(url)
|
||||
resp = request.urlopen(req)
|
||||
if not resp.status == 200:
|
||||
print(f"[ERROR] could not contact server: {url}")
|
||||
quit(1)
|
||||
return resp
|
||||
|
||||
|
||||
def get_choco_package_info() -> str:
|
||||
resp = request_repo_info(URL_CHOCO_PACKAGE)
|
||||
html_txt = str(resp.read())
|
||||
return html_txt
|
||||
|
||||
|
||||
def get_latest_blender_version() -> list:
|
||||
html_txt = get_choco_package_info()
|
||||
return re.findall(RE_BLENDER_VERSION_MIN_MAJ_PAT, html_txt)
|
||||
|
||||
|
||||
URL_IFCOS_RELEASES = "https://github.com/IfcOpenShell/IfcOpenShell/releases"
|
||||
URL_CHOCO_PACKAGE = "https://community.chocolatey.org/packages/blender"
|
||||
URL_BLENDER_CMAKE = "https://raw.githubusercontent.com/blender/blender/{}/build_files/cmake/Modules/FindPythonLibsUnix.cmake"
|
||||
RE_BLENDER_VERSION_MIN_MAJ = r"Latest Version.+<span>Blender (\d+\.\d+)\..+</span>"
|
||||
RE_BLENDER_VERSION_MIN_MAJ_PAT = r"Latest Version.+<span>Blender (\d+\.\d+\.\d+)</span>"
|
||||
RE_BLENDER_PYTHON_VERSION_MAJ_MIN = r"(?:set|SET)\(_PYTHON_VERSION_SUPPORTED (\d+\.\d+)\)"
|
||||
|
||||
|
||||
if sys.argv[1] == "--do_choco_release?":
|
||||
now = datetime.datetime.now()
|
||||
blenderbim_date = (now - datetime.timedelta(days=1)).strftime("%y%m%d")
|
||||
resp = request_repo_info(URL_IFCOS_RELEASES)
|
||||
text = str(resp.read())
|
||||
if blenderbim_date in text:
|
||||
print("do_choco_release", end="")
|
||||
|
||||
|
||||
elif sys.argv[1] == "--latest_blender_release_maj_min_pat?":
|
||||
latest_blender_version = get_latest_blender_version()
|
||||
if latest_blender_version:
|
||||
print(latest_blender_version[0], end="")
|
||||
else:
|
||||
print("[ERROR] could not determine blender_version_min_maj_pat")
|
||||
quit(1)
|
||||
|
||||
|
||||
elif sys.argv[1] == "--latest_blender_release_maj_min?":
|
||||
html_txt = get_choco_package_info()
|
||||
blender_version_min_maj = re.findall(RE_BLENDER_VERSION_MIN_MAJ, html_txt)
|
||||
if blender_version_min_maj:
|
||||
print(blender_version_min_maj[0], end="")
|
||||
else:
|
||||
print("[ERROR] could not determine blender_version_min_maj")
|
||||
quit(1)
|
||||
|
||||
|
||||
elif sys.argv[1] == "--latest_blender_python_version_maj_min?":
|
||||
latest_blender_version = get_latest_blender_version()
|
||||
if latest_blender_version:
|
||||
latest_blender_version_tag = f"v{latest_blender_version[0]}"
|
||||
resp = request_repo_info(URL_BLENDER_CMAKE.format(latest_blender_version_tag))
|
||||
html_txt = str(resp.read())
|
||||
found = re.findall(RE_BLENDER_PYTHON_VERSION_MAJ_MIN, html_txt)
|
||||
if found:
|
||||
print(found[0], end="")
|
||||
else:
|
||||
print("[ERROR] could not determine blender_python_version_maj_min")
|
||||
quit(1)
|
||||
|
||||
|
||||
elif sys.argv[1] == "--pyver?":
|
||||
latest_blender_version = get_latest_blender_version()
|
||||
if latest_blender_version:
|
||||
latest_blender_version_tag = f"v{latest_blender_version[0]}"
|
||||
resp = request_repo_info(URL_BLENDER_CMAKE.format(latest_blender_version_tag))
|
||||
html_txt = str(resp.read())
|
||||
found = re.findall(RE_BLENDER_PYTHON_VERSION_MAJ_MIN, html_txt)
|
||||
if found:
|
||||
print(f"py{found[0].replace('.', '')}", end="")
|
||||
else:
|
||||
print("[ERROR] could not determine pyver")
|
||||
quit(1)
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
# commands to run it on a generic ubuntu 2404 oci container:
|
||||
"""
|
||||
apt update && apt install git wget curl ptpython mono-devel micro
|
||||
mkdir -p /home/runner/work/IfcOpenShell && cd /home/runner/work/IfcOpenShell
|
||||
git clone https://github.com/IfcOpenShell/IfcOpenShell
|
||||
cd /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/
|
||||
micro choco_release.py # paste this script, comment out push command
|
||||
export CHOCO_TOKEN="secret_choco_release_token"
|
||||
python3 choco_release.py
|
||||
"""
|
||||
import datetime
|
||||
import hashlib
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
from urllib import request
|
||||
|
||||
|
||||
def get_repo_tag_names():
|
||||
git_return = os.popen("git tag -l").read()
|
||||
tag_names = [tag_name for tag_name in git_return.split("\n") if tag_name]
|
||||
print(f"{len(tag_names)} tag_names found in repo")
|
||||
return tag_names
|
||||
|
||||
|
||||
def request_repo_info(url: str):
|
||||
req = request.Request(url)
|
||||
resp = request.urlopen(req)
|
||||
if not resp.status == 200:
|
||||
print(f"[ERROR] could not contact server: {url}")
|
||||
quit(1)
|
||||
return resp
|
||||
|
||||
|
||||
def get_choco_package_info() -> str:
|
||||
resp = request_repo_info(URL_CHOCO_PACKAGE)
|
||||
html_txt = str(resp.read())
|
||||
return html_txt
|
||||
|
||||
|
||||
def get_latest_choco_blender_version() -> list:
|
||||
html_txt = get_choco_package_info()
|
||||
return re.findall(RE_BLENDER_VERSION_MIN_MAJ_PAT, html_txt)
|
||||
|
||||
|
||||
def get_file_sha256_hash(file_path):
|
||||
BLOCKSIZE = 65536
|
||||
hasher = hashlib.sha256()
|
||||
|
||||
with open(file_path, "rb") as input_file:
|
||||
buffer = input_file.read(BLOCKSIZE)
|
||||
while len(buffer) > 0:
|
||||
hasher.update(buffer)
|
||||
buffer = input_file.read(BLOCKSIZE)
|
||||
|
||||
return hasher.hexdigest()
|
||||
|
||||
|
||||
def quit_with_error_message(message: str):
|
||||
print(f"ERROR: {message}")
|
||||
quit(0)
|
||||
|
||||
|
||||
start = datetime.datetime.now()
|
||||
|
||||
URL_CHOCO_PACKAGE = "https://community.chocolatey.org/packages/blender"
|
||||
URL_BLENDER_CMAKE = "https://raw.githubusercontent.com/blender/blender/{}/build_files/cmake/Modules/FindPythonLibsUnix.cmake"
|
||||
URL_IFCOS_RELEASES = "https://github.com/IfcOpenShell/IfcOpenShell/releases/download/"
|
||||
RE_BLENDER_VERSION_MIN_MAJ = r"Latest Version.+<span>Blender (\d+\.\d+)\..+</span>"
|
||||
RE_BLENDER_VERSION_MIN_MAJ_PAT = r"Latest Version.+<span>Blender (\d+\.\d+\.\d+)</span>"
|
||||
RE_BLENDER_PYTHON_VERSION_MAJ_MIN = r"\(_PYTHON_VERSION_SUPPORTED (\d+\.\d+)\)"
|
||||
|
||||
BLENDERBIM_DIR = pathlib.Path("/home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/")
|
||||
|
||||
print("_____ check choco release needed?")
|
||||
|
||||
os.chdir(BLENDERBIM_DIR)
|
||||
|
||||
blenderbim_date_yesterday = (datetime.datetime.now() - datetime.timedelta(days=1)).strftime("%y%m%d")
|
||||
should_release = False
|
||||
target_release_tag = ""
|
||||
target_os = "win"
|
||||
|
||||
git_status = os.popen("git status").read()
|
||||
print(git_status)
|
||||
|
||||
for tag_name in get_repo_tag_names():
|
||||
print(tag_name)
|
||||
if blenderbim_date_yesterday in tag_name:
|
||||
should_release = True
|
||||
target_release_tag = tag_name
|
||||
print(f"found {tag_name=} - {should_release=}")
|
||||
break
|
||||
|
||||
if not should_release:
|
||||
print(f"INFO: no blenderbim release tags found for {blenderbim_date_yesterday} -> no choco release today.")
|
||||
quit(0)
|
||||
print(f"{should_release=}")
|
||||
|
||||
if not os.environ.get("CHOCO_TOKEN"):
|
||||
quit_with_error_message("could retrieve CHOCO_TOKEN env var")
|
||||
choco_token = os.environ["CHOCO_TOKEN"]
|
||||
|
||||
print("\n_____ get blender info")
|
||||
# blender_version_min_maj_pat - from chocolatey.org
|
||||
latest_blender_release_maj_min_pat = get_latest_choco_blender_version()
|
||||
if not latest_blender_release_maj_min_pat:
|
||||
quit_with_error_message("could not determine blender_version_min_maj_pat")
|
||||
latest_blender_release_maj_min_pat = latest_blender_release_maj_min_pat[0]
|
||||
print(f"{latest_blender_release_maj_min_pat=}")
|
||||
|
||||
# blender_version_min_maj - from chocolatey.org
|
||||
blender_version_min_maj = latest_blender_release_maj_min_pat.rsplit(".", 1)[0]
|
||||
print(f"{blender_version_min_maj=}")
|
||||
|
||||
# blender_python_version_maj_min - from blender repo
|
||||
python_version = ""
|
||||
latest_blender_version_tag = f"v{latest_blender_release_maj_min_pat}"
|
||||
resp = request_repo_info(URL_BLENDER_CMAKE.format(latest_blender_version_tag))
|
||||
html_txt = str(resp.read())
|
||||
found = re.findall(RE_BLENDER_PYTHON_VERSION_MAJ_MIN, html_txt)
|
||||
if not found:
|
||||
quit_with_error_message("could not determine blender_python_version_maj_min")
|
||||
|
||||
blender_python_version_maj_min = found[0]
|
||||
print(f"{blender_python_version_maj_min=}")
|
||||
python_version = f"py{found[0].replace('.', '')}"
|
||||
print(f"{python_version=}")
|
||||
|
||||
blenderbim_build_version = target_release_tag.replace("blenderbim-", "")
|
||||
|
||||
# url_blenderbim_py3x_win_zip
|
||||
release_zip_file_name = f"{target_release_tag}-{python_version}-{target_os}.zip"
|
||||
|
||||
# download release
|
||||
url_blenderbim_py3x_win_zip = f"{URL_IFCOS_RELEASES}{target_release_tag}/{release_zip_file_name}"
|
||||
os.popen(f"wget {url_blenderbim_py3x_win_zip} --no-verbose").read()
|
||||
|
||||
# sha256sum_blenderbim_py310_win_zip
|
||||
sha256sum_blenderbim_py3x_win_zip = get_file_sha256_hash(release_zip_file_name)
|
||||
|
||||
print("\n_____ fill dynamic chocolatey package parameters")
|
||||
HERE_DIR = pathlib.Path(__file__).parent.absolute()
|
||||
# print(f"[INFO] HERE_DIR: {HERE_DIR}")
|
||||
|
||||
topics = {
|
||||
"spec": {
|
||||
"path": HERE_DIR / "blenderbim.nuspec",
|
||||
"key_values": {
|
||||
"latest_blender_version_maj_min_pat": latest_blender_release_maj_min_pat,
|
||||
"blenderbim_build_version" : blenderbim_build_version,
|
||||
},
|
||||
},
|
||||
"install": {
|
||||
"path": HERE_DIR / "tools" / "chocolateyinstall.ps1",
|
||||
"key_values": {
|
||||
"url_blenderbim_py3x_win_zip" : url_blenderbim_py3x_win_zip,
|
||||
"sha256sum_blenderbim_py3x_win_zip": sha256sum_blenderbim_py3x_win_zip,
|
||||
"latest_blender_version_maj_min" : blender_version_min_maj,
|
||||
},
|
||||
},
|
||||
"uninstall": {
|
||||
"path": HERE_DIR / "tools" / "chocolateyuninstall.ps1",
|
||||
"key_values": {
|
||||
"latest_blender_version_maj_min": blender_version_min_maj,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for topic, info in topics.items():
|
||||
print(f" {topic}:")
|
||||
with open(info["path"], encoding="utf-8") as txt:
|
||||
content = txt.read()
|
||||
|
||||
for key, value in info["key_values"].items():
|
||||
# print(f"[INFO] replace: {env_var_name}")
|
||||
if not key in content:
|
||||
print(f" {key=} not found in {info['path']}")
|
||||
content = content.replace(key, value)
|
||||
|
||||
with open(info["path"], "w", encoding="utf-8") as txt:
|
||||
txt.write(content)
|
||||
print(f" written: {info['path']}")
|
||||
|
||||
print("[INFO] inserting dynamic chocolatey package parameters successful")
|
||||
|
||||
|
||||
print("\n_____ build choco.exe with mono")
|
||||
|
||||
choco_version = "1.1.0"
|
||||
os.popen(f"wget https://github.com/chocolatey/choco/archive/refs/tags/{choco_version}.tar.gz --quiet").read()
|
||||
os.popen(f"tar -xzf {choco_version}.tar.gz").read()
|
||||
print("choco tar unpack successful")
|
||||
os.chdir("choco-1.1.0")
|
||||
os.popen("./build.sh").read()
|
||||
|
||||
os.popen("cp -r build_output/chocolatey /opt/chocolatey").read()
|
||||
os.chdir(BLENDERBIM_DIR)
|
||||
|
||||
if pathlib.Path("/opt/chocolatey/choco.exe").exists():
|
||||
print("choco build successful")
|
||||
|
||||
print("\n_____ build choco pack")
|
||||
|
||||
os.popen("mono /opt/chocolatey/choco.exe pack --allow-unofficial").read()
|
||||
os.popen('mono /opt/chocolatey/choco.exe setapikey --key="{choco_token}" --source="https://push.chocolatey.org/" --allow-unofficial').read()
|
||||
|
||||
print("\n_____ build choco push")
|
||||
os.popen('mono /opt/chocolatey/choco.exe push --source="https://push.chocolatey.org/" --key="$CHOCO_TOKEN" --allow-unofficial --verbose').read()
|
||||
|
||||
print(f"choco push of version: {target_release_tag} successful!")
|
||||
print(f"it took: {datetime.datetime.now() - start}")
|
||||
@@ -1,49 +0,0 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
print("[INFO] inserting dynamic chocolatey package parameters")
|
||||
HERE_DIR = Path(__file__).parent.absolute()
|
||||
# print(f"[INFO] HERE_DIR: {HERE_DIR}")
|
||||
|
||||
topics = {
|
||||
"spec": {
|
||||
"path": HERE_DIR / "blenderbim.nuspec",
|
||||
"env_vars": {
|
||||
"latest_blender_version_maj_min_pat",
|
||||
"blenderbim_build_version",
|
||||
},
|
||||
},
|
||||
"install": {
|
||||
"path": HERE_DIR / "tools" / "chocolateyinstall.ps1",
|
||||
"env_vars": {
|
||||
"url_blenderbim_py310_win_zip",
|
||||
"sha256sum_blenderbim_py310_win_zip",
|
||||
"latest_blender_version_maj_min",
|
||||
},
|
||||
},
|
||||
"uninstall": {
|
||||
"path": HERE_DIR / "tools" / "chocolateyuninstall.ps1",
|
||||
"env_vars": {
|
||||
"latest_blender_version_maj_min",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for topic, info in topics.items():
|
||||
print(f"[INFO] {topic}:")
|
||||
for env_var_name in info["env_vars"]:
|
||||
print(f"[INFO] {env_var_name} exists?: {os.environ[env_var_name]}")
|
||||
|
||||
with open(info["path"], encoding="utf-8") as txt:
|
||||
content = txt.read()
|
||||
|
||||
for env_var_name in info["env_vars"]:
|
||||
# print(f"[INFO] replace: {env_var_name}")
|
||||
content = content.replace(env_var_name, os.environ[env_var_name])
|
||||
|
||||
with open(info["path"], "w", encoding="utf-8") as txt:
|
||||
txt.write(content)
|
||||
print(f"[INFO] written: {info['path']}")
|
||||
|
||||
print("[INFO] inserting dynamic chocolatey package parameters successful")
|
||||
@@ -1,7 +1,7 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$url64 = 'url_blenderbim_py310_win_zip'
|
||||
$checksum64 = 'sha256sum_blenderbim_py310_win_zip'
|
||||
$url64 = 'url_blenderbim_py3x_win_zip'
|
||||
$checksum64 = 'sha256sum_blenderbim_py3x_win_zip'
|
||||
$checksumType64 = 'sha256'
|
||||
|
||||
$appDataUserDir = [System.Environment]::GetEnvironmentVariable('appdata')
|
||||
|
||||
+1267
-1244
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
.env
|
||||
+8
-6
@@ -1,10 +1,13 @@
|
||||
mkdir build && cd build
|
||||
|
||||
REM Remove dot from PY_VER for use in library name
|
||||
REM From https://github.com/tpaviot/pythonocc-core/blob/master/ci/conda/bld.bat
|
||||
set MY_PY_VER=%PY_VER:.=%
|
||||
rem set LIBXML2="%LIBRARY_PREFIX%/lib/libxml2.lib"
|
||||
|
||||
set LIBXML2="%LIBRARY_PREFIX%/lib/libxml2.lib"
|
||||
|
||||
cmake -G "Ninja" ^
|
||||
-D SCHEMA_VERSIONS="2x3;4;4x1;4x3;4x3_add1" ^
|
||||
-D SCHEMA_VERSIONS="2x3;4;4x1;4x3_add2" ^
|
||||
-D CMAKE_BUILD_TYPE:STRING=Release ^
|
||||
-D CMAKE_INSTALL_PREFIX:FILEPATH="%LIBRARY_PREFIX%" ^
|
||||
-D CMAKE_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^
|
||||
@@ -39,11 +42,10 @@ cmake -G "Ninja" ^
|
||||
-D Boost_INCLUDE_DIR:FILEPATH="%LIBRARY_PREFIX%\include" ^
|
||||
-D Boost_USE_STATIC_LIBS:BOOL=OFF ^
|
||||
-D CITYJSON_SUPPORT:BOOL=OFF ^
|
||||
%SRC_DIR%/cmake
|
||||
|
||||
../cmake
|
||||
|
||||
if errorlevel 1 exit 1
|
||||
|
||||
:: Build and install
|
||||
cmake --build . -- install
|
||||
ninja install -j 1
|
||||
|
||||
if errorlevel 1 exit 1
|
||||
|
||||
+3
-5
@@ -6,16 +6,14 @@
|
||||
|
||||
if [ "$(uname)" == "Darwin" ]; then
|
||||
export FSUFFIX=dylib
|
||||
export CFLAGS="$CFLAGS -Wl,-flat_namespace,-undefined,suppress"
|
||||
export CXXFLAGS="$CXXFLAGS -Wl,-flat_namespace,-undefined,suppress"
|
||||
export LDFLAGS="$LDFLAGS -Wl,-flat_namespace,-undefined,suppress"
|
||||
elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
|
||||
export FSUFFIX=so
|
||||
fi
|
||||
|
||||
|
||||
cmake -G Ninja \
|
||||
-DSCHEMA_VERSIONS="2x3;4;4x1;4x3;4x3_add1" \
|
||||
cmake ${CMAKE_ARGS} -G Ninja \
|
||||
-DSCHEMA_VERSIONS="2x3;4;4x1;4x3_add2" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=$PREFIX \
|
||||
${CMAKE_PLATFORM_FLAGS[@]} \
|
||||
@@ -48,4 +46,4 @@ cmake -G Ninja \
|
||||
|
||||
ninja
|
||||
|
||||
ninja install -j 1
|
||||
ninja install -j 1
|
||||
@@ -1,11 +1,58 @@
|
||||
CONDA_BUILD_SYSROOT: # used for github actions conda daily build
|
||||
- /Users/runner/work/MacOSX10.13.sdk # [osx]
|
||||
variant:
|
||||
- novtk
|
||||
- all
|
||||
|
||||
occt:
|
||||
- 7.7.1
|
||||
- 7.8.1
|
||||
|
||||
c_compiler:
|
||||
- vs2022 # [win]
|
||||
|
||||
- vs2022 # [win]
|
||||
- gcc # [linux]
|
||||
- clang # [osx]
|
||||
c_stdlib:
|
||||
- vs # [win]
|
||||
- sysroot # [linux]
|
||||
- macosx_deployment_target # [osx]
|
||||
cxx_compiler:
|
||||
- vs2022 # [win]
|
||||
- vs2022 # [win]
|
||||
- gcc # [linux]
|
||||
- clangxx # [osx]
|
||||
c_compiler_version:
|
||||
- '12' # [linux]
|
||||
- '16' # [osx]
|
||||
cxx_compiler_version:
|
||||
- '12' # [linux]
|
||||
- '16' # [osx]
|
||||
c_stdlib_version:
|
||||
- '2.12' # [linux]
|
||||
- '10.13' # [osx]
|
||||
hdf5:
|
||||
- 1.14.3
|
||||
libboost_devel:
|
||||
- '1.84'
|
||||
libxml2:
|
||||
- '2'
|
||||
mpfr:
|
||||
- '4'
|
||||
gmp:
|
||||
- '6' # [not win]
|
||||
pin_run_as_build:
|
||||
python:
|
||||
min_pin: x.x
|
||||
max_pin: x.x
|
||||
|
||||
zlib:
|
||||
- '1'
|
||||
target_platform:
|
||||
- win-64 # [win]
|
||||
- linux-64 # [linux]
|
||||
- osx-64 # [osx]
|
||||
macos_machine:
|
||||
- x86_64-apple-darwin13.4.0
|
||||
MACOSX_DEPLOYMENT_TARGET:
|
||||
- '10.13'
|
||||
MACOSX_SDK_VERSION:
|
||||
- '10.13'
|
||||
|
||||
CONDA_BUILD_SYSROOT:
|
||||
- "/Users/runner/work/MacOSX10.13.sdk" # [osx]
|
||||
@@ -1,58 +0,0 @@
|
||||
@echo off
|
||||
|
||||
:: This is a batch file to set the environment variables for the project
|
||||
:: It is not necessary for conda compilation, but it provides you with type hints when working with the c++ libraries
|
||||
:: OpenCascade, CGAL, Eigen, etc distributed using conda-forge in your IDE.
|
||||
::
|
||||
:: mamba env update -f environment.build.yml --prune
|
||||
:: mamba activate ifcopenshell-build
|
||||
::
|
||||
:: Note!
|
||||
:: You have to add a .env file next to this env.bat file where you set PREFIX=<path to your conda env>
|
||||
set CONDA_BUILD=1
|
||||
set MY_PY_VER=311
|
||||
|
||||
:: set this file's parent directory as a variable
|
||||
set THIS_DIR=%~dp0
|
||||
|
||||
:: read the .env file located in THIS_DIR and set the environment variables.
|
||||
:: the .env file should contain a line like this:
|
||||
:: PREFIX=C:\Users\your_user_name\mambaforge3\envs\ifcopenshell-build
|
||||
for /f "tokens=*" %%i in (%THIS_DIR%.env) do set %%i
|
||||
|
||||
set LIBRARY_PREFIX=%PREFIX%/Library
|
||||
set CMAKE_PREFIX_PATH=%PREFIX%;%LIBRARY_PREFIX%/include;%LIBRARY_PREFIX%/lib;%LIBRARY_PREFIX%/bin
|
||||
|
||||
set OCC_LIBRARY_DIR=%LIBRARY_PREFIX%/lib
|
||||
set OCC_INCLUDE_DIR=%LIBRARY_PREFIX%/include/opencascade
|
||||
|
||||
set CGAL_DIR=%LIBRARY_PREFIX%/lib/cmake/CGAL
|
||||
set CGAL_INCLUDE_DIR=%LIBRARY_PREFIX%/include
|
||||
set EIGEN_DIR=%LIBRARY_PREFIX%/include/eigen3
|
||||
set LIBXML2_INCLUDE_DIR=%LIBRARY_PREFIX%/include/libxml2
|
||||
set LIBXML2_LIBRARIES=%LIBRARY_PREFIX%/lib/libxml2.lib
|
||||
set Boost_LIBRARY_DIR=%LIBRARY_PREFIX%/lib
|
||||
set Boost_INCLUDE_DIR=%LIBRARY_PREFIX%/include
|
||||
set Boost_USE_STATIC_LIBS=OFF
|
||||
|
||||
set GMP_INCLUDE_DIR=%LIBRARY_PREFIX%/include
|
||||
set GMP_LIBRARY_DIR=%LIBRARY_PREFIX%/lib
|
||||
set MPFR_LIBRARY_DIR=%LIBRARY_PREFIX%/lib
|
||||
|
||||
set HDF5_INCLUDE_DIR=%LIBRARY_PREFIX%/include
|
||||
set HDF5_LIBRARY_DIR=%LIBRARY_PREFIX%/lib
|
||||
set JSON_INCLUDE_DIR=%LIBRARY_PREFIX%/include
|
||||
|
||||
set HDF5_SUPPORT=ON
|
||||
set BUILD_IFCPYTHON=ON
|
||||
set BUILD_IFCGEOM=ON
|
||||
set COLLADA_SUPPORT=OFF
|
||||
set BUILD_EXAMPLES=OFF
|
||||
set BUILD_GEOMSERVER=OFF
|
||||
set GLTF_SUPPORT=ON
|
||||
set BUILD_CONVERT=ON
|
||||
set BUILD_IFCMAX=OFF
|
||||
set IFCXML_SUPPORT=ON
|
||||
|
||||
set PYTHON_EXECUTABLE=%PREFIX%/python.exe
|
||||
set PYTHON_LIBRARY=%PREFIX%/libs/python%MY_PY_VER%.lib
|
||||
@@ -1,17 +0,0 @@
|
||||
name: ifcopenshell-build
|
||||
channels:
|
||||
- conda-forge
|
||||
dependencies:
|
||||
- boa
|
||||
- boost-cpp
|
||||
- occt
|
||||
- libxml2
|
||||
- cgal-cpp
|
||||
- hdf5
|
||||
- mpfr
|
||||
- nlohmann_json
|
||||
- swig
|
||||
- zlib
|
||||
# These needs to be installed per platform
|
||||
#- sel(unix): gmp
|
||||
#- sel(win): mpir
|
||||
+303
@@ -0,0 +1,303 @@
|
||||
{% set version = environ.get('VERSION_OVERRIDE', '0.8.0') %}
|
||||
{% set build = 0 %}
|
||||
|
||||
# Higher number -> Always prioritize "novtk" variant over "all" variant
|
||||
{% set build = build + 200 %} # [variant == "novtk"]
|
||||
{% set build = build + 100 %} # [variant == "all"]
|
||||
|
||||
package:
|
||||
name: ifcopenshell
|
||||
version: {{ version }}
|
||||
|
||||
source:
|
||||
path: ../
|
||||
|
||||
|
||||
build:
|
||||
number: {{ build }}
|
||||
skip: true # [py<39]
|
||||
binary_relocation: false # [osx]
|
||||
string: py{{ CONDA_PY }}_{{ variant }}_h{{ PKG_HASH }}_{{ build }}
|
||||
run_exports:
|
||||
- {{ pin_subpackage('ifcopenshell', max_pin='x.x.x') }} *{{ variant }}*
|
||||
|
||||
|
||||
requirements:
|
||||
build:
|
||||
- cmake
|
||||
- ninja
|
||||
- swig >=4.1.1
|
||||
- {{ stdlib("c") }}
|
||||
- {{ compiler('c') }}
|
||||
- {{ compiler('cxx') }}
|
||||
host:
|
||||
- python
|
||||
- libboost-devel
|
||||
- occt *=*{{ variant }}*
|
||||
- libxml2
|
||||
- cgal-cpp
|
||||
- hdf5
|
||||
- eigen
|
||||
- mpfr
|
||||
- nlohmann_json
|
||||
- gmp # [unix]
|
||||
- mpir # [win]
|
||||
- zlib
|
||||
run:
|
||||
- python
|
||||
- {{ pin_compatible('occt', max_pin='x.x.x') }} *{{ variant }}*
|
||||
- {{ pin_compatible('cgal-cpp', max_pin='x.x') }}
|
||||
|
||||
|
||||
test:
|
||||
imports:
|
||||
- ifcopenshell
|
||||
|
||||
|
||||
about:
|
||||
home: https://ifcopenshell.org
|
||||
license: LGPL-3.0-or-later
|
||||
license_file: COPYING
|
||||
summary: 'IfcOpenShell is a library to support the IFC file format'
|
||||
description: |
|
||||
IfcOpenShell
|
||||
============
|
||||
|
||||
IfcOpenShell is an open source ([LGPL]) software library for working with Industry Foundation Classes ([IFC]). Complete
|
||||
parsing support is provided for [IFC2x3 TC1], [IFC4 Add2 TC1], IFC4x1, IFC4x3, and IFC4x3. Extensive geometric support
|
||||
is implemented for the IFC releases [IFC2x3 TC1] and [IFC4 Add2 TC1]. Extending with support for arbitrary IFC schemas
|
||||
is possible at compile-time when using C++ and at run-time when using Python.
|
||||
|
||||
In addition to a C++ and Python API, IfcOpenShell comes with an ecosystem of tools, notably including IfcConvert (an
|
||||
application to convert IFC models to
|
||||
other formats), the BlenderBIM Add-on (an add-on to Blender providing a graphical IFC authoring platform), and many
|
||||
other libraries, CLI apps, and more. Support is also provided for auxiliary standards such as BCF and IDS.
|
||||
|
||||
For more information, see:
|
||||
|
||||
* [IfcOpenShell Website](http://ifcopenshell.org)
|
||||
* [IfcOpenShell Documentation](http://blenderbim.org/docs-python)
|
||||
* [IfcOpenShell C++ Installation](https://blenderbim.org/docs-python/ifcopenshell/installation.html)
|
||||
* [IfcOpenShell Python Installation](https://blenderbim.org/docs-python/ifcopenshell-python/installation.html)
|
||||
* [IfcOpenShell Python Hello World Tutorial](https://blenderbim.org/docs-python/ifcopenshell-python/hello_world.html)
|
||||
* [BlenderBIM Add-on Website](https://blenderbim.org)
|
||||
* [BlenderBIM Add-on Documentation](http://blenderbim.org/docs)
|
||||
* [Add-on Installation](https://blenderbim.org/docs/users/installation.html)
|
||||
* [Exploring an IFC model](https://blenderbim.org/docs/users/exploring_an_ifc_model.html)
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Service</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Anaconda Daily Build</td>
|
||||
<td><a href="https://anaconda.org/ifcopenshell/ifcopenshell"><img src="https://img.shields.io/conda/vn/ifcopenshell/ifcopenshell" alt="Anaconda-Server Badge"></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Anaconda v0.8.0 Stable</td>
|
||||
<td><a href="https://anaconda.org/conda-forge/ifcopenshell"><img src="https://img.shields.io/conda/vn/conda-forge/ifcopenshell" alt="Anaconda-Server Badge"></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>PyPi Daily Build</td>
|
||||
<td><a href="https://pypi.org/project/ifcopenshell/"><img src="https://img.shields.io/pypi/v/ifcopenshell" alt="PyPi Badge"></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ArchLinux AUR Package Stable</td>
|
||||
<td><a href="https://aur.archlinux.org/packages/ifcopenshell"><img src="https://img.shields.io/aur/version/ifcopenshell" alt="AUR Badge"></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ArchLinux AUR Package git</td>
|
||||
<td><a href="https://aur.archlinux.org/packages/ifcopenshell-git"><img src="https://img.shields.io/aur/version/ifcopenshell-git" alt="AUR Badge"></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>BlenderBIM Add-on Chocolatey (under moderation)</td>
|
||||
<td><a href="https://community.chocolatey.org/packages/blenderbim-nightly/"><img src="https://img.shields.io/chocolatey/v/blenderbim-nightly" alt="Chocolatey Badge"></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sponsor development on OpenCollective</td>
|
||||
<td><a href="https://opencollective.com/opensourcebim/"><img src="https://opencollective.com/opensourcebim/tiers/badge.svg" alt="Financial Contributors"></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Docker hub</td>
|
||||
<td><a href="https://hub.docker.com/r/aecgeeks/ifcopenshell"><img src="https://img.shields.io/docker/pulls/aecgeeks/ifcopenshell" alt="Docker Pulls"></a></td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
Contents
|
||||
--------
|
||||
|
||||
Those marked with an asterisk are part of IfcOpenShell.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>License</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>bcf</td>
|
||||
<td>Library to read and write BCF-XML and query OpenCDE BCF-API modules</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>blenderbim</td>
|
||||
<td>Add-on to Blender providing a graphical native IFC authoring platform</td>
|
||||
<td>GPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>bsdd</td>
|
||||
<td>Library to query the bSDD API</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifc2ca</td>
|
||||
<td>Utility to convert IFC structural analysis models to Code_Aster</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifc4d</td>
|
||||
<td>Convert to and from IFC and project management software</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifc5d</td>
|
||||
<td>Report and optimise cost information from IFC</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcbimtester</td>
|
||||
<td>Wrapper for Gherkin based unit testing for IFC models</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcblender</td>
|
||||
<td>Historic Blender IFC import add-on</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifccityjson</td>
|
||||
<td>Convert CityJSON to IFC</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcclash</td>
|
||||
<td>Clash detection library and CLI app</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifccobie</td>
|
||||
<td>Extract IFC data for COBie handover requirements</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcconvert</td>
|
||||
<td>CLI app to convert IFC to many other formats</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifccsv</td>
|
||||
<td>Library and CLI app to export and import schedules from IFC</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcdiff</td>
|
||||
<td>Compare changes between IFC models</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcfm</td>
|
||||
<td>Extract IFC data for FM handover requirements</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcgeom</td>
|
||||
<td>Internal library for IfcOpenShell</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcgeom_schema_agnostic</td>
|
||||
<td>Internal library for IfcOpenShell</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcgeomserver</td>
|
||||
<td>Internal library for IfcOpenShell</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcjni</td>
|
||||
<td>Internal library for IfcOpenShell</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcmax</td>
|
||||
<td>Historic extension for IFC support in 3DS Max</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcopenshell-python</td>
|
||||
<td>Python library for IFC manipulation</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcparse</td>
|
||||
<td>Internal library for IfcOpenShell</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcpatch</td>
|
||||
<td>Utility to run pre-packaged scripts to manipulate IFCs</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcsverchok</td>
|
||||
<td>Blender Add-on for visual node programming with IFC</td>
|
||||
<td>GPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifctester</td>
|
||||
<td>Library, CLI and webapp for IDS model auditing</td>
|
||||
<td>LGPL-3.0-or-later</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ifcwrap</td>
|
||||
<td>Internal library for IfcOpenShell</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>qtviewer</td>
|
||||
<td>Internal library for IfcOpenShell</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>serializers</td>
|
||||
<td>Internal library for IfcOpenShell</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
[LGPL]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/COPYING.LESSER "LGPL-3.0-or-later"
|
||||
[IFC]: https://technical.buildingsmart.org/standards/ifc/ "IFC"
|
||||
[IFC2x3 TC1]: https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ "IFC2x3 TC1"
|
||||
[IFC4 Add2 TC1]: https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/ "IFC4 Add2 TC1"
|
||||
[Visual Studio]: https://www.visualstudio.com/ "Visual Studio"
|
||||
[Visual C++ Build Tools]: http://landinghub.visualstudio.com/visual-cpp-build-tools "Visual C++ Build Tools"
|
||||
[MSYS2]: https://msys2.github.io/ "MSYS2"
|
||||
[win/readme.md]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/win/readme.md "win/readme.md"
|
||||
[nix/build-all.py]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/nix/build-all.py "nix/build-all.py"
|
||||
doc_url: https://ifcopenshell.org/
|
||||
dev_url: https://github.com/IfcOpenShell/IfcOpenShell
|
||||
|
||||
extra:
|
||||
recipe-maintainers:
|
||||
- adrianinsaval
|
||||
- looooo
|
||||
- Krande
|
||||
@@ -1,64 +0,0 @@
|
||||
context:
|
||||
name: ifcopenshell
|
||||
version: 0.8.0alpha1
|
||||
|
||||
package:
|
||||
name: '{{ name|lower }}'
|
||||
version: '{{ version }}'
|
||||
|
||||
source:
|
||||
path: ..
|
||||
|
||||
build:
|
||||
number: 1
|
||||
|
||||
requirements:
|
||||
build:
|
||||
- "{{ compiler('c') }}"
|
||||
- "{{ compiler('cxx') }}"
|
||||
- ninja >=1.10.2
|
||||
- cmake
|
||||
- swig 4.1.1
|
||||
|
||||
host:
|
||||
- python
|
||||
- boost-cpp
|
||||
- occt ==7.7.0
|
||||
- libxml2
|
||||
- cgal-cpp
|
||||
- hdf5
|
||||
- eigen
|
||||
- mpfr
|
||||
- sel(unix): gmp
|
||||
- sel(win): mpir
|
||||
- nlohmann_json
|
||||
- zlib
|
||||
|
||||
run:
|
||||
- python
|
||||
- {{ pin_compatible('occt', max_pin='x.x.x') }}
|
||||
- {{ pin_compatible('cgal-cpp', max_pin='x.x.x') }}
|
||||
- {{ pin_compatible('boost-cpp', max_pin='x.x.x') }}
|
||||
- libxml2
|
||||
- hdf5
|
||||
- eigen
|
||||
- mpfr
|
||||
- sel(unix): gmp
|
||||
- sel(win): mpir
|
||||
- nlohmann_json
|
||||
- zlib
|
||||
|
||||
test:
|
||||
imports:
|
||||
- ifcopenshell
|
||||
|
||||
about:
|
||||
home: https://ifcopenshell.org
|
||||
license: LGPL-3.0-or-later
|
||||
license_file: COPYING
|
||||
summary: 'IfcOpenShell is a library to support the IFC file format'
|
||||
description: |
|
||||
IfcOpenShell is an open source (LGPL) software library for
|
||||
working with the Industry Foundation Classes (IFC) file format.
|
||||
doc_url: https://blenderbim.org/docs-python/
|
||||
dev_url: https://github.com/IfcOpenShell/IfcOpenShell
|
||||
+51
-3
@@ -53,6 +53,7 @@ import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import glob
|
||||
import subprocess as sp
|
||||
import shutil
|
||||
import tarfile
|
||||
@@ -91,6 +92,8 @@ HDF5_VERSION = "1.12.1"
|
||||
GMP_VERSION = "6.2.1"
|
||||
MPFR_VERSION = "3.1.6" # latest is 4.1.0
|
||||
CGAL_VERSION = "5.3"
|
||||
USD_VERSION = "23.05"
|
||||
TBB_VERSION = "2021.9.0"
|
||||
|
||||
# binaries
|
||||
cp = "cp"
|
||||
@@ -203,6 +206,7 @@ dependency_tree = {
|
||||
'cgal': (),
|
||||
'eigen': (),
|
||||
'freetype': (),
|
||||
# 'usd': ('boost', 'oneTBB')
|
||||
}
|
||||
|
||||
def v(dep):
|
||||
@@ -573,6 +577,7 @@ if "freetype" in targets:
|
||||
download_url = "https://github.com/freetype/freetype",
|
||||
download_name = "freetype2",
|
||||
download_tool=download_tool_git,
|
||||
revision="VER-2-11-1"
|
||||
)
|
||||
|
||||
if USE_OCCT and "occ" in targets:
|
||||
@@ -770,7 +775,42 @@ if "cgal" in targets:
|
||||
download_tool=download_tool_git,
|
||||
revision=f"v{CGAL_VERSION}"
|
||||
)
|
||||
|
||||
|
||||
if "usd" in targets:
|
||||
build_dependency(
|
||||
name=f"oneTBB-{TBB_VERSION}",
|
||||
mode="cmake",
|
||||
build_tool_args=[
|
||||
f"-DCMAKE_INSTALL_PREFIX={DEPS_DIR}/install/tbb-{TBB_VERSION}",
|
||||
f"-DTBB_TEST=OFF"
|
||||
],
|
||||
download_url="https://github.com/oneapi-src/oneTBB",
|
||||
download_name="oneTBB",
|
||||
download_tool=download_tool_git,
|
||||
revision=f"v{TBB_VERSION}"
|
||||
)
|
||||
|
||||
build_dependency(
|
||||
name=f"usd-{USD_VERSION}",
|
||||
mode="cmake",
|
||||
build_tool_args=[
|
||||
f"-DCMAKE_INSTALL_PREFIX={DEPS_DIR}/install/usd-{USD_VERSION}",
|
||||
f"-DBOOST_ROOT={DEPS_DIR}/install/boost-{BOOST_VERSION}",
|
||||
f"-DTBB_ROOT_DIR={DEPS_DIR}/install/tbb-{TBB_VERSION}",
|
||||
f"-DPXR_ENABLE_PYTHON_SUPPORT=FALSE",
|
||||
f"-DPXR_ENABLE_GL_SUPPORT=FALSE",
|
||||
f"-DPXR_BUILD_IMAGING=FALSE",
|
||||
f"-DPXR_BUILD_TUTORIALS=FALSE",
|
||||
f"-DPXR_BUILD_EXAMPLES=FALSE",
|
||||
f"-DPXR_BUILD_USD_TOOLS=FALSE",
|
||||
f"-DPXR_BUILD_TESTS=FALSE"
|
||||
],
|
||||
download_url="https://github.com/PixarAnimationStudios/USD",
|
||||
download_name="USD",
|
||||
download_tool=download_tool_git,
|
||||
revision=f"v{USD_VERSION}"
|
||||
)
|
||||
|
||||
cecho("Building IfcOpenShell:", GREEN)
|
||||
|
||||
IFCOS_DIR = os.path.join(DEPS_DIR, "build", "ifcopenshell")
|
||||
@@ -792,7 +832,8 @@ cmake_args = [
|
||||
"-DJSON_INCLUDE_DIR=" f"{DEPS_DIR}/install/json",
|
||||
"-DEIGEN_DIR=" f"{DEPS_DIR}/install/eigen-3.3.9",
|
||||
"-DBoost_NO_BOOST_CMAKE=" "On",
|
||||
"-DADD_COMMIT_SHA=" +("On" if ADD_COMMIT_SHA else "Off")
|
||||
"-DADD_COMMIT_SHA=" +("On" if ADD_COMMIT_SHA else "Off"),
|
||||
"-DVERSION_OVERRIDE=" +("On" if ADD_COMMIT_SHA else "Off")
|
||||
]
|
||||
|
||||
if "wasm" in flags:
|
||||
@@ -854,6 +895,13 @@ if "hdf5" in targets:
|
||||
else:
|
||||
cmake_args.append("-DHDF5_SUPPORT=Off")
|
||||
|
||||
if "usd" in targets:
|
||||
cmake_args.extend([
|
||||
"-DUSD_SUPPORT=" "On",
|
||||
"-DUSD_INCLUDE_DIR=" f"{DEPS_DIR}/install/usd-{USD_VERSION}/include",
|
||||
"-DUSD_LIBRARY_DIR=" f"{DEPS_DIR}/install/usd-{USD_VERSION}/lib"
|
||||
])
|
||||
|
||||
if not explicit_targets or {"IfcGeom", "IfcConvert", "IfcGeomServer"} & set(explicit_targets):
|
||||
logger.info("\rConfiguring executables...")
|
||||
|
||||
@@ -924,7 +972,7 @@ if "IfcOpenShell-Python" in targets:
|
||||
if platform.system() != "Darwin":
|
||||
if BUILD_CFG == "Release":
|
||||
# TODO: This symbol name depends on the Python version?
|
||||
run([strip, "-s", "-K", "PyInit__ifcopenshell_wrapper", "_ifcopenshell_wrapper.so"], cwd=module_dir)
|
||||
run([strip, "-s", "-K", "PyInit__ifcopenshell_wrapper", glob.glob(os.path.join(module_dir, "_ifcopenshell_wrapper*.so"))[0]], cwd=module_dir)
|
||||
|
||||
return module_dir
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package:
|
||||
name: ifcopenshell
|
||||
version: 0.7.0
|
||||
version: 0.8.0
|
||||
|
||||
source:
|
||||
path: IfcOpenShell
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(name='IfcOpenShell',
|
||||
version='0.7.0',
|
||||
version='0.8.0',
|
||||
description='IfcOpenShell is an open source (LGPL) software library for working with the Industry Foundation Classes (IFC) file format.',
|
||||
author='Thomas Krijnen',
|
||||
author_email='thomas@aecgeeks.com',
|
||||
|
||||
+5
-1
@@ -1,2 +1,6 @@
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
line-length = 120
|
||||
|
||||
[tool.pyright]
|
||||
reportInvalidTypeForm = false
|
||||
disableBytesTypePromotions = true
|
||||
|
||||
@@ -10,7 +10,7 @@ type: software
|
||||
authors:
|
||||
- name: "IfcOpenShell contributors"
|
||||
repository-code: >-
|
||||
https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.7.0/src/bcf
|
||||
https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.8.0/src/bcf
|
||||
abstract: >-
|
||||
Library to read and write BCF-XML and query OpenCDE
|
||||
BCF-API modules
|
||||
|
||||
+26
-4
@@ -1,4 +1,22 @@
|
||||
VERSION:=`date '+%y%m%d'`
|
||||
# BCF - BCF Python library
|
||||
# Copyright (C) 2021 Prabhat Singh <singh01prabhat@gmail.com>
|
||||
#
|
||||
# This file is part of BCF.
|
||||
#
|
||||
# BCF is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BCF is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with BCF. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
VERSION:=$(shell cat ../../VERSION)
|
||||
SED:=sed -i
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
SED:=sed -i '' -e
|
||||
@@ -21,10 +39,14 @@ models:
|
||||
.PHONY: dist
|
||||
dist:
|
||||
rm -rf dist
|
||||
$(SED) "s/999999/$(VERSION)/" pyproject.toml
|
||||
cp pyproject.toml pyproject.toml.bak
|
||||
cp src/bcf/__init__.py __init__.py.bak
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION)"/' pyproject.toml
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION)"/' src/bcf/__init__.py
|
||||
python -m build
|
||||
$(SED) "s/$(VERSION)/999999/" pyproject.toml
|
||||
mv pyproject.toml.bak pyproject.toml
|
||||
mv __init__.py.bak src/bcf/__init__.py
|
||||
|
||||
# .PHONY
|
||||
# api:
|
||||
# openapi-python-client generate --url https://api.swaggerhub.com/apis/buildingSMART/BCF/3.0
|
||||
# openapi-python-client generate --url https://api.swaggerhub.com/apis/buildingSMART/BCF/3.0
|
||||
|
||||
@@ -13,11 +13,11 @@ readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
keywords = ["IFC", "BCF", "BIM"]
|
||||
dependencies = [
|
||||
"xsdata",
|
||||
"xsdata>=24.4",
|
||||
"numpy",
|
||||
"ifcopenshell",
|
||||
]
|
||||
version = "0.0.999999"
|
||||
version = "0.0.0"
|
||||
classifiers = [
|
||||
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
||||
"Operating System :: OS Independent",
|
||||
@@ -138,4 +138,4 @@ max-attributes = 10
|
||||
|
||||
[tool.pylint.format]
|
||||
expected-line-ending-format = "LF"
|
||||
max-line-length = 120
|
||||
max-line-length = 120
|
||||
|
||||
@@ -15,3 +15,5 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with BCF. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__version__ = version = "0.0.0"
|
||||
|
||||
@@ -10,14 +10,14 @@ from xsdata.formats.dataclass.serializers.config import SerializerConfig
|
||||
def build_xml_parser(context: Optional[XmlContext] = None) -> XmlParser:
|
||||
"""Return a parser for an XML file."""
|
||||
parser = XmlParser(context=context or XmlContext())
|
||||
parser.register_namespace("xs", "http://www.w3.org/2001/XMLSchema")
|
||||
parser.register_namespace(ns_map=parser.ns_map, prefix="xs", uri="http://www.w3.org/2001/XMLSchema")
|
||||
return parser
|
||||
|
||||
|
||||
def build_serializer(context: Optional[XmlContext] = None) -> XmlSerializer:
|
||||
"""Return a serializer for an XML file."""
|
||||
return XmlSerializer(
|
||||
config=SerializerConfig(pretty_print=True),
|
||||
config=SerializerConfig(indent=" "),
|
||||
context=context or XmlContext(),
|
||||
)
|
||||
|
||||
@@ -36,8 +36,9 @@ class AbstractXmlParserSerializer(Protocol):
|
||||
xml: The XML file as bytes.
|
||||
clazz: The class to parse to.
|
||||
"""
|
||||
...
|
||||
|
||||
def serialize(self, obj: T, ns_map: Optional[dict[str, str]] = None) -> str:
|
||||
def serialize(self, obj: object, ns_map: Optional[dict[str, str]] = None) -> str:
|
||||
"""
|
||||
Serialize an object to XML.
|
||||
|
||||
@@ -48,6 +49,7 @@ class AbstractXmlParserSerializer(Protocol):
|
||||
Returns:
|
||||
The XML as string.
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class XmlParserSerializer:
|
||||
@@ -68,7 +70,7 @@ class XmlParserSerializer:
|
||||
"""
|
||||
return self.parser.from_bytes(xml, clazz)
|
||||
|
||||
def serialize(self, obj: T, ns_map: Optional[dict[str, str]] = None) -> str:
|
||||
def serialize(self, obj: object, ns_map: Optional[dict[Optional[str], str]] = None) -> str:
|
||||
"""
|
||||
Serialize an object to XML.
|
||||
|
||||
@@ -79,5 +81,5 @@ class XmlParserSerializer:
|
||||
Returns:
|
||||
The XML as string.
|
||||
"""
|
||||
ns_map = ns_map or {"xs": "http://www.w3.org/2001/XMLSchema"}
|
||||
ns_map = ns_map or self.parser.ns_map or {"xs": "http://www.w3.org/2001/XMLSchema"}
|
||||
return self.serializer.render(obj, ns_map)
|
||||
|
||||
@@ -10,7 +10,7 @@ type: software
|
||||
authors:
|
||||
- name: "IfcOpenShell contributors"
|
||||
repository-code: >-
|
||||
https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.7.0/src/blenderbim
|
||||
https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.8.0/src/blenderbim
|
||||
url: 'https://blenderbim.org/'
|
||||
repository-artifact: 'https://blenderbim.org/download.html'
|
||||
abstract: >-
|
||||
|
||||
+96
-247
@@ -16,8 +16,8 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
PYTHON:=python3.10
|
||||
PIP:=pip3.10
|
||||
PYTHON:=python3.11
|
||||
PIP:=pip3.11
|
||||
PATCH:=patch
|
||||
SED:=sed -i
|
||||
ifeq ($(OS),Windows_NT)
|
||||
@@ -35,7 +35,12 @@ SED:=sed -i '' -e
|
||||
endif
|
||||
endif
|
||||
|
||||
VERSION:=`date '+%y%m%d'`
|
||||
IS_STABLE:=FALSE
|
||||
VERSION:=$(shell cat ../../VERSION)
|
||||
VERSION_MAJOR:=$(shell cat '../../VERSION' | cut -d '.' -f 1)
|
||||
VERSION_MINOR:=$(shell cat '../../VERSION' | cut -d '.' -f 2)
|
||||
VERSION_PATCH:=$(shell cat '../../VERSION' | cut -d '.' -f 3)
|
||||
VERSION_DATE:=$(shell date '+%y%m%d')
|
||||
LAST_COMMIT_HASH:=$(shell git rev-parse HEAD)
|
||||
PYVERSION:=py310
|
||||
PYPI_IMP:=cp
|
||||
@@ -55,76 +60,35 @@ PYLIBDIR:=python3.11
|
||||
PYNUMBER:=311
|
||||
PYPI_VERSION:=3.11
|
||||
endif
|
||||
ifeq ($(PYVERSION), py312)
|
||||
PYLIBDIR:=python3.12
|
||||
PYNUMBER:=312
|
||||
PYPI_VERSION:=3.12
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), linux)
|
||||
PYPI_PLATFORM:=--platform manylinux_2_17_x86_64
|
||||
LXML_ARCH:=manylinux_2_28_x86_64
|
||||
SHAPELY_ARCH:=manylinux_2_17_x86_64.manylinux2014_x86_64
|
||||
PILLOW_ARCH:=manylinux_2_28_x86_64
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), macos)
|
||||
PYPI_PLATFORM:=--platform macosx_10_9_x86_64
|
||||
SHAPELY_ARCH:=macosx_10_9_x86_64
|
||||
PILLOW_ARCH:=macosx_10_10_x86_64
|
||||
ifeq ($(PYVERSION), py39)
|
||||
LXML_ARCH:=macosx_11_0_x86_64
|
||||
endif
|
||||
ifeq ($(PYVERSION), py310)
|
||||
LXML_ARCH:=macosx_11_0_x86_64
|
||||
endif
|
||||
ifeq ($(PYVERSION), py311)
|
||||
LXML_ARCH:=macosx_11_0_universal2
|
||||
endif
|
||||
PYPI_PLATFORM:=--platform macosx_10_10_x86_64
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
PYPI_PLATFORM:=--platform macosx_11_0_arm64
|
||||
LXML_ARCH:=macosx_11_0_universal2
|
||||
SHAPELY_ARCH:=macosx_11_0_arm64
|
||||
PILLOW_ARCH:=macosx_11_0_arm64
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), win)
|
||||
PYPI_PLATFORM:=--platform win_amd64
|
||||
LXML_ARCH:=win_amd64
|
||||
SHAPELY_ARCH:=win_amd64
|
||||
PILLOW_ARCH:=win_amd64
|
||||
endif
|
||||
|
||||
LXML_NAME:=lxml
|
||||
LXML_VER:=4.9.4
|
||||
SHAPELY_NAME:=shapely
|
||||
SHAPELY_VER:=2.0.2
|
||||
PILLOW_NAME:=pillow
|
||||
PILLOW_PKG_NAME:=Pillow
|
||||
PILLOW_VER:=9.5.0
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/cp$(PYNUMBER)/s/$(SHAPELY_NAME)/$(SHAPELY_NAME)-$(SHAPELY_VER)-cp$(PYNUMBER)-cp$(PYNUMBER)-$(SHAPELY_ARCH).whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/cp$(PYNUMBER)/p/$(PILLOW_NAME)/$(PILLOW_PKG_NAME)-$(PILLOW_VER)-cp$(PYNUMBER)-cp$(PYNUMBER)-$(PILLOW_ARCH).whl
|
||||
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
ifeq ($(PYVERSION), py39)
|
||||
LXML_URL:=https://anaconda.org/conda-forge/lxml/4.9.1/download/osx-arm64/lxml-4.9.1-py39h0520ce3_1.tar.bz2
|
||||
endif
|
||||
ifeq ($(PYVERSION), py310)
|
||||
LXML_URL:=https://anaconda.org/conda-forge/lxml/4.9.1/download/osx-arm64/lxml-4.9.1-py310h02f21da_0.tar.bz2
|
||||
endif
|
||||
ifeq ($(PYVERSION), py311)
|
||||
LXML_URL:=https://anaconda.org/conda-forge/lxml/4.9.1/download/osx-arm64/lxml-4.9.1-py311h246f609_1.tar.bz2
|
||||
endif
|
||||
else
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/cp$(PYNUMBER)/l/$(LXML_NAME)/$(LXML_NAME)-$(LXML_VER)-cp$(PYNUMBER)-cp$(PYNUMBER)-$(LXML_ARCH).whl
|
||||
endif
|
||||
$(info $$LXML_URL is [${LXML_URL}])
|
||||
$(info $$SHAPELY_URL is [${SHAPELY_URL}])
|
||||
$(info $$PILLOW_URL is [${PILLOW_URL}])
|
||||
|
||||
# Current build commit hash.
|
||||
OLD:=c18e4ea
|
||||
.PHONY: bump
|
||||
bump:
|
||||
cd . && $(SED) "s/$(OLD)/$(NEW)/" Makefile
|
||||
cd ../ifcopenshell-python/ && $(SED) "s/$(OLD)/$(NEW)/" Makefile
|
||||
cd ../ifcopenshell-python/docs/ifcconvert/ && $(SED) "s/$(OLD)/$(NEW)/" installation.rst
|
||||
cd ../ifcopenshell-python/docs/ifcopenshell-python/ && $(SED) "s/$(OLD)/$(NEW)/" installation.rst
|
||||
cd . && $(SED) -b "s/$(OLD)/$(NEW)/" Makefile
|
||||
cd ../ifcopenshell-python/ && $(SED) -b "s/$(OLD)/$(NEW)/" Makefile
|
||||
cd ../ifcopenshell-python/docs/ifcconvert/ && $(SED) -b "s/$(OLD)/$(NEW)/" installation.rst
|
||||
|
||||
.PHONY: dist
|
||||
dist:
|
||||
@@ -137,52 +101,52 @@ endif
|
||||
cp -r blenderbim/* dist/blenderbim/
|
||||
|
||||
# Provides IfcOpenShell Python functionality
|
||||
cd dist/working && wget https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-$(PYNUMBER)-v0.7.0-f7c03db-$(PLATFORM)64.zip
|
||||
cd dist/working && wget https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-$(PYNUMBER)-v0.7.9-${OLD}-$(PLATFORM)64.zip
|
||||
cd dist/working && unzip ifcopenshell-python*
|
||||
cp -r dist/working/ifcopenshell dist/blenderbim/libs/site/packages/
|
||||
|
||||
# See bug #812
|
||||
cd dist/working && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.7.0/src/blenderbim/occ_utils.py
|
||||
cd dist/working && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.8.0/src/blenderbim/occ_utils.py
|
||||
cd dist/working && mv occ_utils.py ../blenderbim/libs/site/packages/ifcopenshell/geom/occ_utils.py
|
||||
rm -rf dist/working
|
||||
|
||||
# Provides dependencies that are part of IfcOpenShell
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://github.com/IfcOpenShell/IfcOpenShell/archive/v0.7.0.zip
|
||||
cd dist/working && unzip v0.7.0.zip
|
||||
# IfcOpenBot sometimes lags behind, so we hotfix the Python utilities
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcopenshell-python/ifcopenshell/util/* dist/blenderbim/libs/site/packages/ifcopenshell/util/
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcopenshell-python/ifcopenshell/api/* dist/blenderbim/libs/site/packages/ifcopenshell/api/
|
||||
cp dist/working/IfcOpenShell-0.7.0/src/ifcopenshell-python/ifcopenshell/*.py dist/blenderbim/libs/site/packages/ifcopenshell/
|
||||
cp dist/working/IfcOpenShell-0.7.0/src/ifcopenshell-python/ifcopenshell/express/rule_executor.py dist/blenderbim/libs/site/packages/ifcopenshell/express/
|
||||
cd dist/working && wget https://github.com/IfcOpenShell/IfcOpenShell/archive/refs/heads/v0.8.0.zip
|
||||
cd dist/working && unzip v0.8.0.zip
|
||||
# IfcOpenBot sometimes lags behind, so we only use its binaries
|
||||
mv dist/blenderbim/libs/site/packages/ifcopenshell/*ifcopenshell_wrapper* dist/working/
|
||||
rm -rf dist/blenderbim/libs/site/packages/ifcopenshell
|
||||
cp -r dist/working/IfcOpenShell-0.8.0/src/ifcopenshell-python/ifcopenshell dist/blenderbim/libs/site/packages/
|
||||
mv dist/working/*ifcopenshell_wrapper* dist/blenderbim/libs/site/packages/ifcopenshell/
|
||||
# Provides bcf functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/bcf/src/bcf dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/IfcOpenShell-0.8.0/src/bcf/src/bcf dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCClash functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcclash/ifcclash dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/IfcOpenShell-0.8.0/src/ifcclash/ifcclash dist/blenderbim/libs/site/packages/
|
||||
# Provides BIMTester functionality
|
||||
cd dist/working && $(PYTHON) -m venv env
|
||||
cd dist/working && . env/bin/activate && $(PIP) install pybabel
|
||||
cd dist/working && . env/bin/activate && $(PIP) install babel
|
||||
cd dist/working && . env/bin/activate && ./env/bin/pybabel compile -d ./IfcOpenShell-0.7.0/src/ifcbimtester/bimtester/locale/
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcbimtester/bimtester dist/blenderbim/libs/site/packages/
|
||||
cd dist/working && . env/bin/activate && ./env/bin/pybabel compile -d ./IfcOpenShell-0.8.0/src/ifcbimtester/bimtester/locale/
|
||||
cp -r dist/working/IfcOpenShell-0.8.0/src/ifcbimtester/bimtester dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCTester functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifctester/ifctester dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/IfcOpenShell-0.8.0/src/ifctester/ifctester dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCFM functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcfm/ifcfm dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/IfcOpenShell-0.8.0/src/ifcfm/ifcfm dist/blenderbim/libs/site/packages/
|
||||
# Provides bSDD functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/bsdd/* dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/IfcOpenShell-0.8.0/src/bsdd/* dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCDiff functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcdiff/* dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/IfcOpenShell-0.8.0/src/ifcdiff/* dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCCSV functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifccsv/* dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/IfcOpenShell-0.8.0/src/ifccsv/* dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCPatch functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcpatch/ifcpatch dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/IfcOpenShell-0.8.0/src/ifcpatch/ifcpatch dist/blenderbim/libs/site/packages/
|
||||
# Provides IFC4D functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifc4d/ifc4d dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/IfcOpenShell-0.8.0/src/ifc4d/ifc4d dist/blenderbim/libs/site/packages/
|
||||
# Provides IFC5D functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifc5d/ifc5d dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/IfcOpenShell-0.8.0/src/ifc5d/ifc5d dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCCityJSON functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifccityjson dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/IfcOpenShell-0.8.0/src/ifccityjson dist/blenderbim/libs/site/packages/
|
||||
# Provides IfcGit functionality
|
||||
cd dist/working && . env/bin/activate && $(PIP) install GitPython --target=./site-packages
|
||||
cp -r dist/working/site-packages/smmap dist/blenderbim/libs/site/packages/
|
||||
@@ -190,49 +154,6 @@ endif
|
||||
cp -r dist/working/site-packages/git dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Provides Mustache templating in construction documentation
|
||||
# TODO: remove this dependency, it seems overkill and we seem to get by with str replaces
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/3f/e7/8750ba6c6101d6aa5ceeb20c013adf2c6f3554a12c71d75654b468404bfa/pystache-0.6.0.tar.gz
|
||||
cd dist/working && tar -xzvf pystache*
|
||||
cd dist/working/pystache-0.6.0/ && $(PYTHON) setup.py build && cp -r build/lib/pystache ../../blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Provides SVG export in construction documentation
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/79/e8/7eb2ba188eda14a4b47e33b51f3b4978985f4116655c699bcd18c79279b5/svgwrite-1.3.1.zip
|
||||
cd dist/working && unzip svgwrite*
|
||||
cp -r dist/working/svgwrite-1.3.1/svgwrite dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Provides fuzzy date parsing for construction sequencing
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/be/ed/5bbc91f03fa4c839c4c7360375da77f9659af5f7086b7a7bdda65771c8e0/python-dateutil-2.8.1.tar.gz
|
||||
cd dist/working && tar -xzvf python-dateutil*
|
||||
cp -r dist/working/python-dateutil-2.8.1/dateutil dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Provides duration parsing for construction sequencing
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/b1/80/fb8c13a4cd38eb5021dc3741a9e588e4d1de88d895c1910c6fc8a08b7a70/isodate-0.6.0.tar.gz
|
||||
cd dist/working && tar -xzvf isodate*
|
||||
cp -r dist/working/isodate-0.6.0/src/isodate dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Provides networkx graph analysis for project dependency calculations
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/b0/21/adfbf6168631e28577e4af9eb9f26d75fe72b2bb1d33762a5f2c425e6c2a/networkx-2.5.1.tar.gz
|
||||
cd dist/working && tar -xzvf networkx*
|
||||
cp -r dist/working/networkx-2.5.1/networkx dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by networkx
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/4f/51/15a4f6b8154d292e130e5e566c730d8ec6c9802563d58760666f1818ba58/decorator-5.0.9.tar.gz
|
||||
cd dist/working && tar -xzvf decorator*
|
||||
cp -r dist/working/decorator-5.0.9/src/decorator.py dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Provides audio playback for costing
|
||||
mkdir -p dist/working
|
||||
git clone https://github.com/Andrej730/aud.git --branch master-reduced-size --depth 1 dist/working/aud
|
||||
@@ -247,110 +168,11 @@ endif
|
||||
cp dist/working/jsgantt* dist/blenderbim/bim/data/gantt/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by IFCDiff
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/0f/ca/caead2949fbb824c7142e3774fa841aa853bb4d4331b440da8c8514dfc6f/deepdiff-5.8.1.tar.gz
|
||||
cd dist/working && tar -xzvf deepdiff*
|
||||
cp -r dist/working/deepdiff-5.8.1/deepdiff dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by deepdiff
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/00/55/ce2cbc6d64034b30cad81a29ba61bdba456f190f5e83c09831304bf68d6b/jsonpickle-1.2.tar.gz
|
||||
cd dist/working && tar -xzvf jsonpickle*
|
||||
cp -r dist/working/jsonpickle-1.2/jsonpickle dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by deepdiff
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/a3/b7/d4d69641cbe707a45c23b190f2d717466ba5accc4c70b5f7a8a450387895/ordered-set-3.1.1.tar.gz
|
||||
cd dist/working && tar -xzvf ordered-set*
|
||||
cp -r dist/working/ordered-set-3.1.1/ordered_set.py dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by lark
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/00/32/8076fa13e832bb4dcff379f18f228e5a53412be0631808b9ca2610c0f566/pyparsing-2.4.5.tar.gz
|
||||
cd dist/working && tar -xzvf pyparsing*
|
||||
cp -r dist/working/pyparsing-2.4.5/pyparsing.py dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by bcf
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/5b/ef/f97c3e1a7efa00e989a793fe15297214fc95ad7d9e3810586bd08ce9f0f3/xmlschema-2.0.2.tar.gz
|
||||
cd dist/working && tar -xzvf xmlschema*
|
||||
cp -r dist/working/xmlschema-2.0.2/xmlschema dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by bcf
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/ad/c7/17c9d16320d8e2cfdb27d2fd298b5e8f7a3f211025b0c1bc7a39a85bd690/xsdata-22.11.tar.gz
|
||||
cd dist/working && tar -xzvf xsdata*
|
||||
cp -r dist/working/xsdata-22.11/xsdata dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by bcf
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/11/bc/5afb61dd5d863e5cf77cd952445c50c17e65953405986f19e97e4389692a/elementpath-3.0.2.tar.gz
|
||||
cd dist/working && tar -xzvf elementpath*
|
||||
cp -r dist/working/elementpath-3.0.2/elementpath dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by bcf
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/21/9f/b251f7f8a76dec1d6651be194dfba8fb8d7781d10ab3987190de8391d08e/six-1.14.0.tar.gz
|
||||
cd dist/working && tar -xzvf six*
|
||||
cp -r dist/working/six-1.14.0/six.py dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by IFCCSV and ifcopenshell.util.selector
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/18/4d/8d522136c37d9e1ea74062b41b8d5e1318ebf45063ae46ce72ed60af223b/lark-parser-0.8.5.tar.gz
|
||||
cd dist/working && tar -xzvf lark-parser*
|
||||
cp -r dist/working/lark-parser-0.8.5/lark dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by IFC4D
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/b0/bb/9c4dddd3ca173cb56241cfb2eddfae24690dc676d357ac4cab17d0a36d9d/PyP6Xer-1.13.0.tar.gz
|
||||
cd dist/working && tar -xzvf PyP6Xer*
|
||||
cp -r dist/working/PyP6Xer-1.13.0/xerparser dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by QTOCalculator
|
||||
mkdir dist/working
|
||||
cd dist/working && wget $(SHAPELY_URL)
|
||||
cd dist/working && cp *.whl shapely.zip && unzip shapely.zip
|
||||
cp -r dist/working/shapely dist/blenderbim/libs/site/packages/
|
||||
ifeq ($(PLATFORM), win)
|
||||
cp -r dist/working/shapely.libs dist/blenderbim/libs/site/packages/
|
||||
endif
|
||||
ifeq ($(PLATFORM), linux)
|
||||
cp -r dist/working/shapely.libs dist/blenderbim/libs/site/packages/
|
||||
endif
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by the BIM tool thumbnail generator
|
||||
mkdir dist/working
|
||||
cd dist/working && wget $(PILLOW_URL)
|
||||
cd dist/working && cp *.whl pillow.zip && unzip pillow.zip
|
||||
cp -r dist/working/PIL dist/blenderbim/libs/site/packages/
|
||||
ifeq ($(PLATFORM), linux)
|
||||
cp -r dist/working/Pillow.libs dist/blenderbim/libs/site/packages/
|
||||
endif
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by xerparser and IFC4D
|
||||
# TODO: remove this dependency. It's only used to show a progress bar.
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/9f/7b/76c4e5ef1a1b528fcaada4133f972e77d33c252831676cf414119ca6093d/tqdm-4.50.0.tar.gz
|
||||
cd dist/working && tar -xzvf tqdm*
|
||||
cp -r dist/working/tqdm-4.50.0/tqdm dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
mkdir dist/working
|
||||
cd dist/working && $(PYTHON) -m venv env
|
||||
cd dist/working && mkdir site-packages
|
||||
# IfcOpenShell dependency - support for new typing features
|
||||
cd dist/working && . env/bin/activate && $(PIP) install typing_extensions --target=./site-packages
|
||||
# Required by IfcCSV
|
||||
cd dist/working && . env/bin/activate && $(PIP) install pandas $(PYPI_PLATFORM) --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --target=./site-packages
|
||||
# Pandas ships with very heavy tests
|
||||
@@ -364,7 +186,46 @@ endif
|
||||
# Provides Brickschema functionality
|
||||
cd dist/working && . env/bin/activate && $(PIP) install "brickschema[persistence]==0.7.6a2" --target=./site-packages
|
||||
# Required for SVG to DXF conversion
|
||||
cd dist/working && . env/bin/activate && $(PIP) install "ezdxf" --target=./site-packages
|
||||
cd dist/working && . env/bin/activate && $(PIP) install ezdxf --target=./site-packages
|
||||
# Required by bcf
|
||||
cd dist/working && . env/bin/activate && $(PIP) install xsdata --target=./site-packages
|
||||
cd dist/working && . env/bin/activate && $(PIP) install xmlschema --target=./site-packages
|
||||
cd dist/working && . env/bin/activate && $(PIP) install elementpath --target=./site-packages
|
||||
cd dist/working && . env/bin/activate && $(PIP) install six --target=./site-packages
|
||||
# Required by drawing module
|
||||
cd dist/working && . env/bin/activate && $(PIP) install lxml $(PYPI_PLATFORM) --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --target=./site-packages
|
||||
# Required by qto and drawing module
|
||||
cd dist/working && . env/bin/activate && $(PIP) install shapely $(PYPI_PLATFORM) --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --target=./site-packages
|
||||
# Required by the BIM type manager thumbnail generator
|
||||
cd dist/working && . env/bin/activate && $(PIP) install pillow $(PYPI_PLATFORM) --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --target=./site-packages
|
||||
# Provides mustache templating in construction docs and web UI data
|
||||
cd dist/working && . env/bin/activate && $(PIP) install pystache --target=./site-packages
|
||||
# Provides SVG export in construction documentation
|
||||
cd dist/working && . env/bin/activate && $(PIP) install svgwrite --target=./site-packages
|
||||
# Provides fuzzy date parsing for construction sequencing
|
||||
cd dist/working && . env/bin/activate && $(PIP) install python-dateutil --target=./site-packages
|
||||
# Provides duration parsing for construction sequencing
|
||||
cd dist/working && . env/bin/activate && $(PIP) install isodate --target=./site-packages
|
||||
# Provides networkx graph analysis for project dependency calculations
|
||||
cd dist/working && . env/bin/activate && $(PIP) install networkx --target=./site-packages
|
||||
# Required by IFCDiff
|
||||
cd dist/working && . env/bin/activate && $(PIP) install deepdiff --target=./site-packages
|
||||
# Required by IFCCSV and ifcopenshell.util.selector
|
||||
cd dist/working && . env/bin/activate && $(PIP) install lark --target=./site-packages
|
||||
# Required by IFC4D
|
||||
cd dist/working && . env/bin/activate && $(PIP) install PyP6Xer --target=./site-packages
|
||||
# Required by web module
|
||||
cd dist/working && . env/bin/activate && $(PIP) install python-socketio[asyncio_client] --target=./site-packages
|
||||
cd dist/working && . env/bin/activate && $(PIP) install aiohttp --target=./site-packages
|
||||
# Required by light module
|
||||
ifeq ($(PLATFORM), linux)
|
||||
# See https://github.com/LBNL-ETA/pyradiance/issues/34
|
||||
cd dist/working && . env/bin/activate && $(PIP) install pyradiance --platform manylinux1_x86_64 --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --target=./site-packages
|
||||
else ifneq ($(PLATFORM), macos)
|
||||
# No support for MacOS Intel from upstream. Too bad :(
|
||||
cd dist/working && . env/bin/activate && $(PIP) install pyradiance $(PYPI_PLATFORM) --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --target=./site-packages
|
||||
endif
|
||||
|
||||
cp -r dist/working/site-packages/* dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
@@ -374,33 +235,15 @@ endif
|
||||
cd dist/working && tar -xzvf behave*
|
||||
cd dist/working/behave-1.2.6/ && cp -r behave ../../blenderbim/libs/site/packages/
|
||||
# See bug #1294
|
||||
cd dist/working/ && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.7.0/src/ifcbimtester/patch/model_core.patch
|
||||
cd dist/working/ && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.7.0/src/ifcbimtester/patch/runner_util.patch
|
||||
cd dist/working/ && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.8.0/src/ifcbimtester/patch/model_core.patch
|
||||
cd dist/working/ && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.8.0/src/ifcbimtester/patch/runner_util.patch
|
||||
cd dist/working/ && $(PATCH) ../blenderbim/libs/site/packages/behave/model_core.py < model_core.patch
|
||||
cd dist/working/ && $(PATCH) ../blenderbim/libs/site/packages/behave/runner_util.py < runner_util.patch
|
||||
# See bug #2159
|
||||
cd dist/working/ && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.7.0/src/ifcbimtester/patch/junit.patch
|
||||
cd dist/working/ && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.8.0/src/ifcbimtester/patch/junit.patch
|
||||
cd dist/working/ && $(PATCH) ../blenderbim/libs/site/packages/behave/reporter/junit.py < junit.patch
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by ids - uh, not any more, but I'm trying it out in the drawing module
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
# No wheels available for MacOS M1, but turns out this Anaconda build works
|
||||
mkdir dist/working
|
||||
cd dist/working && wget $(LXML_URL)
|
||||
cd dist/working && tar -xf lxml*
|
||||
cp -r dist/working/lib/$(PYLIBDIR)/site-packages/lxml dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
else
|
||||
# Wheels are preferred for other OSes. A first attempt at using Anaconda
|
||||
# builds for everything shows it breaks on windows. See #2422.
|
||||
mkdir dist/working
|
||||
cd dist/working && wget $(LXML_URL)
|
||||
cd dist/working && cp *.whl lxml.zip && unzip lxml.zip
|
||||
cp -r dist/working/lxml dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
endif
|
||||
|
||||
# Required by behave
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/f4/65/220bb4075fddb09d5b3ea2c1c1fa66c1c72be9361ec187aab50fa161e576/parse-1.15.0.tar.gz
|
||||
@@ -432,7 +275,7 @@ endif
|
||||
# Required by brickschema
|
||||
# This is a bit of a dodgy one, it should be provided by setuptools which Blender doesn't ship.
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://github.com/IfcOpenShell/IfcOpenShell/raw/v0.7.0/src/blenderbim/scripts/pkg_resources.tar.gz
|
||||
cd dist/working && wget https://github.com/IfcOpenShell/IfcOpenShell/raw/v0.8.0/src/blenderbim/scripts/pkg_resources.tar.gz
|
||||
cd dist/working && tar -xzvf pkg_resources*
|
||||
cd dist/working/ && cp -r pkg_resources ../blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
@@ -456,10 +299,16 @@ endif
|
||||
rm -rf dist/blenderbim/libs/site/packages/numpy
|
||||
rm -rf dist/blenderbim/libs/site/packages/numpy.libs
|
||||
|
||||
cd dist/blenderbim && $(SED) "s/999999/$(VERSION)/" __init__.py
|
||||
cd dist/blenderbim && $(SED) "s/999999/$(VERSION)/" blender_manifest.toml
|
||||
cd dist/blenderbim/bim && $(SED) "s/8888888/$(LAST_COMMIT_HASH)/" __init__.py
|
||||
ifeq ($(IS_STABLE), TRUE)
|
||||
cd dist/blenderbim && $(SED) "s/0, 0, 0/$(VERSION_MAJOR), $(VERSION_MINOR), $(VERSION_PATCH)/" __init__.py
|
||||
cd dist/blenderbim && $(SED) "s/0.0.0/$(VERSION)/" blender_manifest.toml
|
||||
cd dist && zip -r blenderbim-$(VERSION)-$(PYVERSION)-$(PLATFORM).zip ./*
|
||||
else
|
||||
cd dist/blenderbim && $(SED) "s/0, 0, 0/$(VERSION_MAJOR), $(VERSION_MINOR), $(VERSION_PATCH), $(VERSION_DATE)/" __init__.py
|
||||
cd dist/blenderbim && $(SED) "s/0.0.0/$(VERSION).$(VERSION_DATE)/" blender_manifest.toml
|
||||
cd dist/blenderbim/bim && $(SED) "s/8888888/$(LAST_COMMIT_HASH)/" __init__.py
|
||||
cd dist && zip -r blenderbim-$(VERSION).$(VERSION_DATE)-$(PYVERSION)-$(PLATFORM).zip ./*
|
||||
endif
|
||||
rm -rf dist/blenderbim
|
||||
|
||||
.PHONY: test
|
||||
|
||||
@@ -18,30 +18,203 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import site
|
||||
|
||||
# Ensure we don't try to import bpy or blenderbim.bim
|
||||
# to support running core tests.
|
||||
# We assume if bpy was never loaded in current python session
|
||||
# then we're not in Blender. It's still possible to use
|
||||
# bpy in core and core tests for annotations using TYPE_CHECKING.
|
||||
IN_BLENDER = sys.modules.get("bpy", None)
|
||||
if IN_BLENDER:
|
||||
import bpy
|
||||
import addon_utils
|
||||
import platform
|
||||
import traceback
|
||||
import webbrowser
|
||||
from collections import deque
|
||||
|
||||
# NOTE: bl_info is superseded by blender_manifest.toml
|
||||
# if addon is installed as an extension (Blender 4.2+)
|
||||
bl_info = {
|
||||
"name": "BlenderBIM",
|
||||
"description": "Transforms Blender into a native Building Information Model authoring platform using IFC.",
|
||||
"author": "IfcOpenShell Contributors",
|
||||
"blender": (3, 1, 0),
|
||||
"version": (0, 0, 999999),
|
||||
"version": (0, 0, 0),
|
||||
"location": "File Menu, Scene Properties Tab. See documentation for more.",
|
||||
"doc_url": "https://docs.blenderbim.org/",
|
||||
"tracker_url": "https://github.com/IfcOpenShell/IfcOpenShell/issues",
|
||||
"category": "System",
|
||||
}
|
||||
|
||||
if sys.modules.get("bpy", None):
|
||||
last_error = None
|
||||
last_actions: deque = deque(maxlen=10)
|
||||
|
||||
|
||||
def get_debug_info():
|
||||
version = ".".join(
|
||||
[
|
||||
str(x)
|
||||
for x in [
|
||||
addon.bl_info.get("version", (-1, -1, -1))
|
||||
for addon in addon_utils.modules()
|
||||
if addon.bl_info["name"] == "BlenderBIM"
|
||||
][0]
|
||||
]
|
||||
)
|
||||
return {
|
||||
"os": platform.system(),
|
||||
"os_version": platform.version(),
|
||||
"python_version": platform.python_version(),
|
||||
"architecture": platform.architecture(),
|
||||
"machine": platform.machine(),
|
||||
"processor": platform.processor(),
|
||||
"blender_version": bpy.app.version_string,
|
||||
"blenderbim_version": version,
|
||||
"last_actions": last_actions,
|
||||
"last_error": last_error,
|
||||
}
|
||||
|
||||
|
||||
def format_debug_info(info: dict):
|
||||
last_actions = ""
|
||||
for action in info["last_actions"]:
|
||||
last_actions += f"\n# {action['type']}: {action['name']}"
|
||||
if settings := action.get("settings"):
|
||||
last_actions += f"\n>>> {settings}"
|
||||
info["last_actions"] = last_actions
|
||||
text = "\n".join(f"{k}: {v}" for k, v in info.items())
|
||||
return text.strip()
|
||||
|
||||
|
||||
if IN_BLENDER:
|
||||
# Process *.pth in /libs/site/packages to setup globally importable modules
|
||||
# This is 3 levels deep as required by the static RPATH of ../../ from dependencies taken from Anaconda
|
||||
# site.addsitedir(os.path.join(os.path.dirname(os.path.realpath(__file__)), "libs", "site", "packages"))
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), "libs", "site", "packages"))
|
||||
|
||||
import blenderbim.bim
|
||||
try:
|
||||
import ifcopenshell.api
|
||||
|
||||
def register():
|
||||
blenderbim.bim.register()
|
||||
def log_api(usecase_path, ifc_file, settings):
|
||||
last_actions.append(
|
||||
{
|
||||
"type": "ifcopenshell.api",
|
||||
"name": usecase_path,
|
||||
"settings": ifcopenshell.api.serialise_settings(settings),
|
||||
}
|
||||
)
|
||||
|
||||
def unregister():
|
||||
blenderbim.bim.unregister()
|
||||
ifcopenshell.api.add_pre_listener("*", "action_logger", log_api)
|
||||
|
||||
def register():
|
||||
global BLENDER_PACKAGE_NAME, __name__, __package__
|
||||
BLENDER_PACKAGE_NAME = __name__
|
||||
if bpy.app.version >= (4, 2, 0):
|
||||
sys.modules["blenderbim"] = sys.modules[__name__]
|
||||
__name__ = "blenderbim"
|
||||
# Only renaming __name__ is actually required to make imports work.
|
||||
# We renaming __package__ just for consistency.
|
||||
__package__ = "blenderbim"
|
||||
import blenderbim.bim
|
||||
|
||||
blenderbim.bim.register()
|
||||
|
||||
def unregister():
|
||||
import blenderbim.bim
|
||||
|
||||
blenderbim.bim.unregister()
|
||||
|
||||
except:
|
||||
last_error = traceback.format_exc()
|
||||
|
||||
print(last_error)
|
||||
print(format_debug_info(get_debug_info()))
|
||||
print("\nFATAL ERROR: Unable to load the BlenderBIM Add-on")
|
||||
|
||||
class BIM_PT_fatal_error(bpy.types.Panel):
|
||||
bl_label = "BlenderBIM Fatal Error"
|
||||
bl_idname = "SCENE_PT_error_message"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
|
||||
def draw(self, context):
|
||||
info = get_debug_info()
|
||||
|
||||
layout = self.layout
|
||||
layout.alert = True
|
||||
layout.label(text="BlenderBIM could not load.", icon="ERROR")
|
||||
if info["os"] == "Windows":
|
||||
layout.operator("wm.console_toggle", text="View the console for full logs.", icon="CONSOLE")
|
||||
else:
|
||||
layout.label(text="View the console for full logs.", icon="CONSOLE")
|
||||
box = layout.box()
|
||||
py = ".".join(info["python_version"].split(".")[0:2])
|
||||
b3d = ".".join(info["blender_version"].split(".")[0:2])
|
||||
box.label(text=f"Blender {b3d} {info['os']} {info['machine']}", icon="BLENDER")
|
||||
box.label(text=f"Python {py} BBIM {info['blenderbim_version']}", icon="SCRIPTPLUGINS")
|
||||
layout.operator("bim.copy_debug_information", text="Copy Error Message To Clipboard")
|
||||
op = layout.operator("bim.open_uri", text="How Can I Fix This?")
|
||||
op.uri = "https://docs.blenderbim.org/users/troubleshooting.html#installation-issues"
|
||||
|
||||
layout.label(text="Try Reinstalling:", icon="IMPORT")
|
||||
op = layout.operator("bim.open_uri", text="Re-download Add-on")
|
||||
bbim_date = info["blenderbim_version"].split(".")[-1]
|
||||
py_tag = py.replace(".", "")
|
||||
if "Linux" in info["os"]:
|
||||
os = "linux"
|
||||
elif "Darwin" in info["os"]:
|
||||
if "arm64" in info["machine"]:
|
||||
os = "macosm1"
|
||||
else:
|
||||
os = "macos"
|
||||
else:
|
||||
os = "win"
|
||||
op.uri = f"https://github.com/IfcOpenShell/IfcOpenShell/releases/download/blenderbim-{bbim_date}/blenderbim-{bbim_date}-py{py_tag}-{os}.zip"
|
||||
|
||||
class OpenUri(bpy.types.Operator):
|
||||
bl_idname = "bim.open_uri"
|
||||
bl_label = "Open URI"
|
||||
uri: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
webbrowser.open(self.uri)
|
||||
return {"FINISHED"}
|
||||
|
||||
class CopyDebugInformation(bpy.types.Operator):
|
||||
bl_idname = "bim.copy_debug_information"
|
||||
bl_label = "Copy Debug Information"
|
||||
bl_description = "Copies debugging information to your clipboard for use in bugreports"
|
||||
|
||||
def execute(self, context):
|
||||
info = format_debug_info(get_debug_info())
|
||||
context.window_manager.clipboard = info
|
||||
return {"FINISHED"}
|
||||
|
||||
class HiddenPanel:
|
||||
@classmethod
|
||||
def false_poll(cls, context):
|
||||
return False
|
||||
|
||||
def register():
|
||||
# Only show our error panel and nothing else in the scene tab
|
||||
for item_name in dir(bpy.types):
|
||||
item = getattr(bpy.types, item_name)
|
||||
if not hasattr(item, "bl_rna") or not isinstance(item.bl_rna, bpy.types.Panel):
|
||||
continue
|
||||
if getattr(item, "bl_context", None) != "scene":
|
||||
continue
|
||||
|
||||
# Reregister scene panel with a new poll to hide it
|
||||
item.poll = HiddenPanel.false_poll
|
||||
bpy.utils.unregister_class(item)
|
||||
bpy.utils.register_class(item)
|
||||
bpy.utils.register_class(BIM_PT_fatal_error)
|
||||
bpy.utils.register_class(CopyDebugInformation)
|
||||
bpy.utils.register_class(OpenUri)
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(OpenUri)
|
||||
bpy.utils.unregister_class(CopyDebugInformation)
|
||||
bpy.utils.unregister_class(BIM_PT_fatal_error)
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import bpy
|
||||
import bpy.utils.previews
|
||||
import blenderbim
|
||||
import importlib
|
||||
from pathlib import Path
|
||||
from . import handler, ui, prop, operator, helper
|
||||
from typing import Callable, Union
|
||||
|
||||
@@ -84,6 +84,8 @@ modules = {
|
||||
"debug": None,
|
||||
"ifcgit": None,
|
||||
"covering": None,
|
||||
"web": None,
|
||||
"light": None,
|
||||
# Uncomment this line to enable loading of the demo module. Happy hacking!
|
||||
# The name "demo" must correlate to a folder name in `bim/module/`.
|
||||
# "demo": None,
|
||||
@@ -103,6 +105,7 @@ classes = [
|
||||
operator.BIM_OT_select_object,
|
||||
operator.BIM_OT_show_description,
|
||||
operator.ClippingPlaneCutWithCappings,
|
||||
operator.CloseError,
|
||||
operator.EditBlenderCollection,
|
||||
operator.FileAssociate,
|
||||
operator.FileUnassociate,
|
||||
@@ -129,7 +132,6 @@ classes = [
|
||||
prop.GlobalId,
|
||||
prop.BIMObjectProperties,
|
||||
prop.BIMCollectionProperties,
|
||||
prop.BIMMaterialProperties,
|
||||
prop.BIMMeshProperties,
|
||||
prop.BIMFacet,
|
||||
prop.BIMFilterGroup,
|
||||
@@ -140,7 +142,9 @@ classes = [
|
||||
# Tabs panel
|
||||
ui.BIM_PT_tabs,
|
||||
# Project overview
|
||||
ui.BIM_PT_tab_new_project_wizard,
|
||||
ui.BIM_PT_tab_project_info,
|
||||
ui.BIM_PT_tab_spatial_decomposition,
|
||||
ui.BIM_PT_tab_project_setup,
|
||||
ui.BIM_PT_tab_geometry,
|
||||
ui.BIM_PT_tab_stakeholders,
|
||||
@@ -153,9 +157,10 @@ classes = [
|
||||
ui.BIM_PT_tab_representations,
|
||||
ui.BIM_PT_tab_geometric_relationships,
|
||||
ui.BIM_PT_tab_parametric_geometry,
|
||||
ui.BIM_PT_tab_profiles,
|
||||
ui.BIM_PT_tab_object_materials,
|
||||
ui.BIM_PT_tab_materials,
|
||||
ui.BIM_PT_tab_styles,
|
||||
ui.BIM_PT_tab_profiles,
|
||||
# Drawings and documents
|
||||
ui.BIM_PT_tab_sheets,
|
||||
ui.BIM_PT_tab_drawings,
|
||||
@@ -168,6 +173,7 @@ classes = [
|
||||
ui.BIM_PT_tab_structural,
|
||||
# Construction scheduling
|
||||
ui.BIM_PT_tab_status,
|
||||
ui.BIM_PT_tab_qto,
|
||||
ui.BIM_PT_tab_resources,
|
||||
ui.BIM_PT_tab_cost,
|
||||
ui.BIM_PT_tab_sequence,
|
||||
@@ -219,8 +225,6 @@ def register():
|
||||
bpy.types.Screen.BIMTabProperties = bpy.props.PointerProperty(type=prop.BIMTabProperties)
|
||||
bpy.types.Collection.BIMCollectionProperties = bpy.props.PointerProperty(type=prop.BIMCollectionProperties)
|
||||
bpy.types.Object.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
|
||||
bpy.types.Material.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
|
||||
bpy.types.Material.BIMMaterialProperties = bpy.props.PointerProperty(type=prop.BIMMaterialProperties)
|
||||
bpy.types.Mesh.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties)
|
||||
bpy.types.Curve.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties)
|
||||
bpy.types.Camera.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties)
|
||||
@@ -279,8 +283,6 @@ def unregister():
|
||||
del bpy.types.Scene.BIMProperties
|
||||
del bpy.types.Collection.BIMCollectionProperties
|
||||
del bpy.types.Object.BIMObjectProperties
|
||||
del bpy.types.Material.BIMObjectProperties
|
||||
del bpy.types.Material.BIMMaterialProperties
|
||||
del bpy.types.Mesh.BIMMeshProperties
|
||||
del bpy.types.Curve.BIMMeshProperties
|
||||
del bpy.types.Camera.BIMMeshProperties
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
* Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||
*
|
||||
* This file is part of BlenderBIM Add-on.
|
||||
*
|
||||
* BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY, without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* You may copy this `schedule.css` template alongside your input schedule
|
||||
* document with the same filename. For example if you have a schedule called
|
||||
* `door_types.ods`, you can create a `door_types.css` in the same folder to
|
||||
* style that schedule.
|
||||
*/
|
||||
|
||||
/**
|
||||
* If you specify a font size in CSS, such as text { font-size: 5; }, all fonts
|
||||
* will be overriden to match that size.
|
||||
*
|
||||
* If your CSS, ODS, XLSX does not specify a font size, the variables below
|
||||
* will specify the default font size.
|
||||
*
|
||||
* If your ODS, XLSX does specify a font size, they will scale linearly based
|
||||
* on the variables below.
|
||||
*/
|
||||
|
||||
:root {
|
||||
--font-size-pt: 12;
|
||||
--font-size-px: 4.13;
|
||||
--font-width: 0.45;
|
||||
}
|
||||
|
||||
text, tspan { /* 2.5mm */ fill: black; stroke: none; font-family: 'OpenGost Type B TT', 'DejaVu Sans Condensed', 'Liberation Sans', 'Arial Narrow', 'Arial'; }
|
||||
@@ -67,11 +67,11 @@ DATA;
|
||||
#60=IFCMATERIALPROFILESET($,$,(#62),$);
|
||||
#61=IFCRELASSOCIATESMATERIAL('09FXUZCnrFEffxBrtg16gx',$,$,$,(#59),#60);
|
||||
#62=IFCMATERIALPROFILE($,$,#20,#58,$,$);
|
||||
#63=IFCSLABTYPE('1Akbal7tP5DAPW0ti$Qp30',$,'FLR150',$,$,$,$,$,$,.NOTDEFINED.);
|
||||
#63=IFCSLABTYPE('1Akbal7tP5DAPW0ti$Qp30',$,'FLR200',$,$,$,$,$,$,.NOTDEFINED.);
|
||||
#64=IFCMATERIALLAYERSET((#66),$,$);
|
||||
#65=IFCRELASSOCIATESMATERIAL('0jzkXlkBL4HhmQ_FTWW6Cj',$,$,$,(#63),#64);
|
||||
#66=IFCMATERIALLAYER(#20,0.2,$,$,$,$,$);
|
||||
#67=IFCSLABTYPE('0$gpYNi3T08BrxaR67CxgI',$,'FLR250',$,$,$,$,$,$,.NOTDEFINED.);
|
||||
#67=IFCSLABTYPE('0$gpYNi3T08BrxaR67CxgI',$,'FLR300',$,$,$,$,$,$,.NOTDEFINED.);
|
||||
#68=IFCMATERIALLAYERSET((#70),$,$);
|
||||
#69=IFCRELASSOCIATESMATERIAL('3a6kjEM29DleYTlSkA8_DK',$,$,$,(#67),#68);
|
||||
#70=IFCMATERIALLAYER(#20,0.3,$,$,$,$,$);
|
||||
|
||||
@@ -5,7 +5,7 @@ FILE_NAME('EPset_Drawing.ifc','2020-01-01T00:00:00',(),(),'EPset_Drawing','EPset
|
||||
FILE_SCHEMA(('IFC4'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
#1=IFCPROPERTYSETTEMPLATE('2JhNIvqZrFnAgxfhK0XVQX',$,'EPset_Drawing','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation',(#2,#3,#4,#5,#6,#7,#8,#9,#10,#11,#12,#13,#14,#15,#16,#17,#18,#19,#20,#21,#22,#23));
|
||||
#1=IFCPROPERTYSETTEMPLATE('2JhNIvqZrFnAgxfhK0XVQX',$,'EPset_Drawing','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation/DRAWING',(#2,#3,#4,#5,#6,#7,#8,#9,#10,#11,#12,#13,#14,#15,#16,#17,#18,#19,#20,#21,#22,#23));
|
||||
#2=IFCSIMPLEPROPERTYTEMPLATE('23JavTMk98ZxXhrUEnjAcf',$,'TargetView','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#3=IFCSIMPLEPROPERTYTEMPLATE('1yVWUt5H9DAOuu0OaMMLpe',$,'Scale','The scale of this drawing represented as a numerator and denominator, such as 1/100',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#4=IFCSIMPLEPROPERTYTEMPLATE('3gsuPBtU93b8f0gg1pjkq6',$,'HumanScale','The scale of this drawing in human readable format, such as 1:100',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
|
||||
@@ -5,6 +5,7 @@ FILE_NAME('EQto_BodyGeometryValidation.ifc','2020-01-01T00:00:00',(),(),'EQto_Bo
|
||||
FILE_SCHEMA(('IFC4'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
/* This quantity set is Qto_BodyGeometryValidation backport from IFC4X3 to support IFC4. */
|
||||
#1=IFCPROPERTYSETTEMPLATE('2KS9su6r517uLXTGKwwDdn',$,'EQto_BodyGeometryValidation','Quantities supplied for validating the correct interpretation of the body shape representation at import. In case of multiple representation items, the quantities are summed for each of the items (irrespective of any overlap). Choosing a suitable tolerance value for comparing the supplied numbers to the numbers calculated from the reconstructed geometry is at the discretion of the importing application.',.QTO_OCCURRENCEDRIVEN.,'IfcProduct',(#2,#3,#4,#5,#6,#7));
|
||||
#2=IFCSIMPLEPROPERTYTEMPLATE('3iCdOOLRjCwQ_HRTB41Xh8',$,'GrossSurfaceArea','Total gross area of the object, normally generated as perimeter * length + 2 * cross section area. It is the sum of OuterSurfaceArea + (2 x CrossSectionArea) and shall only be given, if the OuterSurfaceArea and CrossSectionArea cannot be established separately.\X2\000A000A\X0\Total gross surface area of the element before applying product-level geometric features such as openings and projections.',.Q_AREA.,$,$,$,$,$,$,.READWRITE.);
|
||||
#3=IFCSIMPLEPROPERTYTEMPLATE('0juemEqF5889vg7HwR87Fv',$,'NetSurfaceArea','Net surface area of the object, normally generated as perimeter * length + 2 * cross section area taking into account possible processing features (cut-out''s, etc.) or openings and recesses.\X2\000A000A\X0\Total net surface area of the element after applying product-level geometric features such as openings and projections.',.Q_AREA.,$,$,$,$,$,$,.READWRITE.);
|
||||
|
||||
@@ -5,20 +5,20 @@ FILE_NAME('Psets_BBIM_Annotation.ifc','2020-01-01T00:00:00',(),(),'Psets_BBIM_An
|
||||
FILE_SCHEMA(('IFC4'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
#1=IFCPROPERTYSETTEMPLATE('3VuPUwdCD2Qx3XDDRs0R1N',$,'EPset_Annotation','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation,IfcTypeProduct',(#2,#3,#4));
|
||||
#1=IFCPROPERTYSETTEMPLATE('3VuPUwdCD2Qx3XDDRs0R1N',$,'EPset_Annotation','',.PSET_TYPEDRIVENOVERRIDE.,'IfcAnnotation,IfcTypeProduct',(#2,#3,#4));
|
||||
#2=IFCSIMPLEPROPERTYTEMPLATE('2P7JN79n96Q9pElZ83LKe4',$,'ZIndex','',.P_SINGLEVALUE.,'IfcInteger',$,$,$,$,$,.READWRITE.);
|
||||
#3=IFCSIMPLEPROPERTYTEMPLATE('1Wpx_r2xj1_9w5JpI0QRJy',$,'Symbol','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#4=IFCSIMPLEPROPERTYTEMPLATE('3q0oxMUKP47vZ4jnyG$dDb',$,'Classes','Classes separarated by spaces that end up in classes for this element in svg. Can be used to specify the text font size: small - 1.8mm; regular - 2.5mm; large - 3.5mm; header - 5mm; title - 7mm. By default regular size is used.',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#5=IFCPROPERTYSETTEMPLATE('0iKwujnQL9IevVQato8f7Z',$,'BBIM_Batting','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation,IfcTypeProduct',(#6,#7));
|
||||
#5=IFCPROPERTYSETTEMPLATE('0iKwujnQL9IevVQato8f7Z',$,'BBIM_Batting','',.PSET_TYPEDRIVENOVERRIDE.,'IfcAnnotation/BATTING,IfcTypeProduct',(#6,#7));
|
||||
#6=IFCSIMPLEPROPERTYTEMPLATE('0t2LEesGT1QRQtrIZUAR8L',$,'Thickness','Batting thickness',.P_SINGLEVALUE.,'IfcPositiveLengthMeasure',$,$,$,$,$,.READWRITE.);
|
||||
#7=IFCSIMPLEPROPERTYTEMPLATE('082PndS6v2kBOiJoSboMnh',$,'Reverse pattern direction','Reverse batting pattern (swap starting and ending points)',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#8=IFCPROPERTYSETTEMPLATE('1Dx2EiZnP67xotInXpwz90',$,'BBIM_Section','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation,IfcTypeProduct',(#9,#10,#11,#12,#13));
|
||||
#8=IFCPROPERTYSETTEMPLATE('1Dx2EiZnP67xotInXpwz90',$,'BBIM_Section','',.PSET_TYPEDRIVENOVERRIDE.,'IfcAnnotation/SECTION,IfcTypeProduct',(#9,#10,#11,#12,#13));
|
||||
#9=IFCSIMPLEPROPERTYTEMPLATE('2a_9s8spHDc9dZHtgg71XL',$,'ShowStartArrow','Display start arrow.',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#10=IFCSIMPLEPROPERTYTEMPLATE('3i6SH_GbT7zhKea$wVE56A',$,'StartArrowSymbol','Custom symbol for the start of the section marker arrow. Need to make sure it''s present in "symbols.svg".',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#11=IFCSIMPLEPROPERTYTEMPLATE('1DtsPn5a9FG8$zXHDDMavY',$,'ShowEndArrow','Display end arrow.',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#12=IFCSIMPLEPROPERTYTEMPLATE('2$6U0mLI9AiPRWeBabdY3u',$,'EndArrowSymbol','Custom symbol for the end of the section marker arrow. Need to make sure it''s present in "symbols.svg".',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#13=IFCSIMPLEPROPERTYTEMPLATE('1naFqntIL7igCY7hCaE7kq',$,'HasConnectedSectionLine','Connect or disconnect section markers with line (by default = True).',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#14=IFCPROPERTYSETTEMPLATE('3V8oZ8YRD3_O7uR5vcUleS',$,'BBIM_Documentation','',.PSET_OCCURRENCEDRIVEN.,'IfcProject',(#15,#16,#17,#18,#19,#20,#21,#22,#23));
|
||||
#14=IFCPROPERTYSETTEMPLATE('3V8oZ8YRD3_O7uR5vcUleS',$,'BBIM_Documentation','',.PSET_TYPEDRIVENOVERRIDE.,'IfcProject',(#15,#16,#17,#18,#19,#20,#21,#22,#23));
|
||||
#15=IFCSIMPLEPROPERTYTEMPLATE('0ulAhgk3v9qfGlDILauR6J',$,'SheetsDir','Default sheets directory',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#16=IFCSIMPLEPROPERTYTEMPLATE('2yvlVKiQXASucfH40deCvu',$,'LayoutsDir','Default layouts directory',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#17=IFCSIMPLEPROPERTYTEMPLATE('2kXZqXicL3jRwsOnLM_0ho',$,'TitleblocksDir','Default titleblocks directory',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
@@ -28,7 +28,7 @@ DATA;
|
||||
#21=IFCSIMPLEPROPERTYTEMPLATE('1UDakJ5_f7kBhggNSW4$h5',$,'SymbolsPath','Default symbols SVG',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#22=IFCSIMPLEPROPERTYTEMPLATE('0d53LEtgLDQxnv__NfgH7i',$,'PatternsPath','Default patterns SVG',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#23=IFCSIMPLEPROPERTYTEMPLATE('26qFNMv7nCHgU6Jd7Anga5',$,'ShadingStylesPath','Default shading styles',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#24=IFCPROPERTYSETTEMPLATE('0I9merLinF5Ap$aZwaclgm',$,'BBIM_Dimension','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation,IfcTypeProduct',(#25,#26,#27,#28));
|
||||
#24=IFCPROPERTYSETTEMPLATE('0I9merLinF5Ap$aZwaclgm',$,'BBIM_Dimension','',.PSET_TYPEDRIVENOVERRIDE.,'IfcAnnotation/DIMENSION,IfcTypeProduct',(#25,#26,#27,#28));
|
||||
#25=IFCSIMPLEPROPERTYTEMPLATE('1rL2AbQsXD8RbpoWH5pYOV',$,'ShowDescriptionOnly','Hide the measurement values and show only annotation description',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#26=IFCSIMPLEPROPERTYTEMPLATE('0SVyOfB0rC2xNfdRYf3XvY',$,'SuppressZeroInches','Suppress 0 inch values in dimension annotation text (for example: 12'' - 0" -> 12'')',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#27=IFCSIMPLEPROPERTYTEMPLATE('2bUmj458PBqPAtUoI3MXsb',$,'TextPrefix','Text to add before annotation measurement value',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
|
||||
@@ -67,11 +67,11 @@ DATA;
|
||||
#60=IFCMATERIALPROFILESET($,$,(#62),$);
|
||||
#61=IFCRELASSOCIATESMATERIAL('09FXUZCnrFEffxBrtg16gx',$,$,$,(#59),#60);
|
||||
#62=IFCMATERIALPROFILE($,$,#20,#58,$,$);
|
||||
#63=IFCSLABTYPE('1Akbal7tP5DAPW0ti$Qp30',$,'FLR150',$,$,$,$,$,$,.NOTDEFINED.);
|
||||
#63=IFCSLABTYPE('1Akbal7tP5DAPW0ti$Qp30',$,'FLR200',$,$,$,$,$,$,.NOTDEFINED.);
|
||||
#64=IFCMATERIALLAYERSET((#66),$,$);
|
||||
#65=IFCRELASSOCIATESMATERIAL('0jzkXlkBL4HhmQ_FTWW6Cj',$,$,$,(#63),#64);
|
||||
#66=IFCMATERIALLAYER(#20,0.2,$,$,$,$,$);
|
||||
#67=IFCSLABTYPE('0$gpYNi3T08BrxaR67CxgI',$,'FLR250',$,$,$,$,$,$,.NOTDEFINED.);
|
||||
#67=IFCSLABTYPE('0$gpYNi3T08BrxaR67CxgI',$,'FLR300',$,$,$,$,$,$,.NOTDEFINED.);
|
||||
#68=IFCMATERIALLAYERSET((#70),$,$);
|
||||
#69=IFCRELASSOCIATESMATERIAL('3a6kjEM29DleYTlSkA8_DK',$,$,$,(#67),#68);
|
||||
#70=IFCMATERIALLAYER(#20,0.3,$,$,$,$,$);
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
import argparse
|
||||
from aiohttp import web
|
||||
import socketio
|
||||
import pystache
|
||||
import json
|
||||
|
||||
sio_port = 8080 # default port
|
||||
|
||||
sio = socketio.AsyncServer(
|
||||
cors_allowed_origins="*",
|
||||
async_mode="aiohttp",
|
||||
)
|
||||
|
||||
# sio.instrument(
|
||||
# auth={
|
||||
# "username": "admin",
|
||||
# "password": "admin",
|
||||
# }
|
||||
# )
|
||||
|
||||
app = web.Application()
|
||||
sio.attach(app)
|
||||
|
||||
blender_messages = {}
|
||||
|
||||
|
||||
# Web namespace
|
||||
class WebNamespace(socketio.AsyncNamespace):
|
||||
def __init__(self, namespace):
|
||||
super().__init__(namespace)
|
||||
|
||||
async def on_connect(self, sid, environ):
|
||||
print(f"Web client connected: {sid}")
|
||||
|
||||
async def on_disconnect(self, sid):
|
||||
print(f"Web client disconnected: {sid}")
|
||||
|
||||
async def on_web_operator(self, sid, data):
|
||||
await sio.emit(
|
||||
"web_operator",
|
||||
data,
|
||||
namespace="/blender",
|
||||
room=data["blenderId"],
|
||||
)
|
||||
|
||||
|
||||
# Blender namespace
|
||||
class BlenderNamespace(socketio.AsyncNamespace):
|
||||
def __init__(self, namespace):
|
||||
super().__init__(namespace)
|
||||
|
||||
async def on_connect(self, sid, environ):
|
||||
print(f"Blender client connected: {sid}")
|
||||
# Notify web client about new connection
|
||||
blender_messages[sid] = {}
|
||||
await sio.emit("blender_connect", sid, namespace="/web")
|
||||
|
||||
async def on_disconnect(self, sid):
|
||||
print(f"Blender client disconnected: {sid}")
|
||||
# Remove client message and notify web client about disconnection
|
||||
if sid in blender_messages:
|
||||
del blender_messages[sid]
|
||||
await sio.emit("blender_disconnect", sid, namespace="/web")
|
||||
|
||||
async def on_data(self, sid, data):
|
||||
print(f"Data from Blender client {sid}")
|
||||
# blender_messages[sid]["default_data"] = data
|
||||
# await sio.emit("default_data", {"blenderId": sid, "data": data}, namespace="/web")
|
||||
|
||||
async def on_csv_data(self, sid, data):
|
||||
print(f"CSV data from Blender client {sid}")
|
||||
# Store the message and forward it to the web client
|
||||
blender_messages[sid]["csv_data"] = data
|
||||
await sio.emit("csv_data", {"blenderId": sid, "data": data}, namespace="/web")
|
||||
|
||||
async def on_gantt_data(self, sid, data):
|
||||
print(f"Gant Chart data from Blender client {sid}")
|
||||
blender_messages[sid]["gantt_data"] = data
|
||||
await sio.emit("gantt_data", {"blenderId": sid, "data": data}, namespace="/web")
|
||||
|
||||
|
||||
# Attach namespaces
|
||||
sio.register_namespace(WebNamespace("/web"))
|
||||
sio.register_namespace(BlenderNamespace("/blender"))
|
||||
|
||||
|
||||
# Define a route to render the index.html template
|
||||
async def index(request):
|
||||
with open("templates/index.html", "r") as f:
|
||||
template = f.read()
|
||||
html_content = pystache.render(template, {"port": sio_port})
|
||||
return web.Response(text=html_content, content_type="text/html")
|
||||
|
||||
|
||||
async def gantt(request):
|
||||
with open("templates/gantt.html", "r") as f:
|
||||
template = f.read()
|
||||
html_content = pystache.render(template, {"port": sio_port})
|
||||
return web.Response(text=html_content, content_type="text/html")
|
||||
|
||||
|
||||
app.router.add_get("/", index)
|
||||
app.router.add_get("/gantt", gantt)
|
||||
app.router.add_static("/jsgantt/", path="../gantt", name="jsgantt")
|
||||
app.router.add_static("/static/", path="./static", name="static")
|
||||
|
||||
|
||||
def main():
|
||||
global sio_port
|
||||
|
||||
parser = argparse.ArgumentParser(description="SocketIO server")
|
||||
parser.add_argument("--host", type=str, default="127.0.0.1", help="Host to run the server on")
|
||||
parser.add_argument("--port", type=int, default=8080, help="Port to run the server on")
|
||||
|
||||
args = parser.parse_args()
|
||||
sio_port = args.port
|
||||
web.run_app(app, host=args.host, port=sio_port)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# web.run_app(app, host="127.0.0.1", port=sio_port)
|
||||
@@ -0,0 +1,280 @@
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #252525;
|
||||
color: #e0e0e0;
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
#container {
|
||||
margin-top: 20px;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
nav {
|
||||
background-color: #121212;
|
||||
padding: 1em 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
nav .logo {
|
||||
margin-left: 40px;
|
||||
height: 40px;
|
||||
/* Adjust height as needed */
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
margin-left: 1px;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
margin-right: 50px;
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
nav ul li a:hover,
|
||||
nav ul li a.active {
|
||||
color: #3fb449;
|
||||
}
|
||||
|
||||
nav .bottom-bar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background-color: #25682a;
|
||||
}
|
||||
|
||||
.table-description {
|
||||
margin-bottom: 1rem;
|
||||
width: 50%;
|
||||
background-color: transparent;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
border-color: #464444;
|
||||
border: 1px solid #464444;
|
||||
border-radius: 0.25rem;
|
||||
box-shadow: 0 0 0.7rem rgba(95, 95, 95, 0.4);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.table-description tr {
|
||||
display: table-row;
|
||||
border-bottom: 1px solid #464444;
|
||||
}
|
||||
|
||||
.gantt-info {
|
||||
margin: 0.5rem;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin: 0.5rem;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.no-print {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------ Overwriting JSGantt CSS rules ------------ */
|
||||
|
||||
div.gantt {
|
||||
background-color: #252525;
|
||||
color: #c7c7c7;
|
||||
}
|
||||
|
||||
.gantt table {
|
||||
border-color: #464444;
|
||||
;
|
||||
}
|
||||
|
||||
.gantt td {
|
||||
border-color: #464444;
|
||||
;
|
||||
}
|
||||
|
||||
/* Headings and cell defaults */
|
||||
.gmajorheading,
|
||||
.gminorheading,
|
||||
.gminorheadingwkend,
|
||||
.gtaskcell,
|
||||
.gtaskcellcurrent,
|
||||
.gtaskcellwkend,
|
||||
.gname,
|
||||
.ggroupitem,
|
||||
.gtaskheading {
|
||||
background-color: #252525;
|
||||
border-color: #464444;
|
||||
;
|
||||
}
|
||||
|
||||
.gtaskheading,
|
||||
.gname,
|
||||
.gtaskname,
|
||||
.gres,
|
||||
.gdur,
|
||||
.gcomp,
|
||||
.gstartdate,
|
||||
.gplanstartdate,
|
||||
.gplanenddate,
|
||||
.gcost,
|
||||
.gchartlbl,
|
||||
.gcontainercol,
|
||||
.genddate {
|
||||
color: #c7c7c7;
|
||||
border-color: #464444;
|
||||
;
|
||||
}
|
||||
|
||||
.gtaskname>div {
|
||||
color: #c7c7c7;
|
||||
}
|
||||
|
||||
.gtaskbarcontainer.gplan,
|
||||
.gchartlbl.gcontainercol {
|
||||
background: #252525;
|
||||
border-color: #464444;
|
||||
}
|
||||
|
||||
.gtaskname div,
|
||||
.gtaskheading div,
|
||||
.gtaskname span {
|
||||
color: #c7c7c7;
|
||||
}
|
||||
|
||||
|
||||
.gtasklist,
|
||||
.gadditional {
|
||||
border: #464444 1px solid
|
||||
}
|
||||
|
||||
.gchartgrid {
|
||||
background-color: #252525;
|
||||
}
|
||||
|
||||
.glistgrid,
|
||||
.glistlbl {
|
||||
background-color: #252525;
|
||||
border-color: #464444;
|
||||
;
|
||||
}
|
||||
|
||||
/* .gTaskInfo {
|
||||
background-color: #2e2e2e;
|
||||
color: #c7c7c7;
|
||||
border-color: #c7c7c7;;
|
||||
} */
|
||||
|
||||
/* Dark mode scrollbar */
|
||||
.frame::-webkit-scrollbar-thumb {
|
||||
background-color: #252525;
|
||||
}
|
||||
|
||||
.frame::-webkit-scrollbar-track {
|
||||
background-color: #252525;
|
||||
}
|
||||
|
||||
/* Highlight row */
|
||||
.gitemhighlight td {
|
||||
background-color: #009136;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Differentiate Group, Milestone and Ordinary task items (applied to row) */
|
||||
.ggroupitem {
|
||||
background-color: #252525;
|
||||
font-weight: bold;
|
||||
border-color: #464444;
|
||||
}
|
||||
|
||||
.gmileitem,
|
||||
.glineitem {
|
||||
background-color: #252525;
|
||||
}
|
||||
|
||||
/* Task bar caption text styles */
|
||||
.gmilecaption,
|
||||
.ggroupcaption,
|
||||
.gcaption {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Task complete %age bar */
|
||||
.gtaskcomplete {
|
||||
background-color: #777777;
|
||||
}
|
||||
|
||||
/* Milestones */
|
||||
.gmdtop {
|
||||
border-bottom: 5px solid #ffffff;
|
||||
}
|
||||
|
||||
.gmdbottom {
|
||||
border-top: 5px solid #ffffff;
|
||||
}
|
||||
|
||||
.gfoldercollapse {
|
||||
color: #c7c7c7;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
|
||||
font-size: 12px;
|
||||
font-family: Courier, "Courier New", monospace;
|
||||
}
|
||||
|
||||
/* Highlight for collapsible row */
|
||||
.gname.ggroupitem {
|
||||
background-color: rgb(75, 75, 75);
|
||||
}
|
||||
|
||||
/* Form label and selected highlighting */
|
||||
.gformlabel {
|
||||
background-color: #2e2e2e;
|
||||
color: #c7c7c7;
|
||||
border: #4a4a4a 1px solid;
|
||||
}
|
||||
|
||||
span.gformlabel:hover {
|
||||
background-color: #3a3a3a;
|
||||
border-color: #565656;
|
||||
}
|
||||
|
||||
span.gselected {
|
||||
background-color: #565656;
|
||||
border-color: #777777;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.gantt-inputtable {
|
||||
background-color: #3b3b3b;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #000;
|
||||
color: #c7c7c7;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #252525;
|
||||
color: #e0e0e0;
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
#container {
|
||||
margin-top: 20px;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 20px
|
||||
}
|
||||
|
||||
.table-container {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.csv-table {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
nav {
|
||||
background-color: #121212;
|
||||
padding: 1em 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
nav .logo {
|
||||
margin-left: 40px;
|
||||
height: 40px;
|
||||
/* Adjust height as needed */
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
margin-left: 1px;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
margin-right: 50px;
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
nav ul li a:hover,
|
||||
nav ul li a.active {
|
||||
color: #3fb449;
|
||||
}
|
||||
|
||||
nav .bottom-bar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background-color: #25682a;
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
// keeps track of blenders connected in form of
|
||||
// shown:bool, workSchedule: {}, ganttTasks: {},
|
||||
const connectedClients = {};
|
||||
let socket;
|
||||
|
||||
// print options
|
||||
const pageSizes = [
|
||||
{ value: "210,297", text: "A4 Portrait" },
|
||||
{ value: "297,210", text: "A4 Landscape" },
|
||||
{ value: "297,420", text: "A3 Portrait" },
|
||||
{ value: "420,297", text: "A3 Landscape" },
|
||||
{ value: "420,594", text: "A2 Portrait" },
|
||||
{ value: "594,420", text: "A2 Landscape" },
|
||||
{ value: "594,841", text: "A1 Portrait" },
|
||||
{ value: "841,594", text: "A1 Landscape" },
|
||||
{ value: "841,1189", text: "A0 Portrait" },
|
||||
{ value: "1189,841", text: "A0 Landscape" },
|
||||
];
|
||||
|
||||
// Document ready function
|
||||
$(document).ready(function () {
|
||||
connectSocket();
|
||||
});
|
||||
|
||||
// Function to connect to Socket.IO server
|
||||
function connectSocket() {
|
||||
const url = "ws://localhost:" + SOCKET_PORT + "/web";
|
||||
socket = io(url);
|
||||
console.log("socket: ", socket);
|
||||
|
||||
// Register socket event handlers
|
||||
socket.on("blender_connect", handleBlenderConnect);
|
||||
socket.on("blender_disconnect", handleBlenderDisconnect);
|
||||
socket.on("gantt_data", handleGanttData);
|
||||
}
|
||||
|
||||
// Function to handle 'blender_connect' event
|
||||
function handleBlenderConnect(blenderId) {
|
||||
console.log("blender_connect: ", blenderId);
|
||||
if (!connectedClients.hasOwnProperty(blenderId)) {
|
||||
connectedClients[blenderId] = {
|
||||
shown: false,
|
||||
workSchedule: {},
|
||||
ganttTasks: {},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle 'blender_disconnect' event
|
||||
function handleBlenderDisconnect(blenderId) {
|
||||
console.log("blender_disconnect: ", blenderId);
|
||||
if (connectedClients.hasOwnProperty(blenderId)) {
|
||||
delete connectedClients[blenderId];
|
||||
removeGanttElement(blenderId);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle 'gantt_data' event
|
||||
function handleGanttData(data) {
|
||||
const blenderId = data["blenderId"];
|
||||
|
||||
console.log(data);
|
||||
|
||||
const filename = data["data"]["IFC_File"];
|
||||
const ganttTasks = data["data"]["gantt_data"]["tasks"];
|
||||
const ganttWorkSched = data["data"]["gantt_data"]["work_schedule"];
|
||||
// const ganttWorkSched = {};
|
||||
|
||||
if (connectedClients.hasOwnProperty(blenderId)) {
|
||||
if (!connectedClients[blenderId].shown) {
|
||||
connectedClients[blenderId] = {
|
||||
shown: true,
|
||||
ganttTasks: ganttTasks,
|
||||
workSchedule: ganttWorkSched,
|
||||
};
|
||||
addGanttElement(blenderId, ganttTasks, ganttWorkSched, filename);
|
||||
} else {
|
||||
updateGanttElement(blenderId, ganttTasks, ganttWorkSched, filename);
|
||||
connectedClients[blenderId].workSchedule = ganttWorkSched;
|
||||
connectedClients[blenderId].ganttTasks = ganttTasks;
|
||||
}
|
||||
} else {
|
||||
connectedClients[blenderId] = {
|
||||
shown: true,
|
||||
ganttTasks: ganttTasks,
|
||||
workSchedule: ganttWorkSched,
|
||||
};
|
||||
addGanttElement(blenderId, ganttTasks, ganttWorkSched, filename);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to add a new gantt with data and filename
|
||||
function addGanttElement(blenderId, tasks, workSched, filename) {
|
||||
const ganttContainer = $("<div></div>")
|
||||
.addClass("gantt-container")
|
||||
.attr("id", "container-" + blenderId);
|
||||
|
||||
const ganttTitle = $("<h3></h3>")
|
||||
.attr("id", "title-" + blenderId)
|
||||
.text(filename)
|
||||
.addClass("no-print")
|
||||
.css("margin-bottom", "10px");
|
||||
|
||||
const workSchedDiv = $("<div></div>").attr("id", "workSched" + blenderId);
|
||||
|
||||
const scheduleTable = $("<table></table>")
|
||||
.addClass("no-print table-description")
|
||||
.attr("id", "workSchedTable-" + blenderId)
|
||||
.hide();
|
||||
|
||||
$.each(workSched, (key, value) => {
|
||||
value = value ? value : "null";
|
||||
$("<tr></tr>")
|
||||
.append($("<td></td>").text(key))
|
||||
.append($("<td></td>").text(value))
|
||||
.appendTo(scheduleTable);
|
||||
});
|
||||
|
||||
const toggleButton = $("<button></button>")
|
||||
.text("Show Schedule Info")
|
||||
.addClass("btn no-print")
|
||||
.on("click", function () {
|
||||
scheduleTable.toggle();
|
||||
const buttonText = scheduleTable.is(":visible")
|
||||
? "Hide Schedule Info"
|
||||
: "Show Schedule Info";
|
||||
toggleButton.text(buttonText);
|
||||
});
|
||||
|
||||
var ganttInfoDiv = $("<div></div>")
|
||||
.addClass("gantt-info")
|
||||
.attr("id", "gantt-info-" + blenderId);
|
||||
|
||||
const scheduleName = $("<span></span>").text("Schedule: " + workSched.Name);
|
||||
|
||||
const createdOn = $("<span></span>")
|
||||
.text("Created: " + new Date(workSched.CreationDate).toLocaleDateString())
|
||||
.css("float", "right");
|
||||
|
||||
const ganttDiv = $("<div></div>")
|
||||
.addClass("gantt-chart")
|
||||
.attr("id", "gantt-" + blenderId);
|
||||
|
||||
ganttInfoDiv.append(scheduleName);
|
||||
ganttInfoDiv.append(createdOn);
|
||||
|
||||
workSchedDiv.append(toggleButton);
|
||||
workSchedDiv.append(scheduleTable);
|
||||
|
||||
ganttContainer.append(ganttTitle);
|
||||
ganttContainer.append(workSchedDiv);
|
||||
ganttContainer.append(ganttInfoDiv);
|
||||
ganttContainer.append(ganttDiv);
|
||||
|
||||
$("#container").append(ganttContainer);
|
||||
|
||||
let g = new JSGantt.GanttChart($("#gantt-" + blenderId)[0], "week");
|
||||
g.setOptions({
|
||||
vCaptionType: "Caption", // Set to Show Caption : None,Caption,Resource,Duration,Complete,
|
||||
vQuarterColWidth: 36,
|
||||
vDateTaskDisplayFormat: "day dd month yyyy", // Shown in tool tip box
|
||||
vDayMajorDateDisplayFormat: "mon yyyy - Week ww", // Set format to dates in the "Major" header of the "Day" view
|
||||
vWeekMinorDateDisplayFormat: "dd mon", // Set format to display dates in the "Minor" header of the "Week" view
|
||||
vLang: "en",
|
||||
vShowTaskInfoLink: 1, // Show link in tool tip (0/1)
|
||||
vShowEndWeekDate: 0, // Show/Hide the date for the last day of the week in header for daily
|
||||
vUseSingleCell: 10000, // Set the threshold cell per table row (Helps performance for large data.
|
||||
vFormatArr: ["Day", "Week", "Month", "Quarter"], // Even with setUseSingleCell using Hour format on such a large chart can cause issues in some browsers,
|
||||
vShowRes: true, // Disable the resource column.
|
||||
vShowComp: false, // Disable the completion column.
|
||||
vShowDur: false, // Disable the duration column, because jsgantt doesn't calculate durations the way we want.
|
||||
vAdditionalHeaders: {
|
||||
ifcduration: { title: "Duration" },
|
||||
resourceUsage: { title: "Resource Usage" },
|
||||
},
|
||||
vUseToolTip: true, // Disable tooltips.
|
||||
vTooltipTemplate: generateTooltip,
|
||||
vTotalHeight: 900,
|
||||
|
||||
vEventsChange: {
|
||||
taskname: editValue, // if you need to use the this scope, do: editValue.bind(this)
|
||||
res: editValue,
|
||||
dur: editValue,
|
||||
comp: editValue,
|
||||
start: editValue,
|
||||
end: editValue,
|
||||
planstart: editValue,
|
||||
planend: editValue,
|
||||
cost: editValue,
|
||||
additional_category: editValue,
|
||||
},
|
||||
});
|
||||
JSGantt.addJSONTask(g, tasks);
|
||||
g.setEditable(true);
|
||||
g.Draw();
|
||||
|
||||
connectedClients[blenderId]["gantt"] = g;
|
||||
|
||||
let printButton = $("<button>", {
|
||||
id: "print-btn-" + blenderId,
|
||||
html: "Print",
|
||||
class: "btn no-print",
|
||||
});
|
||||
|
||||
let printOptions = $("<select>", {
|
||||
id: "print-options-" + blenderId,
|
||||
class: "no-print",
|
||||
});
|
||||
|
||||
$.each(pageSizes, function (index, size) {
|
||||
printOptions.append(
|
||||
$("<option>", {
|
||||
value: size.value,
|
||||
text: size.text,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
printButton.on("click", function () {
|
||||
// make it only the corresponding gantt chart is printed
|
||||
$(".gantt-chart").removeClass("no-print");
|
||||
$(".gantt-chart")
|
||||
.not("#gantt-" + blenderId)
|
||||
.addClass("your-css-class");
|
||||
|
||||
var values = $("#print-options-" + blenderId)
|
||||
.val()
|
||||
.split(",");
|
||||
|
||||
g.setEditable(false);
|
||||
g.setTotalHeight("");
|
||||
g.Draw();
|
||||
|
||||
addEventListener("afterprint", (event) => {
|
||||
g.setEditable(true);
|
||||
},);
|
||||
|
||||
|
||||
let css =
|
||||
"@media print {\n" +
|
||||
" @page {\n" +
|
||||
" size: " +
|
||||
values[0] +
|
||||
"mm " +
|
||||
values[1] +
|
||||
"mm;\n" +
|
||||
" }\n" +
|
||||
" /* Make all text black */\n" +
|
||||
" body, p, span, h1, h2, h3, h4, h5, h6, div, a, li, td, th, * {\n" +
|
||||
" color: black !important;\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
g.printChart(values[0], values[1], css);
|
||||
g.setTotalHeight(900);
|
||||
g.Draw();
|
||||
});
|
||||
|
||||
ganttContainer.append(printOptions);
|
||||
ganttContainer.append(printButton);
|
||||
}
|
||||
|
||||
// Function to update gantt and filename
|
||||
function updateGanttElement(blenderId, tasks, workSched, filename) {
|
||||
// update work schedule table
|
||||
const table = $("#workSchedTable-" + blenderId);
|
||||
table.empty();
|
||||
$.each(workSched, (key, value) => {
|
||||
value = value ? value : "null";
|
||||
$("<tr></tr>")
|
||||
.append($("<td></td>").text(key))
|
||||
.append($("<td></td>").text(value))
|
||||
.appendTo(table);
|
||||
});
|
||||
|
||||
// update gantt chart with new data
|
||||
let g = connectedClients[blenderId]["gantt"];
|
||||
g.ClearTasks();
|
||||
g.Draw();
|
||||
JSGantt.addJSONTask(g, tasks);
|
||||
g.Draw();
|
||||
|
||||
$("#title-" + blenderId).text(filename);
|
||||
}
|
||||
|
||||
// Function to remove gantt element
|
||||
function removeGanttElement(blenderId) {
|
||||
$("#container-" + blenderId).remove();
|
||||
}
|
||||
|
||||
// Utility function to create a tooltip for the gantt chars
|
||||
function generateTooltip(task) {
|
||||
var dataObject = task.getDataObject();
|
||||
var numberResources = dataObject.resourceUsage
|
||||
? dataObject.resourceUsage
|
||||
: "NULL";
|
||||
return `
|
||||
<dl>
|
||||
<dt>Name:</dt><dd>{{pName}}</dd>
|
||||
<dt>Start:</dt><dd>{{pStart}}</dd>
|
||||
<dt>End:</dt><dd>{{pEnd}}</dd>
|
||||
<dt>Duration:</dt><dd>${dataObject.ifcduration}</dd>
|
||||
<dt>Number of Resources:</dt><dd>${numberResources}</dd>
|
||||
<dt>Resources:</dt><dd>{{pRes}}</dd>
|
||||
</dl>
|
||||
`;
|
||||
}
|
||||
|
||||
// Event handlers for editing gantt table data
|
||||
function editValue(list, task, event, cell, column) {
|
||||
console.log("editValue function called with the following parameters:");
|
||||
console.log("list:", list);
|
||||
console.log("task:", task);
|
||||
console.log("event:", event);
|
||||
console.log("cell:", cell);
|
||||
console.log("column:", column);
|
||||
|
||||
const ganttId = task.getGantt()["vDiv"].id;
|
||||
const index = ganttId.indexOf("-") + 1;
|
||||
const blenderId = ganttId.substring(index);
|
||||
const workSchedId = connectedClients[blenderId].workSchedule.id;
|
||||
|
||||
// update data object reprsenting the task
|
||||
const dataObj = task.getDataObject();
|
||||
dataObj[column] = event.target.value;
|
||||
task.setDataObject(dataObj);
|
||||
|
||||
const msg = {
|
||||
sourcePage: "gantt",
|
||||
blenderId: blenderId,
|
||||
operator: {
|
||||
type: "editTask",
|
||||
workScheduleId: workSchedId,
|
||||
taskId: task.getOriginalID(),
|
||||
column: column,
|
||||
value: event.target.value,
|
||||
},
|
||||
};
|
||||
socket.emit("web_operator", msg);
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
// keeps track of blenders connected in form of
|
||||
// {shown:bool, filename:string, headers:array}
|
||||
const connectedClients = {};
|
||||
let socket;
|
||||
|
||||
// Document ready function
|
||||
$(document).ready(function () {
|
||||
connectSocket();
|
||||
});
|
||||
|
||||
// Function to connect to Socket.IO server
|
||||
function connectSocket() {
|
||||
const url = "ws://localhost:" + SOCKET_PORT + "/web";
|
||||
socket = io(url);
|
||||
console.log("socket: ", socket);
|
||||
|
||||
// Register socket event handlers
|
||||
socket.on("blender_connect", handleBlenderConnect);
|
||||
socket.on("blender_disconnect", handleBlenderDisconnect);
|
||||
socket.on("csv_data", handleCsvData);
|
||||
}
|
||||
|
||||
// Function to handle 'blender_connect' event
|
||||
function handleBlenderConnect(blenderId) {
|
||||
console.log("blender_connect: ", blenderId);
|
||||
if (!connectedClients.hasOwnProperty(blenderId)) {
|
||||
connectedClients[blenderId] = { shown: false, ifc_file: "" };
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle 'blender_disconnect' event
|
||||
function handleBlenderDisconnect(blenderId) {
|
||||
console.log("blender_disconnect: ", blenderId);
|
||||
if (connectedClients.hasOwnProperty(blenderId)) {
|
||||
delete connectedClients[blenderId];
|
||||
removeTableElement(blenderId);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle 'csv_data' event
|
||||
function handleCsvData(data) {
|
||||
const blenderId = data["blenderId"];
|
||||
const csvData = data["data"]["csv_data"];
|
||||
const filename = data["data"]["IFC_File"];
|
||||
console.log(data);
|
||||
|
||||
if (connectedClients.hasOwnProperty(blenderId)) {
|
||||
if (!connectedClients[blenderId].shown) {
|
||||
connectedClients[blenderId] = {
|
||||
shown: true,
|
||||
ifc_file: filename,
|
||||
headers: [],
|
||||
};
|
||||
addTableElement(blenderId, csvData, filename);
|
||||
} else {
|
||||
updateTableElement(blenderId, csvData, filename);
|
||||
}
|
||||
} else {
|
||||
connectedClients[blenderId] = {
|
||||
shown: true,
|
||||
ifc_file: filename,
|
||||
headers: [],
|
||||
};
|
||||
addTableElement(blenderId, csvData, filename);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to add a new table with data and filename
|
||||
function addTableElement(blenderId, csvData, filename) {
|
||||
// store headers of the csv data
|
||||
const firstLine = csvData.indexOf("\n");
|
||||
const csvHeaders = csvData.substring(0, firstLine).split(",");
|
||||
connectedClients[blenderId].headers = csvHeaders;
|
||||
|
||||
console.log(connectedClients[blenderId]);
|
||||
const tableContainer = $("<div></div>")
|
||||
.addClass("table-container")
|
||||
.attr("id", "container-" + blenderId);
|
||||
|
||||
const tableTitle = $("<h3></h3>")
|
||||
.attr("id", "title-" + blenderId)
|
||||
.text(filename)
|
||||
.css("margin-bottom", "10px");
|
||||
|
||||
const tableDiv = $("<div></div>")
|
||||
.addClass("csv-table")
|
||||
.attr("id", "table-" + blenderId);
|
||||
|
||||
tableContainer.append(tableTitle);
|
||||
tableContainer.append(tableDiv);
|
||||
$("#container").append(tableContainer);
|
||||
|
||||
function createHeaderMenu(definitions) {
|
||||
var menu = [];
|
||||
|
||||
for (let column of definitions) {
|
||||
// Create text element for checkbox
|
||||
if (!column.hasOwnProperty("key")) {
|
||||
column.visible = true;
|
||||
}
|
||||
let checkbox = document.createElement("span");
|
||||
checkbox.textContent = column.visible ? "\u2611" : "\u2610"; // ☑ or ☐
|
||||
|
||||
// Build label
|
||||
let label = document.createElement("span");
|
||||
let title = document.createElement("span");
|
||||
|
||||
title.textContent = " " + column.title;
|
||||
|
||||
label.appendChild(checkbox);
|
||||
label.appendChild(title);
|
||||
|
||||
// Create menu item
|
||||
menu.push({
|
||||
label: label,
|
||||
action: function (e) {
|
||||
// Prevent menu closing
|
||||
e.stopPropagation();
|
||||
|
||||
// Toggle current column visibility
|
||||
column.visible = !column.visible;
|
||||
console.log(column.title, column.visible);
|
||||
// Change menu item checkbox
|
||||
if (column.visible) {
|
||||
table.showColumn(column.title);
|
||||
checkbox.textContent = "\u2611"; // ☑
|
||||
} else {
|
||||
table.hideColumn(column.title);
|
||||
checkbox.textContent = "\u2610"; // ☐
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
var table = new Tabulator("#table-" + blenderId, {
|
||||
height: "400px",
|
||||
resizableColumnGuide: true,
|
||||
index: "GlobalId",
|
||||
data: csvData,
|
||||
importFormat: "csv",
|
||||
autoColumns: true,
|
||||
selectableRows: 1,
|
||||
layout: "fitColumns",
|
||||
autoColumnsDefinitions: function (definitions) {
|
||||
menu = createHeaderMenu(definitions, table);
|
||||
definitions.forEach((column) => {
|
||||
column.visible = true;
|
||||
column.headerMenu = menu;
|
||||
});
|
||||
return definitions;
|
||||
},
|
||||
});
|
||||
|
||||
table.on("rowSelected", function (row) {
|
||||
var index = row.getIndex(); // the guid of the object
|
||||
|
||||
if (!index) {
|
||||
console.log("No Global ID found");
|
||||
return;
|
||||
}
|
||||
|
||||
// table id is usually "table-BlenderId" so blender id is always
|
||||
// after the first 6 characters
|
||||
var tableId = row.getTable().element.id.substr(6);
|
||||
|
||||
const msg = {
|
||||
sourcePage: "csv",
|
||||
blenderId: tableId,
|
||||
operator: {
|
||||
type: "selection",
|
||||
globalId: index,
|
||||
},
|
||||
};
|
||||
socket.emit("web_operator", msg);
|
||||
});
|
||||
}
|
||||
|
||||
// Function to update table and filename
|
||||
function updateTableElement(blenderId, csvData, filename) {
|
||||
// check if the headers are the same
|
||||
// if yes, just replace the data
|
||||
// else, replace the whole data and column definations
|
||||
const firstLine = csvData.indexOf("\n");
|
||||
const newHeaders = csvData.substring(0, firstLine).split(",");
|
||||
const sameHeaders = compareHeaders(
|
||||
connectedClients[blenderId].headers,
|
||||
newHeaders
|
||||
);
|
||||
|
||||
const table = Tabulator.findTable("#table-" + blenderId)[0];
|
||||
if (table) {
|
||||
if (sameHeaders) {
|
||||
table.replaceData(csvData, { importFormat: "csv" });
|
||||
} else {
|
||||
table.setData(csvData);
|
||||
connectedClients[blenderId].headers = newHeaders;
|
||||
}
|
||||
$("#title-" + blenderId).text(filename);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to remove table element
|
||||
function removeTableElement(blenderId) {
|
||||
$("#container-" + blenderId).remove();
|
||||
}
|
||||
|
||||
// Utility function to compare two csv header
|
||||
function compareHeaders(headers1, headers2) {
|
||||
if (headers1.length !== headers2.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < headers1.length; i++) {
|
||||
if (headers1[i] !== headers2[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Web Client</title>
|
||||
<link rel="stylesheet" type="text/css" href="/jsgantt/jsgantt.css" />
|
||||
<link rel="stylesheet" href="/static/css/gantt.css" />
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://code.jquery.com/jquery-3.6.0.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.socket.io/4.0.0/socket.io.min.js"
|
||||
></script>
|
||||
<script type="text/javascript" src="./jsgantt/jsgantt.js"></script>
|
||||
<script>
|
||||
var SOCKET_PORT = {{port}};
|
||||
</script>
|
||||
<script defer src="./static/js/gantt.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="no-print">
|
||||
<img src="https://blenderbim.org/assets/images/blender/blender-logo.png" alt="Logo" class="logo" />
|
||||
<ul>
|
||||
<li><a href="/">IFC Data</a></li>
|
||||
<li><a href="/gantt" class="active">Gantt Chart</a></li>
|
||||
</ul>
|
||||
<div class="bottom-bar"></div>
|
||||
</nav>
|
||||
<div id="container"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Web Client</title>
|
||||
<link rel="stylesheet" href="/static/css/index.css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/tabulator-tables/dist/css/tabulator_site_dark.min.css"
|
||||
/>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://code.jquery.com/jquery-3.6.0.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://unpkg.com/tabulator-tables/dist/js/tabulator.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.socket.io/4.0.0/socket.io.min.js"
|
||||
></script>
|
||||
<script>
|
||||
var SOCKET_PORT = {{port}};
|
||||
</script>
|
||||
<script defer src="./static/js/index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<img src="https://blenderbim.org/assets/images/blender/blender-logo.png" alt="Logo" class="logo" />
|
||||
<ul>
|
||||
<li><a href="/" class="active">IFC Data</a></li>
|
||||
<li><a href="/gantt">Gantt Chart</a></li>
|
||||
</ul>
|
||||
<div class="bottom-bar"></div>
|
||||
</nav>
|
||||
<div id="container"></div>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
@@ -16,6 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import os
|
||||
import bpy
|
||||
import json
|
||||
@@ -36,6 +37,7 @@ import blenderbim.core.style
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from mathutils import Vector
|
||||
from typing import Union
|
||||
from logging import Logger
|
||||
|
||||
|
||||
class IfcExporter:
|
||||
@@ -87,7 +89,7 @@ class IfcExporter:
|
||||
self.get_application_name(), tool.Blender.get_blenderbim_version()
|
||||
)
|
||||
|
||||
def sync_all_objects(self, skip_unlinking=False) -> list[ifcopenshell.entity_instance]:
|
||||
def sync_all_objects(self) -> list[ifcopenshell.entity_instance]:
|
||||
results: list[ifcopenshell.entity_instance] = []
|
||||
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||
for ifc_definition_id in list(IfcStore.id_map.keys()):
|
||||
@@ -97,7 +99,6 @@ class IfcExporter:
|
||||
continue
|
||||
if obj.library:
|
||||
continue
|
||||
tool.Collector.sync(obj, skip_unlinking)
|
||||
result = self.sync_object_placement(obj)
|
||||
if result:
|
||||
results.append(result)
|
||||
@@ -117,8 +118,8 @@ class IfcExporter:
|
||||
continue
|
||||
try:
|
||||
if isinstance(obj, bpy.types.Material):
|
||||
if tool.Ifc.has_changed_shading(obj):
|
||||
blenderbim.core.style.update_style_colours(tool.Ifc, tool.Style, obj=obj)
|
||||
# TODO: do we add materials to edited_objs?
|
||||
continue
|
||||
else:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if element:
|
||||
@@ -136,9 +137,9 @@ class IfcExporter:
|
||||
return
|
||||
bpy.ops.bim.update_representation(obj=obj.name)
|
||||
|
||||
def has_changed_materials(self, obj):
|
||||
def has_changed_materials(self, obj: bpy.types.Object) -> bool:
|
||||
checksum = obj.data.BIMMeshProperties.material_checksum
|
||||
return checksum != str([s.id() for s in tool.Geometry.get_styles(obj) if s])
|
||||
return checksum != tool.Geometry.get_material_checksum(obj)
|
||||
|
||||
def sync_object_placement(self, obj: bpy.types.Object) -> Union[ifcopenshell.entity_instance, None]:
|
||||
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
@@ -163,10 +164,10 @@ class IfcExporter:
|
||||
bpy.ops.bim.update_representation(obj=obj.name)
|
||||
tool.Geometry.record_object_position(obj)
|
||||
|
||||
def get_application_name(self):
|
||||
def get_application_name(self) -> str:
|
||||
return "BlenderBIM"
|
||||
|
||||
def get_application_version(self):
|
||||
def get_application_version(self) -> str:
|
||||
version = ".".join(
|
||||
[
|
||||
str(x)
|
||||
@@ -184,11 +185,13 @@ class IfcExporter:
|
||||
|
||||
class IfcExportSettings:
|
||||
def __init__(self):
|
||||
self.logger = None
|
||||
self.output_file = None
|
||||
self.logger: Logger = None
|
||||
self.output_file: str = None
|
||||
self.json_version: str = None
|
||||
self.json_compact: bool = None
|
||||
|
||||
@staticmethod
|
||||
def factory(context, output_file, logger):
|
||||
def factory(context: bpy.types.Context, output_file: str, logger: Logger) -> IfcExportSettings:
|
||||
settings = IfcExportSettings()
|
||||
settings.output_file = output_file
|
||||
settings.logger = logger
|
||||
|
||||
@@ -20,6 +20,8 @@ import os
|
||||
import bpy
|
||||
import json
|
||||
import addon_utils
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.representation
|
||||
import ifcopenshell.api.owner.settings
|
||||
import blenderbim.bim
|
||||
import blenderbim.tool as tool
|
||||
@@ -51,10 +53,8 @@ def name_callback(obj, data):
|
||||
return
|
||||
|
||||
if isinstance(obj, bpy.types.Material):
|
||||
if obj.BIMObjectProperties.ifc_definition_id:
|
||||
IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id).Name = obj.name
|
||||
if obj.BIMMaterialProperties.ifc_style_id:
|
||||
IfcStore.get_file().by_id(obj.BIMMaterialProperties.ifc_style_id).Name = obj.name
|
||||
if ifc_definition_id := obj.BIMStyleProperties.ifc_definition_id:
|
||||
IfcStore.get_file().by_id(ifc_definition_id).Name = obj.name
|
||||
refresh_ui_data()
|
||||
return
|
||||
|
||||
@@ -86,11 +86,6 @@ def name_callback(obj, data):
|
||||
refresh_ui_data()
|
||||
|
||||
|
||||
def color_callback(obj, data):
|
||||
if obj.BIMMaterialProperties.ifc_style_id:
|
||||
tool.Ifc.edit(obj)
|
||||
|
||||
|
||||
def active_object_callback():
|
||||
refresh_ui_data()
|
||||
update_bim_tool_props()
|
||||
@@ -193,6 +188,8 @@ def refresh_ui_data():
|
||||
tool.Ifc.get().clear_cache()
|
||||
|
||||
bpy.context.scene.DocProperties.should_draw_decorations = bpy.context.scene.DocProperties.should_draw_decorations
|
||||
if bpy.context.scene.WebProperties.is_connected:
|
||||
tool.Web.send_webui_data()
|
||||
|
||||
|
||||
@persistent
|
||||
@@ -223,7 +220,7 @@ def redo_post(scene):
|
||||
tool.Ifc.rebuild_element_maps()
|
||||
|
||||
|
||||
def get_application(ifc):
|
||||
def get_application(ifc: ifcopenshell.file) -> ifcopenshell.entity_instance:
|
||||
# TODO: cache this for even faster application retrieval. It honestly makes a difference on long scripts.
|
||||
version = get_application_version()
|
||||
for element in ifc.by_type("IfcApplication"):
|
||||
@@ -238,7 +235,20 @@ def get_application(ifc):
|
||||
)
|
||||
|
||||
|
||||
def get_application_version():
|
||||
def get_user(ifc: ifcopenshell.file) -> Union[ifcopenshell.entity_instance, None]:
|
||||
# TODO: cache this for even faster application retrieval. It honestly makes a difference on long scripts.
|
||||
if pao := next(iter(ifc.by_type("IfcPersonAndOrganization")), None):
|
||||
return pao
|
||||
elif ifc.schema == "IFC2X3":
|
||||
if (person := next(iter(ifc.by_type("IfcPerson")), None)) is None:
|
||||
person = tool.Ifc.run("owner.add_person")
|
||||
if (organization := next(iter(ifc.by_type("IfcOrganization")), None)) is None:
|
||||
organization = tool.Ifc.run("owner.add_organisation")
|
||||
pao = tool.Ifc.run("owner.add_person_and_organisation", person=person, organisation=organization)
|
||||
return pao
|
||||
|
||||
|
||||
def get_application_version() -> str:
|
||||
return ".".join(
|
||||
[
|
||||
str(x)
|
||||
@@ -279,16 +289,18 @@ def load_post(scene):
|
||||
key=key, owner=global_subscription_owner, args=(area,), notify=viewport_shading_changed_callback
|
||||
)
|
||||
|
||||
ifcopenshell.api.owner.settings.get_user = lambda ifc: core_owner.get_user(tool.Owner)
|
||||
ifcopenshell.api.owner.settings.get_user = get_user
|
||||
ifcopenshell.api.owner.settings.get_application = get_application
|
||||
AuthoringData.type_thumbnails = {}
|
||||
|
||||
if not bpy.context.preferences.addons["blenderbim"].preferences.should_setup_toolbar:
|
||||
preferences = tool.Blender.get_addon_preferences()
|
||||
if not preferences.should_setup_toolbar:
|
||||
tool.Blender.unregister_toolbar()
|
||||
|
||||
if bpy.context.preferences.addons["blenderbim"].preferences.should_setup_workspace:
|
||||
if preferences.should_setup_workspace:
|
||||
if "BIM" in bpy.data.workspaces:
|
||||
bpy.context.window.workspace = bpy.data.workspaces["BIM"]
|
||||
if preferences.activate_workspace:
|
||||
bpy.context.window.workspace = bpy.data.workspaces["BIM"]
|
||||
else:
|
||||
bpy.ops.workspace.append_activate(idname="BIM", filepath=os.path.join(cwd, "data", "workspace.blend"))
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
import bpy
|
||||
import json
|
||||
import math
|
||||
import zipfile
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.attribute
|
||||
import ifcopenshell.util.element
|
||||
@@ -29,7 +28,7 @@ from mathutils import geometry
|
||||
from mathutils import Vector
|
||||
import blenderbim.tool as tool
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from typing import Optional, Callable, Any
|
||||
from typing import Optional, Callable, Any, Union
|
||||
|
||||
|
||||
def draw_attributes(props, layout, copy_operator=None, popup_active_attribute=None):
|
||||
@@ -91,7 +90,11 @@ def import_attributes(ifc_class, props, data, callback=None):
|
||||
|
||||
|
||||
# A more elegant attribute importer signature, intended to supersede import_attributes
|
||||
def import_attributes2(element, props, callback=None):
|
||||
def import_attributes2(
|
||||
element: Union[str, ifcopenshell.entity_instance],
|
||||
props: bpy.types.PropertyGroup,
|
||||
callback: Optional[Callable] = None,
|
||||
) -> None:
|
||||
if isinstance(element, str):
|
||||
attributes = tool.Ifc.schema().declaration_by_name(element).as_entity().all_attributes()
|
||||
info = {a.name(): None for a in attributes}
|
||||
@@ -221,15 +224,6 @@ def get_enum_items(data, prop_name, context=None):
|
||||
return items
|
||||
|
||||
|
||||
# hack to close popup
|
||||
# https://blender.stackexchange.com/a/202576/130742
|
||||
def close_operator_panel(event):
|
||||
x, y = event.mouse_x, event.mouse_y
|
||||
bpy.context.window.cursor_warp(10, 10)
|
||||
move_back = lambda: bpy.context.window.cursor_warp(x, y)
|
||||
bpy.app.timers.register(move_back, first_interval=0.01)
|
||||
|
||||
|
||||
def convert_property_group_from_si(property_group, skip_props=()):
|
||||
"""Method converts property group values from si to current ifc project units
|
||||
|
||||
@@ -309,6 +303,9 @@ def draw_filter(layout, filter_groups, data, module):
|
||||
elif ifc_filter.type == "group":
|
||||
row = box.row(align=True)
|
||||
row.prop(ifc_filter, "value", text="", icon="OUTLINER_COLLECTION")
|
||||
elif ifc_filter.type == "parent":
|
||||
row = box.row(align=True)
|
||||
row.prop(ifc_filter, "value", text="", icon="FILE_PARENT")
|
||||
elif ifc_filter.type == "query":
|
||||
row = box.row(align=True)
|
||||
row.prop(ifc_filter, "name", text="", icon="POINTCLOUD_DATA")
|
||||
@@ -324,50 +321,3 @@ def draw_filter(layout, filter_groups, data, module):
|
||||
op.group_index = i
|
||||
op.index = j
|
||||
op.module = module
|
||||
|
||||
|
||||
# TODO this should move into ifcopenshell.util
|
||||
|
||||
|
||||
class IfcHeaderExtractor:
|
||||
def __init__(self, filepath: str):
|
||||
self.filepath = filepath
|
||||
|
||||
def extract(self):
|
||||
extension = self.filepath.split(".")[-1]
|
||||
if extension.lower() == "ifc":
|
||||
with open(self.filepath) as ifc_file:
|
||||
return self.extract_ifc_spf(ifc_file)
|
||||
elif extension.lower() == "ifczip":
|
||||
return self.extract_ifc_zip()
|
||||
elif extension.lower() == "ifcsqlite":
|
||||
return {} # TODO
|
||||
|
||||
def extract_ifc_spf(self, ifc_file):
|
||||
# https://www.steptools.com/stds/step/IS_final_p21e3.html#clause-8
|
||||
data = {}
|
||||
max_lines_to_parse = 50
|
||||
for _ in range(max_lines_to_parse):
|
||||
line = next(ifc_file)
|
||||
if isinstance(line, bytes):
|
||||
line = line.decode("utf-8")
|
||||
if line.startswith("FILE_DESCRIPTION"):
|
||||
for i, part in enumerate(line.split("'")):
|
||||
if i == 1:
|
||||
data["description"] = part
|
||||
elif i == 3:
|
||||
data["implementation_level"] = part
|
||||
elif line.startswith("FILE_NAME"):
|
||||
for i, part in enumerate(line.split("'")):
|
||||
if i == 1:
|
||||
data["name"] = part
|
||||
elif i == 3:
|
||||
data["time_stamp"] = part
|
||||
elif line.startswith("FILE_SCHEMA"):
|
||||
data["schema_name"] = line.split("'")[1]
|
||||
break
|
||||
return data
|
||||
|
||||
def extract_ifc_zip(self):
|
||||
archive = zipfile.ZipFile(self.filepath, "r")
|
||||
return self.extract_ifc_spf(archive.open(archive.filelist[0]))
|
||||
|
||||
@@ -19,42 +19,62 @@
|
||||
import os
|
||||
import bpy
|
||||
import uuid
|
||||
import shutil
|
||||
import hashlib
|
||||
import zipfile
|
||||
import tempfile
|
||||
import traceback
|
||||
import ifcopenshell
|
||||
import ifcopenshell.geom
|
||||
import ifcopenshell.ifcopenshell_wrapper
|
||||
import blenderbim
|
||||
import blenderbim.bim.handler
|
||||
import blenderbim.tool as tool
|
||||
from pathlib import Path
|
||||
from blenderbim.tool.brick import BrickStore
|
||||
from typing import Set, Union, Optional
|
||||
from typing import Set, Union, Optional, TypedDict, Callable
|
||||
|
||||
|
||||
IFC_CONNECTED_TYPE = Union[bpy.types.Material, bpy.types.Object]
|
||||
|
||||
|
||||
class OperationData(TypedDict):
|
||||
id: int
|
||||
guid: Union[str, None]
|
||||
obj: str
|
||||
|
||||
|
||||
class Operation(TypedDict):
|
||||
rollback: Callable
|
||||
commit: Callable
|
||||
data: OperationData
|
||||
|
||||
|
||||
class TransactionStep(TypedDict):
|
||||
key: str
|
||||
operations: list[Operation]
|
||||
|
||||
|
||||
class IfcStore:
|
||||
path: str = ""
|
||||
file: ifcopenshell.file = None
|
||||
schema: ifcopenshell.ifcopenshell_wrapper.schema_definition = None
|
||||
cache: ifcopenshell.ifcopenshell_wrapper.HdfSerializer = None
|
||||
cache_path: str = None
|
||||
file: Optional[ifcopenshell.file] = None
|
||||
schema: Optional[ifcopenshell.ifcopenshell_wrapper.schema_definition] = None
|
||||
cache: Optional[ifcopenshell.ifcopenshell_wrapper.HdfSerializer] = None
|
||||
cache_path: Optional[str] = None
|
||||
id_map: dict[int, IFC_CONNECTED_TYPE] = {}
|
||||
guid_map: dict[str, IFC_CONNECTED_TYPE] = {}
|
||||
edited_objs: Set[bpy.types.Object] = set()
|
||||
pset_template_path: str = ""
|
||||
pset_template_file: ifcopenshell.file = None
|
||||
pset_template_file: Optional[ifcopenshell.file] = None
|
||||
classification_path: str = ""
|
||||
classification_file: ifcopenshell.file = None
|
||||
classification_file: Optional[ifcopenshell.file] = None
|
||||
library_path: str = ""
|
||||
library_file: ifcopenshell.file = None
|
||||
library_file: Optional[ifcopenshell.file] = None
|
||||
current_transaction = ""
|
||||
last_transaction = ""
|
||||
history = []
|
||||
future = []
|
||||
schema_identifiers = ["IFC4", "IFC2X3", "IFC4X3"]
|
||||
history: list[TransactionStep] = []
|
||||
future: list[TransactionStep] = []
|
||||
schema_identifiers = ["IFC4", "IFC2X3", "IFC4X3_ADD2"]
|
||||
session_files: dict[str, ifcopenshell.file] = {}
|
||||
|
||||
@staticmethod
|
||||
@@ -74,7 +94,7 @@ class IfcStore:
|
||||
IfcStore.last_transaction = ""
|
||||
IfcStore.history = []
|
||||
IfcStore.future = []
|
||||
IfcStore.schema_identifiers = ["IFC4", "IFC2X3", "IFC4X3"]
|
||||
IfcStore.schema_identifiers = ["IFC4", "IFC2X3", "IFC4X3_ADD2"]
|
||||
IfcStore.session_files = {}
|
||||
|
||||
@staticmethod
|
||||
@@ -97,7 +117,6 @@ class IfcStore:
|
||||
ifc_hash = hashlib.md5(ifc_key.encode("utf-8")).hexdigest()
|
||||
IfcStore.cache_path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "cache", f"{ifc_hash}.h5")
|
||||
cache_settings = ifcopenshell.geom.settings()
|
||||
cache_settings.set(cache_settings.STRICT_TOLERANCE, True)
|
||||
try:
|
||||
IfcStore.cache = ifcopenshell.geom.serializers.hdf5(IfcStore.cache_path, cache_settings)
|
||||
except:
|
||||
@@ -119,7 +138,13 @@ class IfcStore:
|
||||
ifc_hash = hashlib.md5(ifc_key.encode("utf-8")).hexdigest()
|
||||
new_cache_path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "cache", f"{ifc_hash}.h5")
|
||||
IfcStore.cache = None
|
||||
os.replace(IfcStore.cache_path, new_cache_path)
|
||||
try:
|
||||
shutil.move(IfcStore.cache_path, new_cache_path)
|
||||
except PermissionError:
|
||||
try:
|
||||
shutil.copy2(IfcStore.cache_path, new_cache_path)
|
||||
except PermissionError:
|
||||
pass # Well we tried. No cache for you!
|
||||
IfcStore.get_cache()
|
||||
|
||||
@staticmethod
|
||||
@@ -142,7 +167,7 @@ class IfcStore:
|
||||
IfcStore.file = ifcopenshell.open(path)
|
||||
|
||||
@staticmethod
|
||||
def get_schema():
|
||||
def get_schema() -> ifcopenshell.ifcopenshell_wrapper.schema_definition:
|
||||
if IfcStore.file is None:
|
||||
IfcStore.schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(
|
||||
bpy.context.scene.BIMProjectProperties.export_schema
|
||||
@@ -154,14 +179,13 @@ class IfcStore:
|
||||
@staticmethod
|
||||
def get_element(id_or_guid: Union[int, str]) -> IFC_CONNECTED_TYPE:
|
||||
if isinstance(id_or_guid, int):
|
||||
map_object = IfcStore.id_map
|
||||
obj = IfcStore.id_map.get(id_or_guid)
|
||||
else:
|
||||
map_object = IfcStore.guid_map
|
||||
try:
|
||||
obj = map_object[id_or_guid]
|
||||
obj.name # In case the object has been deleted, this triggers an exception
|
||||
except:
|
||||
return
|
||||
obj = IfcStore.guid_map.get(id_or_guid)
|
||||
if obj is None:
|
||||
return None
|
||||
if not tool.Blender.is_valid_data_block(obj):
|
||||
return None
|
||||
return obj
|
||||
|
||||
@staticmethod
|
||||
@@ -181,21 +205,26 @@ class IfcStore:
|
||||
def relink_object(obj: IFC_CONNECTED_TYPE) -> None:
|
||||
if not obj:
|
||||
return
|
||||
if obj.BIMObjectProperties.ifc_definition_id:
|
||||
try:
|
||||
element = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
except:
|
||||
if isinstance(obj, bpy.types.Object):
|
||||
ifc_definition_id = obj.BIMObjectProperties.ifc_definition_id
|
||||
if not ifc_definition_id:
|
||||
return
|
||||
data = {"id": element.id(), "obj": obj.name}
|
||||
try:
|
||||
element = IfcStore.get_file().by_id(ifc_definition_id)
|
||||
except RuntimeError:
|
||||
return
|
||||
data = OperationData(id=element.id(), obj=obj.name)
|
||||
if hasattr(element, "GlobalId"):
|
||||
data["guid"] = element.GlobalId
|
||||
IfcStore.commit_link_element(data)
|
||||
if hasattr(obj, "BIMMaterialProperties") and obj.BIMMaterialProperties.ifc_style_id:
|
||||
return
|
||||
else: # bpy.types.Material
|
||||
ifc_definition_id = obj.BIMStyleProperties.ifc_definition_id
|
||||
try:
|
||||
element = IfcStore.get_file().by_id(obj.BIMMaterialProperties.ifc_style_id)
|
||||
except:
|
||||
element = IfcStore.get_file().by_id(ifc_definition_id)
|
||||
except RuntimeError:
|
||||
return
|
||||
data = {"id": element.id(), "obj": obj.name}
|
||||
data = OperationData(id=element.id(), obj=obj.name)
|
||||
IfcStore.commit_link_element(data)
|
||||
|
||||
@staticmethod
|
||||
@@ -210,44 +239,40 @@ class IfcStore:
|
||||
existing_obj = IfcStore.id_map.get(element.id(), None)
|
||||
if existing_obj == obj:
|
||||
return
|
||||
elif existing_obj:
|
||||
try:
|
||||
existing_obj.name
|
||||
IfcStore.unlink_element(obj=existing_obj)
|
||||
except:
|
||||
pass
|
||||
# TODO: When does this occur?
|
||||
elif existing_obj and tool.Blender.is_valid_data_block(existing_obj):
|
||||
IfcStore.unlink_element(obj=existing_obj)
|
||||
|
||||
IfcStore.id_map[element.id()] = obj
|
||||
if hasattr(element, "GlobalId"):
|
||||
IfcStore.guid_map[element.GlobalId] = obj
|
||||
|
||||
if element.is_a("IfcSurfaceStyle"):
|
||||
obj.BIMMaterialProperties.ifc_style_id = element.id()
|
||||
obj.BIMStyleProperties.ifc_definition_id = element.id()
|
||||
else:
|
||||
obj.BIMObjectProperties.ifc_definition_id = element.id()
|
||||
|
||||
blenderbim.bim.handler.subscribe_to(obj, "name", blenderbim.bim.handler.name_callback)
|
||||
|
||||
if isinstance(obj, bpy.types.Material):
|
||||
blenderbim.bim.handler.subscribe_to(obj, "diffuse_color", blenderbim.bim.handler.color_callback)
|
||||
elif isinstance(obj, bpy.types.Object):
|
||||
if isinstance(obj, bpy.types.Object):
|
||||
blenderbim.bim.handler.subscribe_to(
|
||||
obj, "active_material_index", blenderbim.bim.handler.active_material_index_callback
|
||||
)
|
||||
|
||||
if IfcStore.history:
|
||||
data = {"id": element.id(), "guid": getattr(element, "GlobalId", None), "obj": obj.name}
|
||||
data = OperationData(id=element.id(), guid=getattr(element, "GlobalId", None), obj=obj.name)
|
||||
IfcStore.history[-1]["operations"].append(
|
||||
{"rollback": IfcStore.rollback_link_element, "commit": IfcStore.commit_link_element, "data": data}
|
||||
Operation(rollback=IfcStore.rollback_link_element, commit=IfcStore.commit_link_element, data=data)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def rollback_link_element(data):
|
||||
def rollback_link_element(data: OperationData) -> None:
|
||||
del IfcStore.id_map[data["id"]]
|
||||
if data["guid"]:
|
||||
del IfcStore.guid_map[data["guid"]]
|
||||
|
||||
@staticmethod
|
||||
def commit_link_element(data):
|
||||
def commit_link_element(data: OperationData) -> None:
|
||||
obj = bpy.data.objects.get(data["obj"])
|
||||
if not obj:
|
||||
obj = bpy.data.materials.get(data["obj"])
|
||||
@@ -255,9 +280,7 @@ class IfcStore:
|
||||
if "guid" in data:
|
||||
IfcStore.guid_map[data["guid"]] = obj
|
||||
blenderbim.bim.handler.subscribe_to(obj, "name", blenderbim.bim.handler.name_callback)
|
||||
if isinstance(obj, bpy.types.Material):
|
||||
blenderbim.bim.handler.subscribe_to(obj, "diffuse_color", blenderbim.bim.handler.color_callback)
|
||||
elif isinstance(obj, bpy.types.Object):
|
||||
if isinstance(obj, bpy.types.Object):
|
||||
blenderbim.bim.handler.subscribe_to(
|
||||
obj, "active_material_index", blenderbim.bim.handler.active_material_index_callback
|
||||
)
|
||||
@@ -265,7 +288,7 @@ class IfcStore:
|
||||
# TODO We're handling id_map and guid_map, but what about edited_objs? This might cause big problems.
|
||||
|
||||
@staticmethod
|
||||
def rollback_unlink_element(data) -> None:
|
||||
def rollback_unlink_element(data: OperationData) -> None:
|
||||
if "id" not in data or "obj" not in data:
|
||||
return
|
||||
obj = bpy.data.objects.get(data["obj"])
|
||||
@@ -274,7 +297,7 @@ class IfcStore:
|
||||
IfcStore.guid_map[data["guid"]] = obj
|
||||
|
||||
@staticmethod
|
||||
def commit_unlink_element(data) -> None:
|
||||
def commit_unlink_element(data: OperationData) -> None:
|
||||
del IfcStore.id_map[data["id"]]
|
||||
if data["guid"]:
|
||||
del IfcStore.guid_map[data["guid"]]
|
||||
@@ -283,52 +306,65 @@ class IfcStore:
|
||||
def unlink_element(
|
||||
element: Optional[ifcopenshell.entity_instance] = None, obj: Optional[IFC_CONNECTED_TYPE] = None
|
||||
) -> None:
|
||||
if element is None:
|
||||
try:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
except:
|
||||
pass
|
||||
"""Unlink IFC `element` or Blender `obj`.
|
||||
|
||||
If element is provided then it will be unlinked from the related Blender object.
|
||||
Blender object's IFC information is also will be purged.
|
||||
|
||||
If Blender object is provided then all IFC information will be purged from this object.
|
||||
Method won't be searching for related IFC elements as Blender object might come from
|
||||
different Blender session and there might be an ids/guids clash.
|
||||
|
||||
Only one argument must be provided and other should be omitted as they have different meaning.
|
||||
:raises TypeError: If both arguments or no arguments provided.
|
||||
|
||||
"""
|
||||
if not bool(element) ^ bool(obj):
|
||||
raise TypeError("Only one argument must be provided - element or obj.")
|
||||
|
||||
if obj:
|
||||
IfcStore.purge_blender_ifc_data(obj)
|
||||
return
|
||||
|
||||
assert element # Type checker.
|
||||
if obj is None:
|
||||
try:
|
||||
potential_obj = IfcStore.id_map[element.id()]
|
||||
potential_obj.name
|
||||
obj = potential_obj
|
||||
if tool.Blender.is_valid_data_block(potential_obj):
|
||||
obj = potential_obj
|
||||
IfcStore.purge_blender_ifc_data(obj)
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if element:
|
||||
del IfcStore.id_map[element.id()]
|
||||
else:
|
||||
del IfcStore.id_map[obj.BIMObjectProperties.ifc_definition_id]
|
||||
del IfcStore.id_map[element.id()]
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if element and hasattr(element, "GlobalId"):
|
||||
del IfcStore.guid_map[element.GlobalId]
|
||||
except:
|
||||
pass
|
||||
|
||||
if element and element.is_a("IfcSurfaceStyle"):
|
||||
obj.BIMMaterialProperties.ifc_style_id = 0
|
||||
elif obj:
|
||||
obj.BIMObjectProperties.ifc_definition_id = 0
|
||||
if global_id := getattr(element, "GlobalId", None):
|
||||
try:
|
||||
del IfcStore.guid_map[global_id]
|
||||
except:
|
||||
pass
|
||||
|
||||
if IfcStore.history:
|
||||
data = {}
|
||||
if element:
|
||||
data["id"] = element.id()
|
||||
data["guid"] = getattr(element, "GlobalId", None)
|
||||
data = OperationData(id=element.id(), guid=global_id)
|
||||
if obj:
|
||||
data["obj"] = obj.name
|
||||
IfcStore.history[-1]["operations"].append(
|
||||
{"rollback": IfcStore.rollback_unlink_element, "commit": IfcStore.commit_unlink_element, "data": data}
|
||||
Operation(rollback=IfcStore.rollback_unlink_element, commit=IfcStore.commit_unlink_element, data=data)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def purge_blender_ifc_data(obj: IFC_CONNECTED_TYPE) -> None:
|
||||
if isinstance(obj, bpy.types.Material):
|
||||
obj.BIMStyleProperties.ifc_definition_id = 0
|
||||
else: # bpy.types.Object
|
||||
obj.BIMObjectProperties.ifc_definition_id = 0
|
||||
|
||||
@staticmethod
|
||||
def execute_ifc_operator(operator: bpy.types.Operator, context: bpy.types.Context, is_invoke=False):
|
||||
blenderbim.last_actions.append({"type": "operator", "name": operator.bl_idname})
|
||||
bpy.context.scene.BIMProperties.is_dirty = True
|
||||
is_top_level_operator = not bool(IfcStore.current_transaction)
|
||||
|
||||
@@ -343,10 +379,14 @@ class IfcStore:
|
||||
else:
|
||||
operator.transaction_key = IfcStore.current_transaction
|
||||
|
||||
if is_invoke:
|
||||
result = getattr(operator, "_invoke")(context, None)
|
||||
else:
|
||||
result = getattr(operator, "_execute")(context)
|
||||
try:
|
||||
if is_invoke:
|
||||
result = getattr(operator, "_invoke")(context, None)
|
||||
else:
|
||||
result = getattr(operator, "_execute")(context)
|
||||
except:
|
||||
blenderbim.last_error = traceback.format_exc()
|
||||
raise
|
||||
|
||||
if is_top_level_operator:
|
||||
if tool.Ifc.get():
|
||||
@@ -380,15 +420,15 @@ class IfcStore:
|
||||
rollback = rollback or getattr(operator, "rollback", lambda data: True)
|
||||
commit = commit or getattr(operator, "commit", lambda data: True)
|
||||
if IfcStore.history and IfcStore.history[-1]["key"] == key:
|
||||
IfcStore.history[-1]["operations"].append({"rollback": rollback, "commit": commit, "data": data})
|
||||
IfcStore.history[-1]["operations"].append(OperationData(rollback=rollback, commit=commit, data=data))
|
||||
else:
|
||||
IfcStore.history.append(
|
||||
{"key": key, "operations": [{"rollback": rollback, "commit": commit, "data": data}]}
|
||||
TransactionStep(key=key, operations=[OperationData(rollback=rollback, commit=commit, data=data)])
|
||||
)
|
||||
IfcStore.future = []
|
||||
|
||||
@staticmethod
|
||||
def undo(until_key=None) -> None:
|
||||
def undo(until_key: str = None) -> None:
|
||||
BrickStore.undo()
|
||||
if not IfcStore.history:
|
||||
return
|
||||
@@ -403,7 +443,7 @@ class IfcStore:
|
||||
IfcStore.future.append(event)
|
||||
|
||||
@staticmethod
|
||||
def redo(until_key=None) -> None:
|
||||
def redo(until_key: str = None) -> None:
|
||||
BrickStore.redo()
|
||||
|
||||
if not IfcStore.future:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,7 +36,6 @@ class AggregateData:
|
||||
"relating_object_label": cls.get_relating_object_label(),
|
||||
"has_related_objects": cls.has_related_objects(),
|
||||
"total_parts": cls.total_parts(),
|
||||
"ifc_class": cls.ifc_class(),
|
||||
"total_linked_aggregate": cls.total_linked_aggregate(),
|
||||
}
|
||||
cls.is_loaded = True
|
||||
@@ -68,12 +67,6 @@ class AggregateData:
|
||||
def has_related_objects(cls) -> bool:
|
||||
return bool(cls.get_related_objects())
|
||||
|
||||
@classmethod
|
||||
def ifc_class(cls) -> str:
|
||||
element = tool.Ifc.get_entity(bpy.context.active_object)
|
||||
if element:
|
||||
return element.is_a()
|
||||
|
||||
@classmethod
|
||||
def total_linked_aggregate(cls):
|
||||
element = tool.Ifc.get_entity(bpy.context.active_object)
|
||||
|
||||
@@ -26,53 +26,49 @@ import blenderbim.bim.handler
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
class Operator:
|
||||
def execute(self, context):
|
||||
IfcStore.execute_ifc_operator(self, context)
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class BIM_OT_aggregate_assign_object(bpy.types.Operator, Operator):
|
||||
class BIM_OT_aggregate_assign_object(bpy.types.Operator, tool.Ifc.Operator):
|
||||
"""Create aggregation relationship between two ifc elements"""
|
||||
|
||||
bl_idname = "bim.aggregate_assign_object"
|
||||
bl_label = "Assign Object To Aggregation"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
relating_object: bpy.props.IntProperty()
|
||||
related_object: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
relating_obj = None
|
||||
if self.relating_object:
|
||||
element = tool.Ifc.get().by_id(self.relating_object)
|
||||
if element.IsDecomposedBy:
|
||||
relating_obj = tool.Ifc.get_object(element)
|
||||
else:
|
||||
assembly = element.Decomposes[0].RelatingObject
|
||||
relating_obj = tool.Ifc.get_object(assembly)
|
||||
relating_obj = tool.Ifc.get_object(tool.Ifc.get().by_id(self.relating_object))
|
||||
elif self.related_object:
|
||||
aggregate = ifcopenshell.util.element.get_aggregate(tool.Ifc.get().by_id(self.related_object))
|
||||
if aggregate:
|
||||
relating_obj = tool.Ifc.get_object(aggregate)
|
||||
elif context.active_object:
|
||||
relating_obj = context.active_object
|
||||
if not relating_obj:
|
||||
return
|
||||
|
||||
for obj in bpy.context.selected_objects:
|
||||
for obj in tool.Blender.get_selected_objects():
|
||||
if obj == relating_obj:
|
||||
continue
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
continue
|
||||
result = core.assign_object(
|
||||
tool.Ifc,
|
||||
tool.Aggregate,
|
||||
tool.Collector,
|
||||
relating_obj=relating_obj,
|
||||
related_obj=obj,
|
||||
)
|
||||
if not result:
|
||||
self.report({"ERROR"}, f" Cannot aggregate {obj.name} to {relating_obj.name}")
|
||||
try:
|
||||
core.assign_object(
|
||||
tool.Ifc,
|
||||
tool.Aggregate,
|
||||
tool.Collector,
|
||||
relating_obj=relating_obj,
|
||||
related_obj=obj,
|
||||
)
|
||||
except core.IncompatibleAggregateError:
|
||||
self.report({"ERROR"}, f"Cannot aggregate {obj.name} to {relating_obj.name}")
|
||||
except core.AggregateRepresentationError:
|
||||
self.report({"ERROR"}, f"Cannot aggregate to {relating_obj.name} with a body representation")
|
||||
|
||||
|
||||
class BIM_OT_aggregate_unassign_object(bpy.types.Operator, Operator):
|
||||
class BIM_OT_aggregate_unassign_object(bpy.types.Operator, tool.Ifc.Operator):
|
||||
"""Remove aggregation relationship between two ifc elements"""
|
||||
|
||||
bl_idname = "bim.aggregate_unassign_object"
|
||||
@@ -96,13 +92,14 @@ class BIM_OT_aggregate_unassign_object(bpy.types.Operator, Operator):
|
||||
)
|
||||
|
||||
# Removes Pset related to Linked Aggregates
|
||||
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Linked_Aggregate")
|
||||
if pset:
|
||||
pset = tool.Ifc.get().by_id(pset["id"])
|
||||
ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), pset=pset)
|
||||
if not element.is_a("IfcElementAssembly"):
|
||||
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Linked_Aggregate")
|
||||
if pset:
|
||||
pset = tool.Ifc.get().by_id(pset["id"])
|
||||
ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), product=element, pset=pset)
|
||||
|
||||
|
||||
class BIM_OT_enable_editing_aggregate(bpy.types.Operator, Operator):
|
||||
class BIM_OT_enable_editing_aggregate(bpy.types.Operator, tool.Ifc.Operator):
|
||||
"""Enable editing aggregation relationship"""
|
||||
|
||||
bl_idname = "bim.enable_editing_aggregate"
|
||||
@@ -113,7 +110,7 @@ class BIM_OT_enable_editing_aggregate(bpy.types.Operator, Operator):
|
||||
core.enable_editing_aggregate(tool.Aggregate, obj=context.active_object)
|
||||
|
||||
|
||||
class BIM_OT_disable_editing_aggregate(bpy.types.Operator, Operator):
|
||||
class BIM_OT_disable_editing_aggregate(bpy.types.Operator, tool.Ifc.Operator):
|
||||
"""Disable editing aggregation relationship"""
|
||||
|
||||
bl_idname = "bim.disable_editing_aggregate"
|
||||
@@ -132,6 +129,7 @@ class BIM_OT_add_aggregate(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj: bpy.props.StringProperty()
|
||||
ifc_class: bpy.props.StringProperty(name="IFC Class", default="IfcElementAssembly")
|
||||
aggregate_name: bpy.props.StringProperty(name="Name", default="Default_Name")
|
||||
|
||||
def invoke(self, context, event):
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
@@ -139,20 +137,21 @@ class BIM_OT_add_aggregate(bpy.types.Operator, tool.Ifc.Operator):
|
||||
def draw(self, context):
|
||||
row = self.layout
|
||||
row.prop(self, "ifc_class")
|
||||
row = self.layout
|
||||
row.prop(self, "aggregate_name")
|
||||
|
||||
def _execute(self, context):
|
||||
try:
|
||||
ifc_class = tool.Ifc.schema().declaration_by_name(self.ifc_class).name()
|
||||
except:
|
||||
return
|
||||
aggregate = self.create_aggregate(context, ifc_class)
|
||||
aggregate = self.create_aggregate(context, ifc_class, self.aggregate_name)
|
||||
|
||||
for obj in context.selected_objects:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
continue
|
||||
|
||||
tool.Collector.sync(obj)
|
||||
current_aggregate = ifcopenshell.util.element.get_aggregate(element)
|
||||
current_container = ifcopenshell.util.element.get_container(element)
|
||||
if current_aggregate:
|
||||
@@ -173,8 +172,8 @@ class BIM_OT_add_aggregate(bpy.types.Operator, tool.Ifc.Operator):
|
||||
)
|
||||
core.assign_object(tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=aggregate, related_obj=obj)
|
||||
|
||||
def create_aggregate(self, context, ifc_class):
|
||||
aggregate = bpy.data.objects.new("Assembly", None)
|
||||
def create_aggregate(self, context, ifc_class, aggregate_name):
|
||||
aggregate = bpy.data.objects.new(aggregate_name, None)
|
||||
aggregate.location = context.scene.cursor.location
|
||||
bpy.ops.bim.assign_class(obj=aggregate.name, ifc_class=ifc_class)
|
||||
return aggregate
|
||||
@@ -226,7 +225,7 @@ class BIM_OT_select_aggregate(bpy.types.Operator):
|
||||
# obj = bpy.data.objects.get(self.obj) or context.active_object
|
||||
# aggregate = ifcopenshell.util.element.get_aggregate(tool.Ifc.get_entity(obj))
|
||||
# aggregate_obj = tool.Ifc.get_object(aggregate)
|
||||
|
||||
|
||||
all_parts = []
|
||||
for obj in context.selected_objects:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
@@ -239,7 +238,7 @@ class BIM_OT_select_aggregate(bpy.types.Operator):
|
||||
pass
|
||||
if not element:
|
||||
obj.select_set(False)
|
||||
|
||||
|
||||
if self.select_parts:
|
||||
all_objs = []
|
||||
for part in all_parts:
|
||||
@@ -257,37 +256,37 @@ class BIM_OT_select_aggregate(bpy.types.Operator):
|
||||
for aggregate_element in all_parts:
|
||||
aggregate_obj = tool.Ifc.get_object(aggregate_element)
|
||||
aggregate_obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = aggregate_obj
|
||||
bpy.context.view_layer.objects.active = aggregate_obj
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class BIM_OT_add_part_to_object(bpy.types.Operator, Operator):
|
||||
class BIM_OT_add_part_to_object(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_part_to_object"
|
||||
bl_label = "Add Part to Object"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
part_class: bpy.props.StringProperty(name="Class", options={"HIDDEN"})
|
||||
part_name: bpy.props.StringProperty(name="Name")
|
||||
obj: bpy.props.StringProperty(options={"HIDDEN"})
|
||||
element: bpy.props.IntProperty(options={"HIDDEN"})
|
||||
|
||||
def invoke(self, context, event):
|
||||
self.part_name = "My " + self.part_class.lstrip("Ifc")
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
def _execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) or context.active_object
|
||||
core.add_part_to_object(
|
||||
tool.Ifc,
|
||||
tool.Aggregate,
|
||||
tool.Collector,
|
||||
tool.Blender,
|
||||
obj=obj,
|
||||
obj=tool.Ifc.get_object(tool.Ifc.get().by_id(self.element)) if self.element else context.active_object,
|
||||
part_class=self.part_class,
|
||||
part_name=self.part_name,
|
||||
)
|
||||
blenderbim.core.spatial.import_spatial_decomposition(tool.Spatial)
|
||||
|
||||
|
||||
class BIM_OT_break_link_to_other_aggregates(bpy.types.Operator, Operator):
|
||||
class BIM_OT_break_link_to_other_aggregates(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.break_link_to_other_aggregates"
|
||||
bl_label = "Break link to other aggregates"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -318,7 +317,7 @@ class BIM_OT_break_link_to_other_aggregates(bpy.types.Operator, Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class BIM_OT_select_linked_aggregates(bpy.types.Operator, Operator):
|
||||
class BIM_OT_select_linked_aggregates(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.select_linked_aggregates"
|
||||
bl_label = "Select linked aggregates"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -332,7 +331,7 @@ class BIM_OT_select_linked_aggregates(bpy.types.Operator, Operator):
|
||||
return "Select all aggregates"
|
||||
|
||||
def _execute(self, context):
|
||||
|
||||
|
||||
for obj in context.selected_objects:
|
||||
obj.select_set(False)
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
|
||||
@@ -34,15 +34,27 @@ from bpy.props import (
|
||||
|
||||
def update_relating_object(self, context):
|
||||
def message(self, context):
|
||||
self.layout.label(text="Please select a valid Ifc Element")
|
||||
self.layout.label(text="Please select a valid IFC Element")
|
||||
|
||||
if self.relating_object is None:
|
||||
return
|
||||
if not self.relating_object.BIMObjectProperties.ifc_definition_id:
|
||||
context.window_manager.popup_menu(message, title="Invalid Element Selected", icon="INFO")
|
||||
if self.relating_object:
|
||||
self.related_object = None
|
||||
if not self.relating_object.BIMObjectProperties.ifc_definition_id:
|
||||
context.window_manager.popup_menu(message, title="Invalid Element Selected", icon="INFO")
|
||||
self.relating_object = None
|
||||
|
||||
|
||||
def update_related_object(self, context):
|
||||
def message(self, context):
|
||||
self.layout.label(text="Please select a valid IFC Element")
|
||||
|
||||
if self.related_object:
|
||||
self.relating_object = None
|
||||
if not self.related_object.BIMObjectProperties.ifc_definition_id:
|
||||
context.window_manager.popup_menu(message, title="Invalid Element Selected", icon="INFO")
|
||||
self.related_object = None
|
||||
|
||||
|
||||
class BIMObjectAggregateProperties(PropertyGroup):
|
||||
is_editing: BoolProperty(name="Is Editing")
|
||||
relating_object: PointerProperty(name="Aggregate", type=bpy.types.Object, update=update_relating_object)
|
||||
relating_object: PointerProperty(name="Relating Whole", type=bpy.types.Object, update=update_relating_object)
|
||||
related_object: PointerProperty(name="Related Part", type=bpy.types.Object, update=update_related_object)
|
||||
|
||||
@@ -20,6 +20,7 @@ from bpy.types import Panel
|
||||
from blenderbim.bim.module.aggregate.data import AggregateData
|
||||
from blenderbim.bim.module.group.data import GroupsData, ObjectGroupsData
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
import blenderbim.tool as tool
|
||||
|
||||
|
||||
class BIM_PT_aggregate(Panel):
|
||||
@@ -52,12 +53,21 @@ class BIM_PT_aggregate(Panel):
|
||||
props = context.active_object.BIMObjectAggregateProperties
|
||||
|
||||
if props.is_editing:
|
||||
row = layout.row()
|
||||
row.prop(props, "relating_object", text="Whole")
|
||||
row = layout.row()
|
||||
row.prop(props, "related_object", text="Or Part")
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "relating_object", text="")
|
||||
col = row.column(align=True)
|
||||
if not props.relating_object and not props.related_object:
|
||||
col.enabled = False
|
||||
op = col.operator("bim.aggregate_assign_object", icon="CHECKMARK")
|
||||
if props.relating_object:
|
||||
op = row.operator("bim.aggregate_assign_object", icon="CHECKMARK", text="")
|
||||
op.relating_object = props.relating_object.BIMObjectProperties.ifc_definition_id
|
||||
elif props.related_object:
|
||||
op.related_object = props.related_object.BIMObjectProperties.ifc_definition_id
|
||||
row.operator("bim.disable_editing_aggregate", icon="CANCEL", text="")
|
||||
return
|
||||
else:
|
||||
row = layout.row(align=True)
|
||||
if AggregateData.data["has_relating_object"]:
|
||||
@@ -72,7 +82,7 @@ class BIM_PT_aggregate(Panel):
|
||||
row.operator("bim.add_aggregate", icon="ADD", text="")
|
||||
op = row.operator("bim.aggregate_unassign_object", icon="X", text="")
|
||||
else:
|
||||
row.label(text="No Aggregate", icon="TRIA_UP")
|
||||
row.label(text="No Whole Relationship Found", icon="TRIA_UP")
|
||||
row.operator("bim.enable_editing_aggregate", icon="GREASEPENCIL", text="")
|
||||
row.operator("bim.add_aggregate", icon="ADD", text="")
|
||||
|
||||
@@ -89,19 +99,6 @@ class BIM_PT_aggregate(Panel):
|
||||
op = row.operator("bim.select_parts", icon="RESTRICT_SELECT_OFF", text="")
|
||||
op.obj = context.active_object.name
|
||||
|
||||
ifc_class = AggregateData.data["ifc_class"]
|
||||
part_class = ""
|
||||
if ifc_class == "IfcBuilding":
|
||||
part_class = "IfcBuildingStorey"
|
||||
elif ifc_class == "IfcSite":
|
||||
part_class = "IfcBuilding"
|
||||
elif ifc_class == "IfcProject":
|
||||
part_class = "IfcSite"
|
||||
if part_class != "":
|
||||
op = layout.operator("bim.add_part_to_object", text="Add " + part_class.lstrip("Ifc"))
|
||||
op.part_class = part_class
|
||||
op.obj = context.active_object.name
|
||||
|
||||
|
||||
class BIM_PT_linked_aggregate(Panel):
|
||||
bl_label = "Linked Aggregates"
|
||||
@@ -131,22 +128,29 @@ class BIM_PT_linked_aggregate(Panel):
|
||||
if not AggregateData.is_loaded:
|
||||
AggregateData.load()
|
||||
|
||||
props = context.active_object.BIMObjectAggregateProperties
|
||||
obj = context.active_object
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
props = obj.BIMObjectAggregateProperties
|
||||
row = layout.row(align=True)
|
||||
row.label(text="Advanced Users Only", icon="ERROR")
|
||||
row = layout.row(align=True)
|
||||
|
||||
if type(AggregateData.data['total_linked_aggregate']) is int:
|
||||
if AggregateData.data['total_linked_aggregate'] > 0:
|
||||
row.label(text=f"{AggregateData.data['total_linked_aggregate']} Linked Aggregates")
|
||||
op = row.operator("bim.select_linked_aggregates", text="", icon="OUTLINER_DATA_POINTCLOUD")
|
||||
op.select_parts = False
|
||||
op = row.operator("bim.select_linked_aggregates", text="", icon="OUTLINER_OB_POINTCLOUD")
|
||||
op.select_parts = True
|
||||
row.operator("bim.refresh_linked_aggregate", text="", icon="FILE_REFRESH")
|
||||
op = row.operator("bim.break_link_to_other_aggregates", text="", icon="X")
|
||||
|
||||
|
||||
if element.Decomposes:
|
||||
Number_Linked_Aggregates = AggregateData.data['total_linked_aggregate']
|
||||
if not Number_Linked_Aggregates:
|
||||
row.label(text="Not a Linked Aggregate")
|
||||
else:
|
||||
row.label(text=f"{Number_Linked_Aggregates} Linked Aggregates")
|
||||
op = row.operator("bim.duplicate_linked_aggregate_to_3d_cursor", text="", icon="DUPLICATE")
|
||||
if type(Number_Linked_Aggregates) is int:
|
||||
if Number_Linked_Aggregates > 0:
|
||||
op = row.operator("bim.select_linked_aggregates", text="", icon="OUTLINER_DATA_POINTCLOUD")
|
||||
op.select_parts = False
|
||||
op = row.operator("bim.select_linked_aggregates", text="", icon="OUTLINER_OB_POINTCLOUD")
|
||||
op.select_parts = True
|
||||
row.operator("bim.refresh_linked_aggregate", text="", icon="FILE_REFRESH")
|
||||
op = row.operator("bim.break_link_to_other_aggregates", text="", icon="X")
|
||||
else:
|
||||
row.label(text="No Linked Aggregates")
|
||||
row.label(text="Not an Aggregate")
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -27,15 +27,12 @@ classes = (
|
||||
operator.CopyAttributeToSelection,
|
||||
prop.BIMAttributeProperties,
|
||||
ui.BIM_PT_object_attributes,
|
||||
ui.BIM_PT_material_attributes,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
bpy.types.Object.BIMAttributeProperties = bpy.props.PointerProperty(type=prop.BIMAttributeProperties)
|
||||
bpy.types.Material.BIMAttributeProperties = bpy.props.PointerProperty(type=prop.BIMAttributeProperties)
|
||||
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Object.BIMAttributeProperties
|
||||
del bpy.types.Material.BIMAttributeProperties
|
||||
|
||||
@@ -23,7 +23,6 @@ import blenderbim.tool as tool
|
||||
|
||||
def refresh():
|
||||
AttributesData.is_loaded = False
|
||||
MaterialAttributesData.is_loaded = False
|
||||
|
||||
|
||||
class AttributesData:
|
||||
@@ -51,28 +50,3 @@ class AttributesData:
|
||||
key = "STEP ID"
|
||||
results.append({"name": key, "value": str(value)})
|
||||
return results
|
||||
|
||||
|
||||
class MaterialAttributesData:
|
||||
data = {}
|
||||
is_loaded = False
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
cls.data = {"ifc_definition_id": cls.ifc_definition_id(), "attributes": cls.attributes()}
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def ifc_definition_id(cls):
|
||||
return bpy.context.active_object.active_material.BIMObjectProperties.ifc_definition_id
|
||||
|
||||
@classmethod
|
||||
def attributes(cls):
|
||||
results = []
|
||||
element = tool.Ifc.get_entity(bpy.context.active_object.active_material)
|
||||
data = element.get_info()
|
||||
for key, value in data.items():
|
||||
if value is None or isinstance(value, ifcopenshell.entity_instance) or key in ["id", "type"]:
|
||||
continue
|
||||
results.append({"name": key, "value": str(value)})
|
||||
return results
|
||||
|
||||
@@ -20,6 +20,7 @@ import bpy
|
||||
import json
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.guid
|
||||
import blenderbim.bim.helper
|
||||
import blenderbim.bim.handler
|
||||
import blenderbim.tool as tool
|
||||
@@ -27,26 +28,15 @@ import blenderbim.core.attribute as core
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
class Operator:
|
||||
def execute(self, context):
|
||||
IfcStore.execute_ifc_operator(self, context)
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingAttributes(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_editing_attributes"
|
||||
bl_label = "Enable Editing Attributes"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj: bpy.props.StringProperty()
|
||||
obj_type: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
if self.obj_type == "Object":
|
||||
obj = bpy.data.objects.get(self.obj)
|
||||
elif self.obj_type == "Material":
|
||||
obj = bpy.data.materials.get(self.obj)
|
||||
obj = bpy.data.objects.get(self.obj)
|
||||
props = obj.BIMAttributeProperties
|
||||
props.attributes.clear()
|
||||
|
||||
@@ -84,31 +74,23 @@ class DisableEditingAttributes(bpy.types.Operator):
|
||||
bl_label = "Disable Editing Attributes"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj: bpy.props.StringProperty()
|
||||
obj_type: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
if self.obj_type == "Object":
|
||||
obj = bpy.data.objects.get(self.obj)
|
||||
elif self.obj_type == "Material":
|
||||
obj = bpy.data.materials.get(self.obj)
|
||||
obj = bpy.data.objects.get(self.obj)
|
||||
props = obj.BIMAttributeProperties
|
||||
props.is_editing_attributes = False
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EditAttributes(bpy.types.Operator, Operator):
|
||||
class EditAttributes(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.edit_attributes"
|
||||
bl_label = "Edit Attributes"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj: bpy.props.StringProperty()
|
||||
obj_type: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
if self.obj_type == "Object":
|
||||
obj = bpy.data.objects.get(self.obj)
|
||||
elif self.obj_type == "Material":
|
||||
obj = bpy.data.materials.get(self.obj)
|
||||
obj = bpy.data.objects.get(self.obj)
|
||||
props = obj.BIMAttributeProperties
|
||||
product = tool.Ifc.get_entity(obj)
|
||||
|
||||
@@ -125,11 +107,11 @@ class EditAttributes(bpy.types.Operator, Operator):
|
||||
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.attributes, callback=callback)
|
||||
ifcopenshell.api.run("attribute.edit_attributes", self.file, product=product, attributes=attributes)
|
||||
bpy.ops.bim.disable_editing_attributes(obj=obj.name, obj_type=self.obj_type)
|
||||
bpy.ops.bim.disable_editing_attributes(obj=obj.name)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class GenerateGlobalId(bpy.types.Operator, Operator):
|
||||
class GenerateGlobalId(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.generate_global_id"
|
||||
bl_label = "Regenerate GlobalId"
|
||||
bl_description = "Regenerate GlobalId\n\nSHIFT+CLICK to regenerate GlobalIds for all selected objects"
|
||||
@@ -172,7 +154,7 @@ class GenerateGlobalId(bpy.types.Operator, Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class CopyAttributeToSelection(bpy.types.Operator, Operator):
|
||||
class CopyAttributeToSelection(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.copy_attribute_to_selection"
|
||||
bl_label = "Copy Attribute To Selection"
|
||||
name: bpy.props.StringProperty()
|
||||
|
||||
@@ -19,34 +19,34 @@
|
||||
import blenderbim.bim.helper
|
||||
from bpy.types import Panel
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.attribute.data import AttributesData, MaterialAttributesData
|
||||
from blenderbim.bim.module.attribute.data import AttributesData
|
||||
|
||||
|
||||
def draw_ui(context, layout, obj_type, attributes):
|
||||
obj = context.active_object if obj_type == "Object" else context.active_object.active_material
|
||||
def draw_ui(context, layout, attributes):
|
||||
obj = context.active_object
|
||||
oprops = obj.BIMObjectProperties
|
||||
props = obj.BIMAttributeProperties
|
||||
|
||||
if props.is_editing_attributes:
|
||||
row = layout.row(align=True)
|
||||
op = row.operator("bim.edit_attributes", icon="CHECKMARK", text="Save Attributes")
|
||||
op.obj_type = obj_type
|
||||
op.obj = obj.name
|
||||
op = row.operator("bim.disable_editing_attributes", icon="CANCEL", text="")
|
||||
op.obj_type = obj_type
|
||||
op.obj = obj.name
|
||||
|
||||
blenderbim.bim.helper.draw_attributes(props.attributes, layout, copy_operator="bim.copy_attribute_to_selection")
|
||||
else:
|
||||
row = layout.row()
|
||||
op = row.operator("bim.enable_editing_attributes", icon="GREASEPENCIL", text="Edit")
|
||||
op.obj_type = obj_type
|
||||
op.obj = obj.name
|
||||
|
||||
for attribute in attributes:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=attribute["name"])
|
||||
row.label(text=attribute["value"])
|
||||
# row.label(text=attribute["value"])
|
||||
op = row.operator("bim.select_similar", text=attribute["value"], icon="NONE", emboss=False)
|
||||
op.key = attribute['name']
|
||||
|
||||
|
||||
# TODO: reimplement, see #1222
|
||||
# if "IfcSite/" in context.active_object.name or "IfcBuilding/" in context.active_object.name:
|
||||
@@ -72,32 +72,4 @@ class BIM_PT_object_attributes(Panel):
|
||||
def draw(self, context):
|
||||
if not AttributesData.is_loaded:
|
||||
AttributesData.load()
|
||||
draw_ui(context, self.layout, "Object", AttributesData.data["attributes"])
|
||||
|
||||
|
||||
class BIM_PT_material_attributes(Panel):
|
||||
bl_label = "Material Attributes"
|
||||
bl_idname = "BIM_PT_material_attributes"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "material"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not IfcStore.get_file():
|
||||
return False
|
||||
try:
|
||||
return bool(context.active_object.active_material.BIMObjectProperties.ifc_definition_id)
|
||||
except:
|
||||
return False
|
||||
|
||||
def draw(self, context):
|
||||
if not MaterialAttributesData.is_loaded:
|
||||
MaterialAttributesData.load()
|
||||
elif (
|
||||
context.active_object.active_material.BIMObjectProperties.ifc_definition_id
|
||||
!= MaterialAttributesData.data["ifc_definition_id"]
|
||||
):
|
||||
MaterialAttributesData.load()
|
||||
|
||||
draw_ui(context, self.layout, "Material", MaterialAttributesData.data["attributes"])
|
||||
draw_ui(context, self.layout, AttributesData.data["attributes"])
|
||||
|
||||
@@ -59,6 +59,20 @@ class LoadBcfProject(bpy.types.Operator):
|
||||
if self.filepath:
|
||||
bcfstore.BcfStore.set_by_filepath(self.filepath)
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
# a BCFv2.1 does not need to have a project, but BBIM likes to have one
|
||||
# https://github.com/buildingSMART/BCF-XML/tree/release_2_1/Documentation#bcf-file-structure
|
||||
nameless = "Unknown"
|
||||
if bcfxml.project is None:
|
||||
if bcfxml.version.version_id.startswith("2"):
|
||||
print("No project, we will create one for BBIM.")
|
||||
bcfxml.project_info = bcf.v2.model.ProjectExtension(
|
||||
project=bcf.v2.model.Project(
|
||||
name=nameless,
|
||||
project_id=str(uuid.uuid4())
|
||||
), extension_schema=""
|
||||
)
|
||||
if bcfxml.project.name is None:
|
||||
bcfxml.project.name = nameless
|
||||
context.scene.BCFProperties.name = bcfxml.project.name
|
||||
bpy.ops.bim.load_bcf_topics()
|
||||
return {"FINISHED"}
|
||||
@@ -86,7 +100,19 @@ class LoadBcfTopics(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
context.scene.BCFProperties.topics.clear()
|
||||
for index, topic_guid in enumerate(bcfxml.topics.keys()):
|
||||
# workaround, one non standard topic would break reading entire bcf
|
||||
# ignored these topics ATM
|
||||
# happens on non standard nodes or on missing nodes in markup
|
||||
topics2use = []
|
||||
for topic_guid in bcfxml.topics.keys():
|
||||
# print("topic guid: {}".format(topic_guid))
|
||||
try:
|
||||
topic_titel = bcfxml.topics[topic_guid].topic.title
|
||||
topics2use.append(topic_guid)
|
||||
except:
|
||||
print("Problems on reading topic, thus ignored: {}".format(topic_guid))
|
||||
continue
|
||||
for index, topic_guid in enumerate(topics2use):
|
||||
new = context.scene.BCFProperties.topics.add()
|
||||
bpy.ops.bim.load_bcf_topic(topic_guid=topic_guid, topic_index=index)
|
||||
return {"FINISHED"}
|
||||
@@ -923,9 +949,9 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||
matrix = ifcopenshell.util.geolocation.global2local(
|
||||
matrix,
|
||||
float(props.blender_eastings) * unit_scale,
|
||||
float(props.blender_northings) * unit_scale,
|
||||
float(props.blender_orthogonal_height) * unit_scale,
|
||||
float(props.blender_offset_x) * unit_scale,
|
||||
float(props.blender_offset_y) * unit_scale,
|
||||
float(props.blender_offset_z) * unit_scale,
|
||||
float(props.blender_x_axis_abscissa),
|
||||
float(props.blender_x_axis_ordinate),
|
||||
)
|
||||
@@ -938,33 +964,56 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
# Operators with context overrides are used because they are
|
||||
# significantly faster than looping through all objects
|
||||
|
||||
exception_global_ids = {v.ifc_guid for v in viewpoint.visualization_info.components.visibility.exceptions or []}
|
||||
self.set_exceptions(viewpoint, context)
|
||||
self.set_view_setup_hints(viewpoint, context)
|
||||
# set selection at the end not to conflict with .hide_spaces
|
||||
self.set_selection(viewpoint)
|
||||
self.set_colours(viewpoint)
|
||||
|
||||
def set_exceptions(self, viewpoint, context):
|
||||
if (
|
||||
not hasattr(viewpoint.visualization_info.components, "visibility")
|
||||
or not hasattr(viewpoint.visualization_info.components.visibility.exceptions, "component")
|
||||
):
|
||||
return
|
||||
|
||||
exception_global_ids = {v.ifc_guid for v in viewpoint.visualization_info.components.visibility.exceptions.component or []}
|
||||
|
||||
# print("default_visibility: {}".format(viewpoint.visualization_info.components.visibility.default_visibility))
|
||||
if viewpoint.visualization_info.components.visibility.default_visibility:
|
||||
# default_visibility is True: show all objs, hide the exceptions
|
||||
old = context.area.type
|
||||
context.area.type = "VIEW_3D"
|
||||
bpy.ops.object.hide_view_clear()
|
||||
context.area.type = old
|
||||
for global_id in exception_global_ids:
|
||||
# print("{}: hide".format(global_id))
|
||||
obj = IfcStore.get_element(global_id)
|
||||
if obj and bpy.context.view_layer.objects.get(obj.name):
|
||||
# print(" obj found")
|
||||
obj.hide_set(True)
|
||||
else:
|
||||
# default_visibility is False: hide all objs, show the exceptions
|
||||
objs = []
|
||||
for global_id in exception_global_ids:
|
||||
# print("{}: show".format(global_id))
|
||||
obj = IfcStore.get_element(global_id)
|
||||
if obj:
|
||||
# print(" obj found")
|
||||
objs.append(obj)
|
||||
if objs:
|
||||
old = context.area.type
|
||||
context.area.type = "VIEW_3D"
|
||||
bpy.ops.object.hide_view_clear()
|
||||
context_override = {}
|
||||
context_override["object"] = context_override["active_object"] = objs[0]
|
||||
context_override["selected_objects"] = context_override["selected_editable_objects"] = objs
|
||||
with context.temp_override(**context_override):
|
||||
bpy.ops.object.hide_view_set(unselected=True)
|
||||
bpy.data.objects["Viewpoint"].hide_set(False)
|
||||
context.area.type = old
|
||||
|
||||
def set_view_setup_hints(self, viewpoint, context):
|
||||
if viewpoint.visualization_info.components.view_setup_hints:
|
||||
if not viewpoint.visualization_info.components.view_setup_hints.spaces_visible:
|
||||
self.hide_spaces(context)
|
||||
@@ -976,10 +1025,6 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
self.hide_spaces(context)
|
||||
self.set_openings_visibility(False, context)
|
||||
|
||||
# set selection at the end not to conflict with .hide_spaces
|
||||
self.set_selection(viewpoint)
|
||||
self.set_colours(viewpoint)
|
||||
|
||||
def hide_spaces(self, context):
|
||||
old = context.area.type
|
||||
context.area.type = "VIEW_3D"
|
||||
@@ -997,18 +1042,25 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
selected_global_ids = [s.ifc_guid for s in viewpoint.visualization_info.components.selection.component or []]
|
||||
bpy.ops.object.select_all(action="DESELECT")
|
||||
for global_id in selected_global_ids:
|
||||
# print("{}: selected".format(global_id))
|
||||
obj = IfcStore.get_element(global_id)
|
||||
if obj:
|
||||
# print(" obj found")
|
||||
obj.select_set(True)
|
||||
obj.hide_set(False)
|
||||
|
||||
def set_colours(self, viewpoint):
|
||||
if not viewpoint.visualization_info.components or not viewpoint.visualization_info.components.coloring:
|
||||
return
|
||||
global_id_colours = {}
|
||||
for coloring in viewpoint.visualization_info.components.coloring or []:
|
||||
for component in coloring.components:
|
||||
global_id_colours.setdefault(component.ifc_guid, coloring.color)
|
||||
for acoloring in viewpoint.visualization_info.components.coloring.color:
|
||||
for acomponent in acoloring.component:
|
||||
global_id_colours.setdefault(acomponent.ifc_guid, acoloring.color)
|
||||
for global_id, color in global_id_colours.items():
|
||||
# print("{}: color: {}: {}".format(global_id, color, self.hex_to_rgb(color)))
|
||||
obj = IfcStore.get_element(global_id)
|
||||
if obj:
|
||||
# print(" obj found ")
|
||||
obj.color = self.hex_to_rgb(color)
|
||||
|
||||
def draw_lines(self, viewpoint, context):
|
||||
@@ -1092,8 +1144,14 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
def hex_to_rgb(self, value):
|
||||
value = value.lstrip("#")
|
||||
lv = len(value)
|
||||
t = tuple(int(value[i : i + lv // 3], 16) for i in range(0, lv, lv // 3))
|
||||
return [t[0] / 255.0, t[1] / 255.0, t[2] / 255.0, 1]
|
||||
# https://github.com/buildingSMART/BCF-XML/tree/release_3_0/Documentation#coloring
|
||||
if lv == 8:
|
||||
t = tuple(int(value[i : i + lv // 4], 16) for i in range(0, lv, lv // 4))
|
||||
col = [t[1] / 255.0, t[2] / 255.0, t[3] / 255.0, t[0] / 255.0]
|
||||
else:
|
||||
t = tuple(int(value[i : i + lv // 3], 16) for i in range(0, lv, lv // 3))
|
||||
col = [t[0] / 255.0, t[1] / 255.0, t[2] / 255.0, 1]
|
||||
return col
|
||||
|
||||
|
||||
class OpenBcfReferenceLink(bpy.types.Operator):
|
||||
|
||||
@@ -49,7 +49,7 @@ class BoundaryDecorator:
|
||||
batch.draw(shader)
|
||||
|
||||
def __call__(self, context):
|
||||
self.addon_prefs = context.preferences.addons["blenderbim"].preferences
|
||||
self.addon_prefs = tool.Blender.get_addon_preferences()
|
||||
selected_elements_color = self.addon_prefs.decorator_color_selected
|
||||
unselected_elements_color = self.addon_prefs.decorator_color_unselected
|
||||
special_elements_color = self.addon_prefs.decorator_color_special
|
||||
|
||||
@@ -20,6 +20,7 @@ import bpy
|
||||
import bmesh
|
||||
import logging
|
||||
import shapely
|
||||
import shapely.ops
|
||||
import mathutils
|
||||
import numpy as np
|
||||
import multiprocessing
|
||||
@@ -132,14 +133,11 @@ class Loader:
|
||||
return mesh
|
||||
|
||||
def load_settings(self):
|
||||
settings = ifcopenshell.geom.settings()
|
||||
settings.set(settings.EXCLUDE_SOLIDS_AND_SURFACES, False)
|
||||
settings.set(settings.USE_BREP_DATA, False)
|
||||
return settings
|
||||
return ifcopenshell.geom.settings()
|
||||
|
||||
def load_fallback_settings(self):
|
||||
settings = ifcopenshell.geom.settings()
|
||||
settings.set(settings.INCLUDE_CURVES, True)
|
||||
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.CURVES_SURFACES_AND_SOLIDS)
|
||||
return settings
|
||||
|
||||
def load_importer(self):
|
||||
@@ -553,9 +551,9 @@ class HideBoundaries(bpy.types.Operator, tool.Ifc.Operator):
|
||||
for boundary in element.BoundedBy or []:
|
||||
boundary_obj = tool.Ifc.get_object(boundary)
|
||||
if boundary_obj:
|
||||
to_delete.add(boundary_obj)
|
||||
for boundary_obj in to_delete:
|
||||
tool.Ifc.unlink(obj=boundary_obj)
|
||||
to_delete.add((boundary, boundary_obj))
|
||||
for boundary, boundary_obj in to_delete:
|
||||
tool.Ifc.unlink(element=boundary)
|
||||
bpy.data.objects.remove(boundary_obj)
|
||||
context.scene.BIMBoundaryProperties.boundaries.clear()
|
||||
return {"FINISHED"}
|
||||
@@ -604,6 +602,11 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
parent_boundaries = []
|
||||
|
||||
objs = context.selected_objects
|
||||
|
||||
if not any((element:=tool.Ifc.get_entity(obj)) and element.is_a("IfcSpace") for obj in objs):
|
||||
self.report({"INFO"}, "No IfcSpace elements selected.")
|
||||
return {"FINISHED"}
|
||||
|
||||
if len(objs) == 2:
|
||||
# The user may select two objects, a space and its related building element
|
||||
for obj in objs:
|
||||
@@ -631,24 +634,18 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
# TODO : refactor to be able to generate all boundaries for selected space automatically or with an option
|
||||
|
||||
def msg(self, context):
|
||||
self.layout.label(text="NO ACTIVE STOREY")
|
||||
self.layout.label(text="Please set an active container to detect space boundaries from.")
|
||||
|
||||
element = tool.Ifc.get_entity(objs[0])
|
||||
if element.is_a("IfcSpace"):
|
||||
relating_space = element
|
||||
relating_space_obj = objs[0]
|
||||
|
||||
collection = context.view_layer.active_layer_collection.collection
|
||||
collection_obj = bpy.data.objects.get(collection.name)
|
||||
if not collection_obj:
|
||||
bpy.context.window_manager.popup_menu(msg, title="Error", icon="ERROR")
|
||||
return
|
||||
spatial_element = tool.Ifc.get_entity(collection_obj)
|
||||
if not spatial_element:
|
||||
if not (container := tool.Root.get_default_container()):
|
||||
bpy.context.window_manager.popup_menu(msg, title="Error", icon="ERROR")
|
||||
return
|
||||
|
||||
for subelement in ifcopenshell.util.element.get_decomposition(spatial_element):
|
||||
for subelement in ifcopenshell.util.element.get_decomposition(container):
|
||||
if not (
|
||||
subelement.is_a("IfcWall") or subelement.is_a("IfcSlab") or subelement.is_a("IfcVirtualElement")
|
||||
):
|
||||
@@ -691,8 +688,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
tree = ifcopenshell.geom.tree()
|
||||
shapes = {}
|
||||
settings = ifcopenshell.geom.settings()
|
||||
settings.set(settings.STRICT_TOLERANCE, True)
|
||||
settings.set(settings.DISABLE_OPENING_SUBTRACTIONS, True)
|
||||
settings.set("disable-opening-subtractions", True)
|
||||
iterator = ifcopenshell.geom.iterator(settings, tool.Ifc.get(), multiprocessing.cpu_count(), include=include)
|
||||
if iterator.initialize():
|
||||
while True:
|
||||
@@ -830,17 +826,10 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
# Create shape of opening as a dissolved BMesh
|
||||
settings = ifcopenshell.geom.settings()
|
||||
settings.set(settings.STRICT_TOLERANCE, True)
|
||||
shape = ifcopenshell.geom.create_shape(settings, opening)
|
||||
m = shape.transformation.matrix
|
||||
mat = Matrix(
|
||||
(
|
||||
[m[0], m[3], m[6], m[9]],
|
||||
[m[1], m[4], m[7], m[10]],
|
||||
[m[2], m[5], m[8], m[11]],
|
||||
[0, 0, 0, 1],
|
||||
)
|
||||
)
|
||||
mat = Matrix(ifcopenshell.util.shape.get_shape_matrix(shape))
|
||||
mat.translation = (0, 0, 0)
|
||||
opening_bm = bmesh.new()
|
||||
verts = ifcopenshell.util.shape.get_vertices(shape.geometry)
|
||||
for vert in verts:
|
||||
@@ -1031,12 +1020,10 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
settings = ifcopenshell.geom.settings()
|
||||
if not element.is_a("IfcOpeningElement"):
|
||||
settings.set(settings.DISABLE_OPENING_SUBTRACTIONS, True)
|
||||
settings.set(settings.STRICT_TOLERANCE, True)
|
||||
settings.set("disable-opening-subtractions", True)
|
||||
# geometry = ifcopenshell.geom.create_shape(settings, body)
|
||||
shape = ifcopenshell.geom.create_shape(settings, element)
|
||||
m = shape.transformation.matrix
|
||||
mat = Matrix(([m[0], m[3], m[6], m[9]], [m[1], m[4], m[7], m[10]], [m[2], m[5], m[8], m[11]], [0, 0, 0, 1]))
|
||||
mat = Matrix(ifcopenshell.util.shape.get_shape_matrix(shape))
|
||||
verts = [space_matrix_i @ mat @ Vector(v) for v in ifcopenshell.util.shape.get_vertices(shape.geometry)]
|
||||
faces = ifcopenshell.util.shape.get_faces(shape.geometry)
|
||||
polygons = []
|
||||
|
||||
@@ -26,14 +26,7 @@ from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.tool.brick import BrickStore
|
||||
|
||||
|
||||
class Operator:
|
||||
def execute(self, context):
|
||||
IfcStore.execute_ifc_operator(self, context)
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class LoadBrickProject(bpy.types.Operator, Operator):
|
||||
class LoadBrickProject(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.load_brick_project"
|
||||
bl_label = "Load Brickschema Project"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -46,14 +39,14 @@ class LoadBrickProject(bpy.types.Operator, Operator):
|
||||
root = context.scene.BIMBrickProperties.brick_list_root
|
||||
core.load_brick_project(tool.Brick, filepath=self.filepath, brick_root=root)
|
||||
else:
|
||||
self.report({'ERROR'}, f'Failed to load {self.filepath}')
|
||||
self.report({"ERROR"}, f"Failed to load {self.filepath}")
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
|
||||
class ViewBrickClass(bpy.types.Operator, Operator):
|
||||
class ViewBrickClass(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.view_brick_class"
|
||||
bl_label = "View Brick Class"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -65,7 +58,7 @@ class ViewBrickClass(bpy.types.Operator, Operator):
|
||||
core.view_brick_class(tool.Brick, brick_class=self.brick_class, split_screen=self.split_screen)
|
||||
|
||||
|
||||
class ViewBrickItem(bpy.types.Operator, Operator):
|
||||
class ViewBrickItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.view_brick_item"
|
||||
bl_label = "View Brick Item"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -77,10 +70,10 @@ class ViewBrickItem(bpy.types.Operator, Operator):
|
||||
try:
|
||||
core.view_brick_item(tool.Brick, item=self.item, split_screen=self.split_screen)
|
||||
except:
|
||||
self.report({'ERROR'}, f'Could not find {self.item}')
|
||||
self.report({"ERROR"}, f"Could not find {self.item}")
|
||||
|
||||
|
||||
class RewindBrickClass(bpy.types.Operator, Operator):
|
||||
class RewindBrickClass(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.rewind_brick_class"
|
||||
bl_label = "Rewind Brick Class"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -91,7 +84,7 @@ class RewindBrickClass(bpy.types.Operator, Operator):
|
||||
core.rewind_brick_class(tool.Brick, split_screen=self.split_screen)
|
||||
|
||||
|
||||
class CloseBrickProject(bpy.types.Operator, Operator):
|
||||
class CloseBrickProject(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.close_brick_project"
|
||||
bl_label = "Close Brick Project"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -101,7 +94,7 @@ class CloseBrickProject(bpy.types.Operator, Operator):
|
||||
core.close_brick_project(tool.Brick)
|
||||
|
||||
|
||||
class ConvertBrickProject(bpy.types.Operator, Operator):
|
||||
class ConvertBrickProject(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.convert_brick_project"
|
||||
bl_label = "Convert Brick Project"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -111,7 +104,7 @@ class ConvertBrickProject(bpy.types.Operator, Operator):
|
||||
core.convert_brick_project(tool.Ifc, tool.Brick)
|
||||
|
||||
|
||||
class AssignBrickReference(bpy.types.Operator, Operator):
|
||||
class AssignBrickReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.assign_brick_reference"
|
||||
bl_label = "Assign Brick Reference"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -119,13 +112,13 @@ class AssignBrickReference(bpy.types.Operator, Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
if not context.active_object:
|
||||
self.report({'ERROR'}, f'No Ifc selected')
|
||||
self.report({"ERROR"}, f"No Ifc selected")
|
||||
return
|
||||
props = context.scene.BIMBrickProperties
|
||||
try:
|
||||
props.bricks[props.active_brick_index]
|
||||
except:
|
||||
self.report({'ERROR'}, f'No Brick selected')
|
||||
self.report({"ERROR"}, f"No Brick selected")
|
||||
return
|
||||
core.assign_brick_reference(
|
||||
tool.Ifc,
|
||||
@@ -136,7 +129,7 @@ class AssignBrickReference(bpy.types.Operator, Operator):
|
||||
)
|
||||
|
||||
|
||||
class AddBrick(bpy.types.Operator, Operator):
|
||||
class AddBrick(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_brick"
|
||||
bl_label = "Add Brick"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -155,7 +148,7 @@ class AddBrick(bpy.types.Operator, Operator):
|
||||
)
|
||||
|
||||
|
||||
class AddBrickRelation(bpy.types.Operator, Operator):
|
||||
class AddBrickRelation(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_brick_relation"
|
||||
bl_label = "Add Brick Relation"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -170,15 +163,10 @@ class AddBrickRelation(bpy.types.Operator, Operator):
|
||||
object = props.split_screen_bricks[props.split_screen_active_brick_index].uri
|
||||
else:
|
||||
object = props.namespace + props.new_brick_relation_object
|
||||
core.add_brick_relation(
|
||||
tool.Brick,
|
||||
brick_uri=brick.uri,
|
||||
predicate=props.new_brick_relation_type,
|
||||
object=object
|
||||
)
|
||||
core.add_brick_relation(tool.Brick, brick_uri=brick.uri, predicate=props.new_brick_relation_type, object=object)
|
||||
|
||||
|
||||
class ConvertIfcToBrick(bpy.types.Operator, Operator):
|
||||
class ConvertIfcToBrick(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.convert_ifc_to_brick"
|
||||
bl_label = "Convert IFC To Brick"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -225,7 +213,7 @@ class NewBrickFile(bpy.types.Operator):
|
||||
BrickStore.graph = data["graph"]
|
||||
|
||||
|
||||
class RefreshBrickViewer(bpy.types.Operator, Operator):
|
||||
class RefreshBrickViewer(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.refresh_brick_viewer"
|
||||
bl_label = "Refresh Brick Viewer"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -235,7 +223,7 @@ class RefreshBrickViewer(bpy.types.Operator, Operator):
|
||||
core.refresh_brick_viewer(tool.Brick)
|
||||
|
||||
|
||||
class RemoveBrick(bpy.types.Operator, Operator):
|
||||
class RemoveBrick(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.remove_brick"
|
||||
bl_label = "Remove Brick"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -279,7 +267,7 @@ class SerializeBrick(bpy.types.Operator):
|
||||
return "Save the Brick project"
|
||||
|
||||
|
||||
class AddBrickNamespace(bpy.types.Operator, Operator):
|
||||
class AddBrickNamespace(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_brick_namespace"
|
||||
bl_label = "Add Brick Namespace"
|
||||
bl_description = "Bind a new namespace to the Brick project"
|
||||
@@ -291,7 +279,7 @@ class AddBrickNamespace(bpy.types.Operator, Operator):
|
||||
core.add_brick_namespace(tool.Brick, alias=alias, uri=uri)
|
||||
|
||||
|
||||
class RemoveBrickRelation(bpy.types.Operator, Operator):
|
||||
class RemoveBrickRelation(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.remove_brick_relation"
|
||||
bl_label = "Remove Relation"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -302,4 +290,4 @@ class RemoveBrickRelation(bpy.types.Operator, Operator):
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMBrickProperties
|
||||
brick = props.bricks[props.active_brick_index]
|
||||
core.remove_brick_relation(tool.Brick, brick_uri=brick.uri, predicate=self.predicate, object=self.object)
|
||||
core.remove_brick_relation(tool.Brick, brick_uri=brick.uri, predicate=self.predicate, object=self.object)
|
||||
|
||||
@@ -55,7 +55,7 @@ class ClashDecorator:
|
||||
batch.draw(shader)
|
||||
|
||||
def draw_text(self, context):
|
||||
self.addon_prefs = context.preferences.addons["blenderbim"].preferences
|
||||
self.addon_prefs = tool.Blender.get_addon_preferences()
|
||||
selected_elements_color = self.addon_prefs.decorator_color_selected
|
||||
unselected_elements_color = self.addon_prefs.decorator_color_unselected
|
||||
special_elements_color = self.addon_prefs.decorator_color_special
|
||||
@@ -75,7 +75,7 @@ class ClashDecorator:
|
||||
blf.draw(font_id, text) # Set your text here
|
||||
|
||||
def draw_geometry(self, context):
|
||||
self.addon_prefs = context.preferences.addons["blenderbim"].preferences
|
||||
self.addon_prefs = tool.Blender.get_addon_preferences()
|
||||
selected_elements_color = self.addon_prefs.decorator_color_selected
|
||||
unselected_elements_color = self.addon_prefs.decorator_color_unselected
|
||||
special_elements_color = self.addon_prefs.decorator_color_special
|
||||
|
||||
@@ -54,11 +54,11 @@ classes = (
|
||||
|
||||
def register():
|
||||
bpy.types.Scene.BIMClassificationProperties = bpy.props.PointerProperty(type=prop.BIMClassificationProperties)
|
||||
bpy.types.Object.BIMClassificationReferenceProperties = bpy.props.PointerProperty(
|
||||
bpy.types.Scene.BIMClassificationReferenceProperties = bpy.props.PointerProperty(
|
||||
type=prop.BIMClassificationReferenceProperties
|
||||
)
|
||||
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Scene.BIMClassificationProperties
|
||||
del bpy.types.Object.BIMClassificationReferenceProperties
|
||||
del bpy.types.Scene.BIMClassificationReferenceProperties
|
||||
|
||||
@@ -88,7 +88,7 @@ class ClassificationReferencesData(ReferencesData):
|
||||
cls.data["references"] = cls.references()
|
||||
cls.data["active_classification_library"] = cls.active_classification_library()
|
||||
cls.data["classifications"] = cls.classifications()
|
||||
cls.data["object_type"] = "OBJECT"
|
||||
cls.data["object_type"] = "Object"
|
||||
|
||||
@classmethod
|
||||
def references(cls):
|
||||
@@ -112,17 +112,21 @@ class MaterialClassificationsData(ReferencesData):
|
||||
cls.data["references"] = cls.references()
|
||||
cls.data["active_classification_library"] = cls.active_classification_library()
|
||||
cls.data["classifications"] = cls.classifications()
|
||||
cls.data["object_type"] = "MATERIAL"
|
||||
cls.data["object_type"] = "Material"
|
||||
|
||||
@classmethod
|
||||
def references(cls):
|
||||
results = []
|
||||
element = tool.Ifc.get_entity(bpy.context.active_object.active_material)
|
||||
if element:
|
||||
for reference in ifcopenshell.util.classification.get_references(element):
|
||||
data = reference.get_info()
|
||||
del data["ReferencedSource"]
|
||||
results.append(data)
|
||||
|
||||
props = bpy.context.scene.BIMMaterialProperties
|
||||
if props.materials and props.active_material_index < len(props.materials):
|
||||
material = props.materials[props.active_material_index]
|
||||
if material.ifc_definition_id:
|
||||
element = tool.Ifc.get().by_id(material.ifc_definition_id)
|
||||
for reference in ifcopenshell.util.classification.get_references(element):
|
||||
data = reference.get_info()
|
||||
del data["ReferencedSource"]
|
||||
results.append(data)
|
||||
return results
|
||||
|
||||
|
||||
@@ -136,7 +140,7 @@ class CostClassificationsData(ReferencesData):
|
||||
cls.data["references"] = cls.references()
|
||||
cls.data["active_classification_library"] = cls.active_classification_library()
|
||||
cls.data["classifications"] = cls.classifications()
|
||||
cls.data["object_type"] = "COST"
|
||||
cls.data["object_type"] = "Cost"
|
||||
|
||||
@classmethod
|
||||
def references(cls):
|
||||
|
||||
@@ -77,26 +77,37 @@ class AddManualClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_manual_classification_reference"
|
||||
bl_label = "Add Manual Classification Reference"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj: bpy.props.StringProperty()
|
||||
obj_type: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMClassificationReferenceProperties
|
||||
if self.obj_type == "Object":
|
||||
if context.selected_objects:
|
||||
objects = [o.name for o in context.selected_objects]
|
||||
else:
|
||||
objects = [context.active_object.name]
|
||||
else:
|
||||
objects = [self.obj]
|
||||
props = context.scene.BIMClassificationReferenceProperties
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.reference_attributes)
|
||||
product = tool.Ifc.get_entity(obj)
|
||||
# TODO: refactor and support material and cost item classifications
|
||||
classification = tool.Ifc.get().by_id(int(props.classifications))
|
||||
reference = ifcopenshell.api.run(
|
||||
"classification.add_reference",
|
||||
tool.Ifc.get(),
|
||||
products=[product],
|
||||
classification=classification,
|
||||
identification="X",
|
||||
name="Unnamed",
|
||||
)
|
||||
ifcopenshell.api.run(
|
||||
"classification.edit_reference", tool.Ifc.get(), reference=reference, attributes=attributes
|
||||
)
|
||||
products = [
|
||||
tool.Ifc.get().by_id(ifc_definition_id)
|
||||
for obj in objects
|
||||
if (ifc_definition_id := tool.Blender.get_obj_ifc_definition_id(obj, self.obj_type, context))
|
||||
]
|
||||
if products:
|
||||
classification = tool.Ifc.get().by_id(int(props.classifications))
|
||||
reference = ifcopenshell.api.run(
|
||||
"classification.add_reference",
|
||||
tool.Ifc.get(),
|
||||
products=products,
|
||||
classification=classification,
|
||||
identification="X",
|
||||
name="Unnamed",
|
||||
)
|
||||
ifcopenshell.api.run(
|
||||
"classification.edit_reference", tool.Ifc.get(), reference=reference, attributes=attributes
|
||||
)
|
||||
props.is_adding = False
|
||||
|
||||
|
||||
@@ -150,8 +161,7 @@ class EnableAddingManualClassificationReference(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMClassificationReferenceProperties
|
||||
props = context.scene.BIMClassificationReferenceProperties
|
||||
props.is_adding = True
|
||||
props.reference_attributes.clear()
|
||||
blenderbim.bim.helper.import_attributes2("IfcClassificationReference", props.reference_attributes)
|
||||
@@ -164,8 +174,7 @@ class DisableAddingManualClassificationReference(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMClassificationReferenceProperties
|
||||
props = context.scene.BIMClassificationReferenceProperties
|
||||
props.is_adding = False
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -209,6 +218,10 @@ class DisableEditingClassification(bpy.types.Operator):
|
||||
class RemoveClassification(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.remove_classification"
|
||||
bl_label = "Remove Classification"
|
||||
bl_description = (
|
||||
"The classification and all of its relationships, children references, "
|
||||
"and relationships between objects and child references will be completely removed from a project"
|
||||
)
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
classification: bpy.props.IntProperty()
|
||||
|
||||
@@ -253,8 +266,7 @@ class EnableEditingClassificationReference(bpy.types.Operator):
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object
|
||||
props = obj.BIMClassificationReferenceProperties
|
||||
props = context.scene.BIMClassificationReferenceProperties
|
||||
props.reference_attributes.clear()
|
||||
blenderbim.bim.helper.import_attributes2(tool.Ifc.get().by_id(self.reference), props.reference_attributes)
|
||||
props.active_reference_id = self.reference
|
||||
@@ -268,8 +280,7 @@ class DisableEditingClassificationReference(bpy.types.Operator):
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object
|
||||
obj.BIMClassificationReferenceProperties.active_reference_id = 0
|
||||
context.scene.BIMClassificationReferenceProperties.active_reference_id = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -322,8 +333,7 @@ class EditClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object
|
||||
props = obj.BIMClassificationReferenceProperties
|
||||
props = context.scene.BIMClassificationReferenceProperties
|
||||
attributes = {}
|
||||
for attribute in props.reference_attributes:
|
||||
if attribute.is_null:
|
||||
@@ -364,9 +374,8 @@ class AddClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||
classification = element
|
||||
break
|
||||
|
||||
ifc_file = tool.Ifc.get()
|
||||
products = [
|
||||
ifc_file.by_id(ifc_definition_id)
|
||||
tool.Ifc.get().by_id(ifc_definition_id)
|
||||
for obj in objects
|
||||
if (ifc_definition_id := tool.Blender.get_obj_ifc_definition_id(obj, self.obj_type, context))
|
||||
]
|
||||
|
||||
@@ -118,10 +118,9 @@ class BIM_PT_classifications(Panel):
|
||||
class ReferenceUI:
|
||||
def draw_ui(self, context):
|
||||
obj = context.active_object
|
||||
self.oprops = obj.BIMObjectProperties
|
||||
self.sprops = context.scene.BIMClassificationProperties
|
||||
self.bprops = context.scene.BIMBSDDProperties
|
||||
self.props = obj.BIMClassificationReferenceProperties
|
||||
self.props = context.scene.BIMClassificationReferenceProperties
|
||||
self.file = IfcStore.get_file()
|
||||
|
||||
self.draw_add_ui(context)
|
||||
@@ -155,7 +154,7 @@ class ReferenceUI:
|
||||
blenderbim.bim.helper.draw_attributes(self.props.reference_attributes, self.layout)
|
||||
row = self.layout.row(align=True)
|
||||
op = row.operator("bim.add_manual_classification_reference", text="Save", icon="CHECKMARK")
|
||||
op.type = self.data.data["object_type"]
|
||||
op.obj_type = self.data.data["object_type"]
|
||||
row.operator("bim.disable_adding_manual_classification_reference", text="", icon="CANCEL")
|
||||
else:
|
||||
row = self.layout.row()
|
||||
@@ -295,28 +294,31 @@ class BIM_PT_material_classifications(Panel, ReferenceUI):
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "material"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_materials"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not tool.Ifc.get():
|
||||
return False
|
||||
try:
|
||||
return bool(context.active_object.active_material.BIMObjectProperties.ifc_definition_id)
|
||||
except:
|
||||
return False
|
||||
props = context.scene.BIMMaterialProperties
|
||||
if props.materials and props.active_material_index < len(props.materials):
|
||||
material = props.materials[props.active_material_index]
|
||||
if material.ifc_definition_id:
|
||||
return True
|
||||
return False
|
||||
|
||||
def draw(self, context):
|
||||
if not MaterialClassificationsData.is_loaded:
|
||||
MaterialClassificationsData.load()
|
||||
self.data = MaterialClassificationsData
|
||||
self.obj = context.active_object.active_material.name
|
||||
self.obj = ""
|
||||
self.obj_type = "Material"
|
||||
self.draw_ui(context)
|
||||
|
||||
|
||||
class BIM_PT_cost_classifications(Panel, ReferenceUI):
|
||||
bl_label = "Cost Classifications"
|
||||
bl_label = "Cost Item Classifications"
|
||||
bl_idname = "BIM_PT_cost_classifications"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
|
||||
@@ -24,14 +24,7 @@ import blenderbim.bim.handler
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
class Operator:
|
||||
def execute(self, context):
|
||||
IfcStore.execute_ifc_operator(self, context)
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AddContext(bpy.types.Operator, Operator):
|
||||
class AddContext(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_context"
|
||||
bl_label = "Add Subcontext"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -50,9 +43,13 @@ class AddContext(bpy.types.Operator, Operator):
|
||||
)
|
||||
|
||||
|
||||
class RemoveContext(bpy.types.Operator, Operator):
|
||||
class RemoveContext(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.remove_context"
|
||||
bl_label = "Remove Context"
|
||||
bl_description = (
|
||||
"Remove representation context. Any representation geometry that is assigned to the context is also removed. "
|
||||
"If a context is removed, then any subcontexts are also removed"
|
||||
)
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
context: bpy.props.IntProperty()
|
||||
|
||||
@@ -60,7 +57,7 @@ class RemoveContext(bpy.types.Operator, Operator):
|
||||
core.remove_context(tool.Ifc, context=tool.Ifc.get().by_id(self.context))
|
||||
|
||||
|
||||
class EnableEditingContext(bpy.types.Operator, Operator):
|
||||
class EnableEditingContext(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.enable_editing_context"
|
||||
bl_label = "Enable Editing Context"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -70,7 +67,7 @@ class EnableEditingContext(bpy.types.Operator, Operator):
|
||||
core.enable_editing_context(tool.Context, context=tool.Ifc.get().by_id(self.context))
|
||||
|
||||
|
||||
class DisableEditingContext(bpy.types.Operator, Operator):
|
||||
class DisableEditingContext(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.disable_editing_context"
|
||||
bl_label = "Disable Editing Context"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -79,7 +76,7 @@ class DisableEditingContext(bpy.types.Operator, Operator):
|
||||
core.disable_editing_context(tool.Context)
|
||||
|
||||
|
||||
class EditContext(bpy.types.Operator, Operator):
|
||||
class EditContext(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.edit_context"
|
||||
bl_label = "Edit Context"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@@ -82,6 +82,7 @@ classes = (
|
||||
prop.CostItem,
|
||||
prop.CostItemQuantity,
|
||||
prop.CostItemType,
|
||||
prop.ScheduleColumn,
|
||||
prop.BIMCostProperties,
|
||||
ui.BIM_PT_cost_schedules,
|
||||
ui.BIM_PT_cost_item_quantities,
|
||||
|
||||
@@ -19,10 +19,13 @@
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.cost
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.unit
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.bim.schema
|
||||
from ifcopenshell.util.doc import get_entity_doc, get_predefined_type_doc
|
||||
from typing import Any
|
||||
|
||||
|
||||
def refresh():
|
||||
@@ -34,6 +37,7 @@ def refresh():
|
||||
class CostSchedulesData:
|
||||
data = {}
|
||||
is_loaded = False
|
||||
_cost_values: dict[int, dict[str, Any]]
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
@@ -136,7 +140,7 @@ class CostSchedulesData:
|
||||
data["UnitBasisUnitSymbol"] = "U"
|
||||
if cost_value.Category == "*":
|
||||
is_sum = True
|
||||
cost_quantity = data["TotalCostQuantity"] or 1
|
||||
cost_quantity = 1 if data["TotalCostQuantity"] is None else data["TotalCostQuantity"]
|
||||
if has_unit_basis:
|
||||
data["TotalCost"] = data["TotalAppliedValue"] * cost_quantity / data["UnitBasisValueComponent"]
|
||||
else:
|
||||
@@ -155,6 +159,7 @@ class CostSchedulesData:
|
||||
data["UnitSymbol"] = "-"
|
||||
if cost_item.CostQuantities:
|
||||
quantity = cost_item.CostQuantities[0]
|
||||
data["QuantityType"] = quantity.is_a()
|
||||
unit = ifcopenshell.util.unit.get_property_unit(quantity, tool.Ifc.get())
|
||||
if unit:
|
||||
data["UnitSymbol"] = ifcopenshell.util.unit.get_unit_symbol(unit)
|
||||
@@ -193,10 +198,16 @@ class CostSchedulesData:
|
||||
# data["DerivedUnitSymbol"] = "?"
|
||||
# print("Total Cost", data["DerivedTotalCostQuantity"], cost_item.Name)
|
||||
|
||||
# TODO: dead code?
|
||||
@classmethod
|
||||
def _get_object_quantities(cls, cost_item, element):
|
||||
def _get_object_quantities(
|
||||
cls, cost_item: ifcopenshell.entity_instance, element: ifcopenshell.entity_instance
|
||||
) -> list[int]:
|
||||
if not element.is_a("IfcObject"):
|
||||
return []
|
||||
cost_quantities = cost_item.CostQuantities
|
||||
if not cost_quantities:
|
||||
return []
|
||||
results = []
|
||||
for relationship in element.IsDefinedBy:
|
||||
if not relationship.is_a("IfcRelDefinesByProperties"):
|
||||
@@ -205,7 +216,7 @@ class CostSchedulesData:
|
||||
if not qto.is_a("IfcElementQuantity"):
|
||||
continue
|
||||
for prop in qto.Quantities:
|
||||
if prop in cost_item.CostQuantities or []:
|
||||
if prop in cost_quantities:
|
||||
results.append(prop.id())
|
||||
return results
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class RemoveCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
||||
cost_schedule: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
core.remove_cost_schedule(tool.Ifc, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule))
|
||||
core.remove_cost_schedule(tool.Ifc, tool.Cost, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule))
|
||||
|
||||
|
||||
class EnableEditingCostSchedule(bpy.types.Operator):
|
||||
@@ -223,36 +223,40 @@ class EditCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
class AssignCostItemType(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.assign_cost_item_type"
|
||||
bl_label = "Assign Cost Item Type Product"
|
||||
bl_label = "Assign Cost Item To Product Types"
|
||||
bl_description = "Assign cost item to currently selected or active product types"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
cost_item: bpy.props.IntProperty()
|
||||
prop_name: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
core.assign_cost_item_type(
|
||||
product_types = core.assign_cost_item_type(
|
||||
tool.Ifc,
|
||||
tool.Cost,
|
||||
tool.Spatial,
|
||||
cost_item=tool.Ifc.get().by_id(self.cost_item),
|
||||
prop_name=self.prop_name, # TODO: REVIEW PROP_NAME USABILITY
|
||||
)
|
||||
self.report({"INFO"}, f"Cost item was assigned to {len(product_types)} product types.")
|
||||
|
||||
|
||||
class UnassignCostItemType(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.unassign_cost_item_type"
|
||||
bl_label = "Unassign Cost Item Type"
|
||||
bl_description = "Unassign cost item from currently selected or active product types"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
cost_item: bpy.props.IntProperty()
|
||||
related_object: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
core.unassign_cost_item_type(
|
||||
product_types = core.unassign_cost_item_type(
|
||||
tool.Ifc,
|
||||
tool.Cost,
|
||||
tool.Spatial,
|
||||
cost_item=tool.Ifc.get().by_id(self.cost_item),
|
||||
product_types=[tool.Ifc.get().by_id(self.related_object)] if self.related_object else [],
|
||||
product_types=[tool.Ifc.get().by_id(self.related_object)] if self.related_object else None,
|
||||
)
|
||||
self.report({"INFO"}, f"Cost item was unassigned from {len(product_types)} product types.")
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -287,9 +291,11 @@ class UnassignCostItemQuantity(bpy.types.Operator, tool.Ifc.Operator):
|
||||
tool.Ifc,
|
||||
tool.Cost,
|
||||
cost_item=tool.Ifc.get().by_id(self.cost_item),
|
||||
products=[tool.Ifc.get().by_id(self.related_object)]
|
||||
if self.related_object
|
||||
else tool.Spatial.get_selected_products(),
|
||||
products=(
|
||||
[tool.Ifc.get().by_id(self.related_object)]
|
||||
if self.related_object
|
||||
else tool.Spatial.get_selected_products()
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -509,7 +515,7 @@ class SelectCostScheduleProducts(bpy.types.Operator):
|
||||
|
||||
|
||||
class ImportCostScheduleCsv(bpy.types.Operator, ImportHelper, tool.Ifc.Operator):
|
||||
bl_idname = "import_cost_schedule_csv.bim"
|
||||
bl_idname = "bim.import_cost_schedule_csv"
|
||||
bl_label = "Import Cost Schedule CSV"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
filename_ext = ".csv"
|
||||
@@ -527,6 +533,13 @@ class AddCostColumn(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
name: bpy.props.StringProperty()
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not context.scene.BIMCostProperties.cost_column:
|
||||
cls.poll_message_set("Cost column name is empty")
|
||||
return False
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
core.add_cost_column(tool.Cost, self.name)
|
||||
return {"FINISHED"}
|
||||
@@ -538,7 +551,7 @@ class RemoveCostColumn(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
name: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
def execute(self, context):
|
||||
core.remove_cost_column(tool.Cost, self.name)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -656,13 +669,17 @@ class ExportCostSchedules(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Export a cost schedule to a CSV, XSLX OR ODS file"
|
||||
cost_schedule: bpy.props.IntProperty()
|
||||
format: bpy.props.EnumProperty("Format", items=(("CSV", "CSV", ""), ("XLSX", "XLSX", ""), ("ODS", "ODS", "")))
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
format: bpy.props.EnumProperty(name="Format", items=(("CSV", "CSV", ""), ("XLSX", "XLSX", ""), ("ODS", "ODS", "")))
|
||||
directory: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
filter_folder: bpy.props.BoolProperty(
|
||||
name="Filter Folders",
|
||||
default=True,
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
cost_schedule = tool.Ifc.get().by_id(self.cost_schedule) if self.cost_schedule else None
|
||||
r = core.export_cost_schedules(
|
||||
tool.Cost, filepath=self.filepath, format=self.format, cost_schedule=cost_schedule
|
||||
tool.Cost, filepath=self.directory, format=self.format, cost_schedule=cost_schedule
|
||||
)
|
||||
if isinstance(r, str):
|
||||
self.report({"ERROR"}, r)
|
||||
@@ -676,6 +693,7 @@ class ExportCostSchedules(bpy.types.Operator):
|
||||
def draw(self, context):
|
||||
self.layout.label(text="Choose a format")
|
||||
self.layout.prop(self, "format")
|
||||
self.layout.label(text="Select a directory.")
|
||||
|
||||
|
||||
class ClearCostItemAssignments(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
@@ -175,6 +175,10 @@ def update_active_cost_item_resources(self, context):
|
||||
bpy.ops.bim.load_cost_item_resource_quantities()
|
||||
|
||||
|
||||
class ScheduleColumn(PropertyGroup):
|
||||
schedule_id: IntProperty()
|
||||
|
||||
|
||||
class BIMCostProperties(PropertyGroup):
|
||||
cost_schedule_predefined_types: EnumProperty(
|
||||
items=get_schedule_predefined_types, name="Predefined Type", default=None
|
||||
@@ -210,9 +214,14 @@ class BIMCostProperties(PropertyGroup):
|
||||
cost_value_attributes: CollectionProperty(name="Cost Value Attributes", type=Attribute)
|
||||
cost_value_formula: StringProperty(name="Cost Value Formula")
|
||||
cost_column: StringProperty(name="Cost Column")
|
||||
should_show_column_ui: BoolProperty(name="Should Show Column UI", default=False)
|
||||
should_show_column_ui: BoolProperty(
|
||||
name="Should Show Column UI",
|
||||
description="Display UI for adding cost schedule columns, column names represent a category for cost item values",
|
||||
default=False,
|
||||
)
|
||||
should_show_currency_ui: BoolProperty(name="Should Show Currency UI", default=False)
|
||||
columns: CollectionProperty(name="Columns", type=StrProperty)
|
||||
columns: CollectionProperty(name="Active Schedule Columns", type=StrProperty)
|
||||
columns_storage: CollectionProperty(name="Columns", type=ScheduleColumn)
|
||||
active_column_index: IntProperty(name="Active Column Index")
|
||||
cost_item_products: CollectionProperty(name="Cost Item Products", type=CostItemQuantity)
|
||||
active_cost_item_product_index: IntProperty(name="Active Cost Item Product Index")
|
||||
|
||||
@@ -21,6 +21,7 @@ import blenderbim.bim.module.cost.prop as CostProp
|
||||
from bpy.types import Panel, UIList
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.cost.data import CostSchedulesData
|
||||
from typing import Any
|
||||
|
||||
|
||||
class BIM_PT_cost_schedules(Panel):
|
||||
@@ -53,7 +54,7 @@ class BIM_PT_cost_schedules(Panel):
|
||||
row.label(text="No Cost Schedules found.", icon="TEXT")
|
||||
|
||||
row.operator("bim.add_cost_schedule", icon="ADD", text="")
|
||||
row.operator("import_cost_schedule_csv.bim",icon="IMPORT",text="")
|
||||
row.operator("bim.import_cost_schedule_csv",icon="IMPORT",text="")
|
||||
|
||||
for schedule in CostSchedulesData.data["schedules"]:
|
||||
self.draw_cost_schedule_ui(schedule)
|
||||
@@ -178,24 +179,33 @@ class BIM_PT_cost_schedules(Panel):
|
||||
"active_cost_item_index",
|
||||
)
|
||||
if self.props.active_cost_item_id:
|
||||
cost_item = CostSchedulesData.data["cost_items"][ifc_definition_id]
|
||||
if self.props.cost_item_editing_type == "ATTRIBUTES":
|
||||
self.draw_editable_cost_item_attributes_ui()
|
||||
elif self.props.cost_item_editing_type == "QUANTITIES":
|
||||
self.draw_editable_cost_item_quantities_ui()
|
||||
self.draw_editable_cost_item_quantities_ui(cost_item)
|
||||
elif self.props.cost_item_editing_type == "VALUES":
|
||||
self.draw_editable_cost_item_values_ui()
|
||||
|
||||
def draw_editable_cost_item_attributes_ui(self):
|
||||
blenderbim.bim.helper.draw_attributes(self.props.cost_item_attributes, self.layout)
|
||||
|
||||
def draw_editable_cost_item_quantities_ui(self):
|
||||
def draw_editable_cost_item_quantities_ui(self, cost_item: dict[str, Any]):
|
||||
quantities = CostSchedulesData.data["cost_quantities"]
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.props, "quantity_types", text="")
|
||||
# In IFC, all quantities of IfcCostTime should have 1 type.
|
||||
if quantities:
|
||||
quantity_class = cost_item["QuantityType"]
|
||||
row.label(text=quantity_class)
|
||||
else:
|
||||
row.prop(self.props, "quantity_types", text="")
|
||||
quantity_class = self.props.quantity_types
|
||||
|
||||
op = row.operator("bim.add_cost_item_quantity", text="", icon="ADD")
|
||||
op.cost_item = self.props.active_cost_item_id
|
||||
op.ifc_class = self.props.quantity_types
|
||||
op.ifc_class = quantity_class
|
||||
|
||||
for quantity in CostSchedulesData.data["cost_quantities"]:
|
||||
for quantity in quantities:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=quantity["name"])
|
||||
row.label(text=quantity["value"])
|
||||
@@ -634,7 +644,7 @@ class BIM_UL_cost_items_trait:
|
||||
layout.label(text=cost_item["UnitBasisUnitSymbol"])
|
||||
|
||||
def draw_total_quantity_column(self, layout, cost_item):
|
||||
if cost_item["TotalCostQuantity"]:
|
||||
if cost_item["TotalCostQuantity"] is not None:
|
||||
label = "{0:.2f}".format(cost_item["TotalCostQuantity"]) + f" {cost_item['UnitSymbol'] or '-'}"
|
||||
layout.label(text=label)
|
||||
else:
|
||||
@@ -745,9 +755,11 @@ class BIM_UL_product_cost_items(UIList):
|
||||
class BIM_PT_Costing_Tools(Panel):
|
||||
bl_label = "5D Tools"
|
||||
bl_idname = "BIM_PT_Costing_Tools"
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_region_type = "UI"
|
||||
bl_category = "4D/5D Toolkit"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_cost"
|
||||
|
||||
def draw(self, context):
|
||||
self.props = context.scene.BIMCostProperties
|
||||
|
||||
@@ -29,13 +29,9 @@ def register():
|
||||
if not bpy.app.background:
|
||||
bpy.utils.register_tool(workspace.CoveringTool, after={"bim.structural_tool"}, separator=False, group=False)
|
||||
bpy.types.Scene.BIMCoveringProperties = bpy.props.PointerProperty(type=prop.BIMCoveringProperties)
|
||||
# bpy.types.Object.BIMObjectSpatialProperties = bpy.props.PointerProperty(type=prop.BIMObjectSpatialProperties)
|
||||
# bpy.types.Scene.BIMSpatialManagerProperties = bpy.props.PointerProperty(type=prop.BIMSpatialManagerProperties)
|
||||
|
||||
|
||||
def unregister():
|
||||
if not bpy.app.background:
|
||||
bpy.utils.unregister_tool(workspace.CoveringTool)
|
||||
del bpy.types.Scene.BIMCoveringProperties
|
||||
# del bpy.types.Object.BIMObjectSpatialProperties
|
||||
# del bpy.types.Scene.BIMSpatialManagerProperties
|
||||
|
||||
@@ -28,13 +28,6 @@ from blenderbim.bim.ifc import IfcStore
|
||||
import blenderbim.bim.handler
|
||||
|
||||
|
||||
# declaring it here to avoid circular import problems
|
||||
class Operator:
|
||||
def execute(self, context):
|
||||
IfcStore.execute_ifc_operator(self, context)
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
class CoveringTool(WorkSpaceTool):
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_context_mode = "OBJECT"
|
||||
@@ -53,18 +46,19 @@ class CoveringTool(WorkSpaceTool):
|
||||
def draw_settings(cls, context, layout, ws_tool):
|
||||
CoveringToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
|
||||
|
||||
|
||||
def add_layout_hotkey(layout, text, hotkey, description):
|
||||
args = ["covering", layout, text, hotkey, description]
|
||||
tool.Blender.add_layout_hotkey_operator(*args)
|
||||
|
||||
|
||||
class CoveringToolUI:
|
||||
@classmethod
|
||||
def draw(cls, context, layout, ifc_element_type = None):
|
||||
def draw(cls, context, layout, ifc_element_type=None):
|
||||
cls.layout = layout
|
||||
cls.props = context.scene.BIMModelProperties
|
||||
cls.covering_props = context.scene.BIMCoveringProperties
|
||||
|
||||
|
||||
row = cls.layout.row(align=True)
|
||||
if not tool.Ifc.get():
|
||||
row.label(text="No IFC Project", icon="ERROR")
|
||||
@@ -82,8 +76,6 @@ class CoveringToolUI:
|
||||
|
||||
cls.draw_default_interface()
|
||||
|
||||
|
||||
|
||||
@classmethod
|
||||
def draw_header_interface(cls):
|
||||
cls.draw_type_selection_interface()
|
||||
@@ -95,93 +87,35 @@ class CoveringToolUI:
|
||||
row = cls.layout.row(align=True)
|
||||
row.prop(data=cls.covering_props, property="ceiling_height", text="Ceiling Height")
|
||||
if AuthoringData.data["ifc_classes"]:
|
||||
active_obj = bpy.context.active_object
|
||||
element = tool.Ifc.get_entity(active_obj)
|
||||
collection = bpy.context.view_layer.active_layer_collection.collection
|
||||
collection_obj = collection.BIMCollectionProperties.obj
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_A")
|
||||
row.operator("bim.add_constr_type_instance", text="Add")
|
||||
|
||||
relating_type_id = int(cls.props.relating_type_id)
|
||||
type_material_usage = ifcopenshell.util.element.get_material(tool.Ifc.get().by_id(relating_type_id)).is_a()
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_A")
|
||||
row.operator("bim.add_instance_flooring_covering_from_cursor")
|
||||
|
||||
# PLEASE KEEP COMMENTS AS A REMINDER
|
||||
# elif element and bpy.context.selected_objects and element.is_a("IfcSpace"):
|
||||
# op. = row.operator("bim.add_istance_flooring_from_spaces"):
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_A")
|
||||
row.operator("bim.add_instance_ceiling_covering_from_cursor")
|
||||
|
||||
if (type_material_usage == "IfcMaterialLayerSet" and
|
||||
not bpy.context.selected_objects):
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_A")
|
||||
if tool.Ifc.get_entity(collection_obj):
|
||||
if AuthoringData.data["predefined_type"] == "FLOORING":
|
||||
op = row.operator("bim.add_instance_flooring_covering_from_cursor")
|
||||
elif AuthoringData.data["predefined_type"] == "CEILING":
|
||||
op = row.operator("bim.add_instance_ceiling_covering_from_cursor")
|
||||
else:
|
||||
op = row.operator("bim.add_constr_type_instance", text="Add")
|
||||
op.from_invoke = True
|
||||
if cls.props.relating_type_id.isnumeric():
|
||||
op.relating_type_id = int(cls.props.relating_type_id)
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_A")
|
||||
row.operator("bim.add_instance_flooring_coverings_from_walls")
|
||||
|
||||
else:
|
||||
op = row.operator("bim.add_constr_type_instance", text="Add")
|
||||
op.from_invoke = True
|
||||
if cls.props.relating_type_id.isnumeric():
|
||||
op.relating_type_id = int(cls.props.relating_type_id)
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_A")
|
||||
row.operator("bim.add_instance_ceiling_coverings_from_walls")
|
||||
|
||||
elif (AuthoringData.data["predefined_type"] == "FLOORING" and
|
||||
type_material_usage == "IfcMaterialLayerSet" and
|
||||
element and
|
||||
bpy.context.selected_objects and
|
||||
element.is_a("IfcWall")):
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_A")
|
||||
op = row.operator("bim.add_instance_flooring_coverings_from_walls")
|
||||
|
||||
elif (AuthoringData.data["predefined_type"] == "CEILING" and
|
||||
type_material_usage == "IfcMaterialLayerSet" and
|
||||
element and
|
||||
bpy.context.selected_objects and
|
||||
element.is_a("IfcWall")):
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_A")
|
||||
op = row.operator("bim.add_instance_ceiling_coverings_from_walls")
|
||||
|
||||
elif (element and
|
||||
bpy.context.selected_objects and
|
||||
element.is_a("IfcCovering") and
|
||||
# AuthoringData.data["predefined_type"] == "FLOORING" and
|
||||
AuthoringData.data["active_material_usage"] == "LAYER3"):
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_G")
|
||||
op = row.operator("bim.regen_selected_covering_object")
|
||||
|
||||
|
||||
|
||||
# elif AuthoringData.data["predefined_type"] == "CEILING":
|
||||
# row = cls.layout.row(align=True)
|
||||
# row.prop(data=cls.props, property="ceiling_height", text="ceiling height")
|
||||
# if element and bpy.context.selected_objects and element.is_a("IfcWall"):
|
||||
# op = row.operator("bim.add_instance_ceiling_coverings_from_walls")
|
||||
# elif element and bpy.context.selected_objects and element.is_a("IfcSpace"):
|
||||
# op. = row.operator("bim.add_istance_flooring_from_spaces"):
|
||||
# else:
|
||||
# op = row.operator("bim.add_instance_ceiling_from_cursor")
|
||||
# op = row.operator("bim.add_constr_type_instance", text="Add")
|
||||
# op.from_invoke = True
|
||||
# if cls.props.relating_type_id.isnumeric():
|
||||
# op.relating_type_id = int(cls.props.relating_type_id)
|
||||
else:
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_A")
|
||||
op = row.operator("bim.add_constr_type_instance", text="Add")
|
||||
op.from_invoke = True
|
||||
if cls.props.relating_type_id.isnumeric():
|
||||
op.relating_type_id = int(cls.props.relating_type_id)
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_G")
|
||||
row.operator("bim.regen_selected_covering_object")
|
||||
|
||||
@classmethod
|
||||
def draw_type_selection_interface(cls):
|
||||
@@ -211,7 +145,7 @@ class CoveringToolUI:
|
||||
op.ifc_class = cls.props.ifc_class
|
||||
|
||||
|
||||
class Hotkey(bpy.types.Operator, Operator):
|
||||
class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.covering_hotkey"
|
||||
bl_label = "Hotkey"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -227,7 +161,7 @@ class Hotkey(bpy.types.Operator, Operator):
|
||||
return operator.description or ""
|
||||
|
||||
def _execute(self, context):
|
||||
# self.props = context.scene.BIMCoveringProperties
|
||||
# self.props = context.scene.BIMCoveringProperties
|
||||
getattr(self, f"hotkey_{self.hotkey}")()
|
||||
|
||||
def invoke(self, context, event):
|
||||
@@ -241,20 +175,19 @@ class Hotkey(bpy.types.Operator, Operator):
|
||||
def hotkey_S_A(self):
|
||||
active_obj = bpy.context.active_object
|
||||
element = tool.Ifc.get_entity(active_obj)
|
||||
collection = bpy.context.view_layer.active_layer_collection.collection
|
||||
collection_obj = collection.BIMCollectionProperties.obj
|
||||
container = tool.Root.get_default_container()
|
||||
|
||||
if AuthoringData.data["predefined_type"] == "FLOORING":
|
||||
if element and bpy.context.selected_objects and element.is_a("IfcWall"):
|
||||
bpy.ops.bim.add_instance_flooring_coverings_from_walls()
|
||||
elif tool.Ifc.get_entity(collection_obj):
|
||||
elif container:
|
||||
bpy.ops.bim.add_instance_flooring_covering_from_cursor()
|
||||
else:
|
||||
bpy.ops.bim.add_constr_type_instance()
|
||||
elif AuthoringData.data["predefined_type"] == "CEILING":
|
||||
if element and bpy.context.selected_objects and element.is_a("IfcWall"):
|
||||
bpy.ops.bim.add_instance_ceiling_coverings_from_walls()
|
||||
elif tool.Ifc.get_entity(collection_obj):
|
||||
elif container:
|
||||
bpy.ops.bim.add_instance_ceiling_covering_from_cursor()
|
||||
else:
|
||||
bpy.ops.bim.add_constr_type_instance()
|
||||
@@ -264,9 +197,10 @@ class Hotkey(bpy.types.Operator, Operator):
|
||||
def hotkey_S_G(self):
|
||||
active_obj = bpy.context.active_object
|
||||
element = tool.Ifc.get_entity(active_obj)
|
||||
if (element and
|
||||
bpy.context.selected_objects and
|
||||
element.is_a("IfcCovering") and
|
||||
AuthoringData.data["active_material_usage"] == "LAYER3"):
|
||||
bpy.ops.bim.regen_selected_covering_object()
|
||||
|
||||
if (
|
||||
element
|
||||
and bpy.context.selected_objects
|
||||
and element.is_a("IfcCovering")
|
||||
and AuthoringData.data["active_material_usage"] == "LAYER3"
|
||||
):
|
||||
bpy.ops.bim.regen_selected_covering_object()
|
||||
|
||||
@@ -23,6 +23,7 @@ import ifccsv
|
||||
import logging
|
||||
import tempfile
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.selector
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.bim.module.drawing.scheduler as scheduler
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
@@ -72,7 +73,7 @@ class ReorderCsvAttribute(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
old = context.scene.CsvProperties.csv_attributes[self.old_index]
|
||||
new = context.scene.CsvProperties.csv_attributes[self.new_index]
|
||||
props = ["name", "header", "sort", "group", "varies_value", "summary"]
|
||||
props = ["name", "header", "sort", "group", "varies_value", "summary", "formatting"]
|
||||
for prop in props:
|
||||
value = getattr(new, prop)
|
||||
setattr(new, prop, getattr(old, prop))
|
||||
@@ -184,6 +185,8 @@ class ExportIfcCsv(bpy.types.Operator):
|
||||
|
||||
def invoke(self, context, event):
|
||||
props = context.scene.CsvProperties
|
||||
if props.format == "web":
|
||||
return self.execute(context)
|
||||
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, f".{props.format}")
|
||||
WindowManager = context.window_manager
|
||||
WindowManager.fileselect_add(self)
|
||||
@@ -221,6 +224,10 @@ class ExportIfcCsv(bpy.types.Operator):
|
||||
if attribute.formatting != "{{value}}" and "{{value}}" in attribute.formatting:
|
||||
formatting.append({"name": attribute.name, "format": attribute.formatting})
|
||||
|
||||
file_format = props.format
|
||||
if props.format == "web":
|
||||
file_format = "pd"
|
||||
|
||||
sep = props.csv_custom_delimiter if props.csv_delimiter == "CUSTOM" else props.csv_delimiter
|
||||
ifc_csv.export(
|
||||
ifc_file,
|
||||
@@ -228,7 +235,7 @@ class ExportIfcCsv(bpy.types.Operator):
|
||||
attributes,
|
||||
headers=headers,
|
||||
output=self.filepath,
|
||||
format=props.format,
|
||||
format=file_format,
|
||||
should_preserve_existing=props.should_preserve_existing,
|
||||
delimiter=sep,
|
||||
include_global_id=props.include_global_id,
|
||||
@@ -246,6 +253,11 @@ class ExportIfcCsv(bpy.types.Operator):
|
||||
if props.format != "csv" and props.should_generate_svg:
|
||||
schedule_creator = scheduler.Scheduler()
|
||||
schedule_creator.schedule(self.filepath, tool.Drawing.get_path_with_ext(self.filepath, "svg"))
|
||||
if props.format == "web":
|
||||
tool.Web.send_webui_data(
|
||||
extra_data=ifc_csv.dataframe.to_csv(index=False), extra_data_key="csv_data", event="csv_data"
|
||||
)
|
||||
self.report({"INFO"}, f"Data is exported to {props.format.upper()}.")
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -285,6 +297,7 @@ class ImportIfcCsv(bpy.types.Operator):
|
||||
if not props.should_load_from_memory:
|
||||
ifc_file.write(props.csv_ifc_file)
|
||||
refresh_ui_data()
|
||||
self.report({"INFO"}, "Data is imported to IFC.")
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ class CsvProperties(PropertyGroup):
|
||||
("csv", "csv", ""),
|
||||
("xlsx", "xlsx", ""),
|
||||
("ods", "ods", ""),
|
||||
("web", "web", ""),
|
||||
],
|
||||
name="Output format",
|
||||
default="csv",
|
||||
|
||||
@@ -87,6 +87,11 @@ class BIM_PT_ifccsv(Panel):
|
||||
|
||||
blenderbim.bim.helper.draw_filter(self.layout, props.filter_groups, SearchData, "csv")
|
||||
|
||||
row = layout.row(align=True)
|
||||
op = row.operator("bim.search", text="Select", icon="VIEWZOOM")
|
||||
op.property_group = "CsvProperties"
|
||||
layout.separator()
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.add_csv_attribute", icon="ADD")
|
||||
row.prop(props, "should_show_sort", icon="SORTSIZE", text="")
|
||||
@@ -123,3 +128,6 @@ class BIM_PT_ifccsv(Panel):
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.export_ifccsv", icon="EXPORT", text="Export IFC to " + props.format.upper())
|
||||
row.operator("bim.import_ifccsv", icon="IMPORT")
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -35,12 +35,12 @@ classes = (
|
||||
operator.PrintUnusedElementStats,
|
||||
operator.ProfileImportIFC,
|
||||
operator.PurgeHdf5Cache,
|
||||
operator.PurgeIfcLinks,
|
||||
operator.PurgeUnusedElementsByClass,
|
||||
operator.RewindInspector,
|
||||
operator.SelectExpressFile,
|
||||
operator.SelectHighPolygonMeshes,
|
||||
operator.SelectHighestPolygonMeshes,
|
||||
operator.ToggleDetailedIOSLogs,
|
||||
operator.ValidateIfcFile,
|
||||
prop.BIMDebugProperties,
|
||||
ui.BIM_PT_debug,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user