diff --git a/Pipfile b/Pipfile
index 6f22d9d76..9ff4d1f8a 100644
--- a/Pipfile
+++ b/Pipfile
@@ -9,6 +9,8 @@ pygments = "*"
sphinx = "*"
readthedocs-sphinx-ext = "*"
"doc8" = "*"
+urllib3 = "==1.24.2"
+jinja2 = "==2.10.1"
[dev-packages]
pylint = "<2.0.0"
diff --git a/Pipfile.lock b/Pipfile.lock
index e6e87c489..c91c83feb 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "df9393f239f6ab1cb7db0bba0d309313548c55cfeffc31f47ffcebfd04f619f6"
+ "sha256": "3015027cab3fe037fb0f242030478d824a607e6eff04919add4b768cd9985f38"
},
"pipfile-spec": 6,
"requires": {
@@ -32,10 +32,10 @@
},
"certifi": {
"hashes": [
- "sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7",
- "sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033"
+ "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5",
+ "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae"
],
- "version": "==2018.11.29"
+ "version": "==2019.3.9"
},
"chardet": {
"hashes": [
@@ -44,6 +44,14 @@
],
"version": "==3.0.4"
},
+ "colorama": {
+ "hashes": [
+ "sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d",
+ "sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"
+ ],
+ "markers": "sys_platform == 'win32'",
+ "version": "==0.4.1"
+ },
"doc8": {
"hashes": [
"sha256:2df89f9c1a5abfb98ab55d0175fed633cae0cf45025b8b1e0ee5ea772be28543",
@@ -76,43 +84,44 @@
},
"jinja2": {
"hashes": [
- "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
- "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
+ "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
+ "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
],
- "version": "==2.10"
+ "index": "pypi",
+ "version": "==2.10.1"
},
"markupsafe": {
"hashes": [
- "sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432",
- "sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b",
- "sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9",
- "sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af",
- "sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834",
- "sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd",
- "sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d",
- "sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7",
- "sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b",
- "sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3",
- "sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c",
- "sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2",
- "sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7",
- "sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36",
- "sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1",
- "sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e",
- "sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1",
- "sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c",
- "sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856",
- "sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550",
- "sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492",
- "sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672",
- "sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401",
- "sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6",
- "sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6",
- "sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c",
- "sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd",
- "sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1"
- ],
- "version": "==1.1.0"
+ "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
+ "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
+ "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
+ "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
+ "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
+ "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
+ "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
+ "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
+ "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
+ "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
+ "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
+ "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
+ "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
+ "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
+ "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
+ "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
+ "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
+ "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
+ "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
+ "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
+ "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
+ "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
+ "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
+ "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
+ "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
+ "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
+ "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
+ "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
+ ],
+ "version": "==1.1.1"
},
"packaging": {
"hashes": [
@@ -123,10 +132,10 @@
},
"pbr": {
"hashes": [
- "sha256:f59d71442f9ece3dffc17bc36575768e1ee9967756e6b6535f0ee1f0054c3d68",
- "sha256:f6d5b23f226a2ba58e14e49aa3b1bfaf814d0199144b95d78458212444de1387"
+ "sha256:6901995b9b686cb90cceba67a0f6d4d14ae003cd59bc12beb61549bdfbe3bc89",
+ "sha256:d950c64aeea5456bbd147468382a5bb77fe692c13c9f00f0219814ce5b642755"
],
- "version": "==5.1.1"
+ "version": "==5.2.0"
},
"pygments": {
"hashes": [
@@ -138,25 +147,25 @@
},
"pyparsing": {
"hashes": [
- "sha256:66c9268862641abcac4a96ba74506e594c884e3f57690a696d21ad8210ed667a",
- "sha256:f6c5ef0d7480ad048c054c37632c67fca55299990fff127850181659eea33fc3"
+ "sha256:1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a",
+ "sha256:9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03"
],
- "version": "==2.3.1"
+ "version": "==2.4.0"
},
"pytz": {
"hashes": [
- "sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9",
- "sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c"
+ "sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda",
+ "sha256:d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"
],
- "version": "==2018.9"
+ "version": "==2019.1"
},
"readthedocs-sphinx-ext": {
"hashes": [
- "sha256:42b1c63d63dd483a188b541599bd08a540b2d08ec2b166660179618b6ccc3bb0",
- "sha256:e73770f53a226f6db8199916a12bcee1808e0c0cbe028422668e8c1c7f2fa80c"
+ "sha256:21097cbb37c9a0590e2cb444b55bd87302fc8f69640fa2d4f2d113e98e9558ff",
+ "sha256:d0fd65a9dffc187da94136ff5485e5b3ea96a4734559b1adc7954c1bc1658aa3"
],
"index": "pypi",
- "version": "==0.5.16"
+ "version": "==0.5.17"
},
"requests": {
"hashes": [
@@ -167,9 +176,9 @@
},
"restructuredtext-lint": {
"hashes": [
- "sha256:82880a8de8a41bfc84f533744091b1ead8e2ab9ad6c0a3f60f4750ef6c802350"
+ "sha256:97b3da356d5b3a8514d8f1f9098febd8b41463bed6a1d9f126cf0a048b6fd908"
],
- "version": "==1.2.2"
+ "version": "==1.3.0"
},
"six": {
"hashes": [
@@ -187,19 +196,19 @@
},
"sphinx": {
"hashes": [
- "sha256:429e3172466df289f0f742471d7e30ba3ee11f3b5aecd9a840480d03f14bcfe5",
- "sha256:c4cb17ba44acffae3d3209646b6baec1e215cad3065e852c68cc569d4df1b9f8"
+ "sha256:9f3e17c64b34afc653d7c5ec95766e03043cc6d80b0de224f59b6b6e19d37c3c",
+ "sha256:c7658aab75c920288a8cf6f09f244c6cfdae30d82d803ac1634d9f223a80ca08"
],
"index": "pypi",
- "version": "==1.8.3"
+ "version": "==1.8.5"
},
"sphinx-rtd-theme": {
"hashes": [
- "sha256:02f02a676d6baabb758a20c7a479d58648e0f64f13e07d1b388e9bb2afe86a09",
- "sha256:d0f6bc70f98961145c5b0e26a992829363a197321ba571b31b24ea91879e0c96"
+ "sha256:00cf895504a7895ee433807c62094cf1e95f065843bf3acd17037c3e9a2becd4",
+ "sha256:728607e34d60456d736cc7991fd236afb828b21b82f956c5ea75f94c8414040a"
],
"index": "pypi",
- "version": "==0.4.2"
+ "version": "==0.4.3"
},
"sphinxcontrib-websupport": {
"hashes": [
@@ -210,10 +219,10 @@
},
"stevedore": {
"hashes": [
- "sha256:b92bc7add1a53fb76c634a178978d113330aaf2006f9498d9e2414b31fbfc104",
- "sha256:c58b7c231a9c4890cd3c2b5d2b23bd63fa807ff934d68579e3f6c3a1735e8a7c"
+ "sha256:7be098ff53d87f23d798a7ce7ae5c31f094f3deb92ba18059b1aeb1ca9fec0a0",
+ "sha256:7d1ce610a87d26f53c087da61f06f9b7f7e552efad2a7f6d2322632b5f932ea2"
],
- "version": "==1.30.0"
+ "version": "==1.30.1"
},
"typing": {
"hashes": [
@@ -226,34 +235,44 @@
},
"urllib3": {
"hashes": [
- "sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39",
- "sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22"
+ "sha256:4c291ca23bbb55c76518905869ef34bdd5f0e46af7afe6861e8375643ffee1a0",
+ "sha256:9a247273df709c4fedb38c711e44292304f73f39ab01beda9f6b9fc375669ac3"
],
- "version": "==1.24.1"
+ "index": "pypi",
+ "version": "==1.24.2"
}
},
"develop": {
"astroid": {
"hashes": [
- "sha256:0ef2bf9f07c3150929b25e8e61b5198c27b0dca195e156f0e4d5bdd89185ca1a",
- "sha256:fc9b582dba0366e63540982c3944a9230cbc6f303641c51483fa547dcc22393a"
+ "sha256:87de48a92e29cedf7210ffa853d11441e7ad94cb47bacd91b023499b51cbc756",
+ "sha256:d25869fc7f44f1d9fb7d24fd7ea0639656f5355fc3089cd1f3d18c6ec6b124c7"
],
- "version": "==1.6.5"
+ "version": "==1.6.6"
},
"backports.functools-lru-cache": {
"hashes": [
"sha256:9d98697f088eb1b0fa451391f91afb5e3ebde16bbdb272819fd091151fda4f1a",
"sha256:f0b0e4eba956de51238e17573b7087e852dfe9854afd2e9c873f73fc0ca0a6dd"
],
- "markers": "python_version == '2.7'",
+ "markers": "python_version < '3.4'",
"version": "==1.5"
},
+ "colorama": {
+ "hashes": [
+ "sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d",
+ "sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"
+ ],
+ "markers": "sys_platform == 'win32'",
+ "version": "==0.4.1"
+ },
"configparser": {
"hashes": [
- "sha256:5308b47021bc2340965c371f0f058cc6971a04502638d4244225c49d80db273a"
+ "sha256:8be81d89d6e7b4c0d4e44bcc525845f6da25821de80cb5e06e7e0238a2899e32",
+ "sha256:da60d0014fd8c55eb48c1c5354352e363e2d30bbf7057e5e171a468390184c75"
],
"markers": "python_version == '2.7'",
- "version": "==3.5.0"
+ "version": "==3.7.4"
},
"enum34": {
"hashes": [
@@ -270,15 +289,15 @@
"sha256:9ec02aa7d674acb8618afb127e27fde7fc68994c0437ad759fa094a574adb265",
"sha256:ec0a6cb848cc212002b9828c3e34c675e0c9ff6741dc445cab6fdd4e1085d1f1"
],
+ "markers": "python_version < '3.2'",
"version": "==3.2.0"
},
"isort": {
"hashes": [
- "sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af",
- "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8",
- "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497"
+ "sha256:01cb7e1ca5e6c5b3f235f0385057f70558b70d2f00320208825fa62887292f43",
+ "sha256:268067462aed7eb2a1e237fcb287852f22077de3fb07964e87e00f829eea2d1a"
],
- "version": "==4.3.4"
+ "version": "==4.3.17"
},
"lazy-object-proxy": {
"hashes": [
@@ -290,7 +309,6 @@
"sha256:2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e",
"sha256:2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6",
"sha256:320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b",
- "sha256:4e263e56b27ed395a6a8d0526f349e3fa9a58df68c849866a5befa988ba63d5a",
"sha256:50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5",
"sha256:5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff",
"sha256:61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd",
@@ -347,8 +365,7 @@
},
"wrapt": {
"hashes": [
- "sha256:4aea003270831cceb8a90ff27c4031da6ead7ec1886023b80ce0dfe0adf61533",
- "sha256:75b753eb0c8f2cf4fd4b551a5a9337cc225e345941977a5950de2678ffb75700"
+ "sha256:4aea003270831cceb8a90ff27c4031da6ead7ec1886023b80ce0dfe0adf61533"
],
"version": "==1.11.1"
}
diff --git a/bin/ControlzEx.pdb b/bin/ControlzEx.pdb
deleted file mode 100644
index 60d6fe2bb..000000000
Binary files a/bin/ControlzEx.pdb and /dev/null differ
diff --git a/bin/DocoptNet.pdb b/bin/DocoptNet.pdb
deleted file mode 100644
index e597db467..000000000
Binary files a/bin/DocoptNet.pdb and /dev/null differ
diff --git a/bin/LibGit2Sharp.pdb b/bin/LibGit2Sharp.pdb
deleted file mode 100644
index 752124697..000000000
Binary files a/bin/LibGit2Sharp.pdb and /dev/null differ
diff --git a/bin/MahApps.Metro.pdb b/bin/MahApps.Metro.pdb
deleted file mode 100644
index 8cd7cc10d..000000000
Binary files a/bin/MahApps.Metro.pdb and /dev/null differ
diff --git a/bin/Nett.pdb b/bin/Nett.pdb
deleted file mode 100644
index 758d2f76b..000000000
Binary files a/bin/Nett.pdb and /dev/null differ
diff --git a/bin/Newtonsoft.Json.pdb b/bin/Newtonsoft.Json.pdb
deleted file mode 100644
index 0cfd89345..000000000
Binary files a/bin/Newtonsoft.Json.pdb and /dev/null differ
diff --git a/bin/git2-4aecb64.pdb b/bin/git2-4aecb64.pdb
deleted file mode 100644
index bf2b4981f..000000000
Binary files a/bin/git2-4aecb64.pdb and /dev/null differ
diff --git a/bin/pyRevitLabs.Common.dll b/bin/pyRevitLabs.Common.dll
index 8aee76a60..1d9f8173f 100644
Binary files a/bin/pyRevitLabs.Common.dll and b/bin/pyRevitLabs.Common.dll differ
diff --git a/bin/pyRevitLabs.Common.pdb b/bin/pyRevitLabs.Common.pdb
deleted file mode 100644
index 242834af3..000000000
Binary files a/bin/pyRevitLabs.Common.pdb and /dev/null differ
diff --git a/bin/pyRevitLabs.CommonCLI.dll b/bin/pyRevitLabs.CommonCLI.dll
index 570f99c40..6dd1f8511 100644
Binary files a/bin/pyRevitLabs.CommonCLI.dll and b/bin/pyRevitLabs.CommonCLI.dll differ
diff --git a/bin/pyRevitLabs.CommonCLI.pdb b/bin/pyRevitLabs.CommonCLI.pdb
deleted file mode 100644
index 094f17e48..000000000
Binary files a/bin/pyRevitLabs.CommonCLI.pdb and /dev/null differ
diff --git a/bin/pyRevitLabs.CommonWPF.dll b/bin/pyRevitLabs.CommonWPF.dll
index 72636fc0a..e141a0e9c 100644
Binary files a/bin/pyRevitLabs.CommonWPF.dll and b/bin/pyRevitLabs.CommonWPF.dll differ
diff --git a/bin/pyRevitLabs.CommonWPF.pdb b/bin/pyRevitLabs.CommonWPF.pdb
deleted file mode 100644
index c8c8cd194..000000000
Binary files a/bin/pyRevitLabs.CommonWPF.pdb and /dev/null differ
diff --git a/bin/pyRevitLabs.Language.dll b/bin/pyRevitLabs.Language.dll
index 45179f461..e08423984 100644
Binary files a/bin/pyRevitLabs.Language.dll and b/bin/pyRevitLabs.Language.dll differ
diff --git a/bin/pyRevitLabs.Language.pdb b/bin/pyRevitLabs.Language.pdb
deleted file mode 100644
index c60a5f13f..000000000
Binary files a/bin/pyRevitLabs.Language.pdb and /dev/null differ
diff --git a/bin/pyRevitLabs.TargetApps.Revit.dll b/bin/pyRevitLabs.TargetApps.Revit.dll
index 2c176b6cc..162bf7e64 100644
Binary files a/bin/pyRevitLabs.TargetApps.Revit.dll and b/bin/pyRevitLabs.TargetApps.Revit.dll differ
diff --git a/bin/pyRevitLabs.TargetApps.Revit.pdb b/bin/pyRevitLabs.TargetApps.Revit.pdb
deleted file mode 100644
index 83ec29888..000000000
Binary files a/bin/pyRevitLabs.TargetApps.Revit.pdb and /dev/null differ
diff --git a/bin/pyRevitUpdater.exe b/bin/pyRevitUpdater.exe
deleted file mode 100644
index 3a13bff72..000000000
Binary files a/bin/pyRevitUpdater.exe and /dev/null differ
diff --git a/bin/pyrevit.exe b/bin/pyrevit.exe
index 7a409bf72..608ff450b 100644
Binary files a/bin/pyrevit.exe and b/bin/pyrevit.exe differ
diff --git a/bin/pyrevit.pdb b/bin/pyrevit.pdb
deleted file mode 100644
index 1abf6825a..000000000
Binary files a/bin/pyrevit.pdb and /dev/null differ
diff --git a/dev/WPFEdit/WPFEdit/WPFEdit.csproj b/dev/WPFEdit/WPFEdit/WPFEdit.csproj
index af0f406d2..d4ca04af7 100644
--- a/dev/WPFEdit/WPFEdit/WPFEdit.csproj
+++ b/dev/WPFEdit/WPFEdit/WPFEdit.csproj
@@ -192,6 +192,11 @@
MSBuild:Compile
Designer
+
+ Forms\ParameterItemStyle.xaml
+ MSBuild:Compile
+ Designer
+
Forms\ProgressBar.xaml
MSBuild:Compile
diff --git a/dev/pyRevitLabs/pyRevitLabs.Common/pyRevitLabs.Common.csproj b/dev/pyRevitLabs/pyRevitLabs.Common/pyRevitLabs.Common.csproj
index e75a5c3ad..52217be9d 100644
--- a/dev/pyRevitLabs/pyRevitLabs.Common/pyRevitLabs.Common.csproj
+++ b/dev/pyRevitLabs/pyRevitLabs.Common/pyRevitLabs.Common.csproj
@@ -29,10 +29,11 @@
none
false
bin\Release\
- TRACE
+
+
prompt
4
- AnyCPU
+ x64
false
@@ -103,7 +104,6 @@
-
-
+ copy "$(TargetPath)" "$(TargetDir)..\..\..\..\..\bin"
\ No newline at end of file
diff --git a/dev/pyRevitLabs/pyRevitLabs.CommonCLI/pyRevitLabs.CommonCLI.csproj b/dev/pyRevitLabs/pyRevitLabs.CommonCLI/pyRevitLabs.CommonCLI.csproj
index 0382b68f2..ebd8f773a 100644
--- a/dev/pyRevitLabs/pyRevitLabs.CommonCLI/pyRevitLabs.CommonCLI.csproj
+++ b/dev/pyRevitLabs/pyRevitLabs.CommonCLI/pyRevitLabs.CommonCLI.csproj
@@ -27,10 +27,11 @@
none
true
bin\Release\
- TRACE
+
+
prompt
4
- AnyCPU
+ x64
true
@@ -64,7 +65,6 @@
-
-
+ copy "$(TargetPath)" "$(TargetDir)..\..\..\..\..\bin"
\ No newline at end of file
diff --git a/dev/pyRevitLabs/pyRevitLabs.CommonWPF/pyRevitLabs.CommonWPF.csproj b/dev/pyRevitLabs/pyRevitLabs.CommonWPF/pyRevitLabs.CommonWPF.csproj
index 24c4397f8..c089a7ed3 100644
--- a/dev/pyRevitLabs/pyRevitLabs.CommonWPF/pyRevitLabs.CommonWPF.csproj
+++ b/dev/pyRevitLabs/pyRevitLabs.CommonWPF/pyRevitLabs.CommonWPF.csproj
@@ -27,10 +27,11 @@
none
true
bin\Release\
- TRACE
+
+
prompt
4
- AnyCPU
+ x64
false
@@ -103,7 +104,6 @@
-
-
+ copy "$(TargetPath)" "$(TargetDir)..\..\..\..\..\bin"
\ No newline at end of file
diff --git a/dev/pyRevitLabs/pyRevitLabs.DeffrelDB/pyRevitLabs.DeffrelDB.csproj b/dev/pyRevitLabs/pyRevitLabs.DeffrelDB/pyRevitLabs.DeffrelDB.csproj
index 17a744486..0e1532a3f 100644
--- a/dev/pyRevitLabs/pyRevitLabs.DeffrelDB/pyRevitLabs.DeffrelDB.csproj
+++ b/dev/pyRevitLabs/pyRevitLabs.DeffrelDB/pyRevitLabs.DeffrelDB.csproj
@@ -27,9 +27,11 @@
pdbonly
true
bin\Release\
- TRACE
+
+
prompt
4
+ x64
true
diff --git a/dev/pyRevitLabs/pyRevitLabs.Language/pyRevitLabs.Language.csproj b/dev/pyRevitLabs/pyRevitLabs.Language/pyRevitLabs.Language.csproj
index acab14cdc..374d60bf2 100644
--- a/dev/pyRevitLabs/pyRevitLabs.Language/pyRevitLabs.Language.csproj
+++ b/dev/pyRevitLabs/pyRevitLabs.Language/pyRevitLabs.Language.csproj
@@ -27,9 +27,11 @@
pdbonly
true
bin\Release\
- TRACE
+
+
prompt
4
+ x64
true
@@ -64,4 +66,7 @@
+
+ copy "$(TargetPath)" "$(TargetDir)..\..\..\..\..\bin"
+
\ No newline at end of file
diff --git a/dev/pyRevitLabs/pyRevitLabs.TargetApps.AutoCAD/pyRevitLabs.TargetApps.AutoCAD.csproj b/dev/pyRevitLabs/pyRevitLabs.TargetApps.AutoCAD/pyRevitLabs.TargetApps.AutoCAD.csproj
index 1b4f00f31..283100504 100644
--- a/dev/pyRevitLabs/pyRevitLabs.TargetApps.AutoCAD/pyRevitLabs.TargetApps.AutoCAD.csproj
+++ b/dev/pyRevitLabs/pyRevitLabs.TargetApps.AutoCAD/pyRevitLabs.TargetApps.AutoCAD.csproj
@@ -27,9 +27,11 @@
none
true
bin\Release\
- TRACE
+
+
prompt
4
+ x64
true
diff --git a/dev/pyRevitLabs/pyRevitLabs.TargetApps.Navisworks/pyRevitLabs.TargetApps.Navisworks.csproj b/dev/pyRevitLabs/pyRevitLabs.TargetApps.Navisworks/pyRevitLabs.TargetApps.Navisworks.csproj
index b40b77a0f..8ba772923 100644
--- a/dev/pyRevitLabs/pyRevitLabs.TargetApps.Navisworks/pyRevitLabs.TargetApps.Navisworks.csproj
+++ b/dev/pyRevitLabs/pyRevitLabs.TargetApps.Navisworks/pyRevitLabs.TargetApps.Navisworks.csproj
@@ -27,9 +27,11 @@
none
true
bin\Release\
- TRACE
+
+
prompt
4
+ x64
true
diff --git a/dev/pyRevitLabs/pyRevitLabs.TargetApps.Revit/Properties/AssemblyInfo.cs b/dev/pyRevitLabs/pyRevitLabs.TargetApps.Revit/Properties/AssemblyInfo.cs
index 8351c5dfb..032bd38b0 100644
--- a/dev/pyRevitLabs/pyRevitLabs.TargetApps.Revit/Properties/AssemblyInfo.cs
+++ b/dev/pyRevitLabs/pyRevitLabs.TargetApps.Revit/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.8.8.0")]
-[assembly: AssemblyFileVersion("0.8.8.0")]
+[assembly: AssemblyVersion("0.8.9.0")]
+[assembly: AssemblyFileVersion("0.8.9.0")]
diff --git a/dev/pyRevitLabs/pyRevitLabs.TargetApps.Revit/RevitController.cs b/dev/pyRevitLabs/pyRevitLabs.TargetApps.Revit/RevitController.cs
index 127250169..d124823e6 100644
--- a/dev/pyRevitLabs/pyRevitLabs.TargetApps.Revit/RevitController.cs
+++ b/dev/pyRevitLabs/pyRevitLabs.TargetApps.Revit/RevitController.cs
@@ -421,6 +421,10 @@ public class RevitProduct {
{"20181217_1515", ("19.2.0.65", "2019.2 (Update)")},
{"20190108_1515", ("19.2.1.1", "2019.2 (Full Install)")}, // reported by: https://twitter.com/JarodJSchultz/status/1100459171491676160
{"20190225_1515", ("19.2.10.7", "2019.2.1")}, // release notes https://up.autodesk.com/2019/RVT/Autodesk_Revit_2019_2_1_Readme.html
+
+ // 2020
+ {"20190327_2315", ("20.0.0.377", "2020 First Customer Ship")},
+ {"20190412_1200", ("20.0.1.2", "2020.0.1")},
};
private static Regex BuildNumberFinder = new Regex(@".*(?\d{8}_\d{4}).*");
diff --git a/dev/pyRevitLabs/pyRevitLabs.TargetApps.Revit/pyRevitLabs.TargetApps.Revit.csproj b/dev/pyRevitLabs/pyRevitLabs.TargetApps.Revit/pyRevitLabs.TargetApps.Revit.csproj
index 36a114a3a..5e436074a 100644
--- a/dev/pyRevitLabs/pyRevitLabs.TargetApps.Revit/pyRevitLabs.TargetApps.Revit.csproj
+++ b/dev/pyRevitLabs/pyRevitLabs.TargetApps.Revit/pyRevitLabs.TargetApps.Revit.csproj
@@ -29,9 +29,11 @@
none
true
bin\Release\
- TRACE
+
+
prompt
4
+ x64
true
@@ -40,12 +42,10 @@
- ..\..\..\..\..\..\..\..\Program Files\Autodesk\Revit 2019\RevitAPI.dll
- False
+ ..\..\..\..\..\..\..\..\Program Files\Autodesk\Revit 2020\RevitAPI.dll
- ..\..\..\..\..\..\..\..\Program Files\Autodesk\Revit 2019\RevitAPIUI.dll
- False
+ ..\..\..\..\..\..\..\..\Program Files\Autodesk\Revit 2020\RevitAPIUI.dll
diff --git a/dev/pyRevitLabs/pyRevitManager/Properties/AssemblyInfo.cs b/dev/pyRevitLabs/pyRevitManager/Properties/AssemblyInfo.cs
index 49b8f3f02..10ba5cca3 100644
--- a/dev/pyRevitLabs/pyRevitManager/Properties/AssemblyInfo.cs
+++ b/dev/pyRevitLabs/pyRevitManager/Properties/AssemblyInfo.cs
@@ -51,5 +51,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.9.7.0")]
-[assembly: AssemblyFileVersion("0.9.7.0")]
+[assembly: AssemblyVersion("0.9.8.0")]
+[assembly: AssemblyFileVersion("0.9.8.0")]
diff --git a/dev/pyRevitLabs/pyRevitManager/pyRevitManager.csproj b/dev/pyRevitLabs/pyRevitManager/pyRevitManager.csproj
index a6316da59..e31ce91ff 100644
--- a/dev/pyRevitLabs/pyRevitManager/pyRevitManager.csproj
+++ b/dev/pyRevitLabs/pyRevitManager/pyRevitManager.csproj
@@ -44,11 +44,12 @@
false
- AnyCPU
+ x64
pdbonly
true
- bin\Release\
- TRACE
+ ..\..\..\bin\
+
+
prompt
4
false
@@ -132,19 +133,26 @@
{614720ba-c0e3-4199-9a5e-d2468ffcbfe5}
pyRevitLabs.CommonCLI
+ False
+ False
{c5a03112-6ee1-415f-b53d-5d732d9f47ad}
pyRevitLabs.Common
+ False
+ False
{269fe01f-093a-4774-8017-fefc2342abf5}
pyRevitLabs.Language
+ False
+ False
{ed0fb7a2-e4a8-4490-a020-73140bfbce0b}
pyRevitLabs.TargetApps.Revit
False
+ False
@@ -172,6 +180,9 @@
1.0.2
+
+ 0.25.4
+
2.0.3
@@ -186,9 +197,9 @@
- copy "$(TargetDir)lib\win32\x64\git2-8e0b172.dll" "$(TargetDir)git2-8e0b172.dll"
+ copy "$(TargetDir)lib\win32\x64\git2-4aecb64.dll" "$(TargetDir)git2-4aecb64.dll"
rd /S /Q "$(TargetDir)lib"
-REM del /Q "$(TargetDir)*.pdb"
+del /Q "$(TargetDir)*.pdb"
REM del /Q "$(TargetDir)*.config"
REM del /Q "$(TargetDir)*.xml"
signtool sign /n "Ehsan Iran Nejad" /t http://timestamp.digicert.com /fd sha256 "$(TargetPath)"
diff --git a/dev/pyRevitLabs/pyRevitUpdater/pyRevitUpdater.csproj b/dev/pyRevitLabs/pyRevitUpdater/pyRevitUpdater.csproj
index e6c8a056d..1631b2bb0 100644
--- a/dev/pyRevitLabs/pyRevitUpdater/pyRevitUpdater.csproj
+++ b/dev/pyRevitLabs/pyRevitUpdater/pyRevitUpdater.csproj
@@ -40,13 +40,15 @@
false
- AnyCPU
+ x64
pdbonly
true
bin\Release\
- TRACE
+
+
prompt
4
+ false
pyRevit.ico
diff --git a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.xaml b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.xaml
index b27f4a475..6a4905b0b 100644
--- a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.xaml
+++ b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.xaml
@@ -375,6 +375,9 @@
Revit versions from here. This effectively removes the
pyRevit.addin manifest file from %appdata%/Autodesk/Revit/Addins folders.
+
+ Autodesk Revit 2020
+
Autodesk Revit 2019
diff --git a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/script.py b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/script.py
index 1c3e3c0c4..e6b8fa920 100644
--- a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/script.py
+++ b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/script.py
@@ -80,7 +80,8 @@ def __init__(self, xaml_file_name):
'2016': self.revit2016_cb,
'2017': self.revit2017_cb,
'2018': self.revit2018_cb,
- '2019': self.revit2019_cb}
+ '2019': self.revit2019_cb,
+ '2020': self.revit2020_cb}
self.set_image_source(self.lognone, 'lognone.png')
self.set_image_source(self.logverbose, 'logverbose.png')
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Analysis.panel/Tools.stack2/Inspect.pulldown/Find Referencing Sheets.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Analysis.panel/Tools.stack2/Inspect.pulldown/Find Referencing Sheets.pushbutton/script.py
index 5cc2079c1..1c91731c4 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Analysis.panel/Tools.stack2/Inspect.pulldown/Find Referencing Sheets.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Analysis.panel/Tools.stack2/Inspect.pulldown/Find Referencing Sheets.pushbutton/script.py
@@ -1,36 +1,35 @@
+"""Find all sheets referencing the current view.
+Especially useful for finding legends.
+"""
+#pylint: disable=import-error,invalid-name,broad-except
from pyrevit import revit, DB
+from pyrevit import forms
+from pyrevit import script
+__author__ = "{{author}}"
-__doc__ = 'Find all sheets referencing the current view.'\
- ' Especially useful for finding legends.'
-
-
-cl_views = DB.FilteredElementCollector(revit.doc)
-shts = cl_views.OfCategory(DB.BuiltInCategory.OST_Sheets)\
- .WhereElementIsNotElementType()\
- .ToElements()
-
-sheets = sorted(shts, key=lambda x: x.SheetNumber)
+output = script.get_output()
curview = revit.activeview
count = 0
-print('Searching All Sheets for {0} ID:{1}\n'.format(curview.Name, curview.Id))
-for s in sheets:
- vpsIds = [revit.doc.GetElement(x).ViewId for x in s.GetAllViewports()]
+
+print('Searching All Sheets for {} {}\n'
+ .format(curview.Name, output.linkify(curview.Id)))
+
+for sheet in revit.query.get_sheets(include_placeholders=False):
+ vps_ids = [revit.doc.GetElement(x).ViewId for x in sheet.GetAllViewports()]
curviewelements = DB.FilteredElementCollector(revit.doc)\
- .OwnedByView(s.Id)\
+ .OwnedByView(sheet.Id)\
.WhereElementIsNotElementType()\
.ToElements()
for el in curviewelements:
if isinstance(el, DB.ScheduleSheetInstance):
- vpsIds.append(el.ScheduleId)
+ vps_ids.append(el.ScheduleId)
- if curview.Id in vpsIds:
+ if curview.Id in vps_ids:
count += 1
- print('NUMBER: {0} NAME:{1}'
- .format(s.Parameter[DB.BuiltInParameter.SHEET_NUMBER].AsString().rjust(10),
- s.Parameter[DB.BuiltInParameter.SHEET_NAME].AsString().ljust(50)))
+ revit.report.print_sheet(sheet)
print('\n\nView is referenced on {0} sheets.'.format(count))
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Keynotes.pushbutton/keynotesdb.py b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Keynotes.pushbutton/keynotesdb.py
index 61720e1ec..9be3e1e3b 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Keynotes.pushbutton/keynotesdb.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Keynotes.pushbutton/keynotesdb.py
@@ -363,9 +363,14 @@ def get_keynotes_tree(conn):
for catroot_rkey in keynote_records:
if catroot_rkey.key in parents:
- catroot_rkey.children.extend(parents[catroot_rkey.key])
+ catroot_rkey.children.extend(
+ natsorted(
+ parents[catroot_rkey.key],
+ key=lambda x: x.key
+ )
+ )
- return sorted(cat_roots, key=lambda x: x.key)
+ return natsorted(cat_roots, key=lambda x: x.key)
def find(conn, key):
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Sheets.pulldown/ReOrder Sheets.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Sheets.pulldown/ReOrder Sheets.pushbutton/script.py
index bc494b273..239854d51 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Sheets.pulldown/ReOrder Sheets.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Sheets.pulldown/ReOrder Sheets.pushbutton/script.py
@@ -37,7 +37,7 @@ def __init__(self, xaml_file_name):
@property
def items_list(self):
- return self.items_dg.ItemsSource
+ return self.items_dg.ItemsSource or []
@items_list.setter
def items_list(self, value):
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Create Parallel Section.pushbutton/icon.png b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Create Parallel Section.pushbutton/icon.png
new file mode 100644
index 000000000..04581b6a1
Binary files /dev/null and b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Create Parallel Section.pushbutton/icon.png differ
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Create Parallel Section.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Create Parallel Section.pushbutton/script.py
new file mode 100644
index 000000000..c914b4381
--- /dev/null
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Create Parallel Section.pushbutton/script.py
@@ -0,0 +1,67 @@
+"""Create section parallel to the plane of selected walls or planar element."""
+#pylint: disable=import-error,invalid-name,broad-except
+from pyrevit import revit, DB
+from pyrevit import script
+
+# adapted from https://thebuildingcoder.typepad.com/blog/2012/06/create-section-view-parallel-to-wall.html
+__author__ = 'Source: Jeremy Tammik\nAdapted by: {{author}}'
+
+logger = script.get_logger()
+output = script.get_output()
+
+
+def create_section(wall, section_type):
+ # ensure wall is straight
+ line = wall.Location.Curve
+ # determine section box
+ p = line.GetEndPoint(0)
+ q = line.GetEndPoint(1)
+ v = q - p
+
+ bb = wall.get_BoundingBox(None)
+ minZ = bb.Min.Z
+ maxZ = bb.Max.Z
+
+ w = v.GetLength()
+ # h = maxZ - minZ
+ # d = wall.WallType.Width
+ offset = 0.1 * w
+
+ bbox_min = DB.XYZ(-w, minZ - offset, -offset)
+ bbox_max = DB.XYZ(w, maxZ + offset, 0)
+
+ midpoint = p + 0.5 * v
+ walldir = v.Normalize()
+ up = DB.XYZ.BasisZ
+ viewdir = walldir.CrossProduct(up)
+
+ t = DB.Transform.Identity
+ t.Origin = midpoint
+ t.BasisX = walldir
+ t.BasisY = up
+ t.BasisZ = viewdir
+
+ section_box = DB.BoundingBoxXYZ()
+ section_box.Transform = t
+ section_box.Min = bbox_min
+ section_box.Max = bbox_max
+
+ DB.ViewSection.CreateSection(revit.doc, section_type, section_box)
+
+
+def get_walls():
+ """retrieve wall from selection set"""
+ return [x for x in revit.get_selection() if isinstance(x, DB.Wall)]
+
+
+def get_section_viewfamily():
+ return revit.doc.GetDefaultElementTypeId(
+ DB.ElementTypeGroup.ViewTypeSection
+ )
+
+
+doc_section_type = get_section_viewfamily()
+
+with revit.Transaction("Create Parallel Section"):
+ for selected_wall in get_walls():
+ create_section(selected_wall, doc_section_type)
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/_layout b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/_layout
index 9de468458..b176eb39f 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/_layout
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/_layout
@@ -12,6 +12,7 @@ Find Used View Templates Filters
Copy View Templates to Open Documents
Toggle All Grid Bubbles in Current View
Match Title on Sheet in Open Docs
+Create Parallel Section
Add Views to Sheets
Remove Empty Tags
Remove Underlay From Selected Views
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.splitpushbutton/Match Properties.pushbutton/icon.png b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.splitpushbutton/Match Properties.pushbutton/icon.png
new file mode 100644
index 000000000..2413566ca
Binary files /dev/null and b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.splitpushbutton/Match Properties.pushbutton/icon.png differ
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.splitpushbutton/Match Properties.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.splitpushbutton/Match Properties.pushbutton/script.py
new file mode 100644
index 000000000..1775b7d6e
--- /dev/null
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.splitpushbutton/Match Properties.pushbutton/script.py
@@ -0,0 +1,140 @@
+"""Match instance or type properties between elements and their types.
+
+Shift+Click:
+Reapply the previous match properties.
+
+"""
+#pylint: disable=import-error,invalid-name,broad-except
+import pickle
+
+from pyrevit import revit, DB
+from pyrevit import forms
+from pyrevit import script
+
+__author__ = "{{author}}"
+
+logger = script.get_logger()
+output = script.get_output()
+
+
+class PropKeyValue(object):
+ """Storage class for matched property info and value."""
+ def __init__(self, name, datatype, value, istype):
+ self.name = name
+ self.datatype = datatype
+ self.value = value
+ self.istype = istype
+
+ def __repr__(self):
+ return str(self.__dict__)
+
+
+MEMFILE = script.get_document_data_file(
+ file_id='MatchSelectedProperties',
+ file_ext='pym',
+ add_cmd_name=False
+ )
+
+
+def get_source_properties(src_element):
+ """Return info on selected properties."""
+ props = []
+
+ src_type = revit.query.get_type(src_element)
+
+ selected_params = forms.select_parameter(
+ src_element,
+ title='Select Parameters',
+ multiple=True,
+ include_instance=True,
+ include_type=True
+ ) or []
+
+ logger.debug('Selected parameters: %s', [x.name for x in selected_params])
+
+ for sparam in selected_params:
+ logger.debug('Reading %s', sparam.name)
+ target = src_type if sparam.istype else src_element
+ tparam = target.LookupParameter(sparam.name)
+ if tparam:
+ if tparam.StorageType == DB.StorageType.Integer:
+ value = tparam.AsInteger()
+ elif tparam.StorageType == DB.StorageType.Double:
+ value = tparam.AsDouble()
+ elif tparam.StorageType == DB.StorageType.ElementId:
+ value = tparam.AsElementId().IntegerValue
+ else:
+ value = tparam.AsString()
+
+ props.append(
+ PropKeyValue(
+ name=sparam.name,
+ datatype=tparam.StorageType,
+ value=value,
+ istype=sparam.istype
+ ))
+
+ return props
+
+
+def pick_and_match_types(src_props):
+ """Match property values for selected types."""
+ with forms.WarningBar(title='Pick objects to match type properties:'):
+ while True:
+ dest_element = revit.pick_element()
+
+ if not dest_element:
+ break
+
+ dest_type = revit.query.get_type(dest_element)
+ if dest_type:
+ with revit.Transaction('Match Type Properties'):
+ for pkv in src_props:
+ logger.debug('Applying %s', pkv.name)
+ target = dest_type if pkv.istype else dest_element
+ logger.debug('Target is %s', target)
+ dparam = target.LookupParameter(pkv.name)
+ if dparam and pkv.datatype == dparam.StorageType:
+ if dparam.StorageType == DB.StorageType.ElementId:
+ dparam.Set(DB.ElementId(pkv.value))
+ else:
+ dparam.Set(pkv.value)
+
+
+def recall():
+ """Load last matched properties from memory."""
+ data = []
+ try:
+ with open(MEMFILE, 'r') as mf:
+ data = pickle.load(mf)
+ except Exception as ex:
+ logger.debug(
+ 'Failed loading matched properties from memory | %s', str(ex)
+ )
+ return data
+
+
+def remember(src_props):
+ """Save selected matched properties to memory."""
+ with open(MEMFILE, 'w') as mf:
+ pickle.dump(src_props, mf)
+
+
+# main
+source_props = []
+if __shiftclick__: #pylint: disable=undefined-variable
+ source_props = recall()
+ logger.debug('Recalled data: %s', source_props)
+
+if not source_props:
+ with forms.WarningBar(title='Pick source object:'):
+ source_element = revit.pick_element()
+
+ if source_element:
+ if not source_props:
+ source_props = get_source_properties(source_element)
+ remember(source_props)
+
+
+if source_props:
+ pick_and_match_types(source_props)
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.splitpushbutton/Match Properties.pushbutton/tooltip.mp4 b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.splitpushbutton/Match Properties.pushbutton/tooltip.mp4
new file mode 100644
index 000000000..2a71e4ab6
Binary files /dev/null and b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.splitpushbutton/Match Properties.pushbutton/tooltip.mp4 differ
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.splitpushbutton/_layout b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.splitpushbutton/_layout
index 00c18bccf..c9f4a5f93 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.splitpushbutton/_layout
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.splitpushbutton/_layout
@@ -1,2 +1,3 @@
Match
-Match Paint
\ No newline at end of file
+Match Paint
+Match Properties
\ No newline at end of file
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Make Pattern.pushbutton/patmaker.py b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Make Pattern.pushbutton/patmaker.py
index 9803c82a9..bf0eb1d3c 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Make Pattern.pushbutton/patmaker.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Make Pattern.pushbutton/patmaker.py
@@ -713,10 +713,10 @@ def _make_filledregion(fillpattern_name, fillpattern_id):
def _export_pat(revit_pat, export_dir):
pat_file_contents = revit_pat.get_pat_data()
- with open(op.join(export_dir,
- '{}.pat'.format(
- coreutils.cleanup_filename(revit_pat.name)
- )), 'w') as pat_file:
+ pat_file_name = coreutils.cleanup_filename(revit_pat.name)
+ pat_file_path = op.join(export_dir, '{}.pat'.format(pat_file_name))
+ logger.debug('Exporting pattern to: %s', pat_file_path)
+ with open(pat_file_path, 'w') as pat_file:
pat_file.write(pat_file_contents)
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit2.stack3/Edit.pulldown/Convert Line Styles.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit2.stack3/Edit.pulldown/Convert Line Styles.pushbutton/script.py
index 6d64e10bb..4134ddc41 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit2.stack3/Edit.pulldown/Convert Line Styles.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit2.stack3/Edit.pulldown/Convert Line Styles.pushbutton/script.py
@@ -23,7 +23,7 @@ def __str__(self):
return '{} ({} {} {})'.format(
self.name,
self.weight,
- self.colorhex,
+ self.color_hex,
self.pattern_name
)
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit2.stack3/Override.pulldown/Override VG.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit2.stack3/Override.pulldown/Override VG.pushbutton/script.py
index 82a87441d..c11cb9230 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit2.stack3/Override.pulldown/Override VG.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit2.stack3/Override.pulldown/Override VG.pushbutton/script.py
@@ -14,6 +14,8 @@
logger = script.get_logger()
selection = revit.get_selection()
+# select all individual elements inside a group
+selection.expand_groups()
def find_solid_fillpat():
diff --git a/extensions/pyRevitTemplates.extension/pyRevit.tab/Templates.panel/Cycle Family Types.pushbutton/icon.png b/extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/Cycle Family Types.pushbutton/icon.png
similarity index 100%
rename from extensions/pyRevitTemplates.extension/pyRevit.tab/Templates.panel/Cycle Family Types.pushbutton/icon.png
rename to extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/Cycle Family Types.pushbutton/icon.png
diff --git a/extensions/pyRevitTemplates.extension/pyRevit.tab/Templates.panel/Cycle Family Types.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/Cycle Family Types.pushbutton/script.py
similarity index 94%
rename from extensions/pyRevitTemplates.extension/pyRevit.tab/Templates.panel/Cycle Family Types.pushbutton/script.py
rename to extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/Cycle Family Types.pushbutton/script.py
index d8193a4c4..edaca0b02 100644
--- a/extensions/pyRevitTemplates.extension/pyRevit.tab/Templates.panel/Cycle Family Types.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/Cycle Family Types.pushbutton/script.py
@@ -4,7 +4,7 @@
from pyrevit import forms
__title__ = "Cycle\nTypes"
-__author__ = "{{author}}"
+__author__ = "{{author}}\nGui Talarico"
forms.check_familydoc(doc=revit.doc, exitscript=True)
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/_layout b/extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/_layout
index 2791049e7..2619420c9 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/_layout
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/_layout
@@ -1,3 +1,4 @@
ptools2
+Cycle Family Types
ptools
Wipe
\ No newline at end of file
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack3/Family.pulldown/Import Family Config.pushbutton/icon.png b/extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack3/Family.pulldown/Import Family Config.pushbutton/icon.png
new file mode 100644
index 000000000..ed68a2180
Binary files /dev/null and b/extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack3/Family.pulldown/Import Family Config.pushbutton/icon.png differ
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack3/Family.pulldown/Import Family Config.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack3/Family.pulldown/Import Family Config.pushbutton/script.py
new file mode 100644
index 000000000..9ffc9ff3f
--- /dev/null
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack3/Family.pulldown/Import Family Config.pushbutton/script.py
@@ -0,0 +1,230 @@
+"""Import family configurations from yaml file and modify current family.
+
+Family configuration file is expected to be a yaml file,
+providing info about the parameters and types to be created.
+
+The structure of this config file is as shown below:
+
+parameters:
+ :
+ type:
+ category:
+ instance:
+types:
+ :
+ :
+ :
+ ...
+
+
+Example:
+
+parameters:
+ Shelf Height (Upper):
+ type: Length
+ category: PG_GEOMETRY
+ instance: false
+types:
+ 24D"x36H":
+ Shelf Height (Upper): 3'-0"
+"""
+#pylint: disable=import-error,invalid-name,broad-except
+# TODO: fix parameter ordering
+from collections import namedtuple
+
+from pyrevit import coreutils
+from pyrevit import revit, DB
+from pyrevit import forms
+from pyrevit import script
+
+from winterops import yaml
+
+
+__author__ = "{{author}}"
+
+
+logger = script.get_logger()
+output = script.get_output()
+
+
+DEFAULT_TYPE = 'Text'
+DEFAULT_BIP_CATEGORY = 'PG_CONSTRUCTION'
+
+PARAM_SECTION_NAME = 'parameters'
+TYPES_SECTION_NAME = 'types'
+
+
+ParamConfig = \
+ namedtuple(
+ 'ParamConfig',
+ ['name', 'bicat', 'bitype', 'isinst', 'formula']
+ )
+
+
+ParamValueConfig = \
+ namedtuple(
+ 'ParamValueConfig',
+ ['name', 'value']
+ )
+
+
+TypeConfig = \
+ namedtuple(
+ 'TypeConfig',
+ ['name', 'param_values']
+ )
+
+
+def get_symbol(symbol_name):
+ for fsym in DB.FilteredElementCollector(revit.doc)\
+ .OfClass(DB.FamilySymbol)\
+ .ToElements():
+ name = revit.query.get_name(fsym)
+ if name == symbol_name:
+ return fsym.Id
+
+
+def get_param_config(param_name, param_opts):
+ # Extract parameter configurations from given dict
+ # extract configured values
+ param_bip_cat = coreutils.get_enum_value(
+ DB.BuiltInParameterGroup,
+ param_opts.get('category', DEFAULT_BIP_CATEGORY)
+ )
+ param_type = coreutils.get_enum_value(
+ DB.ParameterType,
+ param_opts.get('type', DEFAULT_TYPE)
+ )
+ param_isinst = param_opts.get('instance', 'false').lower() == 'true'
+ param_formula = param_opts.get('formula', None)
+
+ if not param_bip_cat:
+ logger.critical(
+ 'can not determine parameter category for %s', param_name
+ )
+ return
+ elif not param_type:
+ logger.critical(
+ 'can not determine parameter type', param_name
+ )
+ return
+
+ return ParamConfig(
+ name=param_name,
+ bicat=param_bip_cat,
+ bitype=param_type,
+ isinst=param_isinst,
+ formula=param_formula
+ )
+
+
+def ensure_param(param_name, param_opts):
+ # Create family parameter based on name and options
+ fm = revit.doc.FamilyManager
+ if param_name and param_opts:
+ logger.debug('ensuring parameter: %s', param_name)
+
+ # extract param config from dict
+ pcfg = get_param_config(param_name, param_opts)
+
+ if pcfg:
+ logger.debug('%s %s %s', pcfg.bicat, pcfg.bitype, pcfg.isinst)
+ fparam = revit.query.get_family_parameter(param_name, revit.doc)
+ if not fparam:
+ # create param in family doc
+ fparam = fm.AddParameter(
+ pcfg.name,
+ pcfg.bicat,
+ pcfg.bitype,
+ pcfg.isinst
+ )
+
+ if pcfg.formula:
+ fm.SetFormula(fparam, pcfg.formula)
+
+ return fparam
+
+
+def ensure_params(fconfig):
+ param_cfgs = fconfig.get(PARAM_SECTION_NAME, None)
+ if param_cfgs:
+ for pname, popts in param_cfgs.items():
+ ensure_param(pname, popts)
+
+
+def get_type_config(type_name, type_opts):
+ if type_name and type_opts:
+ pvalue_cfgs = []
+ for pname, pvalue in type_opts.items():
+ pvalue_cfgs.append(ParamValueConfig(name=pname, value=pvalue))
+
+ return TypeConfig(name=type_name, param_values=pvalue_cfgs)
+
+
+def ensure_type(type_config):
+ fm = revit.doc.FamilyManager
+ # extract type config from dict
+ logger.debug('%s %s', type_config.name, type_config.param_values)
+ ftype = revit.query.get_family_type(type_config.name, revit.doc)
+ if not ftype:
+ # create type in family doc
+ ftype = fm.NewType(type_config.name)
+
+ return ftype
+
+
+def ensure_types(fconfig):
+ fm = revit.doc.FamilyManager
+ type_cfgs = fconfig.get(TYPES_SECTION_NAME, None)
+ if type_cfgs:
+ for tname, topts in type_cfgs.items():
+ logger.debug('ensuring type: %s', tname)
+ tcfg = get_type_config(tname, topts)
+ if tcfg:
+ ftype = ensure_type(tcfg)
+ if ftype:
+ logger.debug('setting type values: %s', tname)
+ fm.CurrentType = ftype
+ for pvcfg in tcfg.param_values:
+ fparam = \
+ revit.query.get_family_parameter(
+ pvcfg.name,
+ revit.doc
+ )
+ logger.debug('setting value for: %s', pvcfg.name)
+ if fparam:
+ if fparam.StorageType == DB.StorageType.ElementId \
+ and fparam.Definition.ParameterType == DB.ParameterType.FamilyType:
+ fsym_id = get_symbol(pvcfg.value)
+ fm.Set(fparam, fsym_id)
+ elif fparam.StorageType == DB.StorageType.String:
+ fm.Set(fparam, pvcfg.value)
+ elif fparam.StorageType == DB.StorageType.Integer \
+ and fparam.Definition.ParameterType.YesNo:
+ fm.Set(fparam, 1 if pvcfg.value.lower() == 'true' else 0)
+ else:
+ fm.SetValueString(fparam, pvcfg.value)
+ else:
+ logger.warning('can not find parameter: %s', pvcfg.name)
+
+
+def get_config_file():
+ # Get parameter definition yaml file from user
+ return forms.pick_file(file_ext='yaml')
+
+
+def load_configs(parma_file):
+ # Load contents of yaml file into an ordered dict
+ return yaml.load_as_dict(parma_file)
+
+
+if __name__ == '__main__':
+ forms.check_familydoc(exitscript=True)
+
+ family_cfg_file = get_config_file()
+ if family_cfg_file:
+ family_configs = load_configs(family_cfg_file)
+ logger.debug(family_configs)
+ with revit.Transaction('Import Params from Config'):
+ ensure_params(family_configs)
+ ensure_types(family_configs)
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/select.stack3/Select.pulldown/Select Element Types.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/select.stack3/Select.pulldown/Select Element Types.pushbutton/script.py
index 9b8b9d4c7..bb09154c6 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/select.stack3/Select.pulldown/Select Element Types.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/select.stack3/Select.pulldown/Select Element Types.pushbutton/script.py
@@ -22,7 +22,7 @@
all_options = list(element_types)
all_options.extend(graphic_styles)
-all_options.extend(['Fill Patterns', 'Area Schemes'])
+all_options.extend(['Fill Patterns', 'Area Schemes', 'Line Styles'])
selected_option = \
forms.CommandSwitchWindow.show(all_options,
message='Pick type category:')
@@ -33,10 +33,13 @@
fill_patterns = revit.query.get_types_by_class(DB.FillPatternElement,
doc=revit.doc)
selection.set_to(list(fill_patterns))
- if selected_option == 'Area Schemes':
+ elif selected_option == 'Area Schemes':
area_schemes = revit.query.get_types_by_class(DB.AreaScheme,
doc=revit.doc)
selection.set_to(list(area_schemes))
+ elif selected_option == 'Line Styles':
+ line_styles = revit.query.get_line_styles(doc=revit.doc)
+ selection.set_to(list(line_styles))
elif selected_option.startswith('Graphics Styles: '):
graphic_style_cat = selected_option.replace('Graphics Styles: ', '')
graphic_styles = \
diff --git a/pyrevitlib/pyrevit/compat.py b/pyrevitlib/pyrevit/compat.py
index 59072bfad..2bceb195e 100644
--- a/pyrevitlib/pyrevit/compat.py
+++ b/pyrevitlib/pyrevit/compat.py
@@ -11,10 +11,12 @@
PY3 = sys.version_info[0] == 3
IRONPY273 = sys.version_info[:3] == (2, 7, 3)
IRONPY277 = sys.version_info[:3] == (2, 7, 7)
+IRONPY279 = sys.version_info[:3] == (2, 7, 9)
#pylint: disable=C0103
safe_strtype = str
if PY2:
- safe_strtype = unicode #pylint: disable=E0602
+ # https://gist.github.com/gornostal/1f123aaf838506038710
+ safe_strtype = lambda x: unicode(x) #pylint: disable=E0602,unnecessary-lambda
diff --git a/pyrevitlib/pyrevit/coreutils/__init__.py b/pyrevitlib/pyrevit/coreutils/__init__.py
index de1fd2cca..f72f4df7d 100644
--- a/pyrevitlib/pyrevit/coreutils/__init__.py
+++ b/pyrevitlib/pyrevit/coreutils/__init__.py
@@ -841,9 +841,12 @@ def cleanup_filename(file_name):
Example:
>>> cleanup_filename('Myfile-(3).txt')
- "Myfile3.txt"
+ "Myfile(3).txt"
+
+ >>> cleanup_filename('Perforations 1/8" (New)')
+ "Perforations 18 (New).txt"
"""
- return re.sub(r'[^\w_.)( -#]', '', file_name)
+ return re.sub(r'[^\w_.() -#]|["]', '', file_name)
def _inc_or_dec_string(str_id, shift):
diff --git a/pyrevitlib/pyrevit/forms/ParameterItemStyle.xaml b/pyrevitlib/pyrevit/forms/ParameterItemStyle.xaml
new file mode 100644
index 000000000..a06ae9774
--- /dev/null
+++ b/pyrevitlib/pyrevit/forms/ParameterItemStyle.xaml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pyrevitlib/pyrevit/forms/__init__.py b/pyrevitlib/pyrevit/forms/__init__.py
index 5b60bc84f..8b46cca40 100644
--- a/pyrevitlib/pyrevit/forms/__init__.py
+++ b/pyrevitlib/pyrevit/forms/__init__.py
@@ -8,7 +8,7 @@
import os
import os.path as op
import string
-from collections import OrderedDict
+from collections import OrderedDict, namedtuple
import threading
from functools import wraps
import datetime
@@ -49,6 +49,18 @@
WPF_VISIBLE = framework.Windows.Visibility.Visible
+XAML_FILES_DIR = op.dirname(__file__)
+
+
+ParamDef = namedtuple('ParamDef', ['name', 'istype'])
+"""Parameter definition tuple.
+
+Attributes:
+ name (str): parameter name
+ istype (bool): true if type parameter, otherwise false
+"""
+
+
class WPFWindow(framework.Windows.Window):
r"""WPF Window base class for all pyRevit forms.
@@ -77,8 +89,7 @@ def __init__(self, xaml_source, literal_string=False, handle_esc=True):
if not op.exists(xaml_source):
wpf.LoadComponent(self,
os.path.join(EXEC_PARAMS.command_path,
- xaml_source)
- )
+ xaml_source))
else:
wpf.LoadComponent(self, xaml_source)
else:
@@ -232,7 +243,7 @@ class TemplateUserInputWindow(WPFWindow):
def __init__(self, context, title, width, height, **kwargs):
"""Initialize user input window."""
WPFWindow.__init__(self,
- op.join(op.dirname(__file__), self.xaml_source),
+ op.join(XAML_FILES_DIR, self.xaml_source),
handle_esc=True)
self.Title = title or 'pyRevit'
self.Width = width
@@ -862,7 +873,7 @@ class TemplatePromptBar(WPFWindow):
def __init__(self, height=32, **kwargs):
"""Initialize user prompt window."""
WPFWindow.__init__(self,
- op.join(op.dirname(__file__), self.xaml_source))
+ op.join(XAML_FILES_DIR, self.xaml_source))
self.user_height = height
self.update_window()
@@ -1123,7 +1134,7 @@ class SearchPrompt(WPFWindow):
def __init__(self, search_db, width, height, **kwargs):
"""Initialize search prompt window."""
WPFWindow.__init__(self,
- op.join(op.dirname(__file__), 'SearchPrompt.xaml'))
+ op.join(XAML_FILES_DIR, 'SearchPrompt.xaml'))
self.Width = width
self.MinWidth = self.Width
self.Height = height
@@ -1716,10 +1727,9 @@ def select_swatch(title='Select Color Swatch', button_name='Select'):
>>> forms.select_swatch(title="Select Text Color")
...
"""
- itemplate_xaml_file = \
- os.path.join(op.dirname(__file__), "SwatchContainerStyle.xaml")
- itemplate = \
- wpf.LoadComponent(Controls.ControlTemplate(), itemplate_xaml_file)
+ itemplate = utils.load_ctrl_template(
+ os.path.join(XAML_FILES_DIR, "SwatchContainerStyle.xaml")
+ )
swatch = SelectFromList.show(
colors.COLORS.values(),
title=title,
@@ -1751,15 +1761,13 @@ def select_image(images, title='Select Image', button_name='Select'):
title="Select Variation")
... 'C:/path/to/image1.png'
"""
- ptemplate_xaml_file = \
- os.path.join(op.dirname(__file__), "ImageListPanelStyle.xaml")
- ptemplate = \
- wpf.LoadComponent(Controls.ItemsPanelTemplate(), ptemplate_xaml_file)
+ ptemplate = utils.load_itemspanel_template(
+ os.path.join(XAML_FILES_DIR, "ImageListPanelStyle.xaml")
+ )
- itemplate_xaml_file = \
- os.path.join(op.dirname(__file__), "ImageListContainerStyle.xaml")
- itemplate = \
- wpf.LoadComponent(Controls.ControlTemplate(), itemplate_xaml_file)
+ itemplate = utils.load_ctrl_template(
+ os.path.join(XAML_FILES_DIR, "ImageListContainerStyle.xaml")
+ )
bitmap_images = {}
for imageobj in images:
@@ -1783,6 +1791,74 @@ def select_image(images, title='Select Image', button_name='Select'):
return bitmap_images.get(selected_image, None)
+def select_parameter(src_element,
+ title='Select Parameters',
+ button_name='Select',
+ multiple=True,
+ filterfunc=None,
+ include_instance=True,
+ include_type=True):
+ """Standard form for selecting parameters from given element.
+
+ Args:
+ src_element (DB.Element): source element
+ title (str, optional): list window title
+ button_name (str, optional): list window button caption
+ multiselect (bool, optional):
+ allow multi-selection (uses check boxes). defaults to True
+ filterfunc (function):
+ filter function to be applied to context items.
+ include_instance (bool, optional): list instance parameters
+ include_type (bool, optional): list type parameters
+
+ Returns:
+ list[:obj:`ParamDef`]: list of paramdef objects
+
+ Example:
+ >>> selected_params = forms.select_parameter(
+ ... src_element,
+ ... title='Select Parameters',
+ ... multiple=True,
+ ... include_instance=True,
+ ... include_type=True)
+ ... [, ]
+ """
+ param_defs = []
+ if include_instance:
+ # collect instance parameters
+ param_defs.extend(
+ [ParamDef(name=x.Definition.Name, istype=False)
+ for x in src_element.Parameters
+ if not x.IsReadOnly and x.StorageType != DB.StorageType.None]
+ )
+
+ if include_type:
+ # collect type parameters
+ src_type = revit.query.get_type(src_element)
+ param_defs.extend(
+ [ParamDef(name=x.Definition.Name, istype=True)
+ for x in src_type.Parameters
+ if not x.IsReadOnly and x.StorageType != DB.StorageType.None]
+ )
+
+ if filterfunc:
+ param_defs = filter(filterfunc, param_defs)
+
+ itemplate = utils.load_ctrl_template(
+ os.path.join(XAML_FILES_DIR, "ParameterItemStyle.xaml")
+ )
+ selected_params = SelectFromList.show(
+ param_defs,
+ title=title,
+ button_name=button_name,
+ width=450,
+ multiselect=multiple,
+ item_template=itemplate
+ )
+
+ return selected_params
+
+
def alert(msg, title=None, sub_msg=None, expanded=None, footer='',
ok=True, cancel=False, yes=False, no=False, retry=False,
warn_icon=True, options=None, exitscript=False):
@@ -1941,7 +2017,6 @@ def pick_folder(title=None):
return fb_dlg.SelectedPath
-
def pick_file(file_ext='', files_filter='', init_dir='',
restore_dir=True, multi_file=False, unc_paths=False):
r"""Pick file dialog to select a destination file.
diff --git a/pyrevitlib/pyrevit/forms/utils.py b/pyrevitlib/pyrevit/forms/utils.py
index 6cdb2d507..dc4b630cb 100644
--- a/pyrevitlib/pyrevit/forms/utils.py
+++ b/pyrevitlib/pyrevit/forms/utils.py
@@ -1,7 +1,7 @@
"""Utility functions to support forms module."""
from pyrevit import framework
-from pyrevit.framework import Imaging
+from pyrevit.framework import wpf, Controls, Imaging
def bitmap_from_file(bitmap_file):
@@ -19,3 +19,40 @@ def bitmap_from_file(bitmap_file):
bitmap.CacheOption = Imaging.BitmapCacheOption.OnLoad
bitmap.EndInit()
return bitmap
+
+
+def load_component(xaml_file, comp_type):
+ """Load WPF component from xaml file.
+
+ Args:
+ xaml_file (str): xaml file path
+ comp_type (System.Windows.Controls): WPF control type
+
+ Returns:
+ System.Windows.Controls: loaded WPF control
+ """
+ return wpf.LoadComponent(comp_type, xaml_file)
+
+
+def load_ctrl_template(xaml_file):
+ """Load System.Windows.Controls.ControlTemplate from xaml file.
+
+ Args:
+ xaml_file (str): xaml file path
+
+ Returns:
+ System.Windows.Controls.ControlTemplate: loaded control template
+ """
+ return load_component(xaml_file, Controls.ControlTemplate())
+
+
+def load_itemspanel_template(xaml_file):
+ """Load System.Windows.Controls.ItemsPanelTemplate from xaml file.
+
+ Args:
+ xaml_file (str): xaml file path
+
+ Returns:
+ System.Windows.Controls.ControlTemplate: loaded items-panel template
+ """
+ return load_component(xaml_file, Controls.ItemsPanelTemplate())
diff --git a/pyrevitlib/pyrevit/revit/db/query.py b/pyrevitlib/pyrevit/revit/db/query.py
index d63be838d..1ef2a2bd8 100644
--- a/pyrevitlib/pyrevit/revit/db/query.py
+++ b/pyrevitlib/pyrevit/revit/db/query.py
@@ -83,6 +83,19 @@ def get_name(element, title_on_sheet=False):
return Element.Name.__get__(element)
+def get_type(element):
+ """Get element type.
+
+ Args:
+ element (DB.Element): source element
+
+ Returns:
+ DB.ElementType: type object of given element
+ """
+ type_id = element.GetTypeId()
+ return element.Document.GetElement(type_id)
+
+
def get_symbol_name(element):
return get_name(element.Symbol)
@@ -1173,3 +1186,21 @@ def get_schema_field_values(element, schema):
field_values[field.FieldName] = value
return field_values
+
+
+def get_family_type(type_name, family_doc):
+ if family_doc.IsFamilyDocument:
+ for ftype in family_doc.FamilyManager.Types:
+ if ftype.Name == type_name:
+ return ftype
+ else:
+ raise PyRevitException('Document is not a family')
+
+
+def get_family_parameter(param_name, family_doc):
+ if family_doc.IsFamilyDocument:
+ for fparam in family_doc.FamilyManager.GetParameters():
+ if fparam.Definition.Name == param_name:
+ return fparam
+ else:
+ raise PyRevitException('Document is not a family')
diff --git a/pyrevitlib/pyrevit/revit/selection.py b/pyrevitlib/pyrevit/revit/selection.py
index 81364d0dc..2659b3673 100644
--- a/pyrevitlib/pyrevit/revit/selection.py
+++ b/pyrevitlib/pyrevit/revit/selection.py
@@ -100,6 +100,15 @@ def no_views(self):
def only_views(self):
return self.include(DB.View)
+ def expand_groups(self):
+ expanded_refs = []
+ for element in self.elements:
+ if isinstance(element, DB.Group):
+ expanded_refs.extend(element.GetMemberIds())
+ else:
+ expanded_refs.append(element.Id)
+ self._refs = expanded_refs
+
def _pick_obj(obj_type, pick_message, multiple=False, world=False):
refs = []
diff --git a/pyrevitlib/pyrevit/version b/pyrevitlib/pyrevit/version
index 6e8d609d9..a40b7f4dd 100644
--- a/pyrevitlib/pyrevit/version
+++ b/pyrevitlib/pyrevit/version
@@ -1 +1 @@
-4.6.19
\ No newline at end of file
+4.6.20
\ No newline at end of file
diff --git a/release/pyRevit.aip b/release/pyRevit.aip
index 7b1ee633e..cb1d8e252 100644
--- a/release/pyRevit.aip
+++ b/release/pyRevit.aip
@@ -1,5 +1,5 @@
-
+
@@ -27,10 +27,10 @@
-
+
-
+
@@ -89,10 +89,12 @@
+
+
@@ -143,6 +145,7 @@
+
@@ -175,6 +178,7 @@
+
@@ -438,7 +442,7 @@
-
+
@@ -670,6 +674,7 @@
+
@@ -816,6 +821,9 @@
+
+
+
@@ -850,7 +858,6 @@
-
@@ -907,7 +914,7 @@
-
+
@@ -1036,7 +1043,6 @@
-
@@ -1063,8 +1069,7 @@
-
-
+
@@ -1265,8 +1270,7 @@
-
-
+
@@ -1303,7 +1307,6 @@
-
@@ -1383,13 +1386,11 @@
-
-
+
-
@@ -1421,6 +1422,7 @@
+
@@ -4763,8 +4765,7 @@
-
-
+
@@ -4783,6 +4784,7 @@
+
@@ -4941,6 +4943,9 @@
+
+
+
@@ -5172,21 +5177,16 @@
-
+
-
-
-
-
+
+
-
-
-
+
-
-
+
@@ -5204,7 +5204,6 @@
-
@@ -5220,7 +5219,6 @@
-
@@ -5282,7 +5280,7 @@
-
+
@@ -5379,7 +5377,7 @@
-
+
@@ -5458,6 +5456,10 @@
+
+
+
+
@@ -5557,6 +5559,7 @@
+