diff --git a/.github/workflows/gh-build.yml b/.github/workflows/gh-build.yml new file mode 100644 index 00000000..c26103ff --- /dev/null +++ b/.github/workflows/gh-build.yml @@ -0,0 +1,31 @@ +name: gh-build + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + build_ghuser_components: + runs-on: windows-latest + name: Build components + steps: + - uses: actions/checkout@v2 + - uses: NuGet/setup-nuget@v1.0.5 + + - name: Install CPython and pythonnet package + run: | + choco install python --version=3.9.10 + python -m pip install pythonnet==3.0.3 + + - uses: compas-dev/compas-actions.ghpython_components@v5 + with: + source: src/gh/components + target: build + interpreter: cpython + + - uses: actions/upload-artifact@v2 + with: + name: ghuser-components + path: build \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index d1521ec4..b5ab7242 100644 --- a/.gitmodules +++ b/.gitmodules @@ -14,3 +14,6 @@ [submodule "deps/loguru"] path = deps/loguru url = https://github.com/emilk/loguru.git +[submodule "deps/pybind11"] + path = deps/pybind11 + url = https://github.com/pybind/pybind11.git \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 3033fdb5..d3d19170 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,12 @@ if(NOT GIT_SUBMOD_RESULT EQUAL "0") message(FATAL_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules") endif() +#-------------------------------------------------------------------------- +# pre-compiled definitions +#-------------------------------------------------------------------------- +if(SILENT_LOGGING) + target_compile_definitions(${PROJECT_NAME} PRIVATE SILENT_LOGGING=true) +endif() #-------------------------------------------------------------------------- # pre-compiled definitions diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0e9e1d38..76957eba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,13 +48,120 @@ git add .gitmodules git commit -m "Remove a submodule name" ``` +--- +# Python +DiffCheck is distributed as a Python Grasshopperr plug-in via yak and its source code via PyPI. The plug-in is composed by a series of `.ghuser` components. + +There are 3 ways you can contribute to the Python GH plug-in: +1. By adding new components to the plug-in. +2. By fixing bugs of existing components in the plug-in. +3. By adding new functionalities to existing components in the plug-in. + +Before committing to the repository you need to have tested the components in the Grasshopper environment and be sure that this is working correctly. Also, provide a sufficient documentation in the PR (for now) please. + +Follow these steps to develop and test the Python GH plug-in: +- [GHPy: A) preparation](#ghpy-a-preparation) +- [GHPy: B) development/debug](#ghpy-b-developmentdebug) +- [GHPy: C) Release](#ghpy-c-release) +- [GHPy: D) Documentation](#ghpy-d-documentation) + +## GHPy: A) preparation +Download this repo if you haven't already. +```terminal +git clone https://github.com/diffCheckOrg/diffCheck.git +``` + +Next, if you used diffCheck before as an end-user clean all the `diffCheck folders` in the following directory (the last name will change): +```terminal +C:\Users\\.rhinocode\py39-rh8\site-envs\default-wMh5LZL3 +``` +> note that if you drop an official released diffCheck component from yak, this one will have the `#r : diffCheck==` notation at the top of the script. Get rid of all these release components before to start and be sur to erase again the previous folders (they recreated each time `#r : diffCheck` is called). + +Build the package from the py source code's directory: +```py +python setup.py sdist bdist_wheel +``` + +Lastly, install the pip pacakge from the repository in editable mode. This way, all the modifications made to the source code of the repository will be reflected in the installed package. Open a terminal and run the following command (replace the path with where you download the repository): +```terminal +C:\Users\\.rhinocode\py39-rh8\python.exe -m pip install -e "\src\gh\diffCheck" +``` + +For your info the packages is installed in `C:\Users\andre\.rhinocode\py39-rh8\Lib\site-packages`. + +That's it you are now a contributor to the diffCheck! We raccomand to not download anymore from yak package but rather use the source code in the repository. If you want the latest diffCheck, checkout and pull the main. + +## GHPy: B) development/debug + +### B.1) Code structure +For DiffCheck there are 2 main folders in the repository: +* `src/gh/diffCheck/components` here you can add new components or modify existing ones (for more info on how to create one we point you to [this documentation](https://github.com/compas-dev/compas-actions.ghpython_components)). Here we call the +* `src/gh/diffCheck/diffCheck` this is our package where the core functionalities are implemented. + +### B.2) Developing component's content +The idea is to start by developing the content of the component in the file `src/gh/diffCheck/diffCgeck_app.py`. This would be a simple script that contains the logic of the component. Once the script `diffCheck_app.py` is working correctly, you can move the code to the component file in the `src/gh/diffCheck/components` folder. This is because the component file is the one that will be componentized and distributed via yak. + +We reccomand to use `VSCode` as IDE for developing the components. This is because it has a good integration with the `Grasshopper` environment and it is easy to debug the components. To set up the IDE follow these steps: +1. Install the `ScriptSync` extension for `VSCode`. +2. Install the `ScriptSync` from the yak manager in Rhino. +3. Open the `diffCheckApp.py` from the `src/gh/diffCheck/components` folder you are working on in `VSCode`, and set its path to the ScriptSync ghcomponent. +4. If you modify the code in `VSCode`, the changes will be reflected in the Grasshopper component as soon as you save in `VSCode` again the `code.py`. +5. Once your code is working, prepare the code and componentize it. + +If you want to use the GHEditor it's ok but everytime you modify the pakcage or the component's code, after any modifications you need to restart the Python interpreter from the ScriptEditor (`Tools > Reload Python3 (CPython) Engine`) and recompute the solution in Grasshopper. + +### B.3) Componentize the code +Prepare your component as explained here. You can componentize it locally and test it in Grasshopper. Here's how to componentize: +```terminal +python f:\diffCheck\src\gh\util\componentizer_cpy.py --ghio "C:\Users\andre\.nuget\packages\grasshopper\8.2.23346.13001\lib\net48\" .\src\gh\components\ .\build\gh +``` +> Note that you need to find the path to your GHIO folder. This is the folder where the `Grasshopper.dll` is located. E.g. You can find it in the `nuget` folder in the Rhino installation directory. + +Once you are sure that the component is working correctly, you can push the changes to the repository. + +## GHPy: C) Release +The release will be made via CI from main. As a contributor you don't need to worry about this. The plug-in is componentized, pushed to yak/PyPI and the user can download the latest version from yak. + +## GHPy: D) Documentation +More to come. + + + + --- # C++ ### Naming & synthax convention Here's the naming convention for this project: - ` `: lowerCamelCase. -- `type PrivateVariable`: public member of a class +- `type PublicVariable`: public member of a class - `type m_PrivateVariable`: Hungarian notation with UpperCamelCase for private class members. - `static type s_StaticVariable`: Hungarian notation with UpperCamelCase for static members of class. - `APP_SPEC`: Constants with SNAKE_UPPER_CASE. diff --git a/README.md b/README.md index dbae83cc..62e95560 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,12 @@ -# diffCheck -

+

+ +

+

+ +

-Temporary repository for diffCheck ## Roadmap diff --git a/assets/diagram/rhdfexporter.drawio b/assets/diagram/rhdfexporter.drawio new file mode 100644 index 00000000..a986f367 --- /dev/null +++ b/assets/diagram/rhdfexporter.drawio @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/logo/ViewCapture20240412_103050.png b/assets/logo/ViewCapture20240412_103050.png new file mode 100644 index 00000000..4ed5bf34 Binary files /dev/null and b/assets/logo/ViewCapture20240412_103050.png differ diff --git a/assets/logo/logo_pixelized.xcf b/assets/logo/logo_pixelized.xcf new file mode 100644 index 00000000..d250d23d Binary files /dev/null and b/assets/logo/logo_pixelized.xcf differ diff --git a/assets/logo/logo_pixelized_596_618.png b/assets/logo/logo_pixelized_596_618.png new file mode 100644 index 00000000..5da32d42 Binary files /dev/null and b/assets/logo/logo_pixelized_596_618.png differ diff --git a/assets/logo/logo_pixelized_64_64.png b/assets/logo/logo_pixelized_64_64.png new file mode 100644 index 00000000..9c63053c Binary files /dev/null and b/assets/logo/logo_pixelized_64_64.png differ diff --git a/assets/logo/logo_pixelized_64_64.xcf b/assets/logo/logo_pixelized_64_64.xcf new file mode 100644 index 00000000..00cc168c Binary files /dev/null and b/assets/logo/logo_pixelized_64_64.xcf differ diff --git a/assets/logo/logo_pixelized_b.png b/assets/logo/logo_pixelized_b.png new file mode 100644 index 00000000..0b5eeb24 Binary files /dev/null and b/assets/logo/logo_pixelized_b.png differ diff --git a/assets/logo/logo_pixelized_bw.png b/assets/logo/logo_pixelized_bw.png new file mode 100644 index 00000000..8f758a05 Binary files /dev/null and b/assets/logo/logo_pixelized_bw.png differ diff --git a/assets/logo/logo_pixelized_bw.xcf b/assets/logo/logo_pixelized_bw.xcf new file mode 100644 index 00000000..5d9363f2 Binary files /dev/null and b/assets/logo/logo_pixelized_bw.xcf differ diff --git a/assets/logo/logo_pixelized_bwg.png b/assets/logo/logo_pixelized_bwg.png new file mode 100644 index 00000000..c3342242 Binary files /dev/null and b/assets/logo/logo_pixelized_bwg.png differ diff --git a/assets/logo/logo_pixelized_bwg.xcf b/assets/logo/logo_pixelized_bwg.xcf new file mode 100644 index 00000000..e01e042a Binary files /dev/null and b/assets/logo/logo_pixelized_bwg.xcf differ diff --git a/assets/logo/logo_pixelized_bwvioelt.png b/assets/logo/logo_pixelized_bwvioelt.png new file mode 100644 index 00000000..3a55b576 Binary files /dev/null and b/assets/logo/logo_pixelized_bwvioelt.png differ diff --git a/assets/logo/logo_pixelized_bwvioelt_background.png b/assets/logo/logo_pixelized_bwvioelt_background.png new file mode 100644 index 00000000..2ab3daea Binary files /dev/null and b/assets/logo/logo_pixelized_bwvioelt_background.png differ diff --git a/assets/logo/logo_pixelized_extracolor.png b/assets/logo/logo_pixelized_extracolor.png new file mode 100644 index 00000000..3917e1f2 Binary files /dev/null and b/assets/logo/logo_pixelized_extracolor.png differ diff --git a/assets/logo/logo_pixelized_extracolor.xcf b/assets/logo/logo_pixelized_extracolor.xcf new file mode 100644 index 00000000..c0774616 Binary files /dev/null and b/assets/logo/logo_pixelized_extracolor.xcf differ diff --git a/assets/logo/logo_raw.png b/assets/logo/logo_raw.png new file mode 100644 index 00000000..87292a01 Binary files /dev/null and b/assets/logo/logo_raw.png differ diff --git a/assets/logo/logotests.3dm b/assets/logo/logotests.3dm new file mode 100644 index 00000000..4a19bf17 Binary files /dev/null and b/assets/logo/logotests.3dm differ diff --git a/assets/logo/logotests.3dmbak b/assets/logo/logotests.3dmbak new file mode 100644 index 00000000..94756b83 Binary files /dev/null and b/assets/logo/logotests.3dmbak differ diff --git a/deps/eigen b/deps/eigen index e63d9f6c..9700fc84 160000 --- a/deps/eigen +++ b/deps/eigen @@ -1 +1 @@ -Subproject commit e63d9f6ccb7f6f29f31241b87c542f3f0ab3112b +Subproject commit 9700fc847a39e98dfb7bd85331b5206641050e04 diff --git a/diffCheckErrors.log b/diffCheckErrors.log index 092b5e99..f104f3b2 100644 --- a/diffCheckErrors.log +++ b/diffCheckErrors.log @@ -1,4 +1,4 @@ arguments: loguru -Current dir: F:\diffCheck +Current dir: C:\Users\localuser\diffCheck File verbosity level: -2 date time ( uptime ) [ thread name/id ] file:line v| diff --git a/diffCheckEvery.log b/diffCheckEvery.log deleted file mode 100644 index 20fc75ab..00000000 --- a/diffCheckEvery.log +++ /dev/null @@ -1,6 +0,0 @@ -arguments: loguru -Current dir: F:\diffCheck -File verbosity level: 9 -date time ( uptime ) [ thread name/id ] file:line v| -2024-03-30 12:53:29.971 ( 0.001s) [main thread ] loguru.cpp:841 INFO| Logging to 'diffCheckEvery.log', mode: 'w', verbosity: 9 -2024-03-30 12:53:29.971 ( 0.001s) [main thread ] loguru.cpp:841 INFO| Logging to 'diffCheckErrors.log', mode: 'w', verbosity: -2 diff --git a/examples/exporter.ghx b/examples/exporter.ghx new file mode 100644 index 00000000..983270d9 --- /dev/null +++ b/examples/exporter.ghx @@ -0,0 +1,965 @@ + + + + + + + + 0 + 2 + 2 + + + + + + + 1 + 0 + 8 + + + + + + 6d414e49-3182-4495-b3f1-09564af81365 + Shaded + 1 + + 100;102;0;255 + + + 100;0;150;0 + + + + + + 638485274587794356 + + false + exporter.ghx + + + + + 0 + + + + + + 84 + 292 + + 1.2750001 + + + + + 0 + + + + + + + 0 + + + + + 2 + + + + + Robert McNeel & Associates + 00000000-0000-0000-0000-000000000000 + Grasshopper + 8.6.24101.5001 + + + + + RhinoCodePluginGH, Version=8.6.24101.5001, Culture=neutral, PublicKeyToken=552281e97c755530 + 8.6.24101.5001 + + 066d0a87-236f-4eae-a0f4-9e42f5327962 + RhinoCodePluginGH + + + + + + + + 9 + + + + + c9b2d725-6f87-4b07-af90-bd9aefef68eb + 066d0a87-236f-4eae-a0f4-9e42f5327962 + DFXMLExporter + + + + + + true + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAABg2lDQ1BJQ0MgcHJvZmlsZQAAKM+VkTlIA0EYhT8TJcEDC1OIWGyhVgqiopYSxSAoSIzgVbi7MVHIbsJugo2lYCtYeDRehY21tha2giB4gFhbWCnaiKz/bIQEIYIDw3y8mfeYeQOBg4xpudXdYNl5Jx6LajOzc1romWpC1DFAWDfd3MTUaIKK4+OWKrXedKks/jcakkuuCVWa8JCZc/LCi8L9q/mc4h3hiLmsJ4VPhTsduaDwvdKNIr8oTvscUJkRJxEfFo4Ia+kyNsrYXHYs4T7htqRlS35gpshJxWuKrUzB/LmnemH9kj09pXSZrcQYY4JJNAwKrJAhT5estigucdmPVvC3+P5JcRniWsEUxwhZLHTfj/qD3926qd6eYlJ9FGqePO+tHUJb8LXpeZ+Hnvd1BMFHuLBL/uwBDL6LvlnS2vahcR3OLkuasQ3nG9D8kNMd3ZeCMgOpFLyeyDfNQtM11M4Xe/vZ5/gOEtLV+BXs7kFHWrIXKrw7XN7bn2f8/oh+A2ixcqM29OAgAAAACXBIWXMAAC4iAAAuIgGq4t2SAAAAB3RJTUUH6AQHCzcfT87vFgAAAEZJREFUSEu1yKEBADAIwDCO5n/2QGQnYjJze18xS8wSs8QsMUvMErPELDFLzBKzxCwxS8wSs8QsMUvMErPELDFLzBIzs/cABgWAzBU/nmQAAAAASUVORK5CYII= + + 710c15eb-570f-4237-9cb8-afdde0961b0a + true + false + true + DFXMLExporter + XMLout + 1 + + false + false + false + + + + + + 183 + 45 + 171 + 84 + + + 290 + 87 + + + + + + 4 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 3 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + + + + + true + Press button to export xml + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA6xJREFUSEvVVTlLXGEUHRUHkXHfHRWXcd/3DRVcQBFUVAzaCYKC+AsGohYGDQiipYV2VpLSykawjCIuaOGCgiZFgoVmNImc3HPnPRHHLVXIgcu8ecu59557vu+z/Cs4vLy8fsgv/iLeSbwNfn5+n+fn57G+vo61tTWsrq5iZWUFy8vLWFxcxNTUFAYGBtDa2orq6mqkpqZCCrqQT61uhhfg4+PTLh/+WlhYQHl5uUZZWRlKSkpQVFSE/Px85OTkICMjQ4mTkpKQlZUFm8125e3t7TRonoU1KCjo29LSErq6urQ6RlVVlSZiksLCQuTm5ippWloaUlJSNJKTkyEJroXD7qZ6Ar6+vh/6+/t/j42NoaamBnV1dRq8ZhJ2UlxcrF1kZ2cjPT1dyRMTE7UTKe5WpPpk0HnAER0dfTM7O4uGhgYlrq+vR0tLC+bm5rC7uwsT29vbmJycREFBARwOhyaIj49HXFwcZ8Euit2UDyDar3V2dqK3t1dlYYKenh4cHR0ZtJ44ODjQd5mA5DExMQgJCbmTJBsG7T1aw8PDXSSk1pSD1R8eHhpUnnC5XPq7v7+vw2YCUQAJCQkQF14JZ5+bWgYr1X+pqKgAg4NkkpmZGSV4Cufn5+jo6MDZ2Zn+Hx8fh91uR1RUlCZhR9LFd+G2WWTy78PCwlwk5/BoRSZh+0/h4uICTU1NatORkRG9t7Ozg9jYWERGRiI0NFQHL9dcqNMWyXSZmZmp3mYwCa14c3OjHz+ESc73aVEOmaBc1D8iIoIz0ER5eXlc3ZdMMC32uqa3zUS8fpyAspjktCfdQxKCCSiPKIHg4GB9R1zFDj5KWGzUiz5m2wwuooe2JDmty2esnOR8f2hoSJ9vbW1p9ZSHnXC9yFzdMzDQZ7Var/gxHcHfiYkJ/ZidtLW16T0+o74kZ/Wnp6f6jtPpvK+eBhGJuBbuXaSgd6kdlzxJWC0tSJycnGB4eFhb5/3BwUEcHx/rs729Pa2a5OystLT0Tug81gFRxr2EFjODzjKTPAWSc2YcLOXhjAIDA6m950ompItP8uItO+DCYVCO0dFRbG5uGrTAxsaGykLvs3IhVXuLbD+F5tm9iLCzC+rNvYWLxgy6hBJymNSbFYv7EBAQoM95NsgcX95NDTil5WvulrJ93IdJSjnMquUMgL+/v24r0jXJXz0PCKtI9ZVWraysRG1trRJQ3+bmZq20vb0d3Bi7u7t1Q2xsbHz7iWaA5+vjM/e1ePuZ/B/BYvkDKff7sf0Xzw8AAAAASUVORK5CYII= + + d48261d1-1866-4c21-a3eb-a7e98ef7a2f8 + i_dump + i_dump + true + 0 + true + 8c08df72-4af6-478d-b73d-4cb5062e929c + 1 + Press button to export xml + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 185 + 47 + 90 + 20 + + + 231.5 + 57 + + + + + + + + true + The name of the assembly to export. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA7xJREFUSEvVVUssnGEUHcRExPvNeBvvV7xf8Yh3YiFBlO4kbCS2No3Gqlg0BBuxYEeINGxs2AgLiVZiJSzstJW0upjpQ01O77nz/0Jpq6umJ7mZ3/zmnHvPvff7LP8Kdg8Pj8/yib+IJxKPg4+Pz+v5+Xns7e1hZ2cH29vb2NzcxNraGhYXFzExMYH+/n60tbWhqqoKqampkITeyk+tbobfwMvLq11++H1hYQFlZWUapaWlKC4uRmFhIfLz85GTk4OMjAwlTkpKQlZWFvz8/Byenp7PDJpfwhoYGPhhaWkJnZ2dmh2jsrIS7e3tMHFycqKkaWlpSElJ0UhOToYIOIXD5qZ6AN7e3i/6+vquR0dHUV1djdraWg0+z83NweVyGRJAc3Mz0tPTlTwxMVErkeS+iVWvDLp7sEdFRX2dnp5GQ0ODEtfX12vw+ezsDCsrKwY9MDk5qTbZ7XYViIuLQ2xsLHvBKorclLcg3u90dHSgt7dXbbktMDAwgOPj4zs2HR0d3REgeXR0NIKDg10i8sagvUFbWFjYl+7ubm0qPb9t0fLyMqamprTZp6enhgRQV1d3YxEFxAHEx8dDptAhnE/d1NJYyf5deXk5GJwWU4SVUOji4gItLS36bnZ21qAHxsbGVCAhIQE2mw2RkZEqQkGp4qNw+1mk889DQ0O/kJwjyFEkEbOl0NDQkO6COaZdXV0GPXBwcKDNpf8xMTGIiIhASEiIisozF/WlRZQ+ZWZm6mwzKFJQUICioiKNjY0NDA8P63fmDpyfnxsS0EpN/8PDw9kDFcrLy+N2f6LASxkvZ25uLkwhPpOMFTgcDoPqYYyMjGj2tEecQFBQkPJIVe4K6BP9YqmcCgaXKDs7WzNfXV3VZ37Hd1yunp4egx7Y399X35k97WEltFf66u6BgadWq9XBH3P9+cklOjw8xODgoD6b7+gvR/Py8lIFrq+vtVoze1YtFnEXbqZIwdmld1x5koyPjysBBfg3g1WaS7W7u6vviZmZGSWncElJiUvo7u0BUcqzhARcIhNOp1OPCY4iidmj9fV1XF1dGf/hxtbWFpqamhAQEEDv728yIVW8Eh+/MVtOxu3gnLOZ9JgNpeemLUKqIyyTcyU0vzyLCBuroN/Mls0zg6S00CRmQ2X64O/vr+95N0gff3+aGngms+zk5MjxcRMmKefczFruAPj6+up5JVWT/I/3AWEVq95zLCsqKlBTU6ME9Le1tVUz5aHHg5FbzfOrsbHx8TeaAd6vP9+5f4rH38n/ESyWH1B2wifz0XRNAAAAAElFTkSuQmCC + + 9808dcd4-0a56-4762-9ba9-bb0923820f02 + i_assembly_name + i_assembly_name + true + 0 + true + 642efa41-dbbd-47ee-a53e-e1f51ffa1f12 + 1 + The name of the assembly to export. + 3aceb454-6dbd-4c5b-9b6b-e71f8c1cdf88 + + + + + + 185 + 67 + 90 + 20 + + + 231.5 + 77 + + + + + + + + true + The directors where to export the xml file. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA7xJREFUSEvVVUssnGEUHcRExPvNeBvvV7xf8Yh3YiFBlO4kbCS2No3Gqlg0BBuxYEeINGxs2AgLiVZiJSzstJW0upjpQ01O77nz/0Jpq6umJ7mZ3/zmnHvPvff7LP8Kdg8Pj8/yib+IJxKPg4+Pz+v5+Xns7e1hZ2cH29vb2NzcxNraGhYXFzExMYH+/n60tbWhqqoKqampkITeyk+tbobfwMvLq11++H1hYQFlZWUapaWlKC4uRmFhIfLz85GTk4OMjAwlTkpKQlZWFvz8/Byenp7PDJpfwhoYGPhhaWkJnZ2dmh2jsrIS7e3tMHFycqKkaWlpSElJ0UhOToYIOIXD5qZ6AN7e3i/6+vquR0dHUV1djdraWg0+z83NweVyGRJAc3Mz0tPTlTwxMVErkeS+iVWvDLp7sEdFRX2dnp5GQ0ODEtfX12vw+ezsDCsrKwY9MDk5qTbZ7XYViIuLQ2xsLHvBKorclLcg3u90dHSgt7dXbbktMDAwgOPj4zs2HR0d3REgeXR0NIKDg10i8sagvUFbWFjYl+7ubm0qPb9t0fLyMqamprTZp6enhgRQV1d3YxEFxAHEx8dDptAhnE/d1NJYyf5deXk5GJwWU4SVUOji4gItLS36bnZ21qAHxsbGVCAhIQE2mw2RkZEqQkGp4qNw+1mk889DQ0O/kJwjyFEkEbOl0NDQkO6COaZdXV0GPXBwcKDNpf8xMTGIiIhASEiIisozF/WlRZQ+ZWZm6mwzKFJQUICioiKNjY0NDA8P63fmDpyfnxsS0EpN/8PDw9kDFcrLy+N2f6LASxkvZ25uLkwhPpOMFTgcDoPqYYyMjGj2tEecQFBQkPJIVe4K6BP9YqmcCgaXKDs7WzNfXV3VZ37Hd1yunp4egx7Y399X35k97WEltFf66u6BgadWq9XBH3P9+cklOjw8xODgoD6b7+gvR/Py8lIFrq+vtVoze1YtFnEXbqZIwdmld1x5koyPjysBBfg3g1WaS7W7u6vviZmZGSWncElJiUvo7u0BUcqzhARcIhNOp1OPCY4iidmj9fV1XF1dGf/hxtbWFpqamhAQEEDv728yIVW8Eh+/MVtOxu3gnLOZ9JgNpeemLUKqIyyTcyU0vzyLCBuroN/Mls0zg6S00CRmQ2X64O/vr+95N0gff3+aGngms+zk5MjxcRMmKefczFruAPj6+up5JVWT/I/3AWEVq95zLCsqKlBTU6ME9Le1tVUz5aHHg5FbzfOrsbHx8TeaAd6vP9+5f4rH38n/ESyWH1B2wifz0XRNAAAAAElFTkSuQmCC + + d8eb4d09-c5ce-4358-a4dc-869a7ee7fed5 + i_export_dir + i_export_dir + true + 0 + true + db74a3b5-1227-46f8-823f-2e8caadc27f9 + 1 + The directors where to export the xml file. + 3aceb454-6dbd-4c5b-9b6b-e71f8c1cdf88 + + + + + + 185 + 87 + 90 + 20 + + + 231.5 + 97 + + + + + + + + 1 + true + The breps of the structure. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA+RJREFUSEvVVVso5XsU3shOcr9Fg1w2uSvHXVJuiQe5ZDJvSvJE3mhy4sEpp0QuyS0e5PLAoFxeCJFSJi8k5VKSc3Dksrc5Zs70nfX99qY5Z88Y83Q6q1b7v+v3+9Za3/rW+mn+K9NZWFjcyy9+wF+Lv8xsbGy2+vr6sL6+jtXVVSwuLmJ+fh4TExMYGhpCc3MzysvLkZeXh5SUFAQFBUESOpOrWiPCM2ZlZZUvFz8NDg4iISFBeXx8PGJjYxETE4Po6GhEREQgJCREAfv7+yMsLAx2dnZ6S0vLtyaYb5rW0dHxj9HRURQVFans6MnJyUhKSsLw8DAeHh5wc3ODhYUF5ObmIjAwUHlAQAAkgEEwXhmhvmLW1ta/lJWV/dXQ0IDU1FSkpaU9Oak6PDxEd3c3ent7sbS0hNvbW/Xfz89PVSLJPQhV70xwZqbz9PT8s729HRkZGQo0PT0dmZmZWFtbg16vR2dnJyYnJ1FRUYGqqirU19fj6OhI9YdBvL292QtW8ZMR8gsT7ldJS2lpqaKFAQjORhP88vISDL65uYna2lrV6IGBAbS2tuLg4ABdXV3w8vKCs7PzZwny3gT7ZHlubm4fSkpKVFPJOQM8Zk7w4+NjjI+PY25uDisrKwp8enpaneE36WLlvr6+EBXqBfONEVoaK9n/lpiYCDrVwoaS8y/Bd3Z2VPYtLS04OztT3wTf29vD/v6+6sns7CyEZkWXVHEl2HYa6fzPrq6uHwhOCVKKIyMjMBgMZuAEGRsbQ0dHB87Pz3FxcaHO0Hp6enB9fQ0XFxelKnd3dw7qrxqJdB0aGqq0TWcQgl9dXZmBz8zMgBJmsxsbGxVVJycn2NjYUMpixdIDeHh4ICoqitN9zQAtIi9DZGQkHgPd39+ri18D7+/vR1tbG5qamlBZWYnq6mr1f3d3VwVxcnJSONILYwXkiXxRx5xOOjM7PT19Fryurk5JlZLd2tpS/AstSkmcfOmrsQcme6PVavXBwcFq/AsKCnB3d4fl5eUXg5MWZk8Vyjdn4UlFyqSK9zzEkWeTeIkV/Ai4TqdDXFzcZ4EzmwNaPHcJJUanqqgQypWqeQ6cjaV6srKy4ODgQO7NJ5kmVbyTgw+sgGPPcrkGqKipqSk1wTU1Ndje3v5H5gKq5C3K+Sgw39xFtFesgr3w8fFRQ0PPzs5WE0z5sjdcGWyoqA/29vbqDN8G6ePz29Rkb6VkQ3h4OGR9PLkMo6KBdDxmLW8AbG1t1VKUqgn+3feAphWqfucj8riTCEB+c3JyVKb5+fkoLCxEcXExuL+4FOXOy140k/F9/feb+z1/+Zv8PzKN5m9TzzRCUDHb/QAAAABJRU5ErkJggg== + + ff511bf7-48db-498c-85b4-744eab811099 + i_breps + i_breps + true + 1 + true + 09820e90-22d3-463f-aeb1-e7a483ab60c9 + 1 + The breps of the structure. + 2ceb0405-fdfe-403d-a4d6-8786da45fb9d + + + + + + 185 + 107 + 90 + 20 + + + 231.5 + 117 + + + + + + + + false + The string of xml to be exported. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 96834ab2-ec04-4d8b-bd36-310f89a199da + o_xml + o_xml + false + 0 + true + 0 + The string of xml to be exported. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 305 + 47 + 47 + 26 + + + 328.5 + 60.333332 + + + + + + + + false + The breps of the faces belonging to joints. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + a7380c0c-e690-4b7b-8b20-d2dd6945e4da + o_joints + o_joints + false + 0 + true + 0 + The breps of the faces belonging to joints. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 305 + 73 + 47 + 27 + + + 328.5 + 87 + + + + + + + + false + The breps of the faces belonging to sides. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 21a275d0-1f72-48ed-97d7-b2d5bae06a84 + o_sides + o_sides + false + 0 + true + 0 + The breps of the faces belonging to sides. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 305 + 100 + 47 + 26 + + + 328.5 + 113.666664 + + + + + + + + + + false + IyEgcHl0aG9uMwojIHJlcXVpcmVtZW50czogZGlmZkNoZWNrCgppbXBvcnQgU3lzdGVtCmltcG9ydCB0eXBpbmcKCmltcG9ydCBSaGlubwppbXBvcnQgUmhpbm8uR2VvbWV0cnkgYXMgcmcKCmZyb20gZ2hweXRob25saWIuY29tcG9uZW50YmFzZSBpbXBvcnQgZXhlY3V0aW5nY29tcG9uZW50IGFzIGNvbXBvbmVudAoKZnJvbSBkaWZmQ2hlY2suZGZfZ2VvbWV0cmllcyBpbXBvcnQgREZWZXJ0ZXgsIERGRmFjZSwgREZCZWFtLCBERkFzc2VtYmx5CmltcG9ydCBkaWZmQ2hlY2suZGZfdHJhbnNmb3JtYXRpb25zCmltcG9ydCBkaWZmQ2hlY2suZGZfam9pbnRfZGV0ZWN0b3IKaW1wb3J0IGRpZmZDaGVjay5kZl91dGlsCgoKY2xhc3MgREZYTUxFeHBvcnRlcihjb21wb25lbnQpOgogICAgZGVmIFJ1blNjcmlwdChzZWxmLAogICAgICAgICAgICBpX2R1bXA6IGJvb2wsCiAgICAgICAgICAgIGlfYXNzZW1ibHlfbmFtZTogc3RyLAogICAgICAgICAgICBpX2V4cG9ydF9kaXI6IHN0ciwKICAgICAgICAgICAgaV9icmVwczogU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuSUxpc3RbUmhpbm8uR2VvbWV0cnkuQnJlcF0pOgogICAgICAgICIiIgogICAgICAgICAgICBUaGlzIHJlYWQgYnJlcHMgZnJvbSBSaGlubywgY29udmVydHMgdGhlbSB0byBERkJlYW1zIGFuZCBERkFzc2VtYmxpZXMsIGFuZCBleHBvcnRzIHRoZW0gdG8gWE1MLgogICAgICAgICAgICAKICAgICAgICAgICAgOnBhcmFtIGlfZHVtcDogd2hldGhlciB0byBkdW1wIHRoZSB4bWwKICAgICAgICAgICAgOnBhcmFtIGlfZXhwb3J0X2RpcjogZGlyZWN0b3J5IHRvIGV4cG9ydCB0aGUgeG1sCiAgICAgICAgICAgIDpwYXJhbSBpX2JyZXBzOiBsaXN0IG9mIGJyZXBzCiAgICAgICAgIiIiCiAgICAgICAgIyBiZWFtcwogICAgICAgIGJlYW1zIDogdHlwaW5nLkxpc3RbREZCZWFtXSA9IFtdCiAgICAgICAgZm9yIGJyZXAgaW4gaV9icmVwczoKICAgICAgICAgICAgYmVhbSA9IERGQmVhbS5mcm9tX2JyZXAoYnJlcCkKICAgICAgICAgICAgYmVhbXMuYXBwZW5kKGJlYW0pCgogICAgICAgICMgYXNzZW1ibHkKICAgICAgICBhc3NlbWJseTEgPSBERkFzc2VtYmx5KGJlYW1zLCBpX2Fzc2VtYmx5X25hbWUpCgogICAgICAgICMgZHVtcCB0aGUgeG1sCiAgICAgICAgeG1sIDogc3RyID0gYXNzZW1ibHkxLnRvX3htbCgpCiAgICAgICAgaWYgaV9kdW1wOgogICAgICAgICAgICBhc3NlbWJseTEuZHVtcCh4bWwsIGlfZXhwb3J0X2RpcikKICAgICAgICBvX3htbCA9IHhtbAoKICAgICAgICAjIHNob3cgdGhlIGpvaW50L3NpZGUgZmFjZXMKICAgICAgICBvX2pvaW50cyA9IFtqZi50b19icmVwKCkgZm9yIGpmIGluIGFzc2VtYmx5MS5hbGxfam9pbnRfZmFjZXNdCiAgICAgICAgb19zaWRlcyA9IFtzZi50b19icmVwKCkgZm9yIHNmIGluIGFzc2VtYmx5MS5hbGxfc2lkZV9mYWNlc10KCiAgICAgICAgcmV0dXJuIG9feG1sLCBvX2pvaW50cywgb19zaWRlcw== + S + + + + + *.*.python + 3.* + + + + + + + + + + + 919e146f-30ae-4aae-be34-4d72f555e7da + Brep + + + + + Contains a collection of Breps (Boundary REPresentations) + true + 09820e90-22d3-463f-aeb1-e7a483ab60c9 + Brep + Brep + false + 0 + + + + + + 108 + 107 + 50 + 24 + + + 133.63321 + 119.357155 + + + + + + 1 + + + + + 6 + {0} + + + + + ba3151fb-3a8e-46c1-bdba-27ad41a4d1a2 + + + + + aa56315b-2905-4049-8c41-0cc8b39d864b + + + + + 322f4e22-d195-435e-b290-052cb2318277 + + + + + 7fc04154-255a-413f-a8a1-6ea034e1e779 + + + + + 5981a85d-0063-489b-8bd7-7a1ebe1453a7 + + + + + aeae5255-2a74-4040-9e44-e3aedf934485 + + + + + + + + + + + + + a8b97322-2d53-47cd-905e-b932c3ccd74e + Button + + + + + Button object with two values + False + True + 8c08df72-4af6-478d-b73d-4cb5062e929c + Button + dump! + false + 0 + + + + + + 53 + 46 + 102 + 22 + + + + + + + + + + 06953bda-1d37-4d58-9b38-4b3c74e54c8f + File Path + + + + + Contains a collection of file paths + false + All files|*.* + db74a3b5-1227-46f8-823f-2e8caadc27f9 + File Path + Path + false + 0 + + + + + + 108 + 87 + 50 + 24 + + + 133.05814 + 99.121376 + + + + + + 1 + + + + + 1 + {0} + + + + + false + F:\diffCheck\temp\ + + + + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + 642efa41-dbbd-47ee-a53e-e1f51ffa1f12 + Panel + + false + 0 + 0 + AssemblyTest + + + + + + 55 + 69 + 102 + 20 + + 0 + 0 + 0 + + 55.337097 + 69.41688 + + + + + + + 255;213;217;232 + + true + true + true + false + false + true + + + + + + + + + 537b0419-bbc2-4ff4-bf08-afe526367b2c + Custom Preview + + + + + Allows for customized geometry previews + true + 4646fc38-6159-4526-ae07-13f7dc4d54c6 + Custom Preview + Preview + + + + + + + 479 + 45 + 48 + 44 + + + 513 + 67 + + + + + + Geometry to preview + true + 086a1d3d-246b-49f6-a9b4-24689cf3e1fc + Geometry + G + false + a7380c0c-e690-4b7b-8b20-d2dd6945e4da + 1 + + + + + + 481 + 47 + 17 + 20 + + + 491 + 57 + + + + + + + + The material override + 3131a412-8e5e-44ab-883a-eaf4d47610d8 + Material + M + false + 4ab4fffe-a939-495b-828b-02fd527f45db + 1 + + + + + + 481 + 67 + 17 + 20 + + + 491 + 77 + + + + + + 1 + + + + + 1 + {0} + + + + + + 255;221;160;221 + + + 255;66;48;66 + + 0.5 + + 255;255;255;255 + + 0 + + + + + + + + + + + + + + + 537b0419-bbc2-4ff4-bf08-afe526367b2c + Custom Preview + + + + + Allows for customized geometry previews + true + aa8c3345-4c0f-4f8d-a8da-af99adc98f83 + Custom Preview + Preview + + + + + + + 480 + 92 + 48 + 44 + + + 514 + 114 + + + + + + Geometry to preview + true + 15b754a7-39d2-46c6-ab6a-283c1e8ca0c6 + Geometry + G + false + 21a275d0-1f72-48ed-97d7-b2d5bae06a84 + 1 + + + + + + 482 + 94 + 17 + 20 + + + 492 + 104 + + + + + + + + The material override + 4a3b2a65-efde-445a-b243-524560892e32 + Material + M + false + d8ed0f8f-5311-4c4b-ae32-f035c085b9d5 + 1 + + + + + + 482 + 114 + 17 + 20 + + + 492 + 124 + + + + + + 1 + + + + + 1 + {0} + + + + + + 255;221;160;221 + + + 255;66;48;66 + + 0.5 + + 255;255;255;255 + + 0 + + + + + + + + + + + + + + + 9c53bac0-ba66-40bd-8154-ce9829b9db1a + Colour Swatch + + + + + Colour (palette) swatch + 4ab4fffe-a939-495b-828b-02fd527f45db + Colour Swatch + Swatch + false + 0 + + 255;128;0;255 + + + + + + + 378 + 69 + 88 + 20 + + + 378.22855 + 69.73081 + + + + + + + + + + 9c53bac0-ba66-40bd-8154-ce9829b9db1a + Colour Swatch + + + + + Colour (palette) swatch + d8ed0f8f-5311-4c4b-ae32-f035c085b9d5 + Colour Swatch + Swatch + false + 0 + + 255;102;255;0 + + + + + + + 379 + 116 + 88 + 20 + + + 379.59103 + 116.77558 + + + + + + + + + + + + + + + iVBORw0KGgoAAAANSUhEUgAAAOEAAACWCAIAAACn9nhUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAABQkSURBVHhe7Zt5UNvnmcfZP3Yn/Xfbme1Mmp10ttvZncxsm3ZmG7dpuu1OszPNH9uuJ906WTtNnPgGHGNsDmMOcQiJQ6ALhEAS6ADEfRpsQAJxCt3iFEgIkJA47N0mTurpdNmvJOI42GS6ranfjJ/PPH79/k7phz6/531e/SCOIL4A7BIEq3zq6BpBsAc5SrAOOUqwDjlKsA45SrAOOUqwDjlKsA45SrAOOUqwDjlKsA45SrAOOUqwDjlKsA45SrAOOUqwDjlKsA45SrAOOUqwDjlKsA45SrAOOUqwDjlKsA45SrAOOUqwDjlKsA45SrAOOUqwDjlKsA45SrDOIToa/JMJBAJ753oArA+FNv7MrK+v77384wPn3Dv7AeBK93Z9ujkUR2OfqNvtdrlcaB4ZYHZ2Zhb/DgCH+3y+fZpiEZvM5qnpPx9mq9W6urr6eDXF2XB1lig4/8NgvcPhOIx74wvHoTiKBDA5OTU5OW212m02JwIdq9URi+iiw253GQzDKpVKo9FqHoG2tra2oaFxc3Mz8MnnhA8Mjo6Ojs/OLrrd858TMzMLsZib8zy4iHhwt8+NvT3xWlNTFqiKxBZ7G386MH5rawt3KTQNhULb29sbG/h/Y2cnvL0djoELX1lZsdlsjxxMnioOy9GBgaHJSZfVOj8yYh4bs6EzMeEwm93T0zPDw+apKZfT6ens7G9vbx8aGhp4FEajMT+/QK2uw6cVsxSdep1Oq9VPTc2YTNaDYnTUZjBMjYxYjEZzb69xfNyJjtE4jTUIk8m2b3/E2JgDgU3YeWLCNTHhjC5GNuFst26NTkxM7uzswK3o9f2/wfuPRQzobrXapFLpnTt3ICtSZnRg37TZV1wuv88HOVew28IC7hM3OXoojobDoc7OHpmsQSisPXPmUnJy9tWrOefOJSckpJw/n3zlSjY2KZVtPJ4kISEh8WA4nPz4hMTxSafPv7nsC9mcnrNnzzXUt6nVXXV1HQdFfX0vlyvGS1y7xsWrZ2eXJCamXr6ciTfA4Qh0up59++NsMll9RYUOfalUIxDUlJXV8PkVn7xKp0bTmZ5+bWJiHOlt7wr/MCJeRrLm2op/3esLLHkDi8tBRGjzbm5+UUlJMU44Pj4ul8udzomOjuUf/Xj12LF1h8W1vDDT29NtMpnsdjtVpYfkaLi5ub2srLa8XJWVVYzIyOAVFcmuXStMSEjl8yslEq1c3pyVVfSd73znW9/6pxdf/Pa++Pa3v4V4/fVficXi9fXg6loABSEmSyKRUCisqq+/oVZ3HhRabY9UqubxpPAMweXiGKVIVHvpUoZYXKvVdu/bH05nZvIzMgrl8sazZ5OSkjIQ6en5WB/boampLzU1ta6uDmlv7wqjhcdBoDgJBCBnwOcPLnk3FpdDi0sbHu/Gsm/DuxL0rQSCG1u3BoZ4PB7y5fz8fHd3N+pPh8M1Ojp188ZAerE4KbciN09gMAzOzc1RHj0URzEod3T0ZGTwszKLcnPLcjkCtJyc0pzskpycEnRgJ1LaxYvpL33vyJGXvn/kyA8ejhdf/O57753BCItxMHba6ER/XattRW67nwUfGRpNl0LRghae6XS9sBZqYhHtvj0RsFChaJZI1AJBNTTFgYiamia1em+H6FaJ3++/rws6Xq936SGWlyPtwuLyvMfv9njdnuW55aXFFc+Sf9G7ilhABIKr8HdnZ9tsNqMkXVxcRFXq9frGx8fa9A3vCwSNc6Z021tHs4+PGsZRj1IePRRHUW+trvqVKm2dulmna9NoWyCWVhcJXX0b1mh1bWpNs1rbrKtvb2jsbNR31Td0oI+2sbEL+6i1LTi2qaULH/nW1masEMSswuNZrKnBoNxZW9sOt6Lm7ckXExEDNBbRxlJgdIfY1sgOak1XnbK9qarrwVAr22ujpsbivrsqVRteBQFxUT6icIxdHaTBjNtkGrNYbFNT09HZISpsdGCdZXJqenxyuq3pxmCrc6TLZeqOBjqRcA63OyaHbdvbuIs3UXNjKJ+dnUXdCVOHjcaCvMKftpa07aYUffTsCc0P+7sN2EqOPn5HMdjBUZmscnTC5fHfGZqyzy6F7fNr9rlVtJYZn9m1bDA73IvBSZfHs3J7zD7faRy2zfpnlkKO+TUsznu3/IGPVoMfeXy3S0rL3G5X9HMKYCKRk5MjkSgqKupRQVZW6oqKKktKqpD/MLJjTEd7/ToPSTovr6ymplksrsNYj/qysFCCCrW4WFZeWiPTtSYOKBIHai4O1KBFiHT6upo2pbL1oKiqahgbG7tfjGIGfuvWYG/viFrd0tU1NDhovnVrorvb2Ndnamm50d1tMI5NqIuGFEd2ld/fH+oju4W/vNlv7Ozo6MzNzYWaarW6pqamp6env68v4eTZr+ae+u7ID19u/eqLWT8y9Bspj4LH7ygyBKbkp06dcs2sGqdcfIVUUq+WNzeKdbViXZ1YW1ukqODKRS03BzsGhltvDqo7O+u7e+VNjerODpG2VtHa3Dcytbi8M7sYXljezsvn8viC0NbdJV/YNeNNTLyoUjWiooV8qal5p05dPH/+yunT7588eQHlZnJyFgrKCxeunDqViAkZTE1Kuo5+fPzV1NTct946k53M5XY1xu1eitu9GLf7frS9eKVH0SDrgIvQGi3SZ7SNZNDYyooKjcFgvHP7NuY/mAZtboZ7evpQUl+8eO306UuYil24kPL22+cTE9OxGB+fKldreWfa0+J2EemfjdS43aKf2lM4l3j8Mi63AOWmVqvFjdfV1YXJk0qhqFKqhDq1qE6ubGwwGgw0ZwKP31HUaiiwOJycoWHbou+OY3bdPrs2sxh2LWzMejbROueD1hk/WsdcYHDCbnZ6Y5vmlrfml7c8K3dmPWE4uui9Pb+8nZvHhfHh8CbOjEHfaDSUllYoFK2YgSFBIptiJo4pOWbxcrkegUX0kTKRYjE9r65uwpqqqkZ0Kivra6VNnGZ13G5y3G5S3O7laJuU0q1UCHRIutgNh5SXK0tLq0tK5MjKOBaOVlfrr15NGTKMrAe3l32BtcCOvqlbIFDk54swF0TZnZ7OvX69KCurhMMpKyyskCoUOcdbM+J2Mx+KbNwZf39Lri3HTwnpc3p6GhbGvrR3Op0Y9D3zC57ZBc+cx7OwiHm9xWIhRx+/owCj4cqKr+eGwWiyG002tIYRm3HEZhixRhdtw7E10U0jow60pjHXrSFz/8BEa8fAoNEyPOrADjdujg0Pm5DAYvUoqgjksLo6fWVlQ1SdJkj5QNtUVbW3iK3RHZqjm5pj67GmrqI5W1+7z9G03trsSwUpKZyyMuWZM5cSElLRxsdHviZDGsbhKlVrcnKysrY+GP6NxxtcC2z33zTk5wuKiytLS6sQAkGkLS2VlZTIsLJYKEw7Lr/+t96sr++P9GeXZGfNtz8MorrFON7Z2dkX5cZDYKVer5+cnHyMzw6+oByKowB5AsWWy+l88PnnpxGZzy6YTCPt7V1ms3Pa7OzvN7zxxhsvv/zy17727JtvHnc658fHLVNT9t7ePszlY1+AI492d3dxueXQEUnxwUAqlUiQL/UIeIk1SIpIqFgvwsAp1wuFtSJRrUqkz2xURu3EcA9B0V5K7qyWF6uReq9dK8zPF5aVKZBKcRTyNBKqTNaIxYqKymAw8j4wJcc/vCUM07FnuY9mbmbO45xb2h+ziw5/YDkQ+Xoq8ix0cHAQMye0jwSbkFwpjx6WowCa4uf7SMKRRLuSmZmpUNS3tNxqbze8++65t946cfTo0WPHjj333HN5eaUdHYbW1oH8fL5YIgmGdnz+kMPlOX/hQmWlCnMmqVR7P2Akhua8vHIuV/LuuwmoC1GAJiamoUI9d+4yZlEQDjUrNuWlFefq1V+6l/qle1e/dC8F7TP3ria3ymtF+pjQaBHI0zhnrC+V6iAr5uzb23vz+hi4iujDoUeDTRuhT9rPRuSr09VVnA2jPMaHe/fuffzxxx9++OHdu3d/97uPf//7j6IrPv7tb3+LNagB/H7/3ks+rRyio58Dxi+Hw5GQEC+TqaXSeoynr7zyr8eO/er06dMnT5585pm/glIoOuFiYWFJRkbmevC2byW4urbBL+JDXziErHk/oCmG6czMomvXuCkpuQgM1kiK6ekFubnlHI4Am9LS8rG+iC+TyHSFCtX94CpUwgq1RPzp2R4KLW4Ao3EYZcbeu/9cYik/EnsrIs+ZEP7Vdb9/fSUa64HwtMWOW3R5eRlC9/f3O50O/ExGxzyDgx6r1bO0hEFoET8ieIxbfe9ETytPxlGAgqy3tzcvTyCR6DBAX76c9fzzz3/jG3/35S//9Suv/AR2isUakUhTUFA8O+MOhTaQfJCW/P4VobBaJFKLxZ8G0iRkKi9XwdRYOsTIDo9xEgT6SISxkgC7iUXqynLNp1EWWRNzEaeC7ujjDLEMHT2/hs+vNJnGog+ZIvP6/bF3QXsiRh57rgQwtULl6ok++VxY2hcb6xu/UWtbLl9OQo5EXYDJU39/n8cz/1/HZ3766kZNlde3YLVMTTY3N6Fm3Tv7U8wTcxTpAeaVlkp5PAmfLxUKla+99ovvfe/7r7zy4/j4KyKRCutzcwV6fesHH/xmNTreRR31lZVVCYV1MG9fwFRErAO30Ik5h3jQufv73w8Yj0xZXIzT1vJ4FYicnNJYB97jEFSlqalp09O2QHDTt7IejYB/NeRfC6+shn3+TS9iZXP5k0Dft7rpXw2vroXX1kPriEAIlxsIhoJBdFBfRsSuqqrCUI6q1Gw2w0W32z1kGLBPT4rkNac5ZfGpvAqpbGaGfqfkyTm6ubnZ1KRXqXQ3bhhv3jQVFwtRjDY0NCoUitdf/2VDQ3tv71Bf37BIJJ2cnNjYCEUe2a8F+XxedjYfVsGegwKqQbjiYjmG+OvXURuUR57H5qItR0bE1n37I3G+/34G6teiItmJE2dOnox/550Lb7xx8sSJ06gTkF8lEvWlS0nyGk0w/OHiUhDh8W5Y7POT026zxT1tcVusLqvNZbO77A6nA9McZ2SUdttmZ2zzM7a5aLsXLuucZ24Z2uHyl5aWpqenPR4PRnyv1wtNO1pb8oUCXu+Nlh3xUe2/5JaWzDrd0XnaU82TcRS1Fz6S8+fP1dU1KxSR32P6yU/+Dcqi/DKZTCkpV48de6e+vk+pbCstFV25muZfv7PkDducSxcuxJeWVpSVqQQCxUFRXl4LHWFnUlLWsWMn33kn/s033z1+/NSvf30OIsLvffujQkDKzM4uwSEcTllenhBa5+eL0IHTOBumYgUFhUh4SIGrkdnSht3uMBhGLBYnMqBl2o6wWiO/FGuxOKwWp9Xibu1obZ4R3liv7F37bKxK26xy75Lvzu3bjY2NExMTSKX3vyLVyOT/npedvF2m/t9/fnv6K9nSbLd1hvLok3EUP3eUYhwOh8cTR7/sbHnttaNZWZmowNLSUl966Uh6OhdFKjalp2cpVapQeBul3ubmVk9Pd2pqLrwpLVV8fmRllWRmFnO5UiTUwsKKtLQC9NGBlPv2LC2tgfRR75U4cyywiBZrEBxO+ejo+O3bO6g58ebD4fDY2HhDQ09ZWbVQqNBoOtXq9spKrVyOmRwOrO5oMVVpqpM/fu7y7lceii9f8b5YxEUN05acnLywMK/X67lcrkwmQ/rlpGe8+t57f6M//mr3N79e8vyV4pw5Jzn65Mb6UCiEYS4vr4zHqyopqcnOFnzzm//485//4oUXXvjZz45itsTjyXJzxVVVqjt3djBhwiEY9TC5Fovl8A8HHhQY2dEWFAgLCkSI/HwkRSGXK8YadGJb//DA/pmZfEh5f14PR0dHxySSOqTeU6cuvv32uTNnklAknD17+fz5K2gl5Q28Cv7JD/7i7d24dz4bb+3GXd3+h/fjk1WqhoyMDIz1w8PDELStrQ31QWtra6Ouvq6xWaXX1zY03ui/OTY2RmP9E3MUIEN0dfUqldq6uob6+ubKymouly8QiNTqBo2mESuVSs3ExCRs3jvgk0cD09OP/hugw8CCEd3pfFCU6C8kDOfniwsLK9EWFEjz8nAnoCNBh8+vKi/SpRelvvlR3IndR8Sxub9UVavvfnDXaDT29/ej5oGdeCHMnPBCbpdrxumacbjn3LOjuBXGxoL0Hf4TdBQgOUUjFA6Hdna2b0fZ2trEIgKbMPff9xca+Mxg7Z+XzzyNxBtYWFiorq6TyWqrq9VyeZ1cro519lqZtkRanDv5Otf+nwW2Xz0YHMt/yMypW6EdVOSYM/VG2Xv6+RAdHR03b94kR5+wo19QkM4hbjAYOCDWQ8HQpvd/wsuPiK3V/14PrOPGw0mQnlGXo38Qe6/3dEOO/vH8EYXiA1/5E38o5CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTrkKME65CjBOuQowTqfcZQg2GTPUYJgl7i4/wNojt0NUXmIGwAAAABJRU5ErkJggg== + + + + + \ No newline at end of file diff --git a/src/diffCheck.hh b/src/diffCheck.hh index 2e018738..5a299d98 100644 --- a/src/diffCheck.hh +++ b/src/diffCheck.hh @@ -2,6 +2,7 @@ #include #include +#include // diffCheck includes #include "diffCheck/log.hh" @@ -10,4 +11,5 @@ const diffCheck::Log LOG = diffCheck::Log(); #include "diffCheck/geometry/DFPointCloud.hh" #include "diffCheck/geometry/DFMesh.hh" #include "diffCheck/IOManager.hh" -#include "diffCheck/visualizer.hh" \ No newline at end of file +#include "diffCheck/visualizer.hh" +#include "diffCheck/registrations/DFRefinedRegistration.hh" \ No newline at end of file diff --git a/src/diffCheck/geometry/DFMesh.cc b/src/diffCheck/geometry/DFMesh.cc index 1c2849a8..6cf59627 100644 --- a/src/diffCheck/geometry/DFMesh.cc +++ b/src/diffCheck/geometry/DFMesh.cc @@ -1,5 +1,4 @@ #include "diffCheck/geometry/DFMesh.hh" - #include "diffCheck/IOManager.hh" @@ -18,33 +17,6 @@ namespace diffCheck::geometry { this->Faces[i] = O3DTriangleMesh->triangles_[i]; } - - // if (O3DTriangleMesh->HasVertexNormals()) - // { - // this->NormalsVertex.resize(O3DTriangleMesh->vertex_normals_.size()); - // for (size_t i = 0; i < O3DTriangleMesh->vertex_normals_.size(); i++) - // { - // this->NormalsVertex[i] = O3DTriangleMesh->vertex_normals_[i]; - // } - // } - - // if (O3DTriangleMesh->HasTriangleNormals()) - // { - // this->NormalsFace.resize(O3DTriangleMesh->triangle_normals_.size()); - // for (size_t i = 0; i < O3DTriangleMesh->triangle_normals_.size(); i++) - // { - // this->NormalsFace[i] = O3DTriangleMesh->triangle_normals_[i]; - // } - // } - - // if (O3DTriangleMesh->HasVertexColors()) - // { - // this->ColorsVertex.resize(O3DTriangleMesh->vertex_colors_.size()); - // for (size_t i = 0; i < O3DTriangleMesh->vertex_colors_.size(); i++) - // { - // this->ColorsVertex[i] = O3DTriangleMesh->vertex_colors_[i]; - // } - // } } std::shared_ptr DFMesh::Cvt2O3DTriangleMesh() @@ -83,6 +55,13 @@ namespace diffCheck::geometry return O3DTriangleMesh; } + void DFMesh::ApplyTransformation(const diffCheck::transformation::DFTransformation &transformation) + { + auto O3DTriangleMesh = this->Cvt2O3DTriangleMesh(); + O3DTriangleMesh->Transform(transformation.TransformationMatrix); + this->Cvt2DFMesh(O3DTriangleMesh); + } + void DFMesh::LoadFromPLY(const std::string &path) { std::shared_ptr tempMesh_ptr = diffCheck::io::ReadPLYMeshFromFile(path); diff --git a/src/diffCheck/geometry/DFMesh.hh b/src/diffCheck/geometry/DFMesh.hh index 299a23f0..a4a860b8 100644 --- a/src/diffCheck/geometry/DFMesh.hh +++ b/src/diffCheck/geometry/DFMesh.hh @@ -3,6 +3,8 @@ #include #include +#include + namespace diffCheck::geometry { class DFMesh @@ -11,8 +13,7 @@ namespace diffCheck::geometry DFMesh() = default; ~DFMesh() = default; - ///< Convertes - public: + public: ///< Convertes /** * @brief Convert a open3d triangle mesh to our datatype * @@ -27,8 +28,15 @@ namespace diffCheck::geometry */ std::shared_ptr Cvt2O3DTriangleMesh(); - ///< I/O loader - public: + public: ///< Transformers + /** + * @brief Apply a transformation to the mesh + * + * @param transformation the transformation to apply + */ + void ApplyTransformation(const diffCheck::transformation::DFTransformation &transformation); + + public: ///< I/O loader /** * @brief Read a mesh from a file * @@ -36,15 +44,13 @@ namespace diffCheck::geometry */ void LoadFromPLY(const std::string &path); - ///< Getters - public: + public: ///< Getters /// @brief Number of vertices in the mesh int GetNumVertices() const { return this->Vertices.size(); } /// @brief Number of faces in the mesh int GetNumFaces() const { return this->Faces.size(); } - ///< Basic mesh data - public: + public: ///< Basic mesh data /// @brief Eigen vector of 3D vertices std::vector Vertices; /// @brief Eigen vector of faces diff --git a/src/diffCheck/geometry/DFPointCloud.cc b/src/diffCheck/geometry/DFPointCloud.cc index 39850e97..8ed165d6 100644 --- a/src/diffCheck/geometry/DFPointCloud.cc +++ b/src/diffCheck/geometry/DFPointCloud.cc @@ -33,6 +33,38 @@ namespace diffCheck::geometry return O3DPointCloud; } + std::vector DFPointCloud::ComputeP2PDistance(std::shared_ptr target) + { + std::vector errors; + auto O3DSourcePointCloud = this->Cvt2O3DPointCloud(); + auto O3DTargetPointCloud = target->Cvt2O3DPointCloud(); + + std::vector distances; + + distances = O3DSourcePointCloud->ComputePointCloudDistance(*O3DTargetPointCloud); + return distances; + } + + std::vector DFPointCloud::ComputeBoundingBox() + { + auto O3DPointCloud = this->Cvt2O3DPointCloud(); + auto boundingBox = O3DPointCloud->GetAxisAlignedBoundingBox(); + std::vector extremePoints; + extremePoints.push_back(boundingBox.GetMinBound()); + extremePoints.push_back(boundingBox.GetMaxBound()); + this->BoundingBox = extremePoints; + return extremePoints; + } + void DFPointCloud::ApplyTransformation(const diffCheck::transformation::DFTransformation &transformation) + { + auto O3DPointCloud = this->Cvt2O3DPointCloud(); + O3DPointCloud->Transform(transformation.TransformationMatrix); + this->Points.clear(); + this->Colors.clear(); + this->Normals.clear(); + this->Cvt2DFPointCloud(O3DPointCloud); + } + void DFPointCloud::LoadFromPLY(const std::string &path) { auto cloud = diffCheck::io::ReadPLYPointCloud(path); diff --git a/src/diffCheck/geometry/DFPointCloud.hh b/src/diffCheck/geometry/DFPointCloud.hh index 285f14cc..a1b9b314 100644 --- a/src/diffCheck/geometry/DFPointCloud.hh +++ b/src/diffCheck/geometry/DFPointCloud.hh @@ -3,6 +3,8 @@ #include #include +#include + namespace diffCheck::geometry { @@ -12,8 +14,8 @@ namespace diffCheck::geometry DFPointCloud() = default; ~DFPointCloud() = default; - ///< Converters from other point cloud datatypes libraries to our format - public: + + public: ///< Converters from other point cloud datatypes libraries to our format /** * @brief Converter from open3d point cloud to our datatype * @@ -28,8 +30,36 @@ namespace diffCheck::geometry */ std::shared_ptr Cvt2O3DPointCloud(); - ///< I/O loader - public: + public: ///< Utilities + /** + * @brief Compute the "point to point" distance between this and another point clouds. + * + * For every point in the source point cloud, it looks in the KDTree of the target point cloud and finds the closest point. + * It returns a vector of distances, one for each point in the source point cloud. + * + * @param target The target diffCheck point cloud + * @return std::vector A vector of distances, one for each point in the source point cloud. + * + * @see https://github.com/isl-org/Open3D/blob/main/cpp/open3d/geometry/PointCloud.cpp + */ + std::vector ComputeP2PDistance(std::shared_ptr target); + + /** + * @brief Compute the bounding box of the point cloud and stores it as member of the DFPointCloud object + * + * @return std::vector A vector of two Eigen::Vector3d, with the first one being the minimum point and the second one the maximum point of the bounding box. + */ + std::vector ComputeBoundingBox(); + + public: ///< Transformers + /** + * @brief Apply a transformation to the point cloud + * + * @param transformation the transformation to apply + */ + void ApplyTransformation(const diffCheck::transformation::DFTransformation &transformation); + + public: ///< I/O loader /** * @brief Read a point cloud from a file * @@ -37,8 +67,7 @@ namespace diffCheck::geometry */ void LoadFromPLY(const std::string &path); - ///< Getters - public: + public: ///< Getters /// @brief Number of points in the point cloud int GetNumPoints() const { return this->Points.size(); } /// @brief Number of colors in the point cloud @@ -46,13 +75,14 @@ namespace diffCheck::geometry /// @brief Number of normals in the point cloud int GetNumNormals() const { return this->Normals.size(); } - ///< Basic point cloud data - public: + public: ///< Basic point cloud data /// @brief Eigen vector of 3D points std::vector Points; /// @brief Eigen vector of 3D colors std::vector Colors; /// @brief Eigen vector of 3D normals std::vector Normals; + /// @brief Eigen vector of two 3D vectors forming the bounnding box. + std::vector BoundingBox; }; } // namespace diffCheck::geometry \ No newline at end of file diff --git a/src/diffCheck/registration/.gitkeep b/src/diffCheck/registrations/.gitkeep similarity index 100% rename from src/diffCheck/registration/.gitkeep rename to src/diffCheck/registrations/.gitkeep diff --git a/src/diffCheck/registrations/DFGlobalRegistrations.cc b/src/diffCheck/registrations/DFGlobalRegistrations.cc new file mode 100644 index 00000000..b376eddd --- /dev/null +++ b/src/diffCheck/registrations/DFGlobalRegistrations.cc @@ -0,0 +1,181 @@ +#include "diffCheck/registrations/DFGlobalRegistrations.hh" + +namespace diffCheck::registrations +{ + std::vector DFGlobalRegistrations::EvaluateRegistrations( + std::shared_ptr source, + std::shared_ptr target, + std::vector> transforms) + { + std::vector errors; + for(int i = 0; i < transforms.size(); i++) + { + std::shared_ptr o3DPointCloud = source->Cvt2O3DPointCloud(); + + std::shared_ptr o3DPointCloudAfterTrans = + std::make_shared(o3DPointCloud->Transform(transforms[i])); + + std::shared_ptr dfPointCloudPtrAfterTrans = std::make_shared(); + dfPointCloudPtrAfterTrans->Cvt2DFPointCloud(o3DPointCloudAfterTrans); + std::vector registrationErrors = dfPointCloudPtrAfterTrans->ComputeP2PDistance(target); + errors.push_back(std::accumulate(registrationErrors.begin(), registrationErrors.end(), 0.0) / registrationErrors.size()); + } + return errors; + }; + + diffCheck::transformation::DFTransformation DFGlobalRegistrations::O3DFastGlobalRegistrationFeatureMatching( + std::shared_ptr source, + std::shared_ptr target, + bool voxelise, + double voxelSize, + double radiusKDTreeSearch, + int maxNeighborKDTreeSearch, + double maxCorrespondenceDistance, + int iterationNumber, + int maxTupleCount) + { + std::shared_ptr sourceO3D = source->Cvt2O3DPointCloud(); + std::shared_ptr targetO3D = target->Cvt2O3DPointCloud(); + + // voxelize at the scale of the point cloud + if (voxelise) + { + double absoluteVoxelSize = + voxelSize * std::abs(sourceO3D->GetMaxBound().norm() - sourceO3D->GetMinBound().norm()); + + sourceO3D->VoxelDownSample(absoluteVoxelSize); + targetO3D->VoxelDownSample(absoluteVoxelSize); + } + + if (sourceO3D->normals_.size() == 0) + { + sourceO3D->EstimateNormals(); + } + + if (targetO3D->normals_.size() == 0) + { + targetO3D->EstimateNormals(); + } + + double absoluteRadiusKDTreeSearch = + radiusKDTreeSearch * std::abs(sourceO3D->GetMaxBound().norm() - sourceO3D->GetMinBound().norm()); + + std::shared_ptr sourceFPFHFeatures = + open3d::pipelines::registration::ComputeFPFHFeature( + *sourceO3D, + open3d::geometry::KDTreeSearchParamHybrid(absoluteRadiusKDTreeSearch, maxNeighborKDTreeSearch)); + + std::shared_ptr targetFPFHFeatures = + open3d::pipelines::registration::ComputeFPFHFeature( + *targetO3D, + open3d::geometry::KDTreeSearchParamHybrid(absoluteRadiusKDTreeSearch, maxNeighborKDTreeSearch)); + + std::shared_ptr option = + std::make_shared(); + + option->maximum_correspondence_distance_ = maxCorrespondenceDistance; + option->iteration_number_ = iterationNumber; + option->maximum_tuple_count_ = maxTupleCount; + + + open3d::pipelines::registration::RegistrationResult result = + open3d::pipelines::registration::FastGlobalRegistrationBasedOnFeatureMatching( + *sourceO3D, + *targetO3D, + *sourceFPFHFeatures, + *targetFPFHFeatures, + *option); + diffCheck::transformation::DFTransformation transformation = + diffCheck::transformation::DFTransformation(result.transformation_); + + return transformation; + } + + diffCheck::transformation::DFTransformation DFGlobalRegistrations::O3DRansacOnFeatureMatching( + std::shared_ptr source, + std::shared_ptr target, + bool voxelise, + double voxelSize, + double radiusKDTreeSearch, + int maxNeighborKDTreeSearch, + double maxCorrespondenceDistance, + bool isTEstimatePt2Pt, + int ransacN, + double correspondenceCheckerDistance, + double similarityThreshold, + int ransacMaxIteration, + double ransacConfidenceThreshold) + { + std::shared_ptr sourceO3D = source->Cvt2O3DPointCloud(); + std::shared_ptr targetO3D = target->Cvt2O3DPointCloud(); + + open3d::pipelines::registration::TransformationEstimationPointToPoint transformationEstimation = + open3d::pipelines::registration::TransformationEstimationPointToPoint(isTEstimatePt2Pt); + + // voxelize at the scale of the point cloud + if (voxelise) + { + double absoluteVoxelSize = + voxelSize * std::abs(sourceO3D->GetMaxBound().norm() - sourceO3D->GetMinBound().norm()); + + sourceO3D->VoxelDownSample(absoluteVoxelSize); + targetO3D->VoxelDownSample(absoluteVoxelSize); + } + + if (sourceO3D->normals_.size() == 0) + { + sourceO3D->EstimateNormals(); + } + + if (targetO3D->normals_.size() == 0) + { + targetO3D->EstimateNormals(); + } + + // convert the relative values to absolute ones + double absoluteRadiusKDTreeSearch = + radiusKDTreeSearch * std::abs(sourceO3D->GetMaxBound().norm() - sourceO3D->GetMinBound().norm()); + + double absoluteCorrespodenceCheckerDistance = + correspondenceCheckerDistance * std::abs(sourceO3D->GetMaxBound().norm() - sourceO3D->GetMinBound().norm()); + + double absoluteMaxCorrespondenceDistance = + maxCorrespondenceDistance * std::abs(sourceO3D->GetMaxBound().norm() - sourceO3D->GetMinBound().norm()); + + std::shared_ptr sourceFPFHFeatures = + open3d::pipelines::registration::ComputeFPFHFeature( + *sourceO3D, + open3d::geometry::KDTreeSearchParamHybrid(absoluteRadiusKDTreeSearch, maxNeighborKDTreeSearch)); + + std::shared_ptr targetFPFHFeatures = + open3d::pipelines::registration::ComputeFPFHFeature( + *targetO3D, + open3d::geometry::KDTreeSearchParamHybrid(absoluteRadiusKDTreeSearch, maxNeighborKDTreeSearch)); + + std::vector> correspondanceChecker; + + open3d::pipelines::registration::CorrespondenceCheckerBasedOnDistance checkerOnDistance = + open3d::pipelines::registration::CorrespondenceCheckerBasedOnDistance(absoluteCorrespodenceCheckerDistance); + + open3d::pipelines::registration::CorrespondenceCheckerBasedOnEdgeLength checkerOnEdgeLength = + open3d::pipelines::registration::CorrespondenceCheckerBasedOnEdgeLength(similarityThreshold); + correspondanceChecker.push_back(checkerOnDistance); + + + auto result = open3d::pipelines::registration::RegistrationRANSACBasedOnFeatureMatching( + *sourceO3D, + *targetO3D, + *sourceFPFHFeatures, + *targetFPFHFeatures, + true, + absoluteMaxCorrespondenceDistance, + transformationEstimation, + ransacN, + correspondanceChecker, + open3d::pipelines::registration::RANSACConvergenceCriteria(ransacMaxIteration, ransacConfidenceThreshold)); + + diffCheck::transformation::DFTransformation transformation = diffCheck::transformation::DFTransformation(result.transformation_); + + return transformation; + } +} \ No newline at end of file diff --git a/src/diffCheck/registrations/DFGlobalRegistrations.hh b/src/diffCheck/registrations/DFGlobalRegistrations.hh new file mode 100644 index 00000000..563ad85a --- /dev/null +++ b/src/diffCheck/registrations/DFGlobalRegistrations.hh @@ -0,0 +1,99 @@ +#pragma once + +#include "diffCheck.hh" +#include +#include + +namespace diffCheck::registrations +{ + class DFGlobalRegistrations + { + public: ///< Open3d registrations + /** + * @brief Fast Global Registration based on Feature Matching using (Fast) Point Feature Histograms (FPFH) on the source and target point clouds + * + * Very simply, point features are values computed on a point cloud (for example the normal of a point, the curvature, etc.). + * point features historigrams generalize this concept by computing point features in a local neighborhood of a point, and are stored as + * higher-dimentional historigrams. Those historigrams are then used to compute a transformation between the source and target point clouds. + * + * @note The FPFH hyperspace is dependent on the quality of the surface normal estimations at each point (if pc noisy, historigram different). + * + * @param source the source diffCheck point cloud + * @param target the target diffCheck point cloud + * @param voxelSize the size of the voxels used to downsample the point clouds. It is expressed relative to the point cloud size (0.01 means voxelSize = 1% of maxSize(pointCloud). A higher value will result in a more coarse point cloud (less resulting points). + * @param radiusKDTreeSearch the radius used to search for neighbors in the KDTree.it is expressed relative to the point cloud size (0.01 means radiusKDTreeSearch = 1% of maxSize(pointCloud). It is used for the calculation of FPFHFeatures + * @param maxNeighborKDTreeSearch the maximum number of neighbors to search for in the KDTree. It is used for the calculation of FPFHFeatures. A higher value will result in heavier computation but potentially more precise. + * @param maxCorrespondenceDistance the maximum distance between correspondences. A higher value will result in more correspondences, but potentially include wrong ones. + * @param iterationNumber the number of iterations to run the RanSaC registration algorithm. A higher value will take more time to compute but increases the chances of finding a good transformation. As parameter of the FastGlobalRegistrationOption options + * @param maxTupleCount the maximum number of tuples to consider in the FPFH hyperspace. A higher value will result in heavier computation but potentially more precise. As parameter of the FastGlobalRegistrationOption options + * @return diffCheck::transformation::DFTransformation The result of the registration, containing the transformation matrix and the fitness score. + * + * @see https://www.open3d.org/docs/latest/cpp_api/classopen3d_1_1pipelines_1_1registration_1_1_registration_result.html#a6722256f1f3ddccb2c4ec8d724693974 for more information on the RegistrationResult object + * @see https://link.springer.com/content/pdf/10.1007/978-3-319-46475-6_47.pdf for the original article on Fast Global Registration + * @see https://pcl.readthedocs.io/projects/tutorials/en/latest/pfh_estimation.html#pfh-estimation for more information on PFH (from PCL, not Open3D) + * @see https://mediatum.ub.tum.de/doc/800632/941254.pdf for in-depth documentation on the theory + */ + static diffCheck::transformation::DFTransformation O3DFastGlobalRegistrationFeatureMatching( + std::shared_ptr source, + std::shared_ptr target, + bool voxelize = true, + double voxelSize = 0.005, + double radiusKDTreeSearch = 0.1, + int maxNeighborKDTreeSearch = 50, + double maxCorrespondenceDistance = 0.05, + int iterationNumber = 128, + int maxTupleCount = 1000); + /** + * @brief Ransac registration based on Feature Matching using (Fast) Point Feature Histograms (FPFH) on the source and target point clouds + * + * This method picks random points in the source point cloud, gets the FPFH of those points and find the closest points in the FPFH space of + * the target point cloud. If the transformation the two sets of point yields a low enough error, it is kept. + * + * @param source the source diffCheck point cloud + * @param target the target diffCheck point cloud + * @param voxelSize the size of the voxels used to downsample the point clouds. It is expressed relative to the point cloud size (0.01 means voxelSize = 1% of maxSize(pointCloud). A higher value will result in a more coarse point cloud (less resulting points). + * @param radiusKDTreeSearch the radius used to search for neighbors in the KDTree.it is expressed relative to the point cloud size (0.01 means radiusKDTreeSearch = 1% of maxSize(pointCloud). It is used for the calculation of FPFHFeatures + * @param maxNeighborKDTreeSearch the maximum number of neighbors to search for in the KDTree. It is used for the calculation of FPFHFeatures + * @param maxCorrespondenceDistance the maximum distance between correspondences in the FPFH space. A higher value will result in more correspondences, but potentially include wrong ones. It is exprimed in relative values (it is scaled by the size of the bounding box of the poinnt cloud). + * @param isTEstimatePt2Pt the transformation estimation method to use. By default, it uses a point to point transformation estimation. If true it will scale and deform the cloud. + * @param ransacN the number of points to sample in the source point cloud. A higher value can result in a more precise transformation, but will take more time to compute. + * @param correspondenceCheckersDistance the maximum distance between correspondances in the FPFH space before testing a RanSaC model. It is exprimed in relative values (it is scaled by the size of the bounding box of the poinnt cloud). + * @param similarityThreshold the threshold for the ransac check based on edge length to consider a model as inlier. A higher value will be stricter, discarding more ransac models. + * @param ransacMaxIteration the maximum number of iterations to run the Ransac algorithm. A higher value will take more time to compute but increases the chances of finding a good transformation. + * @param ransacConfidenceThreshold the threshold for the convergence criteria of the ransac models. A higher value will be stricter, discarding more ransac models. + * @return diffCheck::transformation::DFTransformation The result of the registration, containing the transformation matrix and the fitness score. + * + * @see https://www.open3d.org/docs/release/tutorial/pipelines/global_registration.html#RANSAC (from PCL, not Open3D) + */ + static diffCheck::transformation::DFTransformation O3DRansacOnFeatureMatching( + std::shared_ptr source, + std::shared_ptr target, + bool voxelize = true, + double voxelSize = 0.005, + double radiusKDTreeSearch = 0.1, + int maxNeighborKDTreeSearch = 50, + double maxCorrespondenceDistance = 0.05, + bool isTEstimatePt2Pt = false, + int ransacN = 3, + double correspondenceCheckerDistance = 0.05, + double similarityThreshold = 0.9, + int ransacMaxIteration = 100000, + double ransacConfidenceThreshold = 0.999); + + private: ///< o3d utilities to evaluate registration errors + /** + * @brief Evaluate the registration of a source point cloud to a target point cloud by applying a transformation matrix + * to the source point cloud and evaluate the error between the transformed source point cloud and the target point cloud. + * + * @param source The source diffCheck point cloud + * @param target The target diffCheck point cloud + * @param transform The vector of transformation matrix we want to evaluate. they are applied to the source point cloud. + * @return std::vector A vector of mean distances, one for each transform. + */ + static std::vector EvaluateRegistrations( + std::shared_ptr source, + std::shared_ptr target, + std::vector> transforms); + }; + +} \ No newline at end of file diff --git a/src/diffCheck/registrations/DFRefinedRegistration.cc b/src/diffCheck/registrations/DFRefinedRegistration.cc new file mode 100644 index 00000000..46ea511d --- /dev/null +++ b/src/diffCheck/registrations/DFRefinedRegistration.cc @@ -0,0 +1,103 @@ +#include "DFRefinedRegistration.hh" + + +namespace diffCheck::registration +{ + diffCheck::transformation::DFTransformation RefinedRegistration::O3DICP( + std::shared_ptr source, + std::shared_ptr target, + double maxCorrespondenceDistance, + bool scalingForPointToPointTransformationEstimation, + double relativeFitness, + double relativeRMSE, + int maxIteration, + bool usePointToPlane) + { + std::vector minMax = source->ComputeBoundingBox(); + double scale = (minMax[1] - minMax[0]).norm(); + double absoluteMaxCorrespondenceDistance = maxCorrespondenceDistance * scale; + + std::shared_ptr O3Dsource = source->Cvt2O3DPointCloud(); + std::shared_ptr O3Dtarget = target->Cvt2O3DPointCloud(); + Eigen::Matrix4d initialTransformation = Eigen::Matrix4d::Identity(); + open3d::pipelines::registration::ICPConvergenceCriteria criteria + = open3d::pipelines::registration::ICPConvergenceCriteria( + relativeFitness, + relativeRMSE, + maxIteration); + + open3d::pipelines::registration::RegistrationResult result; + + if(usePointToPlane) + { + O3Dsource->EstimateNormals(); + O3Dtarget->EstimateNormals(); + open3d::pipelines::registration::TransformationEstimationPointToPlane transformation_estimation + = open3d::pipelines::registration::TransformationEstimationPointToPlane(); + result = open3d::pipelines::registration::RegistrationICP( + *O3Dsource, + *O3Dtarget, + absoluteMaxCorrespondenceDistance, + initialTransformation, + transformation_estimation, + criteria); + } + else + { + open3d::pipelines::registration::TransformationEstimationPointToPoint transformation_estimation + = open3d::pipelines::registration::TransformationEstimationPointToPoint(scalingForPointToPointTransformationEstimation); + result = open3d::pipelines::registration::RegistrationICP( + *O3Dsource, + *O3Dtarget, + absoluteMaxCorrespondenceDistance, + initialTransformation, + transformation_estimation, + criteria); + } + + diffCheck::transformation::DFTransformation transformation + = diffCheck::transformation::DFTransformation(result.transformation_); + return transformation; + } + diffCheck::transformation::DFTransformation RefinedRegistration::O3DGeneralizedICP( + std::shared_ptr source, + std::shared_ptr target, + double maxCorrespondenceDistance, + int maxIteration, + double relativeFitness, + double relativeRMSE) + { + std::vector minMax = source->ComputeBoundingBox(); + double scale = (minMax[1] - minMax[0]).norm(); + double absoluteMaxCorrespondenceDistance = maxCorrespondenceDistance * scale; + + std::shared_ptr O3Dsource = source->Cvt2O3DPointCloud(); + std::shared_ptr O3Dtarget = target->Cvt2O3DPointCloud(); + + O3Dsource->EstimateCovariances(); + O3Dtarget->EstimateCovariances(); + + Eigen::Matrix4d initialTransformation = Eigen::Matrix4d::Identity(); + open3d::pipelines::registration::ICPConvergenceCriteria criteria + = open3d::pipelines::registration::ICPConvergenceCriteria( + relativeFitness, + relativeRMSE, + maxIteration); + + open3d::pipelines::registration::TransformationEstimationForGeneralizedICP transformation_estimation + = open3d::pipelines::registration::TransformationEstimationForGeneralizedICP(); + + open3d::pipelines::registration::RegistrationResult result + = open3d::pipelines::registration::RegistrationGeneralizedICP( + *O3Dsource, + *O3Dtarget, + absoluteMaxCorrespondenceDistance, + initialTransformation, + transformation_estimation, + criteria); + + diffCheck::transformation::DFTransformation transformation + = diffCheck::transformation::DFTransformation(result.transformation_); + return transformation; + } +} \ No newline at end of file diff --git a/src/diffCheck/registrations/DFRefinedRegistration.hh b/src/diffCheck/registrations/DFRefinedRegistration.hh new file mode 100644 index 00000000..1d0bb322 --- /dev/null +++ b/src/diffCheck/registrations/DFRefinedRegistration.hh @@ -0,0 +1,63 @@ +#pragma once +# include "diffCheck.hh" + +# include + +namespace diffCheck::registration +{ + class RefinedRegistration + { + public: ///< open3d registration methods + /** + * @brief Perform ICP registration using Open3D + * + * The ICP registration looks for points in the target point cloud that are closest to the source + * point cloud and computes the transformation that minimizes the distance between the two point clouds. + * The way the distance is calculated is either with point to point or point to plane methods. + * + * @param source DFPointCloud source point cloud + * @param target DFPointCloud Target point cloud + * @param maxCorrespondenceDistance Maximum relative correspondence distance. 0.01 means 1% of the bounding box diagonal + * @param scalingForPointToPointTransformationEstimation Enable scaling for point-to-point transformation estimation. by default it is false, to only allow rigid transformations + * @param maxIteration Maximum number of ICP iterations to use in the p2p transformation estimation + * @param relativeFitness Threshold for relative fitness to use in the p2p transformation estimation + * @param relativeRMSE Threshold for relative RMSE to use in the p2p transformation estimation + * @param usePointToPlane Use point-to-plane ICP instead of point-to-point. This replaces the p2p with the point-to-plane transformation estimation. + * @return diffCheck::transformation::DFTransformation + */ + static diffCheck::transformation::DFTransformation O3DICP( + std::shared_ptr source, + std::shared_ptr target, + double maxCorrespondenceDistance = 0.05, + bool scalingForPointToPointTransformationEstimation = false, + double relativeFitness = 1e-6, + double relativeRMSE = 1e-6, + int maxIteration = 30, + bool usePointToPlane = false); + + /** + * @brief Perform Generalized ICP registration using Open3D + * + * The Generalized ICP registration additionally identifies planes in the source and target + * point clouds and uses them to improve the registration. According to the original 2009 paper, + * it can be seen as a "plane-to-plane" ICP. The paper is called "Generalized-ICP" and is referenced below. + * + * @param source DFPointCloud source point cloud + * @param target DFPointCloud Target point cloud + * @param maxCorrespondenceDistance Maximum relative correspondence distance. 0.01 means 1% of the bounding box diagonal + * @param maxIteration Maximum number of ICP iterations to use in the p2p transformation estimation + * @param relativeFitness Threshold for relative fitness to use in the p2p transformation estimation + * @param relativeRMSE Threshold for relative RMSE to use in the p2p transformation estimation + * @return diffCheck::transformation::DFTransformation + * + * @see http://dx.doi.org/10.15607/RSS.2009.V.021 for more information + */ + static diffCheck::transformation::DFTransformation O3DGeneralizedICP( + std::shared_ptr source, + std::shared_ptr target, + double maxCorrespondenceDistance = 0.05, + int maxIteration = 30, + double relativeFitness = 1e-6, + double relativeRMSE = 1e-6); + }; +} \ No newline at end of file diff --git a/src/diffCheck/transformation/DFTransformation.cc b/src/diffCheck/transformation/DFTransformation.cc new file mode 100644 index 00000000..1d66cb24 --- /dev/null +++ b/src/diffCheck/transformation/DFTransformation.cc @@ -0,0 +1,7 @@ +#include "DFTransformation.hh" + + +namespace diffCheck::transformation +{ + +} \ No newline at end of file diff --git a/src/diffCheck/transformation/DFTransformation.hh b/src/diffCheck/transformation/DFTransformation.hh new file mode 100644 index 00000000..e45b86ba --- /dev/null +++ b/src/diffCheck/transformation/DFTransformation.hh @@ -0,0 +1,33 @@ +#pragma once +#include + +namespace diffCheck::transformation +{ + class DFTransformation + { + public: + DFTransformation() = default; + DFTransformation(const Eigen::Matrix4d& transformationMatrix) + : TransformationMatrix(transformationMatrix) + {} + DFTransformation(const Eigen::Matrix3d& rotationMatrix, const Eigen::Vector3d& translationVector) + : RotationMatrix(rotationMatrix), TranslationVector(translationVector) + {} + + public: + /** + * @brief 4x4 Transformation matrix for point clouds + */ + Eigen::Matrix4d TransformationMatrix; + + /** + * @brief 3x3 Rotation matrix for point clouds + */ + Eigen::Matrix3d RotationMatrix; + + /** + * @brief 3x1 Translation vector for point clouds + */ + Eigen::Vector3d TranslationVector; + }; +} \ No newline at end of file diff --git a/src/diffCheckApp.cc b/src/diffCheckApp.cc index bca9a8c4..0566c961 100644 --- a/src/diffCheckApp.cc +++ b/src/diffCheckApp.cc @@ -1,41 +1,67 @@ #include "diffCheck.hh" -#include -#include -#include -#include - #include +#include int main() { + // import clouds std::shared_ptr dfPointCloudPtr = std::make_shared(); + std::shared_ptr dfPointCloudPtr_1 = std::make_shared(); + std::shared_ptr dfPointCloudPtr_2 = std::make_shared(); + std::shared_ptr dfPointCloudPtrWithoutNormals = std::make_shared(); + std::shared_ptr dfPointCloudPtrGroundTruth = std::make_shared(); + std::shared_ptr dfPointCloudPtrGroundTruthFromMesh = std::make_shared(); std::shared_ptr dfMeshPtr = std::make_shared(); + std::shared_ptr dfGroundTruth = std::make_shared(); // std::string pathCloud = R"(C:\Users\andre\Downloads\scan_data_normals.ply\scan_data_normals.ply)"; // std::string pathMesh = R"(F:\diffCheck\assets\dataset\mesh_fromRh_unfixedLength.ply)"; // std::string pathMesh = R"(F:\diffCheck\temp\03_mesh.ply)"; // create a sphere from o3d - auto mesh = open3d::geometry::TriangleMesh::CreateSphere(1.0, 4); - DIFFCHECK_INFO("test"); - DIFFCHECK_WARN("test"); - DIFFCHECK_ERROR("test"); - DIFFCHECK_FATAL("test"); + std::string pathCloud = R"(C:\Users\localuser\Downloads\04_pt.ply)"; + std::string pathMesh = R"(C:\Users\localuser\Downloads\04_mesh.ply)"; + // std::string pathMesh = R"(F:\diffCheck\temp\03_mesh.ply)"; + + dfMeshPtr->LoadFromPLY(pathMesh); + dfPointCloudPtr->LoadFromPLY(pathCloud); + + dfGroundTruth->Cvt2DFPointCloud(dfMeshPtr->Cvt2O3DTriangleMesh()->SamplePointsUniformly(10000)); + Eigen::Matrix4d transformation = Eigen::Matrix4d::Identity(); + transformation(0, 3) = 0.0; + transformation(1, 3) = -0.02; + transformation(2, 3) = 0.02; + Eigen::Matrix3d rotation; + rotation = Eigen::AngleAxisd(0.3, Eigen::Vector3d::UnitY()); + transformation.block<3, 3>(0, 0) = rotation * transformation.block<3, 3>(0, 0); + dfPointCloudPtr->ApplyTransformation(transformation); - dfMeshPtr->Cvt2DFMesh(mesh); + diffCheck::transformation::DFTransformation simpleICPTransformation + = diffCheck::registration::RefinedRegistration::O3DICP( + dfPointCloudPtr, + dfGroundTruth, + 0.05); - // dfPointCloudPtr->LoadFromPLY(pathCloud); + diffCheck::transformation::DFTransformation generalizedICPTransformation + = diffCheck::registration::RefinedRegistration::O3DGeneralizedICP( + dfPointCloudPtr, + dfGroundTruth, + 0.05); + dfPointCloudPtr->ApplyTransformation(simpleICPTransformation); + + std::cout< vis = std::make_shared(); // vis->AddPointCloud(dfPointCloudPtr); vis->AddMesh(dfMeshPtr); + vis->AddPointCloud(dfGroundTruth); + vis->AddPointCloud(dfPointCloudPtr); vis->Run(); - - return 0; } \ No newline at end of file diff --git a/src/gh/components/DF_xml_exporter/code.py b/src/gh/components/DF_xml_exporter/code.py new file mode 100644 index 00000000..e3ae43b8 --- /dev/null +++ b/src/gh/components/DF_xml_exporter/code.py @@ -0,0 +1,48 @@ +#! python3 +# r: diffCheck==0.0.9 + +import System +import typing + +import Rhino +import Rhino.Geometry as rg + +from ghpythonlib.componentbase import executingcomponent as component + +import diffCheck +from diffCheck.df_geometries import DFBeam, DFAssembly + + +class DFXMLExporter(component): + def RunScript(self, + i_dump: bool, + i_assembly_name, + i_export_dir, + i_breps: System.Collections.Generic.IList[Rhino.Geometry.Brep]): + """ + This read breps from Rhino, converts them to DFBeams and DFAssemblies, and exports them to XML. + + :param i_dump: whether to dump the xml + :param i_export_dir: directory to export the xml + :param i_breps: list of breps + """ + # beams + beams: typing.List[DFBeam] = [] + for brep in i_breps: + beam = DFBeam.from_brep(brep) + beams.append(beam) + + # assembly + assembly1 = DFAssembly(beams, i_assembly_name) + + # dump the xml + xml: str = assembly1.to_xml() + if i_dump: + assembly1.dump_xml(xml, i_export_dir) + o_xml = xml + + # show the joint/side faces + o_joints = [jf.to_brep() for jf in assembly1.all_joint_faces] + o_sides = [sf.to_brep() for sf in assembly1.all_side_faces] + + return o_xml, o_joints, o_sides \ No newline at end of file diff --git a/src/gh/components/DF_xml_exporter/icon.png b/src/gh/components/DF_xml_exporter/icon.png new file mode 100644 index 00000000..c9e0b54e Binary files /dev/null and b/src/gh/components/DF_xml_exporter/icon.png differ diff --git a/src/gh/components/DF_xml_exporter/metadata.json b/src/gh/components/DF_xml_exporter/metadata.json new file mode 100644 index 00000000..a9d8cda0 --- /dev/null +++ b/src/gh/components/DF_xml_exporter/metadata.json @@ -0,0 +1,92 @@ +{ + "name": "DFXMLExporter", + "nickname": "XMLout", + "category": "diffCheck", + "subcategory": "Utility", + "description": "This component reads breps, convert them to DFBeams and DFAssemblies and export it to XML.", + "exposure": 4, + "instanceGuid": "cdae4bd5-d18e-4b06-9367-791b6b1f6837", + "ghpython": { + "hideOutput": true, + "hideInput": true, + "isAdvancedMode": true, + "marshalOutGuids": true, + "iconDisplay": 2, + "inputParameters": [ + { + "name": "i_dump", + "nickname": "i_dump", + "description": "Press button to export xml", + "optional": true, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "item", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "bool" + }, + { + "name": "i_assembly_name", + "nickname": "i_assembly_name", + "description": "The name of the assembly to export.", + "optional": false, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "item", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "str" + }, + { + "name": "i_export_dir", + "nickname": "i_export_dir", + "description": "The directors where to export the xml file.", + "optional": true, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "item", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "str" + }, + { + "name": "i_breps", + "nickname": "i_breps", + "description": "The breps of the structure.", + "optional": true, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "list", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "brep" + } + ], + "outputParameters": [ + { + "name": "o_xml", + "nickname": "o_xml", + "description": "The string of xml to be exported.", + "optional": false, + "sourceCount": 0, + "graft": false + }, + { + "name": "o_joints", + "nickname": "o_joints", + "description": "The breps of the faces belonging to joints.", + "optional": false, + "sourceCount": 0, + "graft": false + }, + { + "name": "o_sides", + "nickname": "o_sides", + "description": "The breps of the faces belonging to sides.", + "optional": false, + "sourceCount": 0, + "graft": false + } + ] + } +} \ No newline at end of file diff --git a/src/gh/diffCheck/README.md b/src/gh/diffCheck/README.md new file mode 100644 index 00000000..afa64734 --- /dev/null +++ b/src/gh/diffCheck/README.md @@ -0,0 +1,5 @@ +# DiffCheck Grasshopper Plugin + +DiffCheck is a plugin for Rhino/Grasshopper that allows the user to compare a 3D model with its scan. + +More information to come \ No newline at end of file diff --git a/src/gh/diffCheck/diffCheck.egg-info/PKG-INFO b/src/gh/diffCheck/diffCheck.egg-info/PKG-INFO new file mode 100644 index 00000000..b6273c49 --- /dev/null +++ b/src/gh/diffCheck/diffCheck.egg-info/PKG-INFO @@ -0,0 +1,18 @@ +Metadata-Version: 2.1 +Name: diffCheck +Version: 0.0.3 +Summary: DiffCheck is a package to check the differences between two timber structures +Home-page: https://github.com/diffCheckOrg/diffCheck +Author: Andrea Settimi, Damien Gilliard, Eleni Skevaki, Marirena Kladeftira, Julien Gamerro, Stefana Parascho, and Yves Weinand +Author-email: andrea.settimi@epfl.ch +License: UNKNOWN +Description: # DiffCheck Grasshopper Plugin + + DiffCheck is a plugin for Rhino/Grasshopper that allows the user to compare a 3D model with its scan. + + More information to come +Platform: UNKNOWN +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.7 +Description-Content-Type: text/markdown diff --git a/src/gh/diffCheck/diffCheck.egg-info/SOURCES.txt b/src/gh/diffCheck/diffCheck.egg-info/SOURCES.txt new file mode 100644 index 00000000..501a0009 --- /dev/null +++ b/src/gh/diffCheck/diffCheck.egg-info/SOURCES.txt @@ -0,0 +1,13 @@ +README.md +setup.py +diffCheck/__init__.py +diffCheck/df_geometries.py +diffCheck/df_joint_detector.py +diffCheck/df_transformations.py +diffCheck/df_util.py +diffCheck/diffCheck_app.py +diffCheck/test.py +diffCheck.egg-info/PKG-INFO +diffCheck.egg-info/SOURCES.txt +diffCheck.egg-info/dependency_links.txt +diffCheck.egg-info/top_level.txt \ No newline at end of file diff --git a/src/gh/diffCheck/diffCheck.egg-info/dependency_links.txt b/src/gh/diffCheck/diffCheck.egg-info/dependency_links.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/gh/diffCheck/diffCheck.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/src/gh/diffCheck/diffCheck.egg-info/requires.txt b/src/gh/diffCheck/diffCheck.egg-info/requires.txt new file mode 100644 index 00000000..24ce15ab --- /dev/null +++ b/src/gh/diffCheck/diffCheck.egg-info/requires.txt @@ -0,0 +1 @@ +numpy diff --git a/src/gh/diffCheck/diffCheck.egg-info/top_level.txt b/src/gh/diffCheck/diffCheck.egg-info/top_level.txt new file mode 100644 index 00000000..ac76f019 --- /dev/null +++ b/src/gh/diffCheck/diffCheck.egg-info/top_level.txt @@ -0,0 +1 @@ +diffCheck diff --git a/src/gh/diffCheck/diffCheck/__init__.py b/src/gh/diffCheck/diffCheck/__init__.py new file mode 100644 index 00000000..2418e6b6 --- /dev/null +++ b/src/gh/diffCheck/diffCheck/__init__.py @@ -0,0 +1 @@ +__version__ = "0.0.9" \ No newline at end of file diff --git a/src/gh/diffCheck/diffCheck/__pycache__/__init__.cpython-38.pyc b/src/gh/diffCheck/diffCheck/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 00000000..b13b9668 Binary files /dev/null and b/src/gh/diffCheck/diffCheck/__pycache__/__init__.cpython-38.pyc differ diff --git a/src/gh/diffCheck/diffCheck/__pycache__/__init__.cpython-39.pyc b/src/gh/diffCheck/diffCheck/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 00000000..c0735ba9 Binary files /dev/null and b/src/gh/diffCheck/diffCheck/__pycache__/__init__.cpython-39.pyc differ diff --git a/src/gh/diffCheck/diffCheck/__pycache__/df_geometries.cpython-39.pyc b/src/gh/diffCheck/diffCheck/__pycache__/df_geometries.cpython-39.pyc new file mode 100644 index 00000000..e1237df4 Binary files /dev/null and b/src/gh/diffCheck/diffCheck/__pycache__/df_geometries.cpython-39.pyc differ diff --git a/src/gh/diffCheck/diffCheck/__pycache__/df_joint_detector.cpython-39.pyc b/src/gh/diffCheck/diffCheck/__pycache__/df_joint_detector.cpython-39.pyc new file mode 100644 index 00000000..3a848217 Binary files /dev/null and b/src/gh/diffCheck/diffCheck/__pycache__/df_joint_detector.cpython-39.pyc differ diff --git a/src/gh/diffCheck/diffCheck/__pycache__/df_transformations.cpython-39.pyc b/src/gh/diffCheck/diffCheck/__pycache__/df_transformations.cpython-39.pyc new file mode 100644 index 00000000..d784fb97 Binary files /dev/null and b/src/gh/diffCheck/diffCheck/__pycache__/df_transformations.cpython-39.pyc differ diff --git a/src/gh/diffCheck/diffCheck/__pycache__/df_util.cpython-39.pyc b/src/gh/diffCheck/diffCheck/__pycache__/df_util.cpython-39.pyc new file mode 100644 index 00000000..daa54480 Binary files /dev/null and b/src/gh/diffCheck/diffCheck/__pycache__/df_util.cpython-39.pyc differ diff --git a/src/gh/diffCheck/diffCheck/__pycache__/geometries.cpython-38.pyc b/src/gh/diffCheck/diffCheck/__pycache__/geometries.cpython-38.pyc new file mode 100644 index 00000000..1c31d060 Binary files /dev/null and b/src/gh/diffCheck/diffCheck/__pycache__/geometries.cpython-38.pyc differ diff --git a/src/gh/diffCheck/diffCheck/__pycache__/geometries.cpython-39.pyc b/src/gh/diffCheck/diffCheck/__pycache__/geometries.cpython-39.pyc new file mode 100644 index 00000000..624f1cda Binary files /dev/null and b/src/gh/diffCheck/diffCheck/__pycache__/geometries.cpython-39.pyc differ diff --git a/src/gh/diffCheck/diffCheck/__pycache__/test.cpython-39.pyc b/src/gh/diffCheck/diffCheck/__pycache__/test.cpython-39.pyc new file mode 100644 index 00000000..99feaa44 Binary files /dev/null and b/src/gh/diffCheck/diffCheck/__pycache__/test.cpython-39.pyc differ diff --git a/src/gh/diffCheck/diffCheck/df_geometries.py b/src/gh/diffCheck/diffCheck/df_geometries.py new file mode 100644 index 00000000..47dbff55 --- /dev/null +++ b/src/gh/diffCheck/diffCheck/df_geometries.py @@ -0,0 +1,311 @@ +import os +from datetime import datetime +from dataclasses import dataclass +import typing +import uuid + +import Rhino +import Rhino.Geometry as rg + +import xml.etree.ElementTree as ET +from xml.dom.minidom import parseString + +import diffCheck.df_joint_detector + + +@dataclass +class DFVertex: + """ + This class represents a vertex, a simple container with 3 coordinates + """ + + x: float + y: float + z: float + + def __post_init__(self): + self.x = self.x or 0.0 + self.y = self.y or 0.0 + self.z = self.z or 0.0 + + def __repr__(self): + return f"Vertex: X={self.x}, Y={self.y}, Z={self.z}" + + def __hash__(self): + return hash((self.x, self.y, self.z)) + + def __eq__(self, other): + if isinstance(other, DFVertex): + return self.x == other.x and self.y == other.y and self.z == other.z + return False + + @classmethod + def from_rg_point3d(cls, point: rg.Point3d): + """ + Create a DFVertex from a Rhino Point3d object + + :param point: The Rhino Point3d object + :return vertex: The DFVertex object + """ + return cls(point.X, point.Y, point.Z) + + def to_rg_point3d(self): + """ + Convert the vertex to a Rhino Point3d object + + :return point: The Rhino Point3d object + """ + return rg.Point3d(self.x, self.y, self.z) + + +@dataclass +class DFFace: + """ + This class represents a face, in diffCheck, a face is a collection of vertices. + """ + + # just as breps a first outer loop and then inner loops of DFVertices + all_loops: typing.List[typing.List[DFVertex]] + joint_id: int = None + + def __post_init__(self): + if len(self.all_loops[0]) < 3: + raise ValueError("A face must have at least 3 vertices") + self.all_loops = self.all_loops + + self.joint_id = self.joint_id + self.__is_joint = False + self.__id = uuid.uuid4().int + + def __repr__(self): + return f"Face id: {len(self.id)}, IsJoint: {self.is_joint} Loops: {len(self.all_loops)}" + + def __hash__(self): + outer_loop = tuple( + tuple(vertex.__dict__.values()) for vertex in self.all_loops[0] + ) + inner_loops = tuple( + tuple(vertex.__dict__.values()) + for loop in self.all_loops[1:] + for vertex in loop + ) + return hash((outer_loop, inner_loops)) + + def __eq__(self, other): + if isinstance(other, DFFace): + return self.all_loops == other.all_loops + return False + + @classmethod + def from_brep(cls, brep_face: rg.BrepFace, joint_id: int = None): + """ + Create a DFFace from a Rhino Brep face + + :param brep_face: The Rhino Brep face + :param joint_id: The joint id + :return face: The DFFace object + """ + all_loops = [] + + for idx, loop in enumerate(brep_face.Loops): + loop_trims = loop.Trims + loop_curve = loop.To3dCurve() + loop_curve = loop_curve.ToNurbsCurve() + loop_vertices = loop_curve.Points + loop = [] + for l_v in loop_vertices: + vertex = DFVertex(l_v.X, l_v.Y, l_v.Z) + loop.append(vertex) + all_loops.append(loop) + + df_face = cls(all_loops, joint_id) + df_face._brepface = brep_face + + return df_face + + def to_brep(self): + """ + Convert the face to a Rhino Brep planar face + + :return brep_face: The Rhino Brep planar face + """ + brep_curves = [] + + for loop in self.all_loops: + inner_vertices = [ + rg.Point3d(vertex.x, vertex.y, vertex.z) for vertex in loop + ] + inner_polyline = rg.Polyline(inner_vertices) + inner_curve = inner_polyline.ToNurbsCurve() + brep_curves.append(inner_curve) + + brep = rg.Brep.CreatePlanarBreps( + brep_curves, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance + )[0] + + return brep + + def to_mesh(self): + """ + Convert the face to a Rhino Mesh + + :return mesh: The Rhino Mesh object + """ + mesh = rg.Mesh.CreateFromBrep(self.to_brep())[0] + return mesh + + @property + def is_joint(self): + if self.joint_id is not None: + self.__is_joint = True + return True + self.__is_joint = False + return False + + @property + def id(self): + return self.__id + + +@dataclass +class DFBeam: + """ + This class represents a beam, in diffCheck, a beam is a collection of faces + """ + + name: str + faces: typing.List[DFFace] + + def __post_init__(self): + self.name = self.name or "Unnamed Beam" + self.faces = self.faces or [] + self._joint_faces = [] + self._side_faces = [] + + self.__id = uuid.uuid4().int + + @classmethod + def from_brep(cls, brep): + """ + Create a DFBeam from a RhinoBrep object. + It also removes duplicates and creates a list of unique faces. + """ + faces : typing.List[DFFace] = [] + data_faces = diffCheck.df_joint_detector.JointDetector(brep).run() + for data in data_faces: + face = DFFace.from_brep(data[0], data[1]) + faces.append(face) + beam = cls("Beam", faces) + return beam + + def __repr__(self): + return f"Beam: {self.name}, Faces: {len(self.faces)}" + + @property + def id(self): + return self.__id + + @property + def joint_faces(self): + return [face for face in self.faces if face.is_joint] + + @property + def side_faces(self): + return [face for face in self.faces if not face.is_joint] + + +@dataclass +class DFAssembly: + """ + This class represents an assembly of beams + """ + + beams: typing.List[DFBeam] + name: str + + def __post_init__(self): + self.beams = self.beams + self.name = self.name or "Unnamed Assembly" + + self._all_jointfaces = [] + self._all_sidefaces = [] + + def __repr__(self): + return f"Assembly: {self.name}, Beams: {len(self.beams)}" + + def add_beam(self, beam: DFBeam): + self.beams.append(beam) + + def remove_beam(self, beam_id: int): + self.beams = [beam for beam in self.beams if beam.id != beam_id] + + def to_xml(self): + """ + Dump the assembly's meshes to an XML file. On top of the DiffCheck datatypes and structure, + we export the underlaying beams's meshes from Rhino as vertices and faces. + + :return xml_string: The pretty XML string + """ + root = ET.Element("DFAssembly") + root.set("name", self.name) + # dfbeams + for beam in self.beams: + beam_elem = ET.SubElement(root, "DFBeam") + beam_elem.set("name", beam.name) + beam_elem.set("id", str(beam.id)) + # dffaces + for face in beam.faces: + face_elem = ET.SubElement(beam_elem, "DFFace") + face_elem.set("id", str(face.id)) + face_elem.set("is_joint", str(face.is_joint)) + face_elem.set("joint_id", str(face.joint_id)) + # export linked mesh + facerhmesh_elem = ET.SubElement(face_elem, "RhMesh") + mesh = face.to_mesh() + mesh_vertices = mesh.Vertices + for idx, vertex in enumerate(mesh_vertices): + facerhmesh_vertex_elem = ET.SubElement( + facerhmesh_elem, "RhMeshVertex" + ) + facerhmesh_vertex_elem.set("x", str(vertex.X)) + facerhmesh_vertex_elem.set("y", str(vertex.Y)) + facerhmesh_vertex_elem.set("z", str(vertex.Z)) + mesh_faces = mesh.Faces + for idx, face in enumerate(mesh_faces): + facerhmesh_face_elem = ET.SubElement(facerhmesh_elem, "RhMeshFace") + facerhmesh_face_elem.set("v1", str(face.A)) + facerhmesh_face_elem.set("v2", str(face.B)) + facerhmesh_face_elem.set("v3", str(face.C)) + facerhmesh_face_elem.set("v4", str(face.D)) + + tree = ET.ElementTree(root) + xml_string = ET.tostring(root, encoding="unicode") + dom = parseString(xml_string) + pretty_xml = dom.toprettyxml() + + return pretty_xml + + def dump_xml(self, pretty_xml: str, dir: str): + """ + Dump the pretty XML to a file + + :param pretty_xml: The pretty XML string + :param dir: The directory to save the XML + """ + timestamp = datetime.now().strftime("%Y%m%d%H%M%S") + file_path = os.path.join(dir, f"{self.name}_{timestamp}.xml") + + with open(file_path, "w") as f: + f.write(pretty_xml) + + @property + def all_joint_faces(self): + for beam in self.beams: + self._all_jointfaces.extend(beam.joint_faces) + return self._all_jointfaces + + @property + def all_side_faces(self): + for beam in self.beams: + self._all_sidefaces.extend(beam.side_faces) + return self._all_sidefaces diff --git a/src/gh/diffCheck/diffCheck/df_joint_detector.py b/src/gh/diffCheck/diffCheck/df_joint_detector.py new file mode 100644 index 00000000..2a9f0e93 --- /dev/null +++ b/src/gh/diffCheck/diffCheck/df_joint_detector.py @@ -0,0 +1,206 @@ +import Rhino +import scriptcontext as sc +import Rhino.Geometry as rg + +import typing +from dataclasses import dataclass + +import diffCheck.df_util +import diffCheck.df_transformations + +from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML + + +@dataclass +class JointDetector: + """ + This class is responsible for detecting joints in a brep + """ + brep : Rhino.Geometry.Brep + def __post_init__(self): + self.brep = self.brep or None + # list of straight cuts + self._cuts : typing.List[rg.Brep] = [] + # list of holes + self._holes : typing.List[rg.Brep] = [] + # list of mixed joints (cuts+holes) + self._mix : typing.List[rg.Brep]= [] + + # list of DFFaces from joints and sides + self._faces = [] + + def _compute_mass_center(self, b_face: rg.BrepFace) -> rg.Point3d: + """ + Compute the mass center of a brep face + + :param b_face: The brep face to compute the mass center from + :return mass_center: The mass center of the brep face + """ + amp = rg.AreaMassProperties.Compute(b_face) + if amp: + return amp.Centroid + return None + + def run(self) : + """ + Run the joint detector + + :return: a list of faces from joins and faces + """ + ############################################################################ + # 1. Bring to XY, mamke AABB and get negative boolean difference + ############################################################################ + # bring to plane xy + x_form = diffCheck.df_transformations.pln_2_pln_world_transform(self.brep) + + # reverse the transformation + x_form_back = diffCheck.df_transformations.get_inverse_transformation(x_form) + + # compute the bounding box and inflate to include butt joints typo + bbox = self.brep.GetBoundingBox(True) + diagonal = bbox.Diagonal + scaling_factor = diagonal.Length / 10 + bbox.Inflate(scaling_factor, 0, 0) + bbox_b = bbox.ToBrep() + + # boolean difference between the bounding box and the brep transformed + breps_from_booldiff = Rhino.Geometry.Brep.CreateBooleanDifference( + bbox_b, self.brep, sc.doc.ModelAbsoluteTolerance) + if breps_from_booldiff is None or len(breps_from_booldiff) == 0: + ghenv.Component.AddRuntimeMessage(RML.Error, "No breps found after boolean difference.") + + ############################################################################ + # 2. Distinguish holes, cuts, and mix boolean difference results + ############################################################################ + is_hole = False + is_cut = False + is_tenon_mortise = False + is_mix = False + + # parse holes, cuts and mix + for b in breps_from_booldiff: + is_cut = True + for f in b.Faces: + f_brep = f.ToBrep() + f = f_brep.Faces[0] + if not f.IsPlanar(): + is_cut = False + is_hole = True + + b_faces = diffCheck.df_util.explode_brep(b) + for b_face in b_faces: + if b_face.Faces[0].IsPlanar(): + b_face_edges = b_face.Edges + for b_face_edge in b_face_edges: + if not b_face_edge.IsClosed: + is_mix = True + is_hole = False + break + if is_mix: + break + break + + if is_hole: + # TODO: for future development get rid of error + raise NotImplementedError("Hole detected, not implemented yet.") + self._holes.append(b) + elif is_cut: + self._cuts.append(b) + elif is_mix: + self._mix.append(b) + + is_hole = False + is_cut = False + is_mix = False + + # deal with mix + candidate_cuts = [] + candidate_holes = [] + for b in self._mix: + # -- algorithm draft -- + # (1) explode + # (2) seperate in tow list flat surfaces (cuts + cylinder's bases) and non flat surfaces (cylinders) + # (3) cap each object in both lists + # (4) boolunion every object in both lists + # (5) check if closed, if it is + # ---------------------- + # (1) explode + faces_b = diffCheck.df_util.explode_brep(b) + + # (2) seperate in tow list flat surfaces (cuts + cylinder's bases) and non flat surfaces (cylinders) + flat_faces_b = [] + non_flat_faces_b = [] + for f_b in faces_b: + if f_b.Faces[0].IsPlanar(): + flat_faces_b.append(f_b) + else: + non_flat_faces_b.append(f_b) + + # (*) cap the cylinders + non_flat_faces_b = [f_b.CapPlanarHoles(sc.doc.ModelAbsoluteTolerance) for f_b in non_flat_faces_b] + + # (4) boolunion every object in both lists + flat_faces_b = Rhino.Geometry.Brep.CreateBooleanUnion(flat_faces_b, sc.doc.ModelAbsoluteTolerance) + non_flat_faces_b = Rhino.Geometry.Brep.CreateBooleanUnion(non_flat_faces_b, sc.doc.ModelAbsoluteTolerance) + + # (3) cap candidate cuts + flat_faces_b = [f_b.CapPlanarHoles(sc.doc.ModelAbsoluteTolerance) for f_b in flat_faces_b] + # non_flat_faces_b = [f_b.CapPlanarHoles(sc.doc.ModelAbsoluteTolerance) for f_b in non_flat_faces_b] + + # (*) merge all coplanar faces in breps cut candidates + for f_b in flat_faces_b: + if f_b is not None: + f_b.MergeCoplanarFaces(sc.doc.ModelAbsoluteTolerance) + + # (5) check if closed, if it is add to cuts, if not add to holes + for f_b in flat_faces_b: + if f_b is not None: + if f_b.IsSolid: + self._cuts.append(f_b) + if non_flat_faces_b is not None and len(non_flat_faces_b) > 0: + for f_b in non_flat_faces_b: + if f_b is not None: + if f_b.IsSolid: + self._holes.append(f_b) + + ############################################################################ + # 3. Sort faces from joints and faces from sides + ############################################################################ + # retransform back everything + for b in self._holes: + b.Transform(x_form_back) + for b in self._cuts: + b.Transform(x_form_back) + for b in self._mix: + b.Transform(x_form_back) + self.brep.Transform(x_form_back) + + # get all the medians of the faces of cuts only + cuts_faces_centroids : typing.Dict[int, typing.List[rg.Point3d]] = {} + for idx, b in enumerate(self._cuts): + idx = idx + 1 + temp_face_centroids = [] + for f in b.Faces: + centroid = self._compute_mass_center(f) + temp_face_centroids.append(centroid) + cuts_faces_centroids[idx] = temp_face_centroids + + # compare with the brep medians faces to get the joint/sides's faces + for f in self.brep.Faces: + centroid_2test = self._compute_mass_center(f) + for key, centroids in cuts_faces_centroids.items(): + is_joint = False + for centroid in centroids: + if centroid_2test.DistanceTo(centroid) < sc.doc.ModelAbsoluteTolerance: + self._faces.append([f, key]) + is_joint = True + break + if is_joint: + break + if not is_joint: + self._faces.append([f, None]) + + if self._faces is None or len(self._faces) == 0: + ghenv.Component.AddRuntimeMessage(RML.Error, "No faces found after joint detection.") + + return self._faces \ No newline at end of file diff --git a/src/gh/diffCheck/diffCheck/df_transformations.py b/src/gh/diffCheck/diffCheck/df_transformations.py new file mode 100644 index 00000000..20d529b8 --- /dev/null +++ b/src/gh/diffCheck/diffCheck/df_transformations.py @@ -0,0 +1,135 @@ +import Rhino +import Rhino.Geometry as rg +import scriptcontext as sc + +import numpy as np +import math + + +def get_inverse_transformation( + x_form: Rhino.Geometry.Transform, +) -> Rhino.Geometry.Transform: + """ + Get the inverse of a transformation + + :param x_form: the transformation to get the inverse from + :return: the inverse transformation + """ + transformation_matrix = np.array( + [ + [x_form.M00, x_form.M01, x_form.M02, x_form.M03], + [x_form.M10, x_form.M11, x_form.M12, x_form.M13], + [x_form.M20, x_form.M21, x_form.M22, x_form.M23], + [x_form.M30, x_form.M31, x_form.M32, x_form.M33], + ] + ) + inverse_transformation_matrix = np.linalg.inv(transformation_matrix) + + x_form_back = Rhino.Geometry.Transform() + for i in range(4): + for j in range(4): + x_form_back[i, j] = inverse_transformation_matrix[i, j] + + return x_form_back + + +def pln_2_pln_world_transform(brep: Rhino.Geometry.Brep) -> Rhino.Geometry.Transform: + """ + Transform a brep (beam) to the world plane + + :param brep: the brep to transform + :return: the transformation + """ + + def _get_lowest_brep_vertex(brep) -> Rhino.Geometry.Point3d: + """ + Get the the vertex with the lowest y,x and z values + + :param brep: the brep to get the lowest vertex from + :return: the lowest vertex + """ + biggest_vertices = brep.Vertices + lowest_x = 0 + lowest_y = 0 + lowest_z = 0 + for vertex in biggest_vertices: + if vertex.Location.X < lowest_x: + lowest_x = vertex.Location.X + if vertex.Location.Y < lowest_y: + lowest_y = vertex.Location.Y + if vertex.Location.Z < lowest_z: + lowest_z = vertex.Location.Z + return Rhino.Geometry.Point3d(lowest_x, lowest_y, lowest_z) + + # find the longest edge of the brep + edges = brep.Edges + longest_edge = None + longest_edge_length = 0 + for edge in edges: + if edge.GetLength() > longest_edge_length: + longest_edge_length = edge.GetLength() + longest_edge = edge + + # find biggest face + face_indices = longest_edge.AdjacentFaces() + faces = [brep.Faces[face_index] for face_index in face_indices] + biggest_face = None + biggest_face_area = 0 + for face in faces: + if rg.AreaMassProperties.Compute(face).Area > biggest_face_area: + biggest_face_area = rg.AreaMassProperties.Compute(face).Area + biggest_face = face + + # get the plane of the biggest face + if biggest_face.TryGetPlane()[0] is False: + log.error("Could not find plane for longest edge. Exiting...") + return + plane_src = biggest_face.TryGetPlane()[1] + plane_tgt = Rhino.Geometry.Plane.WorldXY + + # plane to plane transformation + x_form_pln2pln = Rhino.Geometry.Transform.PlaneToPlane(plane_src, plane_tgt) + brep.Transform(x_form_pln2pln) + + # adjust to x,y,z positive + lowest_vertex = _get_lowest_brep_vertex(brep) + x_form_transl_A = Rhino.Geometry.Transform.Translation(rg.Vector3d(-lowest_vertex)) + brep.Transform(x_form_transl_A) + + # aabb + bbox = brep.GetBoundingBox(True) + bbox_corners = bbox.GetCorners() + y_val_sum = 0 + x_val_sum = 0 + for corner in bbox_corners: + y_val_sum += corner.Y + x_val_sum += corner.X + + # check if a 90 deg rotation is needed (for the joint detector) + x_form_transl_B = None + x_form_rot90z = None + if x_val_sum > y_val_sum: + # AABB is alligned to x axis. No rotation needed + pass + else: + # AABB is not alligned to y axis. A 90 deg rotation is needed. + x_form_rot90z = Rhino.Geometry.Transform.Rotation( + math.radians(90), rg.Vector3d.ZAxis, rg.Point3d.Origin + ) + brep.Transform(x_form_rot90z) + lowest_vertex = _get_lowest_brep_vertex(brep) + + x_form_transl_B = Rhino.Geometry.Transform.Translation( + rg.Vector3d(-lowest_vertex) + ) + brep.Transform(x_form_transl_B) + + # resume the transformations in one + x_form = Rhino.Geometry.Transform.Identity + if x_form_transl_B: + Rhino.Geometry.Transform.TryGetInverse(x_form_transl_B) + Rhino.Geometry.Transform.TryGetInverse(x_form_rot90z) + x_form = x_form_transl_B * x_form_rot90z + x_form = x_form * x_form_transl_A * x_form_pln2pln + + return x_form diff --git a/src/gh/diffCheck/diffCheck/df_util.py b/src/gh/diffCheck/diffCheck/df_util.py new file mode 100644 index 00000000..0ccf3a0a --- /dev/null +++ b/src/gh/diffCheck/diffCheck/df_util.py @@ -0,0 +1,139 @@ +import Rhino +import Rhino.Geometry as rg +import rhinoscriptsyntax as rs +import scriptcontext as sc + +import typing + + +def explode_brep(brep) -> typing.List[Rhino.Geometry.Brep]: + """ Explode a brep into its faces """ + exploded_objects = [] + if brep.IsSolid: + for face in brep.Faces: + face_brep = face.DuplicateFace(False) + if face_brep: + exploded_objects.append(face_brep) + else: + for face in brep.Faces: + face_brep = face.DuplicateFace(False) + if face_brep: + exploded_objects.append(face_brep) + return exploded_objects + + +def get_crv_circle_center(crv) -> rg.Point3d: + """ Get the center of a circle """ + bbox = crv.GetBoundingBox(True) + bbox_b = bbox.ToBrep() + center_point = bbox_b.GetBoundingBox(True).Center + return center_point + + +def is_pt_unique_in_dict(pt, pt_dict) -> bool: + """ + Detect if the point exists in the dictionary, and if so, return the index + + :param pt: the point to check + :param pt_dict: the dictionary to check + :return: True if the point is unique, False otherwise + """ + is_unique = True + for pt_dict in pt_dict.keys(): + X_a = round(pt.X, 3) + Y_a = round(pt.Y, 3) + Z_a = round(pt.Z, 3) + + X_b = round(pt_dict.X, 3) + Y_b = round(pt_dict.Y, 3) + Z_b = round(pt_dict.Z, 3) + + if X_a == X_b and Y_a == Y_b and Z_a == Z_b: + is_unique = False + break + return is_unique + + +def is_pt_unique_in_list(pt, list) -> bool: + """ + Detect if the point exists in the list, and if so, return the index + + :param pt: the point to check + :param list: the list to check + :return: True if the point is unique, False otherwise + """ + is_unique = True + for pt_list in list: + X_a = round(pt.X, 3) + Y_a = round(pt.Y, 3) + Z_a = round(pt.Z, 3) + + X_b = round(pt_list.X, 3) + Y_b = round(pt_list.Y, 3) + Z_b = round(pt_list.Z, 3) + + if X_a == X_b and Y_a == Y_b and Z_a == Z_b: + is_unique = False + break + return is_unique + + +def detect_idx_pt_in_list(pt, list) -> int: + """ + Detect the index of a point in a list + + :param pt: the point to check + :param list: the list to check + :return: the index of the point in the list + """ + idx = -1 + for pt_list in list: + idx += 1 + X_a = round(pt.X, 3) + Y_a = round(pt.Y, 3) + Z_a = round(pt.Z, 3) + + X_b = round(pt_list.X, 3) + Y_b = round(pt_list.Y, 3) + Z_b = round(pt_list.Z, 3) + + if X_a == X_b and Y_a == Y_b and Z_a == Z_b: + return idx + return idx + + +def compute_ordered_vertices(brep_face) -> typing.List[Rhino.Geometry.Point3d]: + """ Retrieve the ordered vertices of a brep face """ + sorted_vertices = [] + + edges = brep_face.DuplicateEdgeCurves() + edges = list(set(edges)) + + edges_sorted = [] + while len(edges) > 0: + if len(edges_sorted) == 0: + edges_sorted.append(edges[0]) + edges.pop(0) + else: + for edge in edges: + if edges_sorted[-1].PointAtStart == edge.PointAtStart: + edges_sorted.append(edge) + edges.pop(edges.index(edge)) + break + elif edges_sorted[-1].PointAtStart == edge.PointAtEnd: + edges_sorted.append(edge) + edges.pop(edges.index(edge)) + break + elif edges_sorted[-1].PointAtEnd == edge.PointAtStart: + edges_sorted.append(edge) + edges.pop(edges.index(edge)) + break + elif edges_sorted[-1].PointAtEnd == edge.PointAtEnd: + edges_sorted.append(edge) + edges.pop(edges.index(edge)) + break + + for edge in edges_sorted: + sorted_vertices.append(edge.PointAtStart) + + return sorted_vertices diff --git a/src/gh/diffCheck/diffCheck/newmodule.py b/src/gh/diffCheck/diffCheck/newmodule.py new file mode 100644 index 00000000..452195e1 --- /dev/null +++ b/src/gh/diffCheck/diffCheck/newmodule.py @@ -0,0 +1,5 @@ + + + +def test_new_mdoule(): + print("hello from test_new_mdoule") \ No newline at end of file diff --git a/src/gh/diffCheck/diffCheck_app.py b/src/gh/diffCheck/diffCheck_app.py new file mode 100644 index 00000000..a0f84437 --- /dev/null +++ b/src/gh/diffCheck/diffCheck_app.py @@ -0,0 +1,40 @@ +#! python3 + +import Rhino +import Rhino.Geometry as rg + +import os +import typing + +import diffCheck +import diffCheck.df_geometries + +print(diffCheck.__version__) + + +if __name__ == "__main__": + """ + Main function to test the package + :param i_breps: list of breps + :param i_export_dir: directory to export the xml + :param i_dump: whether to dump the xml + """ + # o_joints = diffCheck.df_joint_detector.JointDetector(i_breps[0]).run() + # beams + beams = [] + for brep in i_breps: + beam = diffCheck.df_geometries.DFBeam.from_brep(brep) + beams.append(beam) + + # assembly + assembly1 = diffCheck.df_geometries.DFAssembly(beams, i_assembly_name) + + # dump the xml + xml: str = assembly1.to_xml() + if i_dump: + assembly1.dump_xml(xml, i_export_dir) + o_xml = xml + + # show the joint/side faces + o_joints = [jf.to_brep() for jf in assembly1.all_joint_faces] + o_sides = [sf.to_brep() for sf in assembly1.all_side_faces] diff --git a/src/gh/diffCheck/dist/diffCheck-0.0.3-py3-none-any.whl b/src/gh/diffCheck/dist/diffCheck-0.0.3-py3-none-any.whl new file mode 100644 index 00000000..faa4a55e Binary files /dev/null and b/src/gh/diffCheck/dist/diffCheck-0.0.3-py3-none-any.whl differ diff --git a/src/gh/diffCheck/dist/diffCheck-0.0.3.tar.gz b/src/gh/diffCheck/dist/diffCheck-0.0.3.tar.gz new file mode 100644 index 00000000..882c8b66 Binary files /dev/null and b/src/gh/diffCheck/dist/diffCheck-0.0.3.tar.gz differ diff --git a/src/gh/diffCheck/dist/diffCheck-0.0.9-py3-none-any.whl b/src/gh/diffCheck/dist/diffCheck-0.0.9-py3-none-any.whl new file mode 100644 index 00000000..2c20bda8 Binary files /dev/null and b/src/gh/diffCheck/dist/diffCheck-0.0.9-py3-none-any.whl differ diff --git a/src/gh/diffCheck/dist/diffCheck-0.0.9.tar.gz b/src/gh/diffCheck/dist/diffCheck-0.0.9.tar.gz new file mode 100644 index 00000000..37235594 Binary files /dev/null and b/src/gh/diffCheck/dist/diffCheck-0.0.9.tar.gz differ diff --git a/src/gh/diffCheck/setup.py b/src/gh/diffCheck/setup.py new file mode 100644 index 00000000..921b98c4 --- /dev/null +++ b/src/gh/diffCheck/setup.py @@ -0,0 +1,22 @@ +from setuptools import setup, find_packages + +setup( + name="diffCheck", + version="0.0.9", + packages=find_packages(), + install_requires=[ + "numpy", + # other dependencies... + ], + description="DiffCheck is a package to check the differences between two timber structures", + long_description=open("README.md").read(), + long_description_content_type="text/markdown", + author="Andrea Settimi, Damien Gilliard, Eleni Skevaki, Marirena Kladeftira, Julien Gamerro, Stefana Parascho, and Yves Weinand", + author_email="andrea.settimi@epfl.ch", + url="https://github.com/diffCheckOrg/diffCheck", + classifiers=[ + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + ], +) diff --git a/src/gh/tester.ghx b/src/gh/tester.ghx new file mode 100644 index 00000000..904d106d --- /dev/null +++ b/src/gh/tester.ghx @@ -0,0 +1,5328 @@ + + + + + + + + 0 + 2 + 2 + + + + + + + 1 + 0 + 8 + + + + + + 103ba181-3a3b-4b4e-b795-e493222bd4e6 + Shaded + 1 + + 100;102;0;255 + + + 100;0;150;0 + + + + + + 638480369678877464 + + false + tester.ghx + + + + + 0 + + + + + + 320 + 6 + + 0.25101504 + + + + + 0 + + + + + + + 0 + + + + + F:\diffCheck\src\gh\diffCheck\diffCheck_app.py + F:\diffCheck\src\gh\diffCheck\diffCheck_app.py + not_found + F:\diffCheck\src\gh\diffCheck\diffCheck_app.py + F:\diffCheck\src\gh\diffCheck\diffCheck\diffCheck_app.py + F:\diffCheck\src\gh\diffCheck\diffCheck\test.py + + + + + 2 + + + + + Robert McNeel & Associates + 00000000-0000-0000-0000-000000000000 + Grasshopper + 8.6.24101.5001 + + + + + RhinoCodePluginGH, Version=8.6.24101.5001, Culture=neutral, PublicKeyToken=552281e97c755530 + 8.6.24101.5001 + + 066d0a87-236f-4eae-a0f4-9e42f5327962 + RhinoCodePluginGH + + + + + + + + 52 + + + + + c9b2d725-6f87-4b07-af90-bd9aefef68eb + 066d0a87-236f-4eae-a0f4-9e42f5327962 + script-sync cpython + + + + + + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAABhmlDQ1BJQ0MgcHJvZmlsZQAAKM+VkTtIw1AUhv+mSkUqDhZ84JChCoIFURFHiWIRLJS2QqsOJjd9QZOGJMXFUXAtOPhYrDq4OOvq4CoIgg8QZwcnRRcp8dyk0CJU8MDlfvz3/j/nngsItRLTrI4JQNNtMxGVxHRmVQy8wodB9EPAmMwsI5ZcTKFtfd3Tbaq7CM/C/6pHzVoM8InEc8wwbeIN4plN2+C8TxxiBVklPiceN6lB4keuKx6/cc67LPDMkJlKzBOHiMV8CystzAqmRjxNHFY1nfKFtMcq5y3OWqnCGn3yFwaz+kqS67SGEcUSYohDhIIKiijBRoR2nRQLCTqX2viHXH+cXAq5imDkWEAZGmTXD/4Hv2dr5aYmvaSgBHS+OM7HCBDYBepVx/k+dpz6CeB/Bq70pr9cA2Y/Sa82tfAR0LsNXFw3NWUPuNwBBp4M2ZRdyU9LyOWA9zP6pgzQdwt0r3lza5zj9AFI0ayWb4CDQ2A0T9nrbd7d1Tq3P++484P0A3o2cqrMnZbPAAAACXBIWXMAAAsMAAALDAE/QCLIAAAAB3RJTUUH6AEZFwkM569AfQAABNpJREFUSEu9kntMU3cYhguoOOZ1ujmFXqQtBcEpIwoTxOGQolLwUp24OFS0sEqh0oIV0CIg1FLKsbTlNooFKhRF8TajziW6zYFxcckW9bhlm9uiLk6nAyuWy7tTc0iI4w9l2Z7k++/7nveX9xzGfw+LWMhgV4hd48Y2iN1ZBvEoFiH2ZOrFXkydeJzPvsn05ghhmxIZnCq4xo1TCXe2GaPZJniyKvAqi8AEps5Eb/4LOJVfDQZ4PAswYizLgHHMckxi6vqmeJfMpjdHCNscQgUMDAaMoQJeoQLGUwGTfXR43bvkM3pz5LhxzHXuVMAoqp4x7Ap4sfZT9ejxmk8ppnlrEDE142bCxA3k2vHryKSZYnJrcPxS+vTFcGMR09w55keuAFf/Xs/612OKjxZvepdAMF2NFROT8IHv+5CEroZskeiaJC7Cgz5/MTzYRsVg/64PPJFZhqlUwHTvYrBmFGBZsAybw9ZCGr0SyhXLoVobk0Gfvhju/CJPD2GnY7SwE57CDngJL2FCzBeYsuQC/OM/Rdiq45AsWQP5ygSoEpdi94fRDyslc6SWNH9pvVwgtWb7SQ/k8CfRumHY2ithpACD45YyAA9JP3ykPQiQdSNh4zlsS1gFZaIIuZuEKEx5DwZZKKyZAWhUCdC0i5o9fIK2Pcfm7gmMlIF7zwd4b3MiMMOBhdvvQLJ6C+TrV0CVvBz5qTEoTo+CThmBAzlBaNotgK3AD80av97mUt4s2joESX/ZULlr3pD2I1Deg/nKLiQmN0O2Xoys5HjsksaiUB6Nfcp3UZ67ANX5IThYRMn38dFSxoed4J+lrTRbngio1zuHyid9NABeei+CFQ5EZ91FcsZZyBTtUGUfRGFuLXRqAuaCEtQX51GvlqCllBLr+Wg18HDIzIO9xnc5baeQ9J0YKncNU9aPOYoeLNzZhXWZV5CiOI3MHW3Iy21AsboSRIEe1ZpCNGh3okUXjhaCkhspeRUPh2u5aLNwb1isM0a7Xi98Xj49rR8CuRPvqBxYtuNXbFKcR5rqBLLz7MjPt0BbZIRRo0WdLh82fRLs+/k4ZKLk1ZT4Yy6O1FPT6IujzTMzqT/HGUv1nzp0eOnO1JAsR+rinPuZiYrOPonqLOS57chRH8TevbUo01D16IrRSOSgwxCJK6ZgXK2ZjW/rZuGa1Q+kjYfvW7i40ep7ne5oeNbIL6mTsi9gW95pKNVtUBc1QKOpwn5dGarLC3GxYiN+Mkfgds183LcEo8sahB6bP3rtfAwc5qK3nbORVv0TUdpF1jplx+OtueeRvvskVIV2FJTUQ1tqgpHQotm4EzeMi3GrKhx36+bhgXUuum2B6LEL0NfGQ/8x38u0anhWbe/Yu0H1OZm66wyZuecomVfSRBZpa0h9OUGaK4rJL43rcbN6EX6xhOF3awge2mbjcWsAnrb5oe84F49PcUJp1ctz2SCM+64qGj/URuK3A6G4Z5uLR/YgONoEcB7jwXlqZiO9+vKcIaLHfG2KJa/VLMaPlnDcts3DHy1z8NfhQDxp96Pk3O77Z9gz6PWXp7MiTnG1MhbX66Lwc8MC3GkOwYNDb6GrPQA9J/lwnPbNo1dHRqdJFPVNbYyItEaKbjWFie62vi3680iQqPu4v+jpJzzRg3PssfTq/wGD8Tedsdp6457pjwAAAABJRU5ErkJggg== + + dcf18e47-99f2-42d5-9ca4-7e6aee82d9b6 + true + true + false + true + script-sync cpython + scsy-cpy + 1 + + false + false + false + + + + + + 177 + 92 + 171 + 104 + + + 284 + 144 + + + + + + 5 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 4 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + + + + + true + Connect a button to open a file dialog to select a cpython file to run. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA6xJREFUSEvVVTlLXGEUHRUHkXHfHRWXcd/3DRVcQBFUVAzaCYKC+AsGohYGDQiipYV2VpLSykawjCIuaOGCgiZFgoVmNImc3HPnPRHHLVXIgcu8ecu59557vu+z/Cs4vLy8fsgv/iLeSbwNfn5+n+fn57G+vo61tTWsrq5iZWUFy8vLWFxcxNTUFAYGBtDa2orq6mqkpqZCCrqQT61uhhfg4+PTLh/+WlhYQHl5uUZZWRlKSkpQVFSE/Px85OTkICMjQ4mTkpKQlZUFm8125e3t7TRonoU1KCjo29LSErq6urQ6RlVVlSZiksLCQuTm5ippWloaUlJSNJKTkyEJroXD7qZ6Ar6+vh/6+/t/j42NoaamBnV1dRq8ZhJ2UlxcrF1kZ2cjPT1dyRMTE7UTKe5WpPpk0HnAER0dfTM7O4uGhgYlrq+vR0tLC+bm5rC7uwsT29vbmJycREFBARwOhyaIj49HXFwcZ8Euit2UDyDar3V2dqK3t1dlYYKenh4cHR0ZtJ44ODjQd5mA5DExMQgJCbmTJBsG7T1aw8PDXSSk1pSD1R8eHhpUnnC5XPq7v7+vw2YCUQAJCQkQF14JZ5+bWgYr1X+pqKgAg4NkkpmZGSV4Cufn5+jo6MDZ2Zn+Hx8fh91uR1RUlCZhR9LFd+G2WWTy78PCwlwk5/BoRSZh+0/h4uICTU1NatORkRG9t7Ozg9jYWERGRiI0NFQHL9dcqNMWyXSZmZmp3mYwCa14c3OjHz+ESc73aVEOmaBc1D8iIoIz0ER5eXlc3ZdMMC32uqa3zUS8fpyAspjktCfdQxKCCSiPKIHg4GB9R1zFDj5KWGzUiz5m2wwuooe2JDmty2esnOR8f2hoSJ9vbW1p9ZSHnXC9yFzdMzDQZ7Var/gxHcHfiYkJ/ZidtLW16T0+o74kZ/Wnp6f6jtPpvK+eBhGJuBbuXaSgd6kdlzxJWC0tSJycnGB4eFhb5/3BwUEcHx/rs729Pa2a5OystLT0Tug81gFRxr2EFjODzjKTPAWSc2YcLOXhjAIDA6m950ompItP8uItO+DCYVCO0dFRbG5uGrTAxsaGykLvs3IhVXuLbD+F5tm9iLCzC+rNvYWLxgy6hBJymNSbFYv7EBAQoM95NsgcX95NDTil5WvulrJ93IdJSjnMquUMgL+/v24r0jXJXz0PCKtI9ZVWraysRG1trRJQ3+bmZq20vb0d3Bi7u7t1Q2xsbHz7iWaA5+vjM/e1ePuZ/B/BYvkDKff7sf0Xzw8AAAAASUVORK5CYII= + + 083c2fe3-a45a-43c1-8f85-ce20a4a69a99 + true + btn + btn + true + 0 + true + 5f8bfbf4-70d5-46ba-90fa-f3804e9a9032 + 1 + Connect a button to open a file dialog to select a cpython file to run. + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 179 + 94 + 90 + 20 + + + 225.5 + 104 + + + + + + + + true + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + e0ef2066-70a4-441f-906b-8a4afddb0692 + true + i_export_dir + i_export_dir + true + 0 + true + 77c76654-6be3-4843-b564-afe44705740d + 1 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 179 + 114 + 90 + 20 + + + 225.5 + 124 + + + + + + + + 1 + true + Converts to collection of Breps (Boundary REPresentations) + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAPkSURBVEhL1VVbKOV7FN7ITnK/RYNcNrkrx11SbokHuWQyb0ryRN5ocuLBKadELsktHuTywKBcXgiRUiYvJOVSknNw5LK3OWbO9J31/famOWfPGPN0OqtW+7/r9/vWWt/61vpp/ivTWVhY3MsvfsBfi7/MbGxstvr6+rC+vo7V1VUsLi5ifn4eExMTGBoaQnNzM8rLy5GXl4eUlBQEBQVBEjqTq1ojwjNmZWWVLxc/DQ4OIiEhQXl8fDxiY2MRExOD6OhoREREICQkRAH7+/sjLCwMdnZ2ektLy7cmmG+a1tHR8Y/R0VEUFRWp7OjJyclISkrC8PAwHh4ecHNzg4WFBeTm5iIwMFB5QEAAJIBBMF4Zob5i1tbWv5SVlf3V0NCA1NRUpKWlPTmpOjw8RHd3N3p7e7G0tITb21v138/PT1UiyT0IVe9McGam8/T0/LO9vR0ZGRkKND09HZmZmVhbW4Ner0dnZycmJydRUVGBqqoq1NfX4+joSPWHQby9vdkLVvGTEfILE+5XSUtpaamihQEIzkYT/PLyEgy+ubmJ2tpa1eiBgQG0trbi4OAAXV1d8PLygrOz82cJ8t4E+2R5bm5uH0pKSlRTyTkDPGZO8OPjY4yPj2Nubg4rKysKfHp6Wp3hN+li5b6+vhAV6gXzjRFaGivZ/5aYmAg61cKGkvMvwXd2dlT2LS0tODs7U98E39vbw/7+vurJ7OwshGZFl1RxJdh2Gun8z66urh8ITglSiiMjIzAYDGbgBBkbG0NHRwfOz89xcXGhztB6enpwfX0NFxcXpSp3d3cO6q8aiXQdGhqqtE1nEIJfXV2Zgc/MzIASZrMbGxsVVScnJ9jY2FDKYsXSA3h4eCAqKorTfc0ALSIvQ2RkJB4D3d/fq4tfA+/v70dbWxuamppQWVmJ6upq9X93d1cFcXJyUjjSC2MF5Il8UcecTjozOz09fRa8rq5OSZWS3draUvwLLUpJnHzpq7EHJnuj1Wr1wcHBavwLCgpwd3eH5eXlF4OTFmZPFco3Z+FJRcqkivc8xJFnk3iJFfwIuE6nQ1xc3GeBM5sDWjx3CSVGp6qoEMqVqnkOnI2lerKysuDg4EDuzSeZJlW8k4MPrIBjz3K5BqioqakpNcE1NTXY3t7+R+YCquQtyvkoMN/cRbRXrIK98PHxUUNDz87OVhNM+bI3XBlsqKgP9vb26gzfBunj89vUZG+lZEN4eDhkfTy5DKOigXQ8Zi1vAGxtbdVSlKoJ/t33gKYVqn7nI/K4kwhAfnNyclSm+fn5KCwsRHFxMbi/uBTlzsteNJPxff33m/s9f/mb/D8yjeZvU880QlAx2/0AAAAASUVORK5CYII= + + ae8c9c0d-8d6a-4a8c-812a-110846a2031c + true + i_breps + i_breps + true + 1 + true + 0f309845-29e6-43ae-b255-cdb5c2d13da9 + 1 + + 2ceb0405-fdfe-403d-a4d6-8786da45fb9d + + + + + + 179 + 134 + 90 + 20 + + + 225.5 + 144 + + + + + + + + true + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + d9632669-508e-4a03-b9bc-a5d740ef546f + true + i_assembly_name + i_assembly_name + true + 0 + true + 86bc59e0-752b-48c2-b3e8-8f0c8b9737a3 + 1 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 179 + 154 + 90 + 20 + + + 225.5 + 164 + + + + + + + + true + Converts to collection of boolean values + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAOsSURBVEhL1VU5S1xhFB0VB5Fx3x0Vl3Hf9w0VXEARVFQM2gmCgvgLBqIWBg0IoqWFdlaS0spGsIwiLmjhgoImRYKFZjSJnNxz5z0Rxy1VyIHLvHnLufeee77vs/wrOLy8vH7IL/4i3km8DX5+fp/n5+exvr6OtbU1rK6uYmVlBcvLy1hcXMTU1BQGBgbQ2tqK6upqpKamQgq6kE+tboYX4OPj0y4f/lpYWEB5eblGWVkZSkpKUFRUhPz8fOTk5CAjI0OJk5KSkJWVBZvNduXt7e00aJ6FNSgo6NvS0hK6urq0OkZVVZUmYpLCwkLk5uYqaVpaGlJSUjSSk5MhCa6Fw+6megK+vr4f+vv7f4+NjaGmpgZ1dXUavGYSdlJcXKxdZGdnIz09XckTExO1EynuVqT6ZNB5wBEdHX0zOzuLhoYGJa6vr0dLSwvm5uawu7sLE9vb25icnERBQQEcDocmiI+PR1xcHGfBLordlA8g2q91dnait7dXZWGCnp4eHB0dGbSeODg40HeZgOQxMTEICQm5kyQbBu09WsPDw10kpNaUg9UfHh4aVJ5wuVz6u7+/r8NmAlEACQkJEBdeCWefm1oGK9V/qaioAIODZJKZmRkleArn5+fo6OjA2dmZ/h8fH4fdbkdUVJQmYUfSxXfhtllk8u/DwsJcJOfwaEUmYftP4eLiAk1NTWrTkZERvbezs4PY2FhERkYiNDRUBy/XXKjTFsl0mZmZqd5mMAmteHNzox8/hEnO92lRDpmgXNQ/IiKCM9BEeXl5XN2XTDAt9rqmt81EvH6cgLKY5LQn3UMSggkojyiB4OBgfUdcxQ4+Slhs1Is+ZtsMLqKHtiQ5rctnrJzkfH9oaEifb21tafWUh51wvchc3TMw0Ge1Wq/4MR3B34mJCf2YnbS1tek9PqO+JGf1p6en+o7T6byvngYRibgW7l2koHepHZc8SVgtLUicnJxgeHhYW+f9wcFBHB8f67O9vT2tmuTsrLS09E7oPNYBUca9hBYzg84ykzwFknNmHCzl4YwCAwOpvedKJqSLT/LiLTvgwmFQjtHRUWxubhq0wMbGhspC77NyIVV7i2w/hebZvYiwswvqzb2Fi8YMuoQScpjUmxWL+xAQEKDPeTbIHF/eTQ04peVr7payfdyHSUo5zKrlDIC/v79uK9I1yV89DwirSPWVVq2srERtba0SUN/m5mattL29HdwYu7u7dUNsbGx8+4lmgOfr4zP3tXj7mfwfwWL5Ayn3+7H9F88PAAAAAElFTkSuQmCC + + 1e3c2c63-ede9-4faf-9790-a3d1b9350ba3 + true + i_dump + i_dump + true + 0 + true + 254a4a2f-d415-488e-9851-4a763f1ba58f + 1 + + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 179 + 174 + 90 + 20 + + + 225.5 + 184 + + + + + + + + false + The redirected standard output of the component scriptsync. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 55cc2102-ec2b-4f6f-ba16-74e8aed9df42 + true + stdout + stdout + false + 0 + true + 0 + The redirected standard output of the component scriptsync. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 299 + 94 + 47 + 25 + + + 322.5 + 106.5 + + + + + + + + false + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + a849584f-8d8a-4547-a1a4-36be0bf3ac37 + true + o_xml + o_xml + false + 0 + true + 0 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 299 + 119 + 47 + 25 + + + 322.5 + 131.5 + + + + + + + + false + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + 178951a0-3c74-4810-aef0-87cc45b0502c + true + o_joints + o_joints + false + 0 + true + 0 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 299 + 144 + 47 + 25 + + + 322.5 + 156.5 + + + + + + + + false + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + 76758d37-2a1d-412d-b85b-149ecda8a020 + true + o_sides + o_sides + false + 0 + true + 0 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 299 + 169 + 47 + 25 + + + 322.5 + 181.5 + + + + + + + + + + false + IyEgcHl0aG9uMwojIHI6IG51bXB5Cgpmcm9tIGdocHl0aG9ubGliLmNvbXBvbmVudGJhc2UgaW1wb3J0IGV4ZWN1dGluZ2NvbXBvbmVudCBhcyBjb21wb25lbnQKCmltcG9ydCBTeXN0ZW0KaW1wb3J0IFN5c3RlbS5EcmF3aW5nCmltcG9ydCBTeXN0ZW0uV2luZG93cy5Gb3JtcwppbXBvcnQgUmhpbm8KaW1wb3J0IEdyYXNzaG9wcGVyCmltcG9ydCBHcmFzc2hvcHBlciBhcyBnaApmcm9tIEdyYXNzaG9wcGVyLktlcm5lbCBpbXBvcnQgR0hfUnVudGltZU1lc3NhZ2VMZXZlbCBhcyBSTUwKaW1wb3J0IHN5cwppbXBvcnQgb3MKaW1wb3J0IHRpbWUKCmltcG9ydCBjb250ZXh0bGliCmltcG9ydCBpbwoKaW1wb3J0IGFiYwppbXBvcnQgc29ja2V0CmltcG9ydCB0aHJlYWRpbmcKaW1wb3J0IHF1ZXVlCmltcG9ydCBqc29uCgppbXBvcnQgaW1wb3J0bGliCmltcG9ydCBzeXMKCgpjbGFzcyBHSFRocmVhZCh0aHJlYWRpbmcuVGhyZWFkLCBtZXRhY2xhc3M9YWJjLkFCQ01ldGEpOgogICAgIiIiCiAgICAgICAgQSBiYXNlIGNsYXNzIGZvciBHcmFzc2hvcHBlciB0aHJlYWRzLgogICAgIiIiCiAgICBkZWYgX19pbml0X18oc2VsZiwgbmFtZSA6IHN0cik6CiAgICAgICAgc3VwZXIoKS5fX2luaXRfXyhuYW1lPW5hbWUsIGRhZW1vbj1GYWxzZSkKICAgICAgICBzZWxmLl9jb21wb25lbnRfb25fY2FudmFzID0gVHJ1ZQogICAgICAgIHNlbGYuX2NvbXBvbmVudF9lbmFibGVkID0gVHJ1ZQoKICAgIEBhYmMuYWJzdHJhY3RtZXRob2QKICAgIGRlZiBydW4oc2VsZik6CiAgICAgICAgIiIiIFJ1biB0aGUgdGhyZWFkLiAiIiIKICAgICAgICBwYXNzCgogICAgZGVmIF9jaGVja19pZl9jb21wb25lbnRfb25fY2FudmFzKHNlbGYpOgogICAgICAgICIiIiBDaGVjayBpZiB0aGUgY29tcG9uZW50IGlzIG9uIGNhbnZhcyBmcm9tIHRocmVhZC4gIiIiCiAgICAgICAgZGVmIF9fY2hlY2tfaWZfY29tcG9uZW50X29uX2NhbnZhcygpOgogICAgICAgICAgICBpZiBnaGVudi5Db21wb25lbnQuT25QaW5nRG9jdW1lbnQoKSBpcyBOb25lOgogICAgICAgICAgICAgICAgc2VsZi5fY29tcG9uZW50X29uX2NhbnZhcyA9IEZhbHNlCiAgICAgICAgICAgICAgICByZXR1cm4gRmFsc2UKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIHNlbGYuX2NvbXBvbmVudF9vbl9jYW52YXMgPSBUcnVlCiAgICAgICAgICAgICAgICByZXR1cm4gVHJ1ZQogICAgICAgIGFjdGlvbiA9IFN5c3RlbS5BY3Rpb24oX19jaGVja19pZl9jb21wb25lbnRfb25fY2FudmFzKQogICAgICAgIFJoaW5vLlJoaW5vQXBwLkludm9rZU9uVWlUaHJlYWQoYWN0aW9uKQoKICAgIGRlZiBfY2hlY2tfaWZfY29tcG9uZW50X2VuYWJsZWQoc2VsZik6CiAgICAgICAgIiIiIENoZWNrIGlmIHRoZSBjb21wb25lbnQgaXMgZW5hYmxlZCBmcm9tIHRocmVhZC4gIiIiCiAgICAgICAgZGVmIF9fY2hlY2tfaWZfY29tcG9uZW50X2VuYWJsZWQoKToKICAgICAgICAgICAgaWYgZ2hlbnYuQ29tcG9uZW50LkxvY2tlZDoKICAgICAgICAgICAgICAgIHNlbGYuX2NvbXBvbmVudF9lbmFibGVkID0gRmFsc2UKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIHNlbGYuX2NvbXBvbmVudF9lbmFibGVkID0gVHJ1ZQogICAgICAgIGFjdGlvbiA9IFN5c3RlbS5BY3Rpb24oX19jaGVja19pZl9jb21wb25lbnRfZW5hYmxlZCkKICAgICAgICBSaGluby5SaGlub0FwcC5JbnZva2VPblVpVGhyZWFkKGFjdGlvbikKCiAgICBkZWYgZXhwaXJlX2NvbXBvbmVudF9zb2x1dGlvbihzZWxmKToKICAgICAgICAiIiIgRmlyZSB0aGUgcmVjYWxjdWxhdGlvbiBvZiB0aGUgY29tcG9uZW50IHNvbHV0aW9uIGZyb20gdGhyZWFkLiAiIiIKICAgICAgICBkZWYgX19leHBpcmVfY29tcG9uZW50X3NvbHV0aW9uKCk6CiAgICAgICAgICAgIGdoZW52LkNvbXBvbmVudC5QYXJhbXMuT3V0cHV0WzBdLkNsZWFyRGF0YSgpICAjIGNsZWFyIHRoZSBvdXRwdXQKICAgICAgICAgICAgZ2hlbnYuQ29tcG9uZW50LkV4cGlyZVNvbHV0aW9uKFRydWUpICAjIGV4cGlyZSB0aGUgY29tcG9uZW50CiAgICAgICAgYWN0aW9uID0gU3lzdGVtLkFjdGlvbihfX2V4cGlyZV9jb21wb25lbnRfc29sdXRpb24pCiAgICAgICAgUmhpbm8uUmhpbm9BcHAuSW52b2tlT25VaVRocmVhZChhY3Rpb24pCgogICAgZGVmIGNsZWFyX2NvbXBvbmVudChzZWxmKToKICAgICAgICAiIiIgQ2xlYXIgdGhlIGNvbXBvbmVudCBmcm9tIHRocmVhZC4gIiIiCiAgICAgICAgZGVmIF9fY2xlYXJfY29tcG9uZW50KCk6CiAgICAgICAgICAgIGdoZW52LkNvbXBvbmVudC5DbGVhckRhdGEoKQogICAgICAgIGFjdGlvbiA9IFN5c3RlbS5BY3Rpb24oX19jbGVhcl9jb21wb25lbnQpCiAgICAgICAgUmhpbm8uUmhpbm9BcHAuSW52b2tlT25VaVRocmVhZChhY3Rpb24pCgogICAgZGVmIGFkZF9ydW50aW1lX3dhcm5pbmcoc2VsZiwgZXhjZXB0aW9uIDogc3RyKToKICAgICAgICAiIiIgQWRkIGEgd2FybmluZyB0YWIgdG8gdGhlIGNvbXBvbmVudCBmcm9tIG1haW4gdGhyZWFkLiAiIiIKICAgICAgICBhY3Rpb24gPSBTeXN0ZW0uQWN0aW9uKAogICAgICAgICAgICBsYW1iZGE6IGdoZW52LkNvbXBvbmVudC5BZGRSdW50aW1lTWVzc2FnZShSTUwuV2FybmluZywgZXhjZXB0aW9uKQogICAgICAgICkKICAgICAgICBSaGluby5SaGlub0FwcC5JbnZva2VPblVpVGhyZWFkKGFjdGlvbikKCiAgICBkZWYgYWRkX3J1bnRpbWVfZXJyb3Ioc2VsZiwgZXhjZXB0aW9uIDogc3RyKToKICAgICAgICAiIiIgQWRkIGFuIGVycm9yIHRhYiB0byB0aGUgY29tcG9uZW50IGZyb20gbWFpbiB0aHJlYWQuICIiIgogICAgICAgIGFjdGlvbiA9IFN5c3RlbS5BY3Rpb24oCiAgICAgICAgICAgIGxhbWJkYTogZ2hlbnYuQ29tcG9uZW50LkFkZFJ1bnRpbWVNZXNzYWdlKFJNTC5FcnJvciwgZXhjZXB0aW9uKQogICAgICAgICkKICAgICAgICBSaGluby5SaGlub0FwcC5JbnZva2VPblVpVGhyZWFkKGFjdGlvbikKCiAgICBkZWYgYWRkX3J1bnRpbWVfcmVtYXJrKHNlbGYsIGV4Y2VwdGlvbiA6IHN0cik6CiAgICAgICAgIiIiIEFkZCBhIGJsYW5rIHRhYiB0byB0aGUgY29tcG9uZW50IGZyb20gbWFpbiB0aHJlYWQuICIiIgogICAgICAgIGFjdGlvbiA9IFN5c3RlbS5BY3Rpb24oCiAgICAgICAgICAgIGxhbWJkYTogZ2hlbnYuQ29tcG9uZW50LkFkZFJ1bnRpbWVNZXNzYWdlKFJNTC5SZW1hcmssIGV4Y2VwdGlvbikKICAgICAgICApCiAgICAgICAgUmhpbm8uUmhpbm9BcHAuSW52b2tlT25VaVRocmVhZChhY3Rpb24pCgogICAgQHByb3BlcnR5CiAgICBkZWYgY29tcG9uZW50X2VuYWJsZWQoc2VsZik6CiAgICAgICAgc2VsZi5fY2hlY2tfaWZfY29tcG9uZW50X2VuYWJsZWQoKQogICAgICAgIHJldHVybiBzZWxmLl9jb21wb25lbnRfZW5hYmxlZAoKICAgIEBwcm9wZXJ0eQogICAgZGVmIGNvbXBvbmVudF9vbl9jYW52YXMoc2VsZik6CiAgICAgICAgc2VsZi5fY2hlY2tfaWZfY29tcG9uZW50X29uX2NhbnZhcygpCiAgICAgICAgcmV0dXJuIHNlbGYuX2NvbXBvbmVudF9vbl9jYW52YXMKCmNsYXNzIENsaWVudFRocmVhZChHSFRocmVhZCk6CiAgICAiIiIKICAgIEEgdGhyZWFkIHRvIGNvbm5lY3QgdG8gdGhlIFZTQ29kZSBzZXJ2ZXIuCiAgICAiIiIKICAgIGRlZiBfX2luaXRfXyhzZWxmLCB2c2NvZGVfc2VydmVyX2lwOiBzdHIsIHZzY29kZV9zZXJ2ZXJfcG9ydDogaW50LCBuYW1lOiBzdHIsCiAgICAgICAgICAgICAgICAgcXVldWVfbXNnOiBxdWV1ZS5RdWV1ZSA9IE5vbmUsIGxvY2tfcXVldWVfbXNnOiB0aHJlYWRpbmcuTG9jayA9IE5vbmUsCiAgICAgICAgICAgICAgICAgZXZlbnRfZmlyZV9tc2c6IHRocmVhZGluZy5FdmVudCA9IE5vbmUpOgogICAgICAgIHN1cGVyKCkuX19pbml0X18obmFtZT1uYW1lKQogICAgICAgIHNlbGYudnNjb2RlX3NlcnZlcl9pcCA9IHZzY29kZV9zZXJ2ZXJfaXAKICAgICAgICBzZWxmLnZzY29kZV9zZXJ2ZXJfcG9ydCA9IHZzY29kZV9zZXJ2ZXJfcG9ydAogICAgICAgIHNlbGYuaXNfY29ubmVjdGVkID0gRmFsc2UKICAgICAgICBzZWxmLmNvbm5lY3RfcmVmcmVzaF9yYXRlID0gMSAgIyBzZWNvbmRzCiAgICAgICAgc2VsZi5xdWV1ZV9tc2cgPSBxdWV1ZV9tc2cKICAgICAgICBzZWxmLmxvY2tfcXVldWVfbXNnID0gbG9ja19xdWV1ZV9tc2cKICAgICAgICBzZWxmLmV2ZW50X2ZpcmVfbXNnID0gZXZlbnRfZmlyZV9tc2cKICAgICAgICBzZWxmLmNsaWVudF9zb2NrZXQgPSBzb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVULCBzb2NrZXQuU09DS19TVFJFQU0pCgogICAgZGVmIHJ1bihzZWxmKToKICAgICAgICAiIiIgUnVuIHRoZSB0aHJlYWQuIFNlbmQgdGhlIG1lc3NhZ2UgdG8gdGhlIHZzY29kZSBzZXJ2ZXIuIiIiCiAgICAgICAgd2hpbGUgc2VsZi5jb21wb25lbnRfb25fY2FudmFzIGFuZCBzZWxmLmNvbXBvbmVudF9lbmFibGVkOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBpZiBub3Qgc2VsZi5pc19jb25uZWN0ZWQ6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5jb25uZWN0X3RvX3ZzY29kZV9zZXJ2ZXIoKQogICAgICAgICAgICAgICAgICAgIHNlbGYuY2xlYXJfY29tcG9uZW50KCkKICAgICAgICAgICAgICAgICAgICBzZWxmLmV4cGlyZV9jb21wb25lbnRfc29sdXRpb24oKQogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlCgogICAgICAgICAgICAgICAgc2VsZi5ldmVudF9maXJlX21zZy53YWl0KCkKICAgICAgICAgICAgICAgIHNlbGYuc2VuZF9tZXNzYWdlX2Zyb21fcXVldWUoKQoKICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICAgICAgICAgc2VsZi5hZGRfcnVudGltZV93YXJuaW5nKGYic2NyaXB0LXN5bmM6OlVua293biBlcnJvciBmcm9tIHJ1bjoge3N0cihlKX0iKQogICAgICAgICAgICAgICAgc2VsZi5pc19jb25uZWN0ZWQgPSBGYWxzZQogICAgICAgICAgICAgICAgc2VsZi5jbGllbnRfc29ja2V0ID0gc29ja2V0LnNvY2tldChzb2NrZXQuQUZfSU5FVCwgc29ja2V0LlNPQ0tfU1RSRUFNKQoKICAgICAgICBzZWxmLmNsaWVudF9zb2NrZXQuY2xvc2UoKQoKICAgIGRlZiBzZW5kX21lc3NhZ2VfZnJvbV9xdWV1ZShzZWxmKToKICAgICAgICB3aXRoIHNlbGYubG9ja19xdWV1ZV9tc2c6CiAgICAgICAgICAgIGlmIHNlbGYucXVldWVfbXNnIGFuZCBub3Qgc2VsZi5xdWV1ZV9tc2cuZW1wdHkoKToKICAgICAgICAgICAgICAgIG1zZyA9IHNlbGYucXVldWVfbXNnLmdldCgpCiAgICAgICAgICAgICAgICBzZWxmLnF1ZXVlX21zZy50YXNrX2RvbmUoKQogICAgICAgICAgICAgICAgc2VsZi5ldmVudF9maXJlX21zZy5zZXQoKQogICAgICAgICAgICAgICAgc2VsZi5ldmVudF9maXJlX21zZy5jbGVhcigpCiAgICAgICAgICAgICAgICBzZWxmLmNsaWVudF9zb2NrZXQuc2VuZChtc2cpCgogICAgZGVmIGNvbm5lY3RfdG9fdnNjb2RlX3NlcnZlcihzZWxmKToKICAgICAgICAiIiIgQ29ubmVjdCB0byB0aGUgVlNDb2RlIHNlcnZlci4gIiIiCiAgICAgICAgd2hpbGUgc2VsZi5jb21wb25lbnRfb25fY2FudmFzIGFuZCBub3Qgc2VsZi5pc19jb25uZWN0ZWQ6CiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIHNlbGYuY2xpZW50X3NvY2tldC5zZW5kKGIiIikKICAgICAgICAgICAgICAgIHNlbGYuaXNfY29ubmVjdGVkID0gVHJ1ZQogICAgICAgICAgICBleGNlcHQgc29ja2V0LmVycm9yOgogICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgIHNlbGYuY2xpZW50X3NvY2tldC5jb25uZWN0KChzZWxmLnZzY29kZV9zZXJ2ZXJfaXAsIHNlbGYudnNjb2RlX3NlcnZlcl9wb3J0KSkKICAgICAgICAgICAgICAgICAgICBzZWxmLmlzX2Nvbm5lY3RlZCA9IFRydWUKICAgICAgICAgICAgICAgIGV4Y2VwdCAoQ29ubmVjdGlvblJlZnVzZWRFcnJvciwgQ29ubmVjdGlvblJlc2V0RXJyb3IsIHNvY2tldC5lcnJvcikgYXMgZToKICAgICAgICAgICAgICAgICAgICBzZWxmLmhhbmRsZV9jb25uZWN0aW9uX2Vycm9yKGUpCiAgICAgICAgICAgIGZpbmFsbHk6CiAgICAgICAgICAgICAgICB0aW1lLnNsZWVwKHNlbGYuY29ubmVjdF9yZWZyZXNoX3JhdGUpCgogICAgZGVmIGhhbmRsZV9jb25uZWN0aW9uX2Vycm9yKHNlbGYsIGUpOgogICAgICAgIGVycm9yX21lc3NhZ2VzID0gewogICAgICAgICAgICBDb25uZWN0aW9uUmVmdXNlZEVycm9yOiAic2NyaXB0LXN5bmM6OkNvbm5lY3Rpb24gcmVmdXNlZCBieSB0aGUgdnNjb2RlIiwKICAgICAgICAgICAgQ29ubmVjdGlvblJlc2V0RXJyb3I6ICJzY3JpcHQtc3luYzo6Q29ubmVjdGlvbiB3YXMgZm9yY2libHkgY2xvc2VkIGJ5IHRoZSB2c2NvZGUiLAogICAgICAgICAgICBzb2NrZXQuZXJyb3I6IGYic2NyaXB0LXN5bmM6OkVycm9yIGNvbm5lY3RpbmcgdG8gdGhlIHZzY29kZToge3N0cihlKX0iCiAgICAgICAgfQogICAgICAgIHNlbGYuYWRkX3J1bnRpbWVfd2FybmluZyhlcnJvcl9tZXNzYWdlc1t0eXBlKGUpXSkKICAgICAgICBzZWxmLmlzX2Nvbm5lY3RlZCA9IEZhbHNlIGlmIHR5cGUoZSkgIT0gc29ja2V0LmVycm9yIG9yIGUud2luZXJyb3IgIT0gMTAwNTYgZWxzZSBUcnVlCgoKY2xhc3MgRmlsZUNoYW5nZWRUaHJlYWQoR0hUaHJlYWQpOgogICAgIiIiCiAgICAgICAgQSB0aHJlYWQgdG8gY2hlY2sgaWYgdGhlIGZpbGUgaGFzIGNoYW5nZWQgb24gZGlzay4KICAgICIiIgogICAgZGVmIF9faW5pdF9fKHNlbGYsCiAgICAgICAgICAgICAgICBwYXRoIDogc3RyLAogICAgICAgICAgICAgICAgbmFtZSA6IHN0cgogICAgICAgICAgICAgICAgKToKICAgICAgICBzdXBlcigpLl9faW5pdF9fKG5hbWU9bmFtZSkKICAgICAgICBzZWxmLnBhdGggPSBwYXRoCiAgICAgICAgc2VsZi5yZWZyZXNoX3JhdGUgPSAxMDAwICAjIG1pbGxpc2Vjb25kcwogICAgICAgIHNlbGYuX29uX2ZpbGVfY2hhbmdlZCA9IHRocmVhZGluZy5FdmVudCgpCgogICAgZGVmIHJ1bihzZWxmKToKICAgICAgICAiIiIKICAgICAgICAgICAgQ2hlY2sgaWYgdGhlIGZpbGUgaGFzIGNoYW5nZWQgb24gZGlzay4KICAgICAgICAiIiIKICAgICAgICBsYXN0X21vZGlmaWVkID0gb3MucGF0aC5nZXRtdGltZShzZWxmLnBhdGgpCiAgICAgICAgd2hpbGUgc2VsZi5jb21wb25lbnRfb25fY2FudmFzIGFuZCBub3Qgc2VsZi5fb25fZmlsZV9jaGFuZ2VkLmlzX3NldCgpOgogICAgICAgICAgICBTeXN0ZW0uVGhyZWFkaW5nLlRocmVhZC5TbGVlcChzZWxmLnJlZnJlc2hfcmF0ZSkKICAgICAgICAgICAgbGFzdF9tb2RpZmllZCA9IHNlbGYuaXNfZmlsZV9tb2RpZmllZChsYXN0X21vZGlmaWVkKQogICAgICAgIHNlbGYuX29uX2ZpbGVfY2hhbmdlZC5jbGVhcigpCiAgICAgICAgcmV0dXJuCgogICAgZGVmIHN0b3Aoc2VsZik6CiAgICAgICAgIiIiIFN0b3AgdGhlIHRocmVhZC4gIiIiCiAgICAgICAgc2VsZi5fb25fZmlsZV9jaGFuZ2VkLnNldCgpCgogICAgZGVmIGlzX2ZpbGVfbW9kaWZpZWQoc2VsZiwgbGFzdF9tb2RpZmllZCk6CiAgICAgICAgY3VycmVudF9tb2RpZmllZCA9IG9zLnBhdGguZ2V0bXRpbWUoc2VsZi5wYXRoKQogICAgICAgIGlmIGN1cnJlbnRfbW9kaWZpZWQgIT0gbGFzdF9tb2RpZmllZDoKICAgICAgICAgICAgc2VsZi5leHBpcmVfY29tcG9uZW50X3NvbHV0aW9uKCkKICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRfbW9kaWZpZWQKICAgICAgICByZXR1cm4gbGFzdF9tb2RpZmllZAoKCmNsYXNzIFNjcmlwdFN5bmNDUHkoY29tcG9uZW50KToKICAgIGRlZiBfX2luaXRfXyhzZWxmKToKICAgICAgICBzdXBlcihTY3JpcHRTeW5jQ1B5LCBzZWxmKS5fX2luaXRfXygpCiAgICAgICAgc2VsZi5fdmFyX291dHB1dCA9IFtdCgogICAgICAgIHNlbGYuaXNfc3VjY2VzcyA9IEZhbHNlCgogICAgICAgIHNlbGYuY2xpZW50X3RocmVhZF9uYW1lIDogc3RyID0gZiJzY3JpcHQtc3luYy1jbGllbnQtdGhyZWFkOjp7Z2hlbnYuQ29tcG9uZW50Lkluc3RhbmNlR3VpZH0iCiAgICAgICAgc2VsZi52c2NvZGVfc2VydmVyX2lwID0gIjEyNy4wLjAuMSIKICAgICAgICBzZWxmLnZzY29kZV9zZXJ2ZXJfcG9ydCA9IDU4MjYwCiAgICAgICAgc2VsZi5zdGRvdXQgPSBOb25lCiAgICAgICAgc2VsZi5xdWV1ZV9tc2cgPSBxdWV1ZS5RdWV1ZSgpCiAgICAgICAgc2VsZi5xdWV1ZV9tc2dfbG9jayA9IHRocmVhZGluZy5Mb2NrKCkKICAgICAgICBzZWxmLmV2ZW50X2ZpcmVfbXNnID0gdGhyZWFkaW5nLkV2ZW50KCkKCiAgICAgICAgc2VsZi5maWxlY2hhbmdlZF90aHJlYWRfbmFtZSA6IHN0ciA9IGYic2NyaXB0LXN5bmMtZmlsZUNoYW5nZWQtdGhyZWFkOjp7Z2hlbnYuQ29tcG9uZW50Lkluc3RhbmNlR3VpZH0iCiAgICAgICAgc2VsZi5fX3BhdGhfbmFtZV90YWJsZV92YWx1ZSA9ICJzY3JpcHQtc3luYzo6IiArICJwYXRoOjoiICsgc3RyKGdoZW52LkNvbXBvbmVudC5JbnN0YW5jZUd1aWQpCiAgICAgICAgaWYgc2VsZi5wYXRoIGlzIE5vbmU6CiAgICAgICAgICAgIGdoZW52LkNvbXBvbmVudC5NZXNzYWdlID0gInNlbGVjdC1zY3JpcHQiCgogICAgZGVmIFJlbW92ZWRGcm9tRG9jdW1lbnQoc2VsZiwgZG9jKToKICAgICAgICAiIiIgUmVtb3ZlIHRoZSBjb21wb25lbnQgZnJvbSB0aGUgZG9jdW1lbnQuICIiIgogICAgICAgIGlmIHNlbGYuY2xpZW50X3RocmVhZF9uYW1lIGluIFt0Lm5hbWUgZm9yIHQgaW4gdGhyZWFkaW5nLmVudW1lcmF0ZSgpXToKICAgICAgICAgICAgY2xpZW50X3RocmVhZCA9IFt0IGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKSBpZiB0Lm5hbWUgPT0gc2VsZi5jbGllbnRfdGhyZWFkX25hbWVdWzBdCiAgICAgICAgICAgIGNsaWVudF90aHJlYWQuam9pbigpCiAgICAgICAgaWYgc2VsZi5maWxlY2hhbmdlZF90aHJlYWRfbmFtZSBpbiBbdC5uYW1lIGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKV06CiAgICAgICAgICAgIGZpbGVjaGFuZ2VkX3RocmVhZCA9IFt0IGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKSBpZiB0Lm5hbWUgPT0gc2VsZi5maWxlY2hhbmdlZF90aHJlYWRfbmFtZV1bMF0KICAgICAgICAgICAgZmlsZWNoYW5nZWRfdGhyZWFkLmpvaW4oKQogICAgICAgIGlmIHNlbGYucXVldWVfbXNnIGlzIG5vdCBOb25lOgogICAgICAgICAgICBzZWxmLnF1ZXVlX21zZy5qb2luKCkKICAgICAgICBpZiBzZWxmLnF1ZXVlX21zZ19sb2NrIGlzIG5vdCBOb25lOgogICAgICAgICAgICBzZWxmLnF1ZXVlX21zZ19sb2NrLnJlbGVhc2UoKQogICAgICAgIGlmIHNlbGYuZXZlbnRfZmlyZV9tc2cgaXMgbm90IE5vbmU6CiAgICAgICAgICAgIHNlbGYuZXZlbnRfZmlyZV9tc2cuY2xlYXIoKQoKICAgICAgICAjIGNsZWFyIHRoZSBwYXRoIGZyb20gdGhlIHRhYmxlIHZpZXcKICAgICAgICBkZWwgc2VsZi5wYXRoCgogICAgZGVmIGluaXRfc2NyaXB0X3BhdGgoc2VsZiwgYnRuIDogYm9vbCA9IEZhbHNlKToKICAgICAgICAiIiIKICAgICAgICAgICAgQ2hlY2sgaWYgdGhlIGJ1dHRvbiBpcyBwcmVzc2VkIGFuZCBsb2FkL2NoYW5nZSBwYXRoIHNjcmlwdC4KICAgICAgICAgICAgCiAgICAgICAgICAgIDpwYXJhbSBidG46IEEgYm9vbGVhbiBvZiB0aGUgYnV0dG9uCiAgICAgICAgIiIiCiAgICAgICAgIyBjaGVjayBpZiBidXR0b24gaXMgcHJlc3NlZAogICAgICAgIGlmIGJ0biBpcyBUcnVlOgogICAgICAgICAgICBkaWFsb2cgPSBTeXN0ZW0uV2luZG93cy5Gb3Jtcy5PcGVuRmlsZURpYWxvZygpCiAgICAgICAgICAgIGRpYWxvZy5GaWx0ZXIgPSAiUHl0aG9uIGZpbGVzICgqLnB5KXwqLnB5IgogICAgICAgICAgICBkaWFsb2cuVGl0bGUgPSAiU2VsZWN0IGEgUHl0aG9uIGZpbGUiCiAgICAgICAgICAgIGRpYWxvZy5Jbml0aWFsRGlyZWN0b3J5ID0gb3MucGF0aC5kaXJuYW1lKCIiKQogICAgICAgICAgICBkaWFsb2cuRmlsZU5hbWUgPSAiIgogICAgICAgICAgICBkaWFsb2cuTXVsdGlzZWxlY3QgPSBGYWxzZQogICAgICAgICAgICBkaWFsb2cuQ2hlY2tGaWxlRXhpc3RzID0gVHJ1ZQogICAgICAgICAgICBkaWFsb2cuQ2hlY2tQYXRoRXhpc3RzID0gVHJ1ZQogICAgICAgICAgICBkaWFsb2cuUmVzdG9yZURpcmVjdG9yeSA9IFRydWUKICAgICAgICAgICAgaWYgZGlhbG9nLlNob3dEaWFsb2coKSA9PSBTeXN0ZW0uV2luZG93cy5Gb3Jtcy5EaWFsb2dSZXN1bHQuT0s6CiAgICAgICAgICAgICAgICBzZWxmLnBhdGggPSBkaWFsb2cuRmlsZU5hbWUKCiAgICAgICAgIyBkZWZhdWx0IGluaXQgc3RhdXRzCiAgICAgICAgaWYgc2VsZi5wYXRoIGlzIE5vbmU6CiAgICAgICAgICAgIHJhaXNlIEV4Y2VwdGlvbigic2NyaXB0LXN5bmM6OkZpbGUgbm90IHNlbGVjdGVkIikKCiAgICAgICAgIyBmaSBmaWxlIGlzIGluIHRhYmxlIHZpZXcgYmVmb3JlCiAgICAgICAgaWYgbm90IG9zLnBhdGguZXhpc3RzKHNlbGYucGF0aCk6CiAgICAgICAgICAgIHJhaXNlIEV4Y2VwdGlvbigic2NyaXB0LXN5bmM6OkZpbGUgZG9lcyBub3QgZXhpc3QiKQogICAgCiAgICBkZWYgcmVsb2FkX2FsbF9tb2R1bGVzKHNlbGYsIGRpcmVjdG9yeSk6CiAgICAgICAgZm9yIGZpbGVuYW1lIGluIG9zLmxpc3RkaXIoZGlyZWN0b3J5KToKICAgICAgICAgICAgaWYgZmlsZW5hbWUuZW5kc3dpdGgoJy5weScpIGFuZCBmaWxlbmFtZSAhPSAnX19pbml0X18ucHknOgogICAgICAgICAgICAgICAgbW9kdWxlX25hbWUgPSBmaWxlbmFtZVs6LTNdICAjIHJlbW92ZSAnLnB5JyBmcm9tIGZpbGVuYW1lCiAgICAgICAgICAgICAgICBpZiBtb2R1bGVfbmFtZSBpbiBzeXMubW9kdWxlczoKICAgICAgICAgICAgICAgICAgICBpbXBvcnRsaWIucmVsb2FkKHN5cy5tb2R1bGVzW21vZHVsZV9uYW1lXSkKCiAgICBkZWYgc2FmZV9leGVjKHNlbGYsIHBhdGgsIGdsb2JhbHMsIGxvY2Fscyk6CiAgICAgICAgIiIiCiAgICAgICAgICAgIEV4ZWN1dGUgUHl0aG9uMyBjb2RlIHNhZmVseS4gSXQgcmVkaXJlY3RzIHRoZSBvdXRwdXQgb2YgdGhlIGNvZGUKICAgICAgICAgICAgdG8gYSBzdHJpbmcgYnVmZmVyICdzdGRvdXQnIHRvIG91dHB1dCB0byB0aGUgR0ggY29tcG9uZW50IHBhcmFtLgogICAgICAgICAgICBJdCBpcyBzZW5kIHRvIHRoZSB2c2NvZGUgc2VydmVyLgogICAgICAgICAgICAKICAgICAgICAgICAgOnBhcmFtIHBhdGg6IFRoZSBwYXRoIG9mIHRoZSBmaWxlIHRvIGV4ZWN1dGUuCiAgICAgICAgICAgIDpwYXJhbSBnbG9iYWxzOiBUaGUgZ2xvYmFscyBkaWN0aW9uYXJ5LgogICAgICAgICAgICA6cGFyYW0gbG9jYWxzOiBUaGUgbG9jYWxzIGRpY3Rpb25hcnkuCiAgICAgICAgIiIiCiAgICAgICAgdHJ5OgogICAgICAgICAgICB3aXRoIG9wZW4ocGF0aCwgJ3InKSBhcyBmOgogICAgICAgICAgICAgICAgIyBhZGQgdGhlIHBhdGggYW5kIHN1YiBkaXJlY3RvcmllcyB0byB0aGUgc3lzIHBhdGgKICAgICAgICAgICAgICAgIHBhdGhfZGlyID0gb3MucGF0aC5kaXJuYW1lKHBhdGgpCiAgICAgICAgICAgICAgICBzdWJfZGlycyA9IFtkIGZvciBkIGluIG9zLmxpc3RkaXIocGF0aF9kaXIpIGlmIG9zLnBhdGguaXNkaXIob3MucGF0aC5qb2luKHBhdGhfZGlyLCBkKSldCiAgICAgICAgICAgICAgICBmb3Igc3ViX2RpciBpbiBzdWJfZGlyczoKICAgICAgICAgICAgICAgICAgICBwcmludChzdWJfZGlyKQogICAgICAgICAgICAgICAgICAgIHN5cy5wYXRoLmFwcGVuZChvcy5wYXRoLmpvaW4ocGF0aF9kaXIsIHN1Yl9kaXIpKQogICAgICAgICAgICAgICAgc3lzLnBhdGguYXBwZW5kKHBhdGhfZGlyKQoKICAgICAgICAgICAgICAgICMgcmVsb2FkIGFsbCB0aGUgbW9kdWxlcyBhbHNvIG9mIHRoZSBzdWIgZGlyZWN0b3JpZXMKICAgICAgICAgICAgICAgIGZvciByb290LCBkaXJzLCBmaWxlcyBpbiBvcy53YWxrKHBhdGhfZGlyKToKICAgICAgICAgICAgICAgICAgICBmb3IgZCBpbiBkaXJzOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnJlbG9hZF9hbGxfbW9kdWxlcyhvcy5wYXRoLmpvaW4ocm9vdCwgZCkpCiAgICAgICAgICAgICAgICBzZWxmLnJlbG9hZF9hbGxfbW9kdWxlcyhwYXRoX2RpcikKCiAgICAgICAgICAgICAgICAjIHBhcnNlIHRoZSBjb2RlCiAgICAgICAgICAgICAgICBjb2RlID0gY29tcGlsZShmLnJlYWQoKSwgcGF0aCwgJ2V4ZWMnKQogICAgICAgICAgICAgICAgb3V0cHV0ID0gaW8uU3RyaW5nSU8oKQoKICAgICAgICAgICAgICAgICMgZW1wdHkgdGhlIHF1ZXVlIGFuZCBldmVudAogICAgICAgICAgICAgICAgd2l0aCBzZWxmLnF1ZXVlX21zZ19sb2NrOgogICAgICAgICAgICAgICAgICAgIHdoaWxlIG5vdCBzZWxmLnF1ZXVlX21zZy5lbXB0eSgpOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnF1ZXVlX21zZy5nZXQoKQogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnF1ZXVlX21zZy50YXNrX2RvbmUoKQogICAgICAgICAgICAgICAgc2VsZi5ldmVudF9maXJlX21zZy5jbGVhcigpCgogICAgICAgICAgICAgICAgIyBleGVjdXRlIHRoZSBjb2RlCiAgICAgICAgICAgICAgICB3aXRoIGNvbnRleHRsaWIucmVkaXJlY3Rfc3Rkb3V0KG91dHB1dCk6CiAgICAgICAgICAgICAgICAgICAgZXhlYyhjb2RlLCBnbG9iYWxzLCBsb2NhbHMpCiAgICAgICAgICAgICAgICBsb2NhbHNbInN0ZG91dCJdID0gb3V0cHV0LmdldHZhbHVlKCkKCiAgICAgICAgICAgICAgICAjIHNlbmQgdGhlIG1zZyB0byB0aGUgdnNjb2RlIHNlcnZlcgogICAgICAgICAgICAgICAgbXNnX2pzb24gPSBqc29uLmR1bXBzKHsic2NyaXB0X3BhdGgiOiBwYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZ3VpZCI6IHN0cihnaGVudi5Db21wb25lbnQuSW5zdGFuY2VHdWlkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1zZyI6IG91dHB1dC5nZXR2YWx1ZSgpfSkKICAgICAgICAgICAgICAgIG1zZ19qc29uID0gbXNnX2pzb24uZW5jb2RlKCd1dGYtOCcpCiAgICAgICAgICAgICAgICBzZWxmLnF1ZXVlX21zZy5wdXQobXNnX2pzb24pCiAgICAgICAgICAgICAgICBzZWxmLmV2ZW50X2ZpcmVfbXNnLnNldCgpCgogICAgICAgICAgICAgICAgIyBwYXNzIHRoZSBzY3JpcHQgdmFyaWFibGVzIHRvIHRoZSBHSCBjb21wb25lbnQgb3V0cHV0cwogICAgICAgICAgICAgICAgb3V0cGFyYW0gPSBnaGVudi5Db21wb25lbnQuUGFyYW1zLk91dHB1dAogICAgICAgICAgICAgICAgb3V0cGFyYW1fbmFtZXMgPSBbcC5OaWNrTmFtZSBmb3IgcCBpbiBvdXRwYXJhbV0KICAgICAgICAgICAgICAgIGZvciBvdXRwIGluIG91dHBhcmFtX25hbWVzOgogICAgICAgICAgICAgICAgICAgIGlmIG91dHAgaW4gbG9jYWxzLmtleXMoKToKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fdmFyX291dHB1dC5hcHBlbmQobG9jYWxzW291dHBdKQogICAgICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3Zhcl9vdXRwdXQuYXBwZW5kKE5vbmUpCgogICAgICAgICAgICAgICAgc3lzLnN0ZG91dCA9IHN5cy5fX3N0ZG91dF9fCiAgICAgICAgICAgIHJldHVybiBsb2NhbHMKCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoKICAgICAgICAgICAgIyBzZW5kIHRoZSBlcnJvciBtZXNzYWdlIHRvIHRoZSB2c2NvZGUgc2VydmVyCiAgICAgICAgICAgIGVycl9qc29uID0ganNvbi5kdW1wcyh7InNjcmlwdF9wYXRoIjogcGF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImd1aWQiOiBzdHIoZ2hlbnYuQ29tcG9uZW50Lkluc3RhbmNlR3VpZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtc2ciOiAiZXJyOiIgKyBzdHIoZSl9KQogICAgICAgICAgICBlcnJfanNvbiA9IGVycl9qc29uLmVuY29kZSgndXRmLTgnKQogICAgICAgICAgICBzZWxmLnF1ZXVlX21zZy5wdXQoZXJyX2pzb24pCiAgICAgICAgICAgIHNlbGYuZXZlbnRfZmlyZV9tc2cuc2V0KCkKICAgICAgICAgICAgCiAgICAgICAgICAgIHN5cy5zdGRvdXQgPSBzeXMuX19zdGRvdXRfXwoKICAgICAgICAgICAgZXJyX21zZyA9IGYic2NyaXB0LXN5bmM6OkVycm9yIGluIHRoZSBjb2RlOiB7c3RyKGUpfSIKICAgICAgICAgICAgcmFpc2UgRXhjZXB0aW9uKGVycl9tc2cpCgogICAgZGVmIFJ1blNjcmlwdChzZWxmLAogICAgICAgICAgICBidG46IGJvb2wsCiAgICAgICAgICAgIGlfZXhwb3J0X2RpciwKICAgICAgICAgICAgaV9icmVwczogU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuSUxpc3RbUmhpbm8uR2VvbWV0cnkuQnJlcF0sCiAgICAgICAgICAgIGlfYXNzZW1ibHlfbmFtZSwKICAgICAgICAgICAgaV9kdW1wOiBib29sKToKICAgICAgICAiIiIgVGhpcyBtZXRob2QgaXMgY2FsbGVkIHdoZW5ldmVyIHRoZSBjb21wb25lbnQgaGFzIHRvIGJlIHJlY2FsY3VsYXRlZCBpdCdzIHRoZSBzb2x2ZSBtYWluIGluc3RhbmNlLiAiIiIKCiAgICAgICAgc2VsZi5pc19zdWNjZXNzID0gRmFsc2UKCiAgICAgICAgIyBzZXQgdGhlIHBhdGggaWYgYnV0dG9uIGlzIHByZXNzZWQKICAgICAgICBzZWxmLmluaXRfc2NyaXB0X3BhdGgoYnRuKQoKICAgICAgICAjIGZpbGUgY2hhbmdlIGxpc3RlbmVyIHRocmVhZAogICAgICAgIGlmIHNlbGYuZmlsZWNoYW5nZWRfdGhyZWFkX25hbWUgbm90IGluIFt0Lm5hbWUgZm9yIHQgaW4gdGhyZWFkaW5nLmVudW1lcmF0ZSgpXToKICAgICAgICAgICAgRmlsZUNoYW5nZWRUaHJlYWQoc2VsZi5wYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmZpbGVjaGFuZ2VkX3RocmVhZF9uYW1lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkuc3RhcnQoKQoKICAgICAgICAjIHNldCB1cCB0aGUgdGNwIGNsaWVudCB0byBjb25uZWN0IHRvIHRoZSB2c2NvZGUgc2VydmVyCiAgICAgICAgXyA9IFtwcmludCh0Lm5hbWUpIGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKV0KICAgICAgICBpZiBzZWxmLmNsaWVudF90aHJlYWRfbmFtZSBub3QgaW4gW3QubmFtZSBmb3IgdCBpbiB0aHJlYWRpbmcuZW51bWVyYXRlKCldOgogICAgICAgICAgICBDbGllbnRUaHJlYWQoc2VsZi52c2NvZGVfc2VydmVyX2lwLAogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnZzY29kZV9zZXJ2ZXJfcG9ydCwKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5jbGllbnRfdGhyZWFkX25hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucXVldWVfbXNnLAogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnF1ZXVlX21zZ19sb2NrLAogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmV2ZW50X2ZpcmVfbXNnCiAgICAgICAgICAgICAgICAgICAgICAgICkuc3RhcnQoKQoKICAgICAgICAjIGFkZCB0byB0aGUgZ2xvYmFscyBhbGwgdGhlIGlucHV0IHBhcmFtZXRlcnMgb2YgdGhlIGNvbXBvbmVudCAodGhlIGxvY2FscykKICAgICAgICBnbG9iYWxzKCkudXBkYXRlKGxvY2FscygpKQoKICAgICAgICBwYXRoX2RpciA9IG9zLnBhdGguZGlybmFtZShzZWxmLnBhdGgpCiAgICAgICAgc3ViX2RpcnMgPSBbXQogICAgICAgIGZvciByb290LCBkaXJzLCBmaWxlcyBpbiBvcy53YWxrKHBhdGhfZGlyKToKICAgICAgICAgICAgZm9yIGQgaW4gZGlyczoKICAgICAgICAgICAgICAgIHN1Yl9kaXJzLmFwcGVuZChvcy5wYXRoLmpvaW4ocm9vdCwgZCkpCiAgICAgICAgICAgICAgICBwcmludChkKQogICAgICAgIHN5cy5wYXRoLmV4dGVuZChbcGF0aF9kaXJdICsgc3ViX2RpcnMpCgogICAgICAgICMgcmVsb2FkIGFsbCB0aGUgbW9kdWxlcyBhbHNvIG9mIHRoZSBzdWIgZGlyZWN0b3JpZXMKICAgICAgICBmb3Igcm9vdCwgZGlycywgZmlsZXMgaW4gb3Mud2FsayhwYXRoX2Rpcik6CiAgICAgICAgICAgIGZvciBkIGluIGRpcnM6CiAgICAgICAgICAgICAgICBzZWxmLnJlbG9hZF9hbGxfbW9kdWxlcyhvcy5wYXRoLmpvaW4ocm9vdCwgZCkpCiAgICAgICAgc2VsZi5yZWxvYWRfYWxsX21vZHVsZXMocGF0aF9kaXIpCgogICAgICAgIHJlcyA9IHNlbGYuc2FmZV9leGVjKHNlbGYucGF0aCwgTm9uZSwgZ2xvYmFscygpKQogICAgICAgIHNlbGYuaXNfc3VjY2VzcyA9IFRydWUKICAgICAgICByZXR1cm4KCiAgICBkZWYgQWZ0ZXJSdW5TY3JpcHQoc2VsZik6CiAgICAgICAgIiIiCiAgICAgICAgICAgIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBhcyBzb29uIGFzIHRoZSBjb21wb25lbnQgaGFzIGZpbmlzaGVkCiAgICAgICAgICAgIGl0cyBjYWxjdWxhdGlvbi4gSXQgaXMgdXNlZCB0byBsb2FkIHRoZSBHSENvbXBvbmVudCBvdXRwdXRzCiAgICAgICAgICAgIHdpdGggdGhlIHZhbHVlcyBjcmVhdGVkIGluIHRoZSBzY3JpcHQuCiAgICAgICAgIiIiCiAgICAgICAgaWYgbm90IHNlbGYuaXNfc3VjY2VzczoKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgb3V0cGFyYW0gPSBbcCBmb3IgcCBpbiBnaGVudi5Db21wb25lbnQuUGFyYW1zLk91dHB1dF0KICAgICAgICBvdXRwYXJhbV9uYW1lcyA9IFtwLk5pY2tOYW1lIGZvciBwIGluIG91dHBhcmFtXQogICAgICAgIAogICAgICAgICMgVE9ETzogYWRkIHRoZSBjb252ZXJzaW9uIHRvIGRhdGF0cmVlIGZvciBuZXN0ZWQgbGlzdHMgYW5kIHR1cGxlcwogICAgICAgIGZvciBpZHgsIG91dHAgaW4gZW51bWVyYXRlKG91dHBhcmFtKToKICAgICAgICAgICAgIyBkZXRlY3QgaWYgdGhlIG91dHB1dCBpcyBhIGxpc3QKICAgICAgICAgICAgaWYgdHlwZShzZWxmLl92YXJfb3V0cHV0W2lkeF0pID09IGxpc3Qgb3IgdHlwZShzZWxmLl92YXJfb3V0cHV0W2lkeF0pID09IHR1cGxlOgogICAgICAgICAgICAgICAgZ2hlbnYuQ29tcG9uZW50LlBhcmFtcy5PdXRwdXRbaWR4XS5Wb2xhdGlsZURhdGEuQ2xlYXIoKQogICAgICAgICAgICAgICAgZ2hlbnYuQ29tcG9uZW50LlBhcmFtcy5PdXRwdXRbaWR4XS5BZGRWb2xhdGlsZURhdGFMaXN0KGdoLktlcm5lbC5EYXRhLkdIX1BhdGgoMCksIHNlbGYuX3Zhcl9vdXRwdXRbaWR4XSkKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIGdoZW52LkNvbXBvbmVudC5QYXJhbXMuT3V0cHV0W2lkeF0uVm9sYXRpbGVEYXRhLkNsZWFyKCkKICAgICAgICAgICAgICAgIGdoZW52LkNvbXBvbmVudC5QYXJhbXMuT3V0cHV0W2lkeF0uQWRkVm9sYXRpbGVEYXRhKGdoLktlcm5lbC5EYXRhLkdIX1BhdGgoMCksIDAsIHNlbGYuX3Zhcl9vdXRwdXRbaWR4XSkKICAgICAgICBzZWxmLl92YXJfb3V0cHV0LmNsZWFyKCkKCiAgICBAcHJvcGVydHkKICAgIGRlZiBwYXRoKHNlbGYpOgogICAgICAgICIiIiBHZXQgdGhlIHBhdGggb2YgdGhlIGZpbGUgZnJvbSB0aGUgdGFibGUgdmlldyB0byBiZSBzdGlja2luZyBiZXR3ZWVuIHRoZSBzZXNzaW9ucy4gIiIiCiAgICAgICAgdGFibGVfdmFsdWUgPSBnaGVudi5Db21wb25lbnQuT25QaW5nRG9jdW1lbnQoKS5WYWx1ZVRhYmxlLkdldFZhbHVlKAogICAgICAgICAgICBzZWxmLl9fcGF0aF9uYW1lX3RhYmxlX3ZhbHVlLCAibm90X2ZvdW5kIgogICAgICAgICkKICAgICAgICBpZiB0YWJsZV92YWx1ZSAhPSAibm90X2ZvdW5kIjoKICAgICAgICAgICAgcmV0dXJuIHRhYmxlX3ZhbHVlCiAgICAgICAgZWxzZToKICAgICAgICAgICAgcmV0dXJuIE5vbmUKCiAgICBAcGF0aC5zZXR0ZXIKICAgIGRlZiBwYXRoKHNlbGYsIHBhdGggOiBzdHIpOgogICAgICAgICIiIiBTZXQgdGhlIHBhdGggb2YgdGhlIGZpbGUgdG8gdGhlIHRhYmxlIHZpZXcgdG8gYmUgc3RpY2tpbmcgYmV0d2VlbiB0aGUgc2Vzc2lvbnMuICIiIgogICAgICAgIGdoZW52LkNvbXBvbmVudC5PblBpbmdEb2N1bWVudCgpLlZhbHVlVGFibGUuU2V0VmFsdWUoc2VsZi5fX3BhdGhfbmFtZV90YWJsZV92YWx1ZSwgcGF0aCkKCiAgICAgICAgc2NyaXB0X25hbWUgPSBvcy5wYXRoLmJhc2VuYW1lKHBhdGgpCiAgICAgICAgZ2hlbnYuQ29tcG9uZW50Lk1lc3NhZ2UgPSBmIntzY3JpcHRfbmFtZX0iCgogICAgICAgIGlmIHNlbGYuZmlsZWNoYW5nZWRfdGhyZWFkX25hbWUgaW4gW3QubmFtZSBmb3IgdCBpbiB0aHJlYWRpbmcuZW51bWVyYXRlKCldOgogICAgICAgICAgICBfID0gW3QgZm9yIHQgaW4gdGhyZWFkaW5nLmVudW1lcmF0ZSgpIGlmIHQubmFtZSA9PSBzZWxmLmZpbGVjaGFuZ2VkX3RocmVhZF9uYW1lXVswXS5zdG9wKCkKCiAgICBAcGF0aC5kZWxldGVyCiAgICBkZWYgcGF0aChzZWxmKToKICAgICAgICAiIiIgRGVsZXRlIHRoZSBwYXRoIG9mIHRoZSBmaWxlIGZyb20gdGhlIHRhYmxlIHZpZXcgaWYgdGhlIG9iamVjdCBpcyBlcmFzZWQuICIiIgogICAgICAgIGdoZW52LkNvbXBvbmVudC5PblBpbmdEb2N1bWVudCgpLlZhbHVlVGFibGUuRGVsZXRlVmFsdWUoc2VsZi5fX3BhdGhfbmFtZV90YWJsZV92YWx1ZSkK + S + + + + + *.*.python + 3.* + + + + + + + + + + + a8b97322-2d53-47cd-905e-b932c3ccd74e + Button + + + + + Button object with two values + False + True + 5f8bfbf4-70d5-46ba-90fa-f3804e9a9032 + true + Button + + false + 0 + + + + + + 80 + 79 + 66 + 22 + + + + + + + + + + 919e146f-30ae-4aae-be34-4d72f555e7da + Brep + + + + + Contains a collection of Breps (Boundary REPresentations) + true + 0f309845-29e6-43ae-b255-cdb5c2d13da9 + true + Brep + Brep + false + 0 + + + + + + 92 + 132 + 50 + 24 + + + 117.58312 + 144.94077 + + + + + + 1 + + + + + 1 + {0} + + + + + 5981a85d-0063-489b-8bd7-7a1ebe1453a7 + + + + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + 6ffd83cc-a073-46cd-8213-4c0663708aa7 + Panel + + false + 1 + 99e48b23-64d9-4e2f-859d-62348fa491ae + 1 + Double click to edit panel content… + + + + + + 731 + 203 + 494 + 251 + + 0 + 0 + 0 + + 731.9958 + 203.22206 + + + + + + + 255;213;217;232 + + true + true + true + false + false + true + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + 5262b483-9441-440a-a74d-8b235aad399d + Panel + + false + 1 + 0 + Double click to edit panel content… + + + + + + 494 + 71 + 343 + 118 + + 0 + 0 + 0 + + 494.05792 + 71.25596 + + + + + + + 255;213;217;232 + + true + true + true + false + false + true + + + + + + + + + 537b0419-bbc2-4ff4-bf08-afe526367b2c + Custom Preview + + + + + Allows for customized geometry previews + true + 6f2c8a4b-d787-4606-9170-900f972641c6 + true + Custom Preview + Preview + + + + + + + 473 + 320 + 48 + 44 + + + 507 + 342 + + + + + + Geometry to preview + true + 43f69636-7c49-4472-9329-bd25ec713d12 + true + Geometry + G + false + d9399b7b-ece0-4d60-ba8e-0bb8c0bdf01a + 1 + + + + + + 475 + 322 + 17 + 20 + + + 485 + 332 + + + + + + + + The material override + e22d7711-ceb9-48df-9270-b376fcd13ae6 + true + Material + M + false + b14c32be-c541-4fae-93c2-449d7543457e + 1 + + + + + + 475 + 342 + 17 + 20 + + + 485 + 352 + + + + + + 1 + + + + + 1 + {0} + + + + + + 255;221;160;221 + + + 255;66;48;66 + + 0.5 + + 255;255;255;255 + + 0 + + + + + + + + + + + + + + + 537b0419-bbc2-4ff4-bf08-afe526367b2c + Custom Preview + + + + + Allows for customized geometry previews + true + 53c99f0b-499f-4471-9227-acc96558bfea + true + Custom Preview + Preview + + + + + + + 473 + 382 + 48 + 44 + + + 507 + 404 + + + + + + Geometry to preview + true + 525f46ad-33c4-44dc-8862-35b0ddce4d1d + true + Geometry + G + false + 8051ced1-c685-4aac-b373-3da1f25a7345 + 1 + + + + + + 475 + 384 + 17 + 20 + + + 485 + 394 + + + + + + + + The material override + 2e7559ef-c4d5-4ffe-a304-c34c078e5af0 + true + Material + M + false + fc5dba97-2c1a-4749-9c61-3f88abff00ff + 1 + + + + + + 475 + 404 + 17 + 20 + + + 485 + 414 + + + + + + 1 + + + + + 1 + {0} + + + + + + 255;221;160;221 + + + 255;66;48;66 + + 0.5 + + 255;255;255;255 + + 0 + + + + + + + + + + + + + + + 9c53bac0-ba66-40bd-8154-ce9829b9db1a + Colour Swatch + + + + + Colour (palette) swatch + b14c32be-c541-4fae-93c2-449d7543457e + true + Colour Swatch + Swatch + false + 0 + + 255;128;0;255 + + + + + + + 369 + 343 + 88 + 20 + + + 369.056 + 343.67847 + + + + + + + + + + a8b97322-2d53-47cd-905e-b932c3ccd74e + Button + + + + + Button object with two values + False + True + 254a4a2f-d415-488e-9851-4a763f1ba58f + true + Button + dump! + false + 0 + + + + + + 41 + 187 + 102 + 22 + + + + + + + + + + 06953bda-1d37-4d58-9b38-4b3c74e54c8f + File Path + + + + + Contains a collection of file paths + false + All files|*.* + 77c76654-6be3-4843-b564-afe44705740d + true + File Path + Path + false + 0 + + + + + + 94 + 105 + 50 + 24 + + + 119.05513 + 117.20451 + + + + + + 1 + + + + + 1 + {0} + + + + + false + F:\diffCheck\temp\ + + + + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + 86bc59e0-752b-48c2-b3e8-8f0c8b9737a3 + true + Panel + + false + 0 + 0 + AssemblyTest + + + + + + 44 + 161 + 102 + 20 + + 0 + 0 + 0 + + 44.200005 + 161.50002 + + + + + + + 255;213;217;232 + + true + true + true + false + false + true + + + + + + + + + 9c53bac0-ba66-40bd-8154-ce9829b9db1a + Colour Swatch + + + + + Colour (palette) swatch + fc5dba97-2c1a-4749-9c61-3f88abff00ff + true + Colour Swatch + Swatch + false + 0 + + 255;102;255;0 + + + + + + + 369 + 405 + 88 + 20 + + + 369.17673 + 405.9497 + + + + + + + + + + 537b0419-bbc2-4ff4-bf08-afe526367b2c + Custom Preview + + + + + Allows for customized geometry previews + true + f2ae36bd-8b62-496c-ac97-17ab79c53f42 + Custom Preview + Preview + + + + + + + 590 + 220 + 48 + 44 + + + 624 + 242 + + + + + + Geometry to preview + true + 85ca540e-0ffd-46e5-b014-a0ddacc0562b + Geometry + G + false + 0 + + + + + + 592 + 222 + 17 + 20 + + + 602 + 232 + + + + + + + + The material override + 6d95716c-757a-4c8f-8bb0-1685e7e04a52 + Material + M + false + 83adf7c8-580d-4af6-a713-84bf5f8bd2d3 + 1 + + + + + + 592 + 242 + 17 + 20 + + + 602 + 252 + + + + + + 1 + + + + + 1 + {0} + + + + + + 255;221;160;221 + + + 255;66;48;66 + + 0.5 + + 255;255;255;255 + + 0 + + + + + + + + + + + + + + + 9c53bac0-ba66-40bd-8154-ce9829b9db1a + Colour Swatch + + + + + Colour (palette) swatch + 83adf7c8-580d-4af6-a713-84bf5f8bd2d3 + true + Colour Swatch + Swatch + false + 0 + + 255;255;0;0 + + + + + + + 465 + 242 + 88 + 20 + + + 465.53714 + 242.746 + + + + + + + + + + 919e146f-30ae-4aae-be34-4d72f555e7da + Brep + + + + + Contains a collection of Breps (Boundary REPresentations) + true + 39d914fb-05fc-4c33-93a8-98326df3e596 + true + Brep + Brep + false + 0 + + + + + + 159 + 848 + 50 + 24 + + + 184.61072 + 860.9274 + + + + + + 1 + + + + + 6 + {0} + + + + + ba3151fb-3a8e-46c1-bdba-27ad41a4d1a2 + + + + + 322f4e22-d195-435e-b290-052cb2318277 + + + + + aa56315b-2905-4049-8c41-0cc8b39d864b + + + + + 7fc04154-255a-413f-a8a1-6ea034e1e779 + + + + + 5981a85d-0063-489b-8bd7-7a1ebe1453a7 + + + + + aeae5255-2a74-4040-9e44-e3aedf934485 + + + + + + + + + + + + + 06953bda-1d37-4d58-9b38-4b3c74e54c8f + File Path + + + + + Contains a collection of file paths + false + All files|*.* + 5238ab80-c5e8-4c25-b453-6fecfe57f6f1 + true + File Path + Path + false + 0 + + + + + + 159 + 822 + 50 + 24 + + + 184.87698 + 834.0722 + + + + + + 1 + + + + + 1 + {0} + + + + + false + F:\__TEMP\test\ + + + + + + + + + + + + + a8b97322-2d53-47cd-905e-b932c3ccd74e + Button + + + + + Button object with two values + False + True + 66637ff1-037c-4e4c-ba3a-0930de00a3ea + true + Button + dump! + false + 0 + + + + + + 106 + 761 + 102 + 22 + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + 66ce41af-42cf-48a0-871c-5d06b68b6ae7 + true + Panel + + false + 0 + 0 + AssemblyTest + + + + + + 111 + 795 + 102 + 20 + + 0 + 0 + 0 + + 111.36775 + 795.778 + + + + + + + 255;213;217;232 + + true + true + true + false + false + true + + + + + + + + + 537b0419-bbc2-4ff4-bf08-afe526367b2c + Custom Preview + + + + + Allows for customized geometry previews + true + 649b3c81-ba59-413f-ad42-15bca79f15e2 + true + Custom Preview + Preview + + + + + + + 602 + 839 + 48 + 44 + + + 636 + 861 + + + + + + Geometry to preview + true + 799c43bc-4b78-4d8f-a2ed-f604ed2b1ddb + true + Geometry + G + false + 86cd065e-41a3-4149-9a68-e3130b58ce76 + 1 + + + + + + 604 + 841 + 17 + 20 + + + 614 + 851 + + + + + + + + The material override + 07e88719-b77c-4ac3-a12c-cc329aefe255 + true + Material + M + false + c0aa2559-2d8c-481d-a41d-c02943a5f981 + 1 + + + + + + 604 + 861 + 17 + 20 + + + 614 + 871 + + + + + + 1 + + + + + 1 + {0} + + + + + + 255;221;160;221 + + + 255;66;48;66 + + 0.5 + + 255;255;255;255 + + 0 + + + + + + + + + + + + + + + 537b0419-bbc2-4ff4-bf08-afe526367b2c + Custom Preview + + + + + Allows for customized geometry previews + true + 4d39988a-2c7d-4bb0-9261-f460ec916be1 + true + Custom Preview + Preview + + + + + + + 603 + 886 + 48 + 44 + + + 637 + 908 + + + + + + Geometry to preview + true + 8d9e002d-b2f2-4476-8f21-adea36efcb4a + true + Geometry + G + false + c60f388a-008e-4a06-9770-68a2fa0520e7 + 1 + + + + + + 605 + 888 + 17 + 20 + + + 615 + 898 + + + + + + + + The material override + 58e8f37f-40e5-4060-83b0-c395fb2daf6d + true + Material + M + false + 28b353a5-44f7-436e-8a36-957623e89dde + 1 + + + + + + 605 + 908 + 17 + 20 + + + 615 + 918 + + + + + + 1 + + + + + 1 + {0} + + + + + + 255;221;160;221 + + + 255;66;48;66 + + 0.5 + + 255;255;255;255 + + 0 + + + + + + + + + + + + + + + 9c53bac0-ba66-40bd-8154-ce9829b9db1a + Colour Swatch + + + + + Colour (palette) swatch + c0aa2559-2d8c-481d-a41d-c02943a5f981 + true + Colour Swatch + Swatch + false + 0 + + 255;128;0;255 + + + + + + + 478 + 863 + 88 + 20 + + + 478.32407 + 863.82697 + + + + + + + + + + 9c53bac0-ba66-40bd-8154-ce9829b9db1a + Colour Swatch + + + + + Colour (palette) swatch + 28b353a5-44f7-436e-8a36-957623e89dde + true + Colour Swatch + Swatch + false + 0 + + 255;102;255;0 + + + + + + + 480 + 911 + 88 + 20 + + + 480.05487 + 911.1751 + + + + + + + + + + c9b2d725-6f87-4b07-af90-bd9aefef68eb + 066d0a87-236f-4eae-a0f4-9e42f5327962 + DFXMLExporter + + + + + + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAABg2lDQ1BJQ0MgcHJvZmlsZQAAKM+VkTlIA0EYhT8TJcEDC1OIWGyhVgqiopYSxSAoSIzgVbi7MVHIbsJugo2lYCtYeDRehY21tha2giB4gFhbWCnaiKz/bIQEIYIDw3y8mfeYeQOBg4xpudXdYNl5Jx6LajOzc1romWpC1DFAWDfd3MTUaIKK4+OWKrXedKks/jcakkuuCVWa8JCZc/LCi8L9q/mc4h3hiLmsJ4VPhTsduaDwvdKNIr8oTvscUJkRJxEfFo4Ia+kyNsrYXHYs4T7htqRlS35gpshJxWuKrUzB/LmnemH9kj09pXSZrcQYY4JJNAwKrJAhT5estigucdmPVvC3+P5JcRniWsEUxwhZLHTfj/qD3926qd6eYlJ9FGqePO+tHUJb8LXpeZ+Hnvd1BMFHuLBL/uwBDL6LvlnS2vahcR3OLkuasQ3nG9D8kNMd3ZeCMgOpFLyeyDfNQtM11M4Xe/vZ5/gOEtLV+BXs7kFHWrIXKrw7XN7bn2f8/oh+A2ixcqM29OAgAAAACXBIWXMAAC4iAAAuIgGq4t2SAAAAB3RJTUUH6AQHCzcfT87vFgAAAEZJREFUSEu1yKEBADAIwDCO5n/2QGQnYjJze18xS8wSs8QsMUvMErPELDFLzBKzxCwxS8wSs8QsMUvMErPELDFLzBIzs/cABgWAzBU/nmQAAAAASUVORK5CYII= + + 0bc1d704-d9a5-496a-8097-0e77a2179817 + true + true + false + true + DFXMLExporter + XMLout + 1 + + false + false + false + + + + + + 291 + 1184 + 171 + 84 + + + 398 + 1226 + + + + + + 4 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 3 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + + + + + true + Press button to export xml + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA6xJREFUSEvVVTlLXGEUHRUHkXHfHRWXcd/3DRVcQBFUVAzaCYKC+AsGohYGDQiipYV2VpLSykawjCIuaOGCgiZFgoVmNImc3HPnPRHHLVXIgcu8ecu59557vu+z/Cs4vLy8fsgv/iLeSbwNfn5+n+fn57G+vo61tTWsrq5iZWUFy8vLWFxcxNTUFAYGBtDa2orq6mqkpqZCCrqQT61uhhfg4+PTLh/+WlhYQHl5uUZZWRlKSkpQVFSE/Px85OTkICMjQ4mTkpKQlZUFm8125e3t7TRonoU1KCjo29LSErq6urQ6RlVVlSZiksLCQuTm5ippWloaUlJSNJKTkyEJroXD7qZ6Ar6+vh/6+/t/j42NoaamBnV1dRq8ZhJ2UlxcrF1kZ2cjPT1dyRMTE7UTKe5WpPpk0HnAER0dfTM7O4uGhgYlrq+vR0tLC+bm5rC7uwsT29vbmJycREFBARwOhyaIj49HXFwcZ8Euit2UDyDar3V2dqK3t1dlYYKenh4cHR0ZtJ44ODjQd5mA5DExMQgJCbmTJBsG7T1aw8PDXSSk1pSD1R8eHhpUnnC5XPq7v7+vw2YCUQAJCQkQF14JZ5+bWgYr1X+pqKgAg4NkkpmZGSV4Cufn5+jo6MDZ2Zn+Hx8fh91uR1RUlCZhR9LFd+G2WWTy78PCwlwk5/BoRSZh+0/h4uICTU1NatORkRG9t7Ozg9jYWERGRiI0NFQHL9dcqNMWyXSZmZmp3mYwCa14c3OjHz+ESc73aVEOmaBc1D8iIoIz0ER5eXlc3ZdMMC32uqa3zUS8fpyAspjktCfdQxKCCSiPKIHg4GB9R1zFDj5KWGzUiz5m2wwuooe2JDmty2esnOR8f2hoSJ9vbW1p9ZSHnXC9yFzdMzDQZ7Var/gxHcHfiYkJ/ZidtLW16T0+o74kZ/Wnp6f6jtPpvK+eBhGJuBbuXaSgd6kdlzxJWC0tSJycnGB4eFhb5/3BwUEcHx/rs729Pa2a5OystLT0Tug81gFRxr2EFjODzjKTPAWSc2YcLOXhjAIDA6m950ompItP8uItO+DCYVCO0dFRbG5uGrTAxsaGykLvs3IhVXuLbD+F5tm9iLCzC+rNvYWLxgy6hBJymNSbFYv7EBAQoM95NsgcX95NDTil5WvulrJ93IdJSjnMquUMgL+/v24r0jXJXz0PCKtI9ZVWraysRG1trRJQ3+bmZq20vb0d3Bi7u7t1Q2xsbHz7iWaA5+vjM/e1ePuZ/B/BYvkDKff7sf0Xzw8AAAAASUVORK5CYII= + + ff7bc6fc-cd70-4c56-8f79-fc4cbd06681c + true + i_dump + i_dump + true + 0 + true + 508c9c16-1d49-4404-84cc-7cc48c8f273b + 1 + Press button to export xml + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 293 + 1186 + 90 + 20 + + + 339.5 + 1196 + + + + + + + + true + The name of the assembly to export. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + eac6f337-07dc-4148-804b-ee5f29e1c0f7 + true + i_assembly_name + i_assembly_name + true + 0 + true + a170d6d1-471e-4c64-9806-444e47f21d66 + 1 + The name of the assembly to export. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 293 + 1206 + 90 + 20 + + + 339.5 + 1216 + + + + + + + + true + The directors where to export the xml file. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 0341be27-157c-4fa0-8841-4876c4aa61b9 + true + i_export_dir + i_export_dir + true + 0 + true + 3f1b8093-20ad-4b03-90b2-110f234137fc + 1 + The directors where to export the xml file. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 293 + 1226 + 90 + 20 + + + 339.5 + 1236 + + + + + + + + 1 + true + The breps of the structure. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA+RJREFUSEvVVVso5XsU3shOcr9Fg1w2uSvHXVJuiQe5ZDJvSvJE3mhy4sEpp0QuyS0e5PLAoFxeCJFSJi8k5VKSc3Dksrc5Zs70nfX99qY5Z88Y83Q6q1b7v+v3+9Za3/rW+mn+K9NZWFjcyy9+wF+Lv8xsbGy2+vr6sL6+jtXVVSwuLmJ+fh4TExMYGhpCc3MzysvLkZeXh5SUFAQFBUESOpOrWiPCM2ZlZZUvFz8NDg4iISFBeXx8PGJjYxETE4Po6GhEREQgJCREAfv7+yMsLAx2dnZ6S0vLtyaYb5rW0dHxj9HRURQVFans6MnJyUhKSsLw8DAeHh5wc3ODhYUF5ObmIjAwUHlAQAAkgEEwXhmhvmLW1ta/lJWV/dXQ0IDU1FSkpaU9Oak6PDxEd3c3ent7sbS0hNvbW/Xfz89PVSLJPQhV70xwZqbz9PT8s729HRkZGQo0PT0dmZmZWFtbg16vR2dnJyYnJ1FRUYGqqirU19fj6OhI9YdBvL292QtW8ZMR8gsT7ldJS2lpqaKFAQjORhP88vISDL65uYna2lrV6IGBAbS2tuLg4ABdXV3w8vKCs7PzZwny3gT7ZHlubm4fSkpKVFPJOQM8Zk7w4+NjjI+PY25uDisrKwp8enpaneE36WLlvr6+EBXqBfONEVoaK9n/lpiYCDrVwoaS8y/Bd3Z2VPYtLS04OztT3wTf29vD/v6+6sns7CyEZkWXVHEl2HYa6fzPrq6uHwhOCVKKIyMjMBgMZuAEGRsbQ0dHB87Pz3FxcaHO0Hp6enB9fQ0XFxelKnd3dw7qrxqJdB0aGqq0TWcQgl9dXZmBz8zMgBJmsxsbGxVVJycn2NjYUMpixdIDeHh4ICoqitN9zQAtIi9DZGQkHgPd39+ri18D7+/vR1tbG5qamlBZWYnq6mr1f3d3VwVxcnJSONILYwXkiXxRx5xOOjM7PT19Fryurk5JlZLd2tpS/AstSkmcfOmrsQcme6PVavXBwcFq/AsKCnB3d4fl5eUXg5MWZk8Vyjdn4UlFyqSK9zzEkWeTeIkV/Ai4TqdDXFzcZ4EzmwNaPHcJJUanqqgQypWqeQ6cjaV6srKy4ODgQO7NJ5kmVbyTgw+sgGPPcrkGqKipqSk1wTU1Ndje3v5H5gKq5C3K+Sgw39xFtFesgr3w8fFRQ0PPzs5WE0z5sjdcGWyoqA/29vbqDN8G6ePz29Rkb6VkQ3h4OGR9PLkMo6KBdDxmLW8AbG1t1VKUqgn+3feAphWqfucj8riTCEB+c3JyVKb5+fkoLCxEcXExuL+4FOXOy140k/F9/feb+z1/+Zv8PzKN5m9TzzRCUDHb/QAAAABJRU5ErkJggg== + + f7f134be-ff73-4607-8432-4027726d7c9a + true + i_breps + i_breps + true + 1 + true + f6905f9e-831e-4c85-831f-4a85822df09c + 1 + The breps of the structure. + 2ceb0405-fdfe-403d-a4d6-8786da45fb9d + + + + + + 293 + 1246 + 90 + 20 + + + 339.5 + 1256 + + + + + + + + false + The string of xml to be exported. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 63fce5d6-5cca-4c37-978e-16ad72dccdf6 + true + o_xml + o_xml + false + 0 + true + 0 + The string of xml to be exported. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 413 + 1186 + 47 + 26 + + + 436.5 + 1199.3334 + + + + + + + + false + The breps of the faces belonging to joints. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + d876ac7a-afbf-4696-a6c0-6b8d5230d058 + true + o_joints + o_joints + false + 0 + true + 0 + The breps of the faces belonging to joints. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 413 + 1212 + 47 + 27 + + + 436.5 + 1226 + + + + + + + + false + The breps of the faces belonging to sides. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + cd81b022-0563-4d70-8ad2-86542a5f5a10 + true + o_sides + o_sides + false + 0 + true + 0 + The breps of the faces belonging to sides. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 413 + 1239 + 47 + 27 + + + 436.5 + 1252.6667 + + + + + + + + + + false + IyEgcHl0aG9uMwoKaW1wb3J0IFJoaW5vCmltcG9ydCBSaGluby5HZW9tZXRyeSBhcyByZwoKaW1wb3J0IG9zCmltcG9ydCB0eXBpbmcKCmltcG9ydCBkaWZmQ2hlY2sKCmltcG9ydCBkaWZmQ2hlY2submV3bW9kdWxlCmRpZmZDaGVjay5uZXdtb2R1bGUudGVzdF9uZXdfbWRvdWxlKCkKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICAiIiIKICAgICAgICBNYWluIGZ1bmN0aW9uIHRvIHRlc3QgdGhlIHBhY2thZ2UKICAgICAgICA6cGFyYW0gaV9icmVwczogbGlzdCBvZiBicmVwcwogICAgICAgIDpwYXJhbSBpX2V4cG9ydF9kaXI6IGRpcmVjdG9yeSB0byBleHBvcnQgdGhlIHhtbAogICAgICAgIDpwYXJhbSBpX2R1bXA6IHdoZXRoZXIgdG8gZHVtcCB0aGUgeG1sCiAgICAiIiIKICAgICMgYmVhbXMKICAgIGJlYW1zID0gW10KICAgIGZvciBicmVwIGluIGlfYnJlcHM6CiAgICAgICAgYmVhbSA9IGRpZmZDaGVjay5kZl9nZW9tZXRyaWVzLkRGQmVhbS5mcm9tX2JyZXAoYnJlcCkKICAgICAgICBiZWFtcy5hcHBlbmQoYmVhbSkKCiAgICAjIGFzc2VtYmx5CiAgICBhc3NlbWJseTEgPSBkaWZmQ2hlY2suZGZfZ2VvbWV0cmllcy5ERkFzc2VtYmx5KGJlYW1zLCBpX2Fzc2VtYmx5X25hbWUpCgogICAgIyBkdW1wIHRoZSB4bWwKICAgIHhtbDogc3RyID0gYXNzZW1ibHkxLnRvX3htbCgpCiAgICBpZiBpX2R1bXA6CiAgICAgICAgYXNzZW1ibHkxLmR1bXBfeG1sKHhtbCwgaV9leHBvcnRfZGlyKQogICAgb194bWwgPSB4bWwKCiAgICAjIHNob3cgdGhlIGpvaW50L3NpZGUgZmFjZXMKICAgIG9fam9pbnRzID0gW2pmLnRvX2JyZXAoKSBmb3IgamYgaW4gYXNzZW1ibHkxLmFsbF9qb2ludF9mYWNlc10KICAgIG9fc2lkZXMgPSBbc2YudG9fYnJlcCgpIGZvciBzZiBpbiBhc3NlbWJseTEuYWxsX3NpZGVfZmFjZXNdCg== + S + + + + + *.*.python + 3.* + + + + + + + + + + + 919e146f-30ae-4aae-be34-4d72f555e7da + Brep + + + + + Contains a collection of Breps (Boundary REPresentations) + true + f6905f9e-831e-4c85-831f-4a85822df09c + true + Brep + Brep + false + 0 + + + + + + 214 + 1246 + 50 + 24 + + + 239.74905 + 1258.8203 + + + + + + 1 + + + + + 6 + {0} + + + + + ba3151fb-3a8e-46c1-bdba-27ad41a4d1a2 + + + + + aa56315b-2905-4049-8c41-0cc8b39d864b + + + + + 322f4e22-d195-435e-b290-052cb2318277 + + + + + 7fc04154-255a-413f-a8a1-6ea034e1e779 + + + + + 5981a85d-0063-489b-8bd7-7a1ebe1453a7 + + + + + aeae5255-2a74-4040-9e44-e3aedf934485 + + + + + + + + + + + + + a8b97322-2d53-47cd-905e-b932c3ccd74e + Button + + + + + Button object with two values + False + True + 508c9c16-1d49-4404-84cc-7cc48c8f273b + true + Button + dump! + false + 0 + + + + + + 161 + 1185 + 102 + 22 + + + + + + + + + + 06953bda-1d37-4d58-9b38-4b3c74e54c8f + File Path + + + + + Contains a collection of file paths + false + All files|*.* + 3f1b8093-20ad-4b03-90b2-110f234137fc + true + File Path + Path + false + 0 + + + + + + 214 + 1226 + 50 + 24 + + + 239.17398 + 1238.5846 + + + + + + 1 + + + + + 1 + {0} + + + + + false + F:\diffCheck\temp\ + + + + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + a170d6d1-471e-4c64-9806-444e47f21d66 + true + Panel + + false + 0 + 0 + AssemblyTest + + + + + + 161 + 1208 + 102 + 20 + + 0 + 0 + 0 + + 161.45294 + 1208.8801 + + + + + + + 255;213;217;232 + + true + true + true + false + false + true + + + + + + + + + 537b0419-bbc2-4ff4-bf08-afe526367b2c + Custom Preview + + + + + Allows for customized geometry previews + true + e82c0b60-8d4c-487a-8a2a-60ccdfb2c440 + true + Custom Preview + Preview + + + + + + + 587 + 1184 + 48 + 44 + + + 621 + 1206 + + + + + + Geometry to preview + true + f483e244-6e89-4839-a140-53b2307e5305 + true + Geometry + G + false + d876ac7a-afbf-4696-a6c0-6b8d5230d058 + 1 + + + + + + 589 + 1186 + 17 + 20 + + + 599 + 1196 + + + + + + + + The material override + 5eadcdca-b596-4817-b74a-daf84cb33bba + true + Material + M + false + 1652822d-91b6-4619-a0f1-929bd813d353 + 1 + + + + + + 589 + 1206 + 17 + 20 + + + 599 + 1216 + + + + + + 1 + + + + + 1 + {0} + + + + + + 255;221;160;221 + + + 255;66;48;66 + + 0.5 + + 255;255;255;255 + + 0 + + + + + + + + + + + + + + + 537b0419-bbc2-4ff4-bf08-afe526367b2c + Custom Preview + + + + + Allows for customized geometry previews + true + 1cf1d421-79da-445c-baea-160043841df5 + true + Custom Preview + Preview + + + + + + + 588 + 1231 + 48 + 44 + + + 622 + 1253 + + + + + + Geometry to preview + true + f3c7f1be-a13f-418f-bdc3-968772d68045 + true + Geometry + G + false + cd81b022-0563-4d70-8ad2-86542a5f5a10 + 1 + + + + + + 590 + 1233 + 17 + 20 + + + 600 + 1243 + + + + + + + + The material override + 14b44143-7bb4-4e4b-a0c1-8aeb245e6588 + true + Material + M + false + c217b73e-3729-4db1-951f-b5914db0d7d8 + 1 + + + + + + 590 + 1253 + 17 + 20 + + + 600 + 1263 + + + + + + 1 + + + + + 1 + {0} + + + + + + 255;221;160;221 + + + 255;66;48;66 + + 0.5 + + 255;255;255;255 + + 0 + + + + + + + + + + + + + + + 9c53bac0-ba66-40bd-8154-ce9829b9db1a + Colour Swatch + + + + + Colour (palette) swatch + 1652822d-91b6-4619-a0f1-929bd813d353 + true + Colour Swatch + Swatch + false + 0 + + 255;128;0;255 + + + + + + + 484 + 1209 + 88 + 20 + + + 484.3444 + 1209.1941 + + + + + + + + + + 9c53bac0-ba66-40bd-8154-ce9829b9db1a + Colour Swatch + + + + + Colour (palette) swatch + c217b73e-3729-4db1-951f-b5914db0d7d8 + true + Colour Swatch + Swatch + false + 0 + + 255;102;255;0 + + + + + + + 485 + 1256 + 88 + 20 + + + 485.70688 + 1256.2388 + + + + + + + + + + 719467e6-7cf5-4848-99b0-c5dd57e5442c + 066d0a87-236f-4eae-a0f4-9e42f5327962 + Python 3 Script + + + + + + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABCxJREFUSEvdlF1MW2UcxvHCZMbEKNFUo7I5NnRjDHpOe9oOEGETxWWuMXpr9MIlOgqjsDG+xgoYLxZj9GahH7RjhY5BWRnlY3y24tgX4saIVJ0rzN1pHPMjxOh7Hv/vOacQLmtMTHySf9om7/t7nz7neU/KfyrhYFuW3uZy6w86Y3qb++fsMvdfOTbvj3q7PybaO5xSZddz2tLkJZQ68wl8L6fU3Zpd5lkWDvkgHDoFAkOsDMBwpBuGyjN/CLXBp7QtySnH5mrm7vl3ocznEe1+gvthOHxWhdMYa0IwHA01KhuSld7mcVIkK/qyU2F9RedKwrWxOgjj0XM0vZBq+yHVh/3aluQk2HxVQvnpiFDZSROgORsxVvdExMM9f3LnUh3BG4bogKHkDhDtrY8b7G3PGuyB9VN3ThmxJvSTVD8AE8FNjSOQHON+ecmazpasbnlx3xF5vjhVQ62XvtT1hr6s7YpQ0Q6xKkBzhvLugqG6R42kpo/cDipgqYE+CW52TEBqmvTLd60W3N4HfFsCzO9ZxlzeYxpWFXcs2Dy/CRWn1YZwsPIgOZxnfV6DD6vOj48RfFI5wNQc9cjf781H7FXg5m5gtgDy5V21GloVVdCtOk40hMD8YXLXPOvVSEZV500RWJqjsLRMwdQyVSLHit/HjSJg5kXgkgUsKk5raFViZcf1VddKS3ph5K4TcXDnBDcfHyf4ZAK8Ymmect2ZfjOVzRbextU8YNoMRAxgF7LuASkPaHiKqKrrdxVMWdfyrAdgbBhcNDVeOPD2p/5Cb1/LW94wn4/Uod/zF98pYjf3fIzZ/GVcyQWmJGBCAEZ2AuHtgHfjBg1P/6C6+wfFsRaHoTa8UvRhn46acYLmF9yxQpml/cCtvVDynqO8v1QjwedGYFwPDGcB/S+ABbd8p6FVidWhMakurGZNGZuOjXiwZM1bBfNZfJ1a8hrwdTFwvRC4lq9GEiX4aDYwtAPoex7oSQcCaT4NrcpUP1CeeIhmaojJMVZCzj9bhcepgt8oFQS+eglK3hcJPimqkQxmAqEMoHsz0JkGuV23Q0OrMld0PWQ8NnxXOcAxDotjYjdb2u9U4IlIqILsWoHMLuXKLCLJbEyQ2dBOmZ3fLrNghswCm2TW/syC7NG9q2HXS2ocfMTkmPjA3BRtz22aymRxOoDDeSRUQXY171dt6b8jtvCKE/Mvq5HwvCkSFhHjbDQrzsKZcda3Nc660+OsI+0TbUtyYnNFTn4rlQp+YVrLu38bWG/Gfda12cU6nr7PfLp/9jaVZwrew+VdVEHq9zj1e4hXcBvQuxUssNHJ1zDvky65NbVc2ZCsMFmwgUUNCxjLWatgcAuvIJiPnLt1LnYy9YZ8QvewtiV5YUZ8kG7lARbKGGDdm25RJCsUSYw5nwjLJx8thTdl7bb+T5WS8jfirxG8xR5eUAAAAABJRU5ErkJggg== + + 0ee66d25-d08b-438a-a320-7d5b9c94eb52 + true + true + true + true + Python 3 Script + Py3 + 1 + + false + false + true + + + + + + 741 + 741 + 72 + 44 + + + 770 + 763 + + + + + + 2 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 2 + 3ede854e-c753-40eb-84cb-b48008f14fd4 + 08908df5-fa14-4982-9ab2-1aa0927566aa + + + + + true + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + 304ad97a-0eb9-4b5e-b99c-67c7dc5cf217 + true + x + x + true + 0 + true + 0 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 743 + 743 + 12 + 20 + + + 750.5 + 753 + + + + + + + + true + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + 4d5c2100-1520-4ea1-bb18-50d5e8b0298a + true + y + y + true + 0 + true + 0 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 743 + 763 + 12 + 20 + + + 750.5 + 773 + + + + + + + + The execution information, as output and error streams + 968967a6-00d1-4d3d-b3ad-6c70cfd8eb1b + true + out + out + false + 0 + + + + + + 785 + 743 + 26 + 20 + + + 798 + 753 + + + + + + + + false + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + a527438a-a4ac-4f54-9476-6d7db1e76864 + true + a + a + false + 0 + true + 0 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 785 + 763 + 26 + 20 + + + 798 + 773 + + + + + + + + + + aW1wb3J0IHN5cw0KDQpwcmludChzeXMuZXhlY3V0YWJsZSk= + Py3 + + + + + *.*.python + 3.* + + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + 27b8206c-38aa-46d8-a4b0-7b5ce810d60a + true + Panel + + false + 0 + 968967a6-00d1-4d3d-b3ad-6c70cfd8eb1b + 1 + Double click to edit panel content… + + + + + + 1063 + 752 + 613 + 192 + + 0 + 0 + 0 + + 1063.0818 + 752.3753 + + + + + + + 255;213;217;232 + + true + true + true + false + false + true + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + e074f5dc-5825-470f-9d04-403633051d0e + true + Panel + + false + 1 + 109ec47e-a6f8-4875-8368-b724abf2abe2 + 1 + Double click to edit panel content… + + + + + + 679 + 763 + 484 + 241 + + 0 + 0 + 0 + + 679.09973 + 763.01855 + + + + + + + 255;213;217;232 + + true + true + true + false + false + true + + + + + + + + + 719467e6-7cf5-4848-99b0-c5dd57e5442c + 066d0a87-236f-4eae-a0f4-9e42f5327962 + Python 3 Script + + + + + + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABCxJREFUSEvdlF1MW2UcxvHCZMbEKNFUo7I5NnRjDHpOe9oOEGETxWWuMXpr9MIlOgqjsDG+xgoYLxZj9GahH7RjhY5BWRnlY3y24tgX4saIVJ0rzN1pHPMjxOh7Hv/vOacQLmtMTHySf9om7/t7nz7neU/KfyrhYFuW3uZy6w86Y3qb++fsMvdfOTbvj3q7PybaO5xSZddz2tLkJZQ68wl8L6fU3Zpd5lkWDvkgHDoFAkOsDMBwpBuGyjN/CLXBp7QtySnH5mrm7vl3ocznEe1+gvthOHxWhdMYa0IwHA01KhuSld7mcVIkK/qyU2F9RedKwrWxOgjj0XM0vZBq+yHVh/3aluQk2HxVQvnpiFDZSROgORsxVvdExMM9f3LnUh3BG4bogKHkDhDtrY8b7G3PGuyB9VN3ThmxJvSTVD8AE8FNjSOQHON+ecmazpasbnlx3xF5vjhVQ62XvtT1hr6s7YpQ0Q6xKkBzhvLugqG6R42kpo/cDipgqYE+CW52TEBqmvTLd60W3N4HfFsCzO9ZxlzeYxpWFXcs2Dy/CRWn1YZwsPIgOZxnfV6DD6vOj48RfFI5wNQc9cjf781H7FXg5m5gtgDy5V21GloVVdCtOk40hMD8YXLXPOvVSEZV500RWJqjsLRMwdQyVSLHit/HjSJg5kXgkgUsKk5raFViZcf1VddKS3ph5K4TcXDnBDcfHyf4ZAK8Ymmect2ZfjOVzRbextU8YNoMRAxgF7LuASkPaHiKqKrrdxVMWdfyrAdgbBhcNDVeOPD2p/5Cb1/LW94wn4/Uod/zF98pYjf3fIzZ/GVcyQWmJGBCAEZ2AuHtgHfjBg1P/6C6+wfFsRaHoTa8UvRhn46acYLmF9yxQpml/cCtvVDynqO8v1QjwedGYFwPDGcB/S+ABbd8p6FVidWhMakurGZNGZuOjXiwZM1bBfNZfJ1a8hrwdTFwvRC4lq9GEiX4aDYwtAPoex7oSQcCaT4NrcpUP1CeeIhmaojJMVZCzj9bhcepgt8oFQS+eglK3hcJPimqkQxmAqEMoHsz0JkGuV23Q0OrMld0PWQ8NnxXOcAxDotjYjdb2u9U4IlIqILsWoHMLuXKLCLJbEyQ2dBOmZ3fLrNghswCm2TW/syC7NG9q2HXS2ocfMTkmPjA3BRtz22aymRxOoDDeSRUQXY171dt6b8jtvCKE/Mvq5HwvCkSFhHjbDQrzsKZcda3Nc660+OsI+0TbUtyYnNFTn4rlQp+YVrLu38bWG/Gfda12cU6nr7PfLp/9jaVZwrew+VdVEHq9zj1e4hXcBvQuxUssNHJ1zDvky65NbVc2ZCsMFmwgUUNCxjLWatgcAuvIJiPnLt1LnYy9YZ8QvewtiV5YUZ8kG7lARbKGGDdm25RJCsUSYw5nwjLJx8thTdl7bb+T5WS8jfirxG8xR5eUAAAAABJRU5ErkJggg== + + 82cff84c-8203-4d2d-a1d0-814c858ec33d + true + true + true + true + Python 3 Script + Py3 + 1 + + false + false + true + + + + + + 171 + 1 + 101 + 44 + + + 229 + 23 + + + + + + 1 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 2 + 3ede854e-c753-40eb-84cb-b48008f14fd4 + 08908df5-fa14-4982-9ab2-1aa0927566aa + + + + + 1 + true + Converts to collection of Breps (Boundary REPresentations) + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAPkSURBVEhL1VVbKOV7FN7ITnK/RYNcNrkrx11SbokHuWQyb0ryRN5ocuLBKadELsktHuTywKBcXgiRUiYvJOVSknNw5LK3OWbO9J31/famOWfPGPN0OqtW+7/r9/vWWt/61vpp/ivTWVhY3MsvfsBfi7/MbGxstvr6+rC+vo7V1VUsLi5ifn4eExMTGBoaQnNzM8rLy5GXl4eUlBQEBQVBEjqTq1ojwjNmZWWVLxc/DQ4OIiEhQXl8fDxiY2MRExOD6OhoREREICQkRAH7+/sjLCwMdnZ2ektLy7cmmG+a1tHR8Y/R0VEUFRWp7OjJyclISkrC8PAwHh4ecHNzg4WFBeTm5iIwMFB5QEAAJIBBMF4Zob5i1tbWv5SVlf3V0NCA1NRUpKWlPTmpOjw8RHd3N3p7e7G0tITb21v138/PT1UiyT0IVe9McGam8/T0/LO9vR0ZGRkKND09HZmZmVhbW4Ner0dnZycmJydRUVGBqqoq1NfX4+joSPWHQby9vdkLVvGTEfILE+5XSUtpaamihQEIzkYT/PLyEgy+ubmJ2tpa1eiBgQG0trbi4OAAXV1d8PLygrOz82cJ8t4E+2R5bm5uH0pKSlRTyTkDPGZO8OPjY4yPj2Nubg4rKysKfHp6Wp3hN+li5b6+vhAV6gXzjRFaGivZ/5aYmAg61cKGkvMvwXd2dlT2LS0tODs7U98E39vbw/7+vurJ7OwshGZFl1RxJdh2Gun8z66urh8ITglSiiMjIzAYDGbgBBkbG0NHRwfOz89xcXGhztB6enpwfX0NFxcXpSp3d3cO6q8aiXQdGhqqtE1nEIJfXV2Zgc/MzIASZrMbGxsVVScnJ9jY2FDKYsXSA3h4eCAqKorTfc0ALSIvQ2RkJB4D3d/fq4tfA+/v70dbWxuamppQWVmJ6upq9X93d1cFcXJyUjjSC2MF5Il8UcecTjozOz09fRa8rq5OSZWS3draUvwLLUpJnHzpq7EHJnuj1Wr1wcHBavwLCgpwd3eH5eXlF4OTFmZPFco3Z+FJRcqkivc8xJFnk3iJFfwIuE6nQ1xc3GeBM5sDWjx3CSVGp6qoEMqVqnkOnI2lerKysuDg4EDuzSeZJlW8k4MPrIBjz3K5BqioqakpNcE1NTXY3t7+R+YCquQtyvkoMN/cRbRXrIK98PHxUUNDz87OVhNM+bI3XBlsqKgP9vb26gzfBunj89vUZG+lZEN4eDhkfTy5DKOigXQ8Zi1vAGxtbdVSlKoJ/t33gKYVqn7nI/K4kwhAfnNyclSm+fn5KCwsRHFxMbi/uBTlzsteNJPxff33m/s9f/mb/D8yjeZvU880QlAx2/0AAAAASUVORK5CYII= + + 08532ae2-a7b8-4bcb-ba9f-c6a7a22fe36f + true + i_breps + i_breps + true + 1 + true + 0f309845-29e6-43ae-b255-cdb5c2d13da9 + 1 + + 2ceb0405-fdfe-403d-a4d6-8786da45fb9d + + + + + + 173 + 3 + 41 + 40 + + + 195 + 23 + + + + + + + + The execution information, as output and error streams + e73efe6e-ad59-49eb-837e-2c03904e0016 + true + out + out + false + 0 + + + + + + 244 + 3 + 26 + 20 + + + 257 + 13 + + + + + + + + false + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + f4b0de2e-fef0-4b9d-876f-55b17adececd + true + a + a + false + 0 + true + 0 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 244 + 23 + 26 + 20 + + + 257 + 33 + + + + + + + + + + IyEgcHl0aG9uMw0KDQppbXBvcnQgUmhpbm8NCmltcG9ydCBSaGluby5HZW9tZXRyeSBhcyByZw0KDQppbXBvcnQgb3MNCmltcG9ydCB0eXBpbmcNCg0KaW1wb3J0IGRpZmZDaGVjaw0KaW1wb3J0IGRpZmZDaGVjay5kZl91dGlsIA0KZnJvbSBkaWZmQ2hlY2suZGZfZ2VvbWV0cmllcyBpbXBvcnQgREZWZXJ0ZXgsIERGRmFjZSwgREZCZWFtLCBERkFzc2VtYmx5DQoNCiMgIyBmcm9tIGRpZmZDaGVjayBpbXBvcnQgZGZfam9pbnRfZGV0ZWN0b3INCg0KaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoNCiAgICAiIiINCiAgICAgICAgTWFpbiBmdW5jdGlvbiB0byB0ZXN0IHRoZSBwYWNrYWdlDQogICAgICAgIDpwYXJhbSBpX2JyZXBzOiBsaXN0IG9mIGJyZXBzDQogICAgICAgIDpwYXJhbSBpX2V4cG9ydF9kaXI6IGRpcmVjdG9yeSB0byBleHBvcnQgdGhlIHhtbA0KICAgICAgICA6cGFyYW0gaV9kdW1wOiB3aGV0aGVyIHRvIGR1bXAgdGhlIHhtbA0KICAgICIiIg0KICAgICMgYmVhbXMNCiAgICB2ZXJ0ZXgxID0gREZWZXJ0ZXgoMSwgMSwgMSkNCiAgICB2ZXJ0ZXgyID0gREZWZXJ0ZXgoMiwgMiwgMikNCiAgICB2ZXJ0ZXgzID0gREZWZXJ0ZXgoMywgMywgMykNCiAgICB2ZXJ0ZXg0ID0gREZWZXJ0ZXgoNCwgNCwgNCkNCiAgICB2ZXJ0aWNlcyA9IFtdDQogICAgdmVydGljZXNfdGVtcCA9IFt2ZXJ0ZXgxLCB2ZXJ0ZXgyLCB2ZXJ0ZXgzLCB2ZXJ0ZXg0XQ0KICAgIHZlcnRpY2VzLmFwcGVuZCh2ZXJ0aWNlc190ZW1wKQ0KDQogICAgZmFjZTEgPSBERkZhY2UodmVydGljZXMpDQogICAgZmFjZTIgPSBERkZhY2UodmVydGljZXMpDQogICAgZmFjZXMzID0gREZGYWNlKHZlcnRpY2VzKQ0KICAgIGZhY2VzNCA9IERGRmFjZSh2ZXJ0aWNlcykNCg0KICAgIGJlYW1zOiB0eXBpbmcuTGlzdFtERkJlYW1dID0gW10NCiAgICBiZWFtMSA9IERGQmVhbSgiQmVhbTEiLCBbZmFjZTEsIGZhY2UyXSkNCiAgICBiZWFtMiA9IERGQmVhbSgiQmVhbTIiLCBbZmFjZXMzLCBmYWNlczRdKQ0KDQogICAgZmFjZXMgPSBkaWZmQ2hlY2suZGZfam9pbnRfZGV0ZWN0b3IuSm9pbnREZXRlY3RvcihpX2JyZXBzWzBdKS5ydW4oKQ0KICAgICMgYmVhbV94ID0gREZCZWFtKCJCZWFtWCIsIGZhY2VzKQ0KICAgICMgYmVhbV94ID0gREZCZWFtLmZyb21fYnJlcChpX2JyZXBzWzBdKQ0KDQogICAgYmVhbXMuYXBwZW5kKGJlYW0xKQ0KICAgIGJlYW1zLmFwcGVuZChiZWFtMikNCg0KICAgIGFzc2VtYmx5MSA9IERGQXNzZW1ibHkoYmVhbXMsICJBc3NlbWJseTEiKQ0KDQoNCg0KDQojICAgICAjIGZvciBicmVwIGluIGlfYnJlcHM6DQojICAgICAjICAgICBiZWFtID0gREZCZWFtLmZyb21fYnJlcChicmVwKQ0KIyAgICAgIyAgICAgYmVhbXMuYXBwZW5kKGJlYW0pDQoNCiMgICAgICMgIyBhc3NlbWJseQ0KIyAgICAgIyBhc3NlbWJseTEgPSBERkFzc2VtYmx5KGJlYW1zLCBpX2Fzc2VtYmx5X25hbWUpDQoNCiMgICAgICMgIyBkdW1wIHRoZSB4bWwNCiMgICAgICMgeG1sOiBzdHIgPSBhc3NlbWJseTEudG9feG1sKCkNCiMgICAgICMgaWYgaV9kdW1wOg0KIyAgICAgIyAgICAgYXNzZW1ibHkxLmR1bXBfeG1sKHhtbCwgaV9leHBvcnRfZGlyKQ0KIyAgICAgIyBvX3htbCA9IHhtbA0KDQojICAgICAjICMgc2hvdyB0aGUgam9pbnQvc2lkZSBmYWNlcw0KIyAgICAgIyBvX2pvaW50cyA9IFtqZi50b19icmVwKCkgZm9yIGpmIGluIGFzc2VtYmx5MS5hbGxfam9pbnRfZmFjZXNdDQojICAgICAjIG9fc2lkZXMgPSBbc2YudG9fYnJlcCgpIGZvciBzZiBpbiBhc3NlbWJseTEuYWxsX3NpZGVfZmFjZXNdDQo= + Py3 + + + + + *.*.python + 3.* + + + + + + + + + + + c9b2d725-6f87-4b07-af90-bd9aefef68eb + 066d0a87-236f-4eae-a0f4-9e42f5327962 + DFXMLExporter + + + + + + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAABg2lDQ1BJQ0MgcHJvZmlsZQAAKM+VkTlIA0EYhT8TJcEDC1OIWGyhVgqiopYSxSAoSIzgVbi7MVHIbsJugo2lYCtYeDRehY21tha2giB4gFhbWCnaiKz/bIQEIYIDw3y8mfeYeQOBg4xpudXdYNl5Jx6LajOzc1romWpC1DFAWDfd3MTUaIKK4+OWKrXedKks/jcakkuuCVWa8JCZc/LCi8L9q/mc4h3hiLmsJ4VPhTsduaDwvdKNIr8oTvscUJkRJxEfFo4Ia+kyNsrYXHYs4T7htqRlS35gpshJxWuKrUzB/LmnemH9kj09pXSZrcQYY4JJNAwKrJAhT5estigucdmPVvC3+P5JcRniWsEUxwhZLHTfj/qD3926qd6eYlJ9FGqePO+tHUJb8LXpeZ+Hnvd1BMFHuLBL/uwBDL6LvlnS2vahcR3OLkuasQ3nG9D8kNMd3ZeCMgOpFLyeyDfNQtM11M4Xe/vZ5/gOEtLV+BXs7kFHWrIXKrw7XN7bn2f8/oh+A2ixcqM29OAgAAAACXBIWXMAAC4iAAAuIgGq4t2SAAAAB3RJTUUH6AQHCzcfT87vFgAAAEZJREFUSEu1yKEBADAIwDCO5n/2QGQnYjJze18xS8wSs8QsMUvMErPELDFLzBKzxCwxS8wSs8QsMUvMErPELDFLzBIzs/cABgWAzBU/nmQAAAAASUVORK5CYII= + + 4de40153-0a75-4628-b563-344d5ffd67b3 + true + true + false + true + DFXMLExporter + XMLout + 1 + + false + false + true + + + + + + 269 + 779 + 171 + 84 + + + 376 + 821 + + + + + + 4 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 4 + 3ede854e-c753-40eb-84cb-b48008f14fd4 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + + + + + true + Press button to export xml + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA6xJREFUSEvVVTlLXGEUHRUHkXHfHRWXcd/3DRVcQBFUVAzaCYKC+AsGohYGDQiipYV2VpLSykawjCIuaOGCgiZFgoVmNImc3HPnPRHHLVXIgcu8ecu59557vu+z/Cs4vLy8fsgv/iLeSbwNfn5+n+fn57G+vo61tTWsrq5iZWUFy8vLWFxcxNTUFAYGBtDa2orq6mqkpqZCCrqQT61uhhfg4+PTLh/+WlhYQHl5uUZZWRlKSkpQVFSE/Px85OTkICMjQ4mTkpKQlZUFm8125e3t7TRonoU1KCjo29LSErq6urQ6RlVVlSZiksLCQuTm5ippWloaUlJSNJKTkyEJroXD7qZ6Ar6+vh/6+/t/j42NoaamBnV1dRq8ZhJ2UlxcrF1kZ2cjPT1dyRMTE7UTKe5WpPpk0HnAER0dfTM7O4uGhgYlrq+vR0tLC+bm5rC7uwsT29vbmJycREFBARwOhyaIj49HXFwcZ8Euit2UDyDar3V2dqK3t1dlYYKenh4cHR0ZtJ44ODjQd5mA5DExMQgJCbmTJBsG7T1aw8PDXSSk1pSD1R8eHhpUnnC5XPq7v7+vw2YCUQAJCQkQF14JZ5+bWgYr1X+pqKgAg4NkkpmZGSV4Cufn5+jo6MDZ2Zn+Hx8fh91uR1RUlCZhR9LFd+G2WWTy78PCwlwk5/BoRSZh+0/h4uICTU1NatORkRG9t7Ozg9jYWERGRiI0NFQHL9dcqNMWyXSZmZmp3mYwCa14c3OjHz+ESc73aVEOmaBc1D8iIoIz0ER5eXlc3ZdMMC32uqa3zUS8fpyAspjktCfdQxKCCSiPKIHg4GB9R1zFDj5KWGzUiz5m2wwuooe2JDmty2esnOR8f2hoSJ9vbW1p9ZSHnXC9yFzdMzDQZ7Var/gxHcHfiYkJ/ZidtLW16T0+o74kZ/Wnp6f6jtPpvK+eBhGJuBbuXaSgd6kdlzxJWC0tSJycnGB4eFhb5/3BwUEcHx/rs729Pa2a5OystLT0Tug81gFRxr2EFjODzjKTPAWSc2YcLOXhjAIDA6m950ompItP8uItO+DCYVCO0dFRbG5uGrTAxsaGykLvs3IhVXuLbD+F5tm9iLCzC+rNvYWLxgy6hBJymNSbFYv7EBAQoM95NsgcX95NDTil5WvulrJ93IdJSjnMquUMgL+/v24r0jXJXz0PCKtI9ZVWraysRG1trRJQ3+bmZq20vb0d3Bi7u7t1Q2xsbHz7iWaA5+vjM/e1ePuZ/B/BYvkDKff7sf0Xzw8AAAAASUVORK5CYII= + + d2a467a2-6e5c-4d7d-ab29-b4f069e2f8fa + true + i_dump + i_dump + true + 0 + true + 66637ff1-037c-4e4c-ba3a-0930de00a3ea + 1 + Press button to export xml + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 271 + 781 + 90 + 20 + + + 317.5 + 791 + + + + + + + + true + The name of the assembly to export. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 1a5dae8c-fb00-417f-93e7-28d577f4f02e + true + i_assembly_name + i_assembly_name + true + 0 + true + 66ce41af-42cf-48a0-871c-5d06b68b6ae7 + 1 + The name of the assembly to export. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 271 + 801 + 90 + 20 + + + 317.5 + 811 + + + + + + + + true + The directors where to export the xml file. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 00cdf837-c7db-48a9-83e1-57e3739e8261 + true + i_export_dir + i_export_dir + true + 0 + true + 5238ab80-c5e8-4c25-b453-6fecfe57f6f1 + 1 + The directors where to export the xml file. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 271 + 821 + 90 + 20 + + + 317.5 + 831 + + + + + + + + 1 + true + The breps of the structure. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA+RJREFUSEvVVVso5XsU3shOcr9Fg1w2uSvHXVJuiQe5ZDJvSvJE3mhy4sEpp0QuyS0e5PLAoFxeCJFSJi8k5VKSc3Dksrc5Zs70nfX99qY5Z88Y83Q6q1b7v+v3+9Za3/rW+mn+K9NZWFjcyy9+wF+Lv8xsbGy2+vr6sL6+jtXVVSwuLmJ+fh4TExMYGhpCc3MzysvLkZeXh5SUFAQFBUESOpOrWiPCM2ZlZZUvFz8NDg4iISFBeXx8PGJjYxETE4Po6GhEREQgJCREAfv7+yMsLAx2dnZ6S0vLtyaYb5rW0dHxj9HRURQVFans6MnJyUhKSsLw8DAeHh5wc3ODhYUF5ObmIjAwUHlAQAAkgEEwXhmhvmLW1ta/lJWV/dXQ0IDU1FSkpaU9Oak6PDxEd3c3ent7sbS0hNvbW/Xfz89PVSLJPQhV70xwZqbz9PT8s729HRkZGQo0PT0dmZmZWFtbg16vR2dnJyYnJ1FRUYGqqirU19fj6OhI9YdBvL292QtW8ZMR8gsT7ldJS2lpqaKFAQjORhP88vISDL65uYna2lrV6IGBAbS2tuLg4ABdXV3w8vKCs7PzZwny3gT7ZHlubm4fSkpKVFPJOQM8Zk7w4+NjjI+PY25uDisrKwp8enpaneE36WLlvr6+EBXqBfONEVoaK9n/lpiYCDrVwoaS8y/Bd3Z2VPYtLS04OztT3wTf29vD/v6+6sns7CyEZkWXVHEl2HYa6fzPrq6uHwhOCVKKIyMjMBgMZuAEGRsbQ0dHB87Pz3FxcaHO0Hp6enB9fQ0XFxelKnd3dw7qrxqJdB0aGqq0TWcQgl9dXZmBz8zMgBJmsxsbGxVVJycn2NjYUMpixdIDeHh4ICoqitN9zQAtIi9DZGQkHgPd39+ri18D7+/vR1tbG5qamlBZWYnq6mr1f3d3VwVxcnJSONILYwXkiXxRx5xOOjM7PT19Fryurk5JlZLd2tpS/AstSkmcfOmrsQcme6PVavXBwcFq/AsKCnB3d4fl5eUXg5MWZk8Vyjdn4UlFyqSK9zzEkWeTeIkV/Ai4TqdDXFzcZ4EzmwNaPHcJJUanqqgQypWqeQ6cjaV6srKy4ODgQO7NJ5kmVbyTgw+sgGPPcrkGqKipqSk1wTU1Ndje3v5H5gKq5C3K+Sgw39xFtFesgr3w8fFRQ0PPzs5WE0z5sjdcGWyoqA/29vbqDN8G6ePz29Rkb6VkQ3h4OGR9PLkMo6KBdDxmLW8AbG1t1VKUqgn+3feAphWqfucj8riTCEB+c3JyVKb5+fkoLCxEcXExuL+4FOXOy140k/F9/feb+z1/+Zv8PzKN5m9TzzRCUDHb/QAAAABJRU5ErkJggg== + + d4f34513-7e3b-44d3-a110-13f6f2645a98 + true + i_breps + i_breps + true + 1 + true + 39d914fb-05fc-4c33-93a8-98326df3e596 + 1 + The breps of the structure. + 2ceb0405-fdfe-403d-a4d6-8786da45fb9d + + + + + + 271 + 841 + 90 + 20 + + + 317.5 + 851 + + + + + + + + The execution information, as output and error streams + 109ec47e-a6f8-4875-8368-b724abf2abe2 + true + out + out + false + 0 + + + + + + 391 + 781 + 47 + 20 + + + 414.5 + 791 + + + + + + + + false + The string of xml to be exported. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 660dadfd-116c-4c27-a8a3-cecab444fb7a + true + o_xml + o_xml + false + 0 + true + 0 + The string of xml to be exported. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 391 + 801 + 47 + 20 + + + 414.5 + 811 + + + + + + + + false + The breps of the faces belonging to joints. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 86cd065e-41a3-4149-9a68-e3130b58ce76 + true + o_joints + o_joints + false + 0 + true + 0 + The breps of the faces belonging to joints. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 391 + 821 + 47 + 20 + + + 414.5 + 831 + + + + + + + + false + The breps of the faces belonging to sides. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + c60f388a-008e-4a06-9770-68a2fa0520e7 + true + o_sides + o_sides + false + 0 + true + 0 + The breps of the faces belonging to sides. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 391 + 841 + 47 + 20 + + + 414.5 + 851 + + + + + + + + + + false + IyEgcHl0aG9uMwojIHI6IGRpZmZDaGVjaz09MC4wLjgKCgppbXBvcnQgU3lzdGVtCmltcG9ydCB0eXBpbmcKCmltcG9ydCBSaGlubwppbXBvcnQgUmhpbm8uR2VvbWV0cnkgYXMgcmcKCmZyb20gZ2hweXRob25saWIuY29tcG9uZW50YmFzZSBpbXBvcnQgZXhlY3V0aW5nY29tcG9uZW50IGFzIGNvbXBvbmVudAoKaW1wb3J0IGRpZmZDaGVjawpmcm9tIGRpZmZDaGVjay5kZl9nZW9tZXRyaWVzIGltcG9ydCBERkJlYW0sIERGQXNzZW1ibHkKCgpjbGFzcyBERlhNTEV4cG9ydGVyKGNvbXBvbmVudCk6CiAgICBkZWYgUnVuU2NyaXB0KHNlbGYsCiAgICAgICAgICAgIGlfZHVtcDogYm9vbCwKICAgICAgICAgICAgaV9hc3NlbWJseV9uYW1lLAogICAgICAgICAgICBpX2V4cG9ydF9kaXIsCiAgICAgICAgICAgIGlfYnJlcHM6IFN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLklMaXN0W1JoaW5vLkdlb21ldHJ5LkJyZXBdKToKICAgICAgICAiIiIKICAgICAgICAgICAgVGhpcyByZWFkIGJyZXBzIGZyb20gUmhpbm8sIGNvbnZlcnRzIHRoZW0gdG8gREZCZWFtcyBhbmQgREZBc3NlbWJsaWVzLCBhbmQgZXhwb3J0cyB0aGVtIHRvIFhNTC4KICAgICAgICAgICAgCiAgICAgICAgICAgIDpwYXJhbSBpX2R1bXA6IHdoZXRoZXIgdG8gZHVtcCB0aGUgeG1sCiAgICAgICAgICAgIDpwYXJhbSBpX2V4cG9ydF9kaXI6IGRpcmVjdG9yeSB0byBleHBvcnQgdGhlIHhtbAogICAgICAgICAgICA6cGFyYW0gaV9icmVwczogbGlzdCBvZiBicmVwcwogICAgICAgICIiIgogICAgICAgICMgYmVhbXMKICAgICAgICBiZWFtczogdHlwaW5nLkxpc3RbREZCZWFtXSA9IFtdCiAgICAgICAgZm9yIGJyZXAgaW4gaV9icmVwczoKICAgICAgICAgICAgYmVhbSA9IERGQmVhbS5mcm9tX2JyZXAoYnJlcCkKICAgICAgICAgICAgYmVhbXMuYXBwZW5kKGJlYW0pCgogICAgICAgICMgYXNzZW1ibHkKICAgICAgICBhc3NlbWJseTEgPSBERkFzc2VtYmx5KGJlYW1zLCBpX2Fzc2VtYmx5X25hbWUpCgogICAgICAgICMgZHVtcCB0aGUgeG1sCiAgICAgICAgeG1sOiBzdHIgPSBhc3NlbWJseTEudG9feG1sKCkKICAgICAgICBpZiBpX2R1bXA6CiAgICAgICAgICAgIGFzc2VtYmx5MS5kdW1wX3htbCh4bWwsIGlfZXhwb3J0X2RpcikKICAgICAgICBvX3htbCA9IHhtbAoKICAgICAgICAjIHNob3cgdGhlIGpvaW50L3NpZGUgZmFjZXMKICAgICAgICBvX2pvaW50cyA9IFtqZi50b19icmVwKCkgZm9yIGpmIGluIGFzc2VtYmx5MS5hbGxfam9pbnRfZmFjZXNdCiAgICAgICAgb19zaWRlcyA9IFtzZi50b19icmVwKCkgZm9yIHNmIGluIGFzc2VtYmx5MS5hbGxfc2lkZV9mYWNlc10KCiAgICAgICAgcmV0dXJuIG9feG1sLCBvX2pvaW50cywgb19zaWRlcw== + S + + + + + *.*.python + 3.* + + + + + + + + + + + c9b2d725-6f87-4b07-af90-bd9aefef68eb + 066d0a87-236f-4eae-a0f4-9e42f5327962 + DFXMLExporter + + + + + + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAABg2lDQ1BJQ0MgcHJvZmlsZQAAKM+VkTlIA0EYhT8TJcEDC1OIWGyhVgqiopYSxSAoSIzgVbi7MVHIbsJugo2lYCtYeDRehY21tha2giB4gFhbWCnaiKz/bIQEIYIDw3y8mfeYeQOBg4xpudXdYNl5Jx6LajOzc1romWpC1DFAWDfd3MTUaIKK4+OWKrXedKks/jcakkuuCVWa8JCZc/LCi8L9q/mc4h3hiLmsJ4VPhTsduaDwvdKNIr8oTvscUJkRJxEfFo4Ia+kyNsrYXHYs4T7htqRlS35gpshJxWuKrUzB/LmnemH9kj09pXSZrcQYY4JJNAwKrJAhT5estigucdmPVvC3+P5JcRniWsEUxwhZLHTfj/qD3926qd6eYlJ9FGqePO+tHUJb8LXpeZ+Hnvd1BMFHuLBL/uwBDL6LvlnS2vahcR3OLkuasQ3nG9D8kNMd3ZeCMgOpFLyeyDfNQtM11M4Xe/vZ5/gOEtLV+BXs7kFHWrIXKrw7XN7bn2f8/oh+A2ixcqM29OAgAAAACXBIWXMAAC4iAAAuIgGq4t2SAAAAB3RJTUUH6AQHCzcfT87vFgAAAEZJREFUSEu1yKEBADAIwDCO5n/2QGQnYjJze18xS8wSs8QsMUvMErPELDFLzBKzxCwxS8wSs8QsMUvMErPELDFLzBIzs/cABgWAzBU/nmQAAAAASUVORK5CYII= + + 180538b6-48a7-45a7-9f63-4236e4b1aade + true + true + false + true + DFXMLExporter + XMLout + 1 + + false + false + false + + + + + + 288 + 1080 + 171 + 84 + + + 395 + 1122 + + + + + + 4 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 3 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + + + + + true + Press button to export xml + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA6xJREFUSEvVVTlLXGEUHRUHkXHfHRWXcd/3DRVcQBFUVAzaCYKC+AsGohYGDQiipYV2VpLSykawjCIuaOGCgiZFgoVmNImc3HPnPRHHLVXIgcu8ecu59557vu+z/Cs4vLy8fsgv/iLeSbwNfn5+n+fn57G+vo61tTWsrq5iZWUFy8vLWFxcxNTUFAYGBtDa2orq6mqkpqZCCrqQT61uhhfg4+PTLh/+WlhYQHl5uUZZWRlKSkpQVFSE/Px85OTkICMjQ4mTkpKQlZUFm8125e3t7TRonoU1KCjo29LSErq6urQ6RlVVlSZiksLCQuTm5ippWloaUlJSNJKTkyEJroXD7qZ6Ar6+vh/6+/t/j42NoaamBnV1dRq8ZhJ2UlxcrF1kZ2cjPT1dyRMTE7UTKe5WpPpk0HnAER0dfTM7O4uGhgYlrq+vR0tLC+bm5rC7uwsT29vbmJycREFBARwOhyaIj49HXFwcZ8Euit2UDyDar3V2dqK3t1dlYYKenh4cHR0ZtJ44ODjQd5mA5DExMQgJCbmTJBsG7T1aw8PDXSSk1pSD1R8eHhpUnnC5XPq7v7+vw2YCUQAJCQkQF14JZ5+bWgYr1X+pqKgAg4NkkpmZGSV4Cufn5+jo6MDZ2Zn+Hx8fh91uR1RUlCZhR9LFd+G2WWTy78PCwlwk5/BoRSZh+0/h4uICTU1NatORkRG9t7Ozg9jYWERGRiI0NFQHL9dcqNMWyXSZmZmp3mYwCa14c3OjHz+ESc73aVEOmaBc1D8iIoIz0ER5eXlc3ZdMMC32uqa3zUS8fpyAspjktCfdQxKCCSiPKIHg4GB9R1zFDj5KWGzUiz5m2wwuooe2JDmty2esnOR8f2hoSJ9vbW1p9ZSHnXC9yFzdMzDQZ7Var/gxHcHfiYkJ/ZidtLW16T0+o74kZ/Wnp6f6jtPpvK+eBhGJuBbuXaSgd6kdlzxJWC0tSJycnGB4eFhb5/3BwUEcHx/rs729Pa2a5OystLT0Tug81gFRxr2EFjODzjKTPAWSc2YcLOXhjAIDA6m950ompItP8uItO+DCYVCO0dFRbG5uGrTAxsaGykLvs3IhVXuLbD+F5tm9iLCzC+rNvYWLxgy6hBJymNSbFYv7EBAQoM95NsgcX95NDTil5WvulrJ93IdJSjnMquUMgL+/v24r0jXJXz0PCKtI9ZVWraysRG1trRJQ3+bmZq20vb0d3Bi7u7t1Q2xsbHz7iWaA5+vjM/e1ePuZ/B/BYvkDKff7sf0Xzw8AAAAASUVORK5CYII= + + ee32ac69-2980-466c-a27d-24c46e0f978d + true + i_dump + i_dump + true + 0 + true + 0 + Press button to export xml + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 290 + 1082 + 90 + 20 + + + 336.5 + 1092 + + + + + + + + true + The name of the assembly to export. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 7937e977-a894-475a-9126-ab9f2badf263 + true + i_assembly_name + i_assembly_name + true + 0 + true + 0 + The name of the assembly to export. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 290 + 1102 + 90 + 20 + + + 336.5 + 1112 + + + + + + + + true + The directors where to export the xml file. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 5b90a98b-2119-45b1-9acc-86618952952a + true + i_export_dir + i_export_dir + true + 0 + true + 0 + The directors where to export the xml file. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 290 + 1122 + 90 + 20 + + + 336.5 + 1132 + + + + + + + + 1 + true + The breps of the structure. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA+RJREFUSEvVVVso5XsU3shOcr9Fg1w2uSvHXVJuiQe5ZDJvSvJE3mhy4sEpp0QuyS0e5PLAoFxeCJFSJi8k5VKSc3Dksrc5Zs70nfX99qY5Z88Y83Q6q1b7v+v3+9Za3/rW+mn+K9NZWFjcyy9+wF+Lv8xsbGy2+vr6sL6+jtXVVSwuLmJ+fh4TExMYGhpCc3MzysvLkZeXh5SUFAQFBUESOpOrWiPCM2ZlZZUvFz8NDg4iISFBeXx8PGJjYxETE4Po6GhEREQgJCREAfv7+yMsLAx2dnZ6S0vLtyaYb5rW0dHxj9HRURQVFans6MnJyUhKSsLw8DAeHh5wc3ODhYUF5ObmIjAwUHlAQAAkgEEwXhmhvmLW1ta/lJWV/dXQ0IDU1FSkpaU9Oak6PDxEd3c3ent7sbS0hNvbW/Xfz89PVSLJPQhV70xwZqbz9PT8s729HRkZGQo0PT0dmZmZWFtbg16vR2dnJyYnJ1FRUYGqqirU19fj6OhI9YdBvL292QtW8ZMR8gsT7ldJS2lpqaKFAQjORhP88vISDL65uYna2lrV6IGBAbS2tuLg4ABdXV3w8vKCs7PzZwny3gT7ZHlubm4fSkpKVFPJOQM8Zk7w4+NjjI+PY25uDisrKwp8enpaneE36WLlvr6+EBXqBfONEVoaK9n/lpiYCDrVwoaS8y/Bd3Z2VPYtLS04OztT3wTf29vD/v6+6sns7CyEZkWXVHEl2HYa6fzPrq6uHwhOCVKKIyMjMBgMZuAEGRsbQ0dHB87Pz3FxcaHO0Hp6enB9fQ0XFxelKnd3dw7qrxqJdB0aGqq0TWcQgl9dXZmBz8zMgBJmsxsbGxVVJycn2NjYUMpixdIDeHh4ICoqitN9zQAtIi9DZGQkHgPd39+ri18D7+/vR1tbG5qamlBZWYnq6mr1f3d3VwVxcnJSONILYwXkiXxRx5xOOjM7PT19Fryurk5JlZLd2tpS/AstSkmcfOmrsQcme6PVavXBwcFq/AsKCnB3d4fl5eUXg5MWZk8Vyjdn4UlFyqSK9zzEkWeTeIkV/Ai4TqdDXFzcZ4EzmwNaPHcJJUanqqgQypWqeQ6cjaV6srKy4ODgQO7NJ5kmVbyTgw+sgGPPcrkGqKipqSk1wTU1Ndje3v5H5gKq5C3K+Sgw39xFtFesgr3w8fFRQ0PPzs5WE0z5sjdcGWyoqA/29vbqDN8G6ePz29Rkb6VkQ3h4OGR9PLkMo6KBdDxmLW8AbG1t1VKUqgn+3feAphWqfucj8riTCEB+c3JyVKb5+fkoLCxEcXExuL+4FOXOy140k/F9/feb+z1/+Zv8PzKN5m9TzzRCUDHb/QAAAABJRU5ErkJggg== + + b2b35e86-d097-457c-8dd0-fa8f391f2d52 + true + i_breps + i_breps + true + 1 + true + 0 + The breps of the structure. + 2ceb0405-fdfe-403d-a4d6-8786da45fb9d + + + + + + 290 + 1142 + 90 + 20 + + + 336.5 + 1152 + + + + + + + + false + The string of xml to be exported. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + dae952a3-80b5-46b4-83e6-d4a74502350d + true + o_xml + o_xml + false + 0 + true + 0 + The string of xml to be exported. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 410 + 1082 + 47 + 26 + + + 433.5 + 1095.3334 + + + + + + + + false + The breps of the faces belonging to joints. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + f9949a62-8862-4f11-9b42-5d9d2d9760da + true + o_joints + o_joints + false + 0 + true + 0 + The breps of the faces belonging to joints. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 410 + 1108 + 47 + 27 + + + 433.5 + 1122 + + + + + + + + false + The breps of the faces belonging to sides. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 5c203e94-0aef-400c-8aec-d20d76f0571e + true + o_sides + o_sides + false + 0 + true + 0 + The breps of the faces belonging to sides. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 410 + 1135 + 47 + 27 + + + 433.5 + 1148.6667 + + + + + + + + + + false + IyEgcHl0aG9uMwoKaW1wb3J0IFJoaW5vCmltcG9ydCBSaGluby5HZW9tZXRyeSBhcyByZwoKaW1wb3J0IG9zCmltcG9ydCB0eXBpbmcKCmltcG9ydCBkaWZmQ2hlY2sKCmltcG9ydCBkaWZmQ2hlY2submV3bW9kdWxlCmRpZmZDaGVjay5uZXdtb2R1bGUudGVzdF9uZXdfbWRvdWxlKCkKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICAiIiIKICAgICAgICBNYWluIGZ1bmN0aW9uIHRvIHRlc3QgdGhlIHBhY2thZ2UKICAgICAgICA6cGFyYW0gaV9icmVwczogbGlzdCBvZiBicmVwcwogICAgICAgIDpwYXJhbSBpX2V4cG9ydF9kaXI6IGRpcmVjdG9yeSB0byBleHBvcnQgdGhlIHhtbAogICAgICAgIDpwYXJhbSBpX2R1bXA6IHdoZXRoZXIgdG8gZHVtcCB0aGUgeG1sCiAgICAiIiIKICAgICMgYmVhbXMKICAgIGJlYW1zID0gW10KICAgIGZvciBicmVwIGluIGlfYnJlcHM6CiAgICAgICAgYmVhbSA9IGRpZmZDaGVjay5kZl9nZW9tZXRyaWVzLkRGQmVhbS5mcm9tX2JyZXAoYnJlcCkKICAgICAgICBiZWFtcy5hcHBlbmQoYmVhbSkKCiAgICAjIGFzc2VtYmx5CiAgICBhc3NlbWJseTEgPSBkaWZmQ2hlY2suZGZfZ2VvbWV0cmllcy5ERkFzc2VtYmx5KGJlYW1zLCBpX2Fzc2VtYmx5X25hbWUpCgogICAgIyBkdW1wIHRoZSB4bWwKICAgIHhtbDogc3RyID0gYXNzZW1ibHkxLnRvX3htbCgpCiAgICBpZiBpX2R1bXA6CiAgICAgICAgYXNzZW1ibHkxLmR1bXBfeG1sKHhtbCwgaV9leHBvcnRfZGlyKQogICAgb194bWwgPSB4bWwKCiAgICAjIHNob3cgdGhlIGpvaW50L3NpZGUgZmFjZXMKICAgIG9fam9pbnRzID0gW2pmLnRvX2JyZXAoKSBmb3IgamYgaW4gYXNzZW1ibHkxLmFsbF9qb2ludF9mYWNlc10KICAgIG9fc2lkZXMgPSBbc2YudG9fYnJlcCgpIGZvciBzZiBpbiBhc3NlbWJseTEuYWxsX3NpZGVfZmFjZXNdCg== + S + + + + + *.*.python + 3.* + + + + + + + + + + + a8b97322-2d53-47cd-905e-b932c3ccd74e + Button + + + + + Button object with two values + False + True + ef4234f1-74d1-42d5-8449-ae68033cb1a1 + true + Button + + false + 0 + + + + + + 35 + 235 + 66 + 22 + + + + + + + + + + 919e146f-30ae-4aae-be34-4d72f555e7da + Brep + + + + + Contains a collection of Breps (Boundary REPresentations) + true + 07b41f33-b1e8-491e-82ae-3da0f5326222 + true + Brep + Brep + false + 0 + + + + + + 61 + 342 + 50 + 24 + + + 86.79881 + 354.94077 + + + + + + 1 + + + + + 1 + {0} + + + + + 5981a85d-0063-489b-8bd7-7a1ebe1453a7 + + + + + + + + + + + + + a8b97322-2d53-47cd-905e-b932c3ccd74e + Button + + + + + Button object with two values + False + True + d89a87be-095f-41ba-bcfa-14a27b69959f + true + Button + dump! + false + 0 + + + + + + 10 + 397 + 102 + 22 + + + + + + + + + + 06953bda-1d37-4d58-9b38-4b3c74e54c8f + File Path + + + + + Contains a collection of file paths + false + All files|*.* + 78f00f3a-c6ac-40ac-9725-ad949c6e7593 + true + File Path + Path + false + 0 + + + + + + 63 + 315 + 50 + 24 + + + 88.27081 + 327.20453 + + + + + + 1 + + + + + 1 + {0} + + + + + false + F:\diffCheck\temp\ + + + + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + c4486e03-f65b-4cbb-aaea-81fdbdcd7cf0 + true + Panel + + false + 0 + 0 + AssemblyTest + + + + + + 13 + 371 + 102 + 20 + + 0 + 0 + 0 + + 13.415691 + 371.5 + + + + + + + 255;213;217;232 + + true + true + true + false + false + true + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + f98c6a9b-86ca-429d-8692-dcc245c0e6e5 + true + Panel + + false + 0 + 0 + diffCheck + + + + + + -13 + 263 + 113 + 38 + + 0 + 0 + 0 + + -12.635988 + 263.5192 + + + + + + + 255;213;217;232 + + true + true + false + false + false + true + + + + + + + + + c9b2d725-6f87-4b07-af90-bd9aefef68eb + 066d0a87-236f-4eae-a0f4-9e42f5327962 + script-sync cpython + + + + + + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAABhmlDQ1BJQ0MgcHJvZmlsZQAAKM+VkTtIw1AUhv+mSkUqDhZ84JChCoIFURFHiWIRLJS2QqsOJjd9QZOGJMXFUXAtOPhYrDq4OOvq4CoIgg8QZwcnRRcp8dyk0CJU8MDlfvz3/j/nngsItRLTrI4JQNNtMxGVxHRmVQy8wodB9EPAmMwsI5ZcTKFtfd3Tbaq7CM/C/6pHzVoM8InEc8wwbeIN4plN2+C8TxxiBVklPiceN6lB4keuKx6/cc67LPDMkJlKzBOHiMV8CystzAqmRjxNHFY1nfKFtMcq5y3OWqnCGn3yFwaz+kqS67SGEcUSYohDhIIKiijBRoR2nRQLCTqX2viHXH+cXAq5imDkWEAZGmTXD/4Hv2dr5aYmvaSgBHS+OM7HCBDYBepVx/k+dpz6CeB/Bq70pr9cA2Y/Sa82tfAR0LsNXFw3NWUPuNwBBp4M2ZRdyU9LyOWA9zP6pgzQdwt0r3lza5zj9AFI0ayWb4CDQ2A0T9nrbd7d1Tq3P++484P0A3o2cqrMnZbPAAAACXBIWXMAAAsOAAALDgFAvuFBAAAAB3RJTUUH6AEZFwkM569AfQAABNpJREFUSEu9kntMU3cYhguoOOZ1ujmFXqQtBcEpIwoTxOGQolLwUp24OFS0sEqh0oIV0CIg1FLKsbTlNooFKhRF8TajziW6zYFxcckW9bhlm9uiLk6nAyuWy7tTc0iI4w9l2Z7k++/7nveX9xzGfw+LWMhgV4hd48Y2iN1ZBvEoFiH2ZOrFXkydeJzPvsn05ghhmxIZnCq4xo1TCXe2GaPZJniyKvAqi8AEps5Eb/4LOJVfDQZ4PAswYizLgHHMckxi6vqmeJfMpjdHCNscQgUMDAaMoQJeoQLGUwGTfXR43bvkM3pz5LhxzHXuVMAoqp4x7Ap4sfZT9ejxmk8ppnlrEDE142bCxA3k2vHryKSZYnJrcPxS+vTFcGMR09w55keuAFf/Xs/612OKjxZvepdAMF2NFROT8IHv+5CEroZskeiaJC7Cgz5/MTzYRsVg/64PPJFZhqlUwHTvYrBmFGBZsAybw9ZCGr0SyhXLoVobk0Gfvhju/CJPD2GnY7SwE57CDngJL2FCzBeYsuQC/OM/Rdiq45AsWQP5ygSoEpdi94fRDyslc6SWNH9pvVwgtWb7SQ/k8CfRumHY2ithpACD45YyAA9JP3ykPQiQdSNh4zlsS1gFZaIIuZuEKEx5DwZZKKyZAWhUCdC0i5o9fIK2Pcfm7gmMlIF7zwd4b3MiMMOBhdvvQLJ6C+TrV0CVvBz5qTEoTo+CThmBAzlBaNotgK3AD80av97mUt4s2joESX/ZULlr3pD2I1Deg/nKLiQmN0O2Xoys5HjsksaiUB6Nfcp3UZ67ANX5IThYRMn38dFSxoed4J+lrTRbngio1zuHyid9NABeei+CFQ5EZ91FcsZZyBTtUGUfRGFuLXRqAuaCEtQX51GvlqCllBLr+Wg18HDIzIO9xnc5baeQ9J0YKncNU9aPOYoeLNzZhXWZV5CiOI3MHW3Iy21AsboSRIEe1ZpCNGh3okUXjhaCkhspeRUPh2u5aLNwb1isM0a7Xi98Xj49rR8CuRPvqBxYtuNXbFKcR5rqBLLz7MjPt0BbZIRRo0WdLh82fRLs+/k4ZKLk1ZT4Yy6O1FPT6IujzTMzqT/HGUv1nzp0eOnO1JAsR+rinPuZiYrOPonqLOS57chRH8TevbUo01D16IrRSOSgwxCJK6ZgXK2ZjW/rZuGa1Q+kjYfvW7i40ep7ne5oeNbIL6mTsi9gW95pKNVtUBc1QKOpwn5dGarLC3GxYiN+Mkfgds183LcEo8sahB6bP3rtfAwc5qK3nbORVv0TUdpF1jplx+OtueeRvvskVIV2FJTUQ1tqgpHQotm4EzeMi3GrKhx36+bhgXUuum2B6LEL0NfGQ/8x38u0anhWbe/Yu0H1OZm66wyZuecomVfSRBZpa0h9OUGaK4rJL43rcbN6EX6xhOF3awge2mbjcWsAnrb5oe84F49PcUJp1ctz2SCM+64qGj/URuK3A6G4Z5uLR/YgONoEcB7jwXlqZiO9+vKcIaLHfG2KJa/VLMaPlnDcts3DHy1z8NfhQDxp96Pk3O77Z9gz6PWXp7MiTnG1MhbX66Lwc8MC3GkOwYNDb6GrPQA9J/lwnPbNo1dHRqdJFPVNbYyItEaKbjWFie62vi3680iQqPu4v+jpJzzRg3PssfTq/wGD8Tedsdp6457pjwAAAABJRU5ErkJggg== + + 08fe15ed-12b6-4c72-a8ba-350c0da17df3 + true + true + false + true + script-sync cpython + scsy-cpy + 1 + + false + false + false + + + + + + 154 + 261 + 179 + 124 + + + 269 + 323 + + + + + + 6 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 4 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + + + + + true + Connect a button to open a file dialog to select a cpython file to run. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA6xJREFUSEvVVTlLXGEUHRUHkXHfHRWXcd/3DRVcQBFUVAzaCYKC+AsGohYGDQiipYV2VpLSykawjCIuaOGCgiZFgoVmNImc3HPnPRHHLVXIgcu8ecu59557vu+z/Cs4vLy8fsgv/iLeSbwNfn5+n+fn57G+vo61tTWsrq5iZWUFy8vLWFxcxNTUFAYGBtDa2orq6mqkpqZCCrqQT61uhhfg4+PTLh/+WlhYQHl5uUZZWRlKSkpQVFSE/Px85OTkICMjQ4mTkpKQlZUFm8125e3t7TRonoU1KCjo29LSErq6urQ6RlVVlSZiksLCQuTm5ippWloaUlJSNJKTkyEJroXD7qZ6Ar6+vh/6+/t/j42NoaamBnV1dRq8ZhJ2UlxcrF1kZ2cjPT1dyRMTE7UTKe5WpPpk0HnAER0dfTM7O4uGhgYlrq+vR0tLC+bm5rC7uwsT29vbmJycREFBARwOhyaIj49HXFwcZ8Euit2UDyDar3V2dqK3t1dlYYKenh4cHR0ZtJ44ODjQd5mA5DExMQgJCbmTJBsG7T1aw8PDXSSk1pSD1R8eHhpUnnC5XPq7v7+vw2YCUQAJCQkQF14JZ5+bWgYr1X+pqKgAg4NkkpmZGSV4Cufn5+jo6MDZ2Zn+Hx8fh91uR1RUlCZhR9LFd+G2WWTy78PCwlwk5/BoRSZh+0/h4uICTU1NatORkRG9t7Ozg9jYWERGRiI0NFQHL9dcqNMWyXSZmZmp3mYwCa14c3OjHz+ESc73aVEOmaBc1D8iIoIz0ER5eXlc3ZdMMC32uqa3zUS8fpyAspjktCfdQxKCCSiPKIHg4GB9R1zFDj5KWGzUiz5m2wwuooe2JDmty2esnOR8f2hoSJ9vbW1p9ZSHnXC9yFzdMzDQZ7Var/gxHcHfiYkJ/ZidtLW16T0+o74kZ/Wnp6f6jtPpvK+eBhGJuBbuXaSgd6kdlzxJWC0tSJycnGB4eFhb5/3BwUEcHx/rs729Pa2a5OystLT0Tug81gFRxr2EFjODzjKTPAWSc2YcLOXhjAIDA6m950ompItP8uItO+DCYVCO0dFRbG5uGrTAxsaGykLvs3IhVXuLbD+F5tm9iLCzC+rNvYWLxgy6hBJymNSbFYv7EBAQoM95NsgcX95NDTil5WvulrJ93IdJSjnMquUMgL+/v24r0jXJXz0PCKtI9ZVWraysRG1trRJQ3+bmZq20vb0d3Bi7u7t1Q2xsbHz7iWaA5+vjM/e1ePuZ/B/BYvkDKff7sf0Xzw8AAAAASUVORK5CYII= + + f703fbba-ff07-4709-8112-cd955660e259 + true + btn + btn + true + 0 + true + ef4234f1-74d1-42d5-8449-ae68033cb1a1 + 1 + Connect a button to open a file dialog to select a cpython file to run. + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 156 + 263 + 98 + 20 + + + 206.5 + 273 + + + + + + + + 1 + true + Pass a list with the name of the custom packages you want to reload. This function is useful if you are developing a i.e. PyPI package and you want to reload the submodules after you modified something. The function will reload the package and all its submodules. If you want to reload the package and all its submodules, just pass the package name. If you want to reload only a submodule, pass the package name and the submodule name separated by a dot. If you want to reload multiple submodules, pass the package + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 0484038e-7609-494e-abc2-e4c58b9763d1 + true + packages_2_reload + packages_2_reload + true + 1 + true + f98c6a9b-86ca-429d-8692-dcc245c0e6e5 + 1 + Pass a list with the name of the custom packages you want to reload. This function is useful if you are developing a i.e. PyPI package and you want to reload the submodules after you modified something. The function will reload the package and all its submodules. If you want to reload the package and all its submodules, just pass the package name. If you want to reload only a submodule, pass the package name and the submodule name separated by a dot. If you want to reload multiple submodules, pass the package + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 156 + 283 + 98 + 20 + + + 206.5 + 293 + + + + + + + + true + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + 23c12915-418c-45d4-8a9f-82667941634f + true + i_export_dir + i_export_dir + true + 0 + true + 78f00f3a-c6ac-40ac-9725-ad949c6e7593 + 1 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 156 + 303 + 98 + 20 + + + 206.5 + 313 + + + + + + + + 1 + true + A generic x input. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA+RJREFUSEvVVVso5XsU3shOcr9Fg1w2uSvHXVJuiQe5ZDJvSvJE3mhy4sEpp0QuyS0e5PLAoFxeCJFSJi8k5VKSc3Dksrc5Zs70nfX99qY5Z88Y83Q6q1b7v+v3+9Za3/rW+mn+K9NZWFjcyy9+wF+Lv8xsbGy2+vr6sL6+jtXVVSwuLmJ+fh4TExMYGhpCc3MzysvLkZeXh5SUFAQFBUESOpOrWiPCM2ZlZZUvFz8NDg4iISFBeXx8PGJjYxETE4Po6GhEREQgJCREAfv7+yMsLAx2dnZ6S0vLtyaYb5rW0dHxj9HRURQVFans6MnJyUhKSsLw8DAeHh5wc3ODhYUF5ObmIjAwUHlAQAAkgEEwXhmhvmLW1ta/lJWV/dXQ0IDU1FSkpaU9Oak6PDxEd3c3ent7sbS0hNvbW/Xfz89PVSLJPQhV70xwZqbz9PT8s729HRkZGQo0PT0dmZmZWFtbg16vR2dnJyYnJ1FRUYGqqirU19fj6OhI9YdBvL292QtW8ZMR8gsT7ldJS2lpqaKFAQjORhP88vISDL65uYna2lrV6IGBAbS2tuLg4ABdXV3w8vKCs7PzZwny3gT7ZHlubm4fSkpKVFPJOQM8Zk7w4+NjjI+PY25uDisrKwp8enpaneE36WLlvr6+EBXqBfONEVoaK9n/lpiYCDrVwoaS8y/Bd3Z2VPYtLS04OztT3wTf29vD/v6+6sns7CyEZkWXVHEl2HYa6fzPrq6uHwhOCVKKIyMjMBgMZuAEGRsbQ0dHB87Pz3FxcaHO0Hp6enB9fQ0XFxelKnd3dw7qrxqJdB0aGqq0TWcQgl9dXZmBz8zMgBJmsxsbGxVVJycn2NjYUMpixdIDeHh4ICoqitN9zQAtIi9DZGQkHgPd39+ri18D7+/vR1tbG5qamlBZWYnq6mr1f3d3VwVxcnJSONILYwXkiXxRx5xOOjM7PT19Fryurk5JlZLd2tpS/AstSkmcfOmrsQcme6PVavXBwcFq/AsKCnB3d4fl5eUXg5MWZk8Vyjdn4UlFyqSK9zzEkWeTeIkV/Ai4TqdDXFzcZ4EzmwNaPHcJJUanqqgQypWqeQ6cjaV6srKy4ODgQO7NJ5kmVbyTgw+sgGPPcrkGqKipqSk1wTU1Ndje3v5H5gKq5C3K+Sgw39xFtFesgr3w8fFRQ0PPzs5WE0z5sjdcGWyoqA/29vbqDN8G6ePz29Rkb6VkQ3h4OGR9PLkMo6KBdDxmLW8AbG1t1VKUqgn+3feAphWqfucj8riTCEB+c3JyVKb5+fkoLCxEcXExuL+4FOXOy140k/F9/feb+z1/+Zv8PzKN5m9TzzRCUDHb/QAAAABJRU5ErkJggg== + + 770c2c41-936b-4563-8085-69258fb43fe4 + true + i_breps + i_breps + true + 1 + true + 07b41f33-b1e8-491e-82ae-3da0f5326222 + 1 + A generic x input. + 2ceb0405-fdfe-403d-a4d6-8786da45fb9d + + + + + + 156 + 323 + 98 + 20 + + + 206.5 + 333 + + + + + + + + true + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + c87fd4ae-11b7-4647-804e-d9cf678a79b3 + true + i_assembly_name + i_assembly_name + true + 0 + true + c4486e03-f65b-4cbb-aaea-81fdbdcd7cf0 + 1 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 156 + 343 + 98 + 20 + + + 206.5 + 353 + + + + + + + + true + Converts to collection of boolean values + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAOsSURBVEhL1VU5S1xhFB0VB5Fx3x0Vl3Hf9w0VXEARVFQM2gmCgvgLBqIWBg0IoqWFdlaS0spGsIwiLmjhgoImRYKFZjSJnNxz5z0Rxy1VyIHLvHnLufeee77vs/wrOLy8vH7IL/4i3km8DX5+fp/n5+exvr6OtbU1rK6uYmVlBcvLy1hcXMTU1BQGBgbQ2tqK6upqpKamQgq6kE+tboYX4OPj0y4f/lpYWEB5eblGWVkZSkpKUFRUhPz8fOTk5CAjI0OJk5KSkJWVBZvNduXt7e00aJ6FNSgo6NvS0hK6urq0OkZVVZUmYpLCwkLk5uYqaVpaGlJSUjSSk5MhCa6Fw+6megK+vr4f+vv7f4+NjaGmpgZ1dXUavGYSdlJcXKxdZGdnIz09XckTExO1EynuVqT6ZNB5wBEdHX0zOzuLhoYGJa6vr0dLSwvm5uawu7sLE9vb25icnERBQQEcDocmiI+PR1xcHGfBLordlA8g2q91dnait7dXZWGCnp4eHB0dGbSeODg40HeZgOQxMTEICQm5kyQbBu09WsPDw10kpNaUg9UfHh4aVJ5wuVz6u7+/r8NmAlEACQkJEBdeCWefm1oGK9V/qaioAIODZJKZmRkleArn5+fo6OjA2dmZ/h8fH4fdbkdUVJQmYUfSxXfhtllk8u/DwsJcJOfwaEUmYftP4eLiAk1NTWrTkZERvbezs4PY2FhERkYiNDRUBy/XXKjTFsl0mZmZqd5mMAmteHNzox8/hEnO92lRDpmgXNQ/IiKCM9BEeXl5XN2XTDAt9rqmt81EvH6cgLKY5LQn3UMSggkojyiB4OBgfUdcxQ4+Slhs1Is+ZtsMLqKHtiQ5rctnrJzkfH9oaEifb21tafWUh51wvchc3TMw0Ge1Wq/4MR3B34mJCf2YnbS1tek9PqO+JGf1p6en+o7T6byvngYRibgW7l2koHepHZc8SVgtLUicnJxgeHhYW+f9wcFBHB8f67O9vT2tmuTsrLS09E7oPNYBUca9hBYzg84ykzwFknNmHCzl4YwCAwOpvedKJqSLT/LiLTvgwmFQjtHRUWxubhq0wMbGhspC77NyIVV7i2w/hebZvYiwswvqzb2Fi8YMuoQScpjUmxWL+xAQEKDPeTbIHF/eTQ04peVr7payfdyHSUo5zKrlDIC/v79uK9I1yV89DwirSPWVVq2srERtba0SUN/m5mattL29HdwYu7u7dUNsbGx8+4lmgOfr4zP3tXj7mfwfwWL5Ayn3+7H9F88PAAAAAElFTkSuQmCC + + de47b8a3-cb7b-43e4-b958-28f86271d143 + true + i_dump + i_dump + true + 0 + true + d89a87be-095f-41ba-bcfa-14a27b69959f + 1 + + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 156 + 363 + 98 + 20 + + + 206.5 + 373 + + + + + + + + false + The redirected standard output of the component scriptsync. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 99e48b23-64d9-4e2f-859d-62348fa491ae + true + stdout + stdout + false + 0 + true + 0 + The redirected standard output of the component scriptsync. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 284 + 263 + 47 + 30 + + + 307.5 + 278 + + + + + + + + false + Generic example output of the component + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABBNJREFUSEvVVVsorWkYXshKcj6znM/n81nORCiFTFxRLtw4JFe2JDQy2pLkggunwo22K0opCZHsRHEhKWXPTBp2sazN0DPf8631r+wxe9tzNc1bb+tvrfU/z/s+7/N+n+q/Cj8TE5Mv4hP/In8S+WNhYWHxcWJiAltbW9jY2MDa2hpWVlawuLiIqakpDAwMoKGhAaWlpcjIyEBQUBBEQb+KV9V6hO+EmZlZuXjxz8nJSaSkpMhMTk5GYmIi4uPjERMTg8jISISGhkpgPz8/hIeHw8rK6s7U1PSdAeaboba1tf1jfn4elZWVsjpmenq6JCJJXFwcoqKiJGhwcDACAgJk+vv7QxBoBYZGD/UPYW5u/nN9ff1Td3c3MjMz0djYiP7+fszNzWFzcxPT09NISEiQXURERCAnJ0f+trq6itraWojiHoRUHwxwr8LPzc3ty8jICPLz85Gbm4u6ujqMjo7i6uoK19fX8rOsrAyxsbEoLCzE0dERzs/PcXh4iPHxcXh6enIW7CJBD/kihPYbFRUVqKmpkbJkZ2cjLy9P5v7+Pm5vb3F/fy+BkpKSsL29jYWFBdAMy8vLUlJ3d3fY29s/C5KPBlhjlDo5Oemqq6ul1tScEpGE2dfXB51Oh4eHB5ycnEiStrY2hISESP19fX1l9UIBeHt7Q7jwTmDW6qHFYEX1v6WmpoLJQSokypCLiookwdPTE56fn7G0tPTVkH18fKDRaODq6ipJSCi6uBbYViox+S5HR0cdwTk8WpEktOZLm+7t7UlwRk9Pz1c29fLygoeHB1xcXODg4CBJxfO9IHivEkyfw8LCpLeZJKEV6ZaXOTw8bOxgfX3dWL0iD/V3dnbmDCRRdHQ0t/szCd4Le2npbYWIzySiW5h85hZzBo+Pj3LYJH1ZPeURSsDOzk7iiO/ZwS8iVVbUi39m20zqS58rXXV1daG3txenp6cSXKvVorOzUw6U2rNjVk952AklFXPVz8AQtWq1+o5tM1taWjA2Nob29nYMDQ1hZmZGfj84OIibmxu5E8fHx7KYkpIStLa2GqvnzIRE3AWji2TQu9SO1mtubpYbysNudnbWaEfKcnZ2hsvLS1xcXODg4AA8s1g9wQMDA7kjzwLu1R4wknmWcGhZWVnS501NTcZB0orUm4u4u7uLnZ0ddHR0KMsl5eF229jYUPvXm8wQXXwQf3wgKJ3xMqk1h0lADpRVK7IIUGlv4ZxHAfPNs4ihYRfUm9VyaZQkKCVUgFmxcB+sra3l77wbxBy/f5oa4p1oWUsXiePDmAoo5VCqFncALC0t5Xkluib4m/cBQy2k+p1WTUtLk/MgAPUtLi6WlZaXl4MHY1VVFXh+FRQU8Gj4xHf1EG8H79e/37lv5Y/fyf+jUKn+AkB0rPmebpkgAAAAAElFTkSuQmCC + + 58680e01-bd51-44b8-bac4-82d9b43f37b0 + true + o_xml + o_xml + false + 0 + true + 0 + Generic example output of the component + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 284 + 293 + 47 + 30 + + + 307.5 + 308 + + + + + + + + false + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + d9399b7b-ece0-4d60-ba8e-0bb8c0bdf01a + true + o_joints + o_joints + false + 0 + true + 0 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 284 + 323 + 47 + 30 + + + 307.5 + 338 + + + + + + + + false + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + 8051ced1-c685-4aac-b373-3da1f25a7345 + true + o_sides + o_sides + false + 0 + true + 0 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 284 + 353 + 47 + 30 + + + 307.5 + 368 + + + + + + + + + + false + ZnJvbSBnaHB5dGhvbmxpYi5jb21wb25lbnRiYXNlIGltcG9ydCBleGVjdXRpbmdjb21wb25lbnQgYXMgY29tcG9uZW50CgppbXBvcnQgU3lzdGVtCmltcG9ydCBTeXN0ZW0uRHJhd2luZwppbXBvcnQgU3lzdGVtLldpbmRvd3MuRm9ybXMKaW1wb3J0IFJoaW5vCmltcG9ydCBHcmFzc2hvcHBlcgppbXBvcnQgR3Jhc3Nob3BwZXIgYXMgZ2gKZnJvbSBHcmFzc2hvcHBlci5LZXJuZWwgaW1wb3J0IEdIX1J1bnRpbWVNZXNzYWdlTGV2ZWwgYXMgUk1MCmltcG9ydCBzeXMKaW1wb3J0IG9zCmltcG9ydCB0aW1lCgppbXBvcnQgY29udGV4dGxpYgppbXBvcnQgaW8KCmltcG9ydCBhYmMKaW1wb3J0IHNvY2tldAppbXBvcnQgdGhyZWFkaW5nCmltcG9ydCBxdWV1ZQppbXBvcnQganNvbgoKaW1wb3J0IGltcG9ydGxpYgppbXBvcnQgaW5zcGVjdAppbXBvcnQgc3lzCgoKY2xhc3MgR0hUaHJlYWQodGhyZWFkaW5nLlRocmVhZCwgbWV0YWNsYXNzPWFiYy5BQkNNZXRhKToKICAgICIiIgogICAgICAgIEEgYmFzZSBjbGFzcyBmb3IgR3Jhc3Nob3BwZXIgdGhyZWFkcy4KICAgICIiIgogICAgZGVmIF9faW5pdF9fKHNlbGYsIG5hbWUgOiBzdHIpOgogICAgICAgIHN1cGVyKCkuX19pbml0X18obmFtZT1uYW1lLCBkYWVtb249RmFsc2UpCiAgICAgICAgc2VsZi5fY29tcG9uZW50X29uX2NhbnZhcyA9IFRydWUKICAgICAgICBzZWxmLl9jb21wb25lbnRfZW5hYmxlZCA9IFRydWUKCiAgICBAYWJjLmFic3RyYWN0bWV0aG9kCiAgICBkZWYgcnVuKHNlbGYpOgogICAgICAgICIiIiBSdW4gdGhlIHRocmVhZC4gIiIiCiAgICAgICAgcGFzcwoKICAgIGRlZiBfY2hlY2tfaWZfY29tcG9uZW50X29uX2NhbnZhcyhzZWxmKToKICAgICAgICAiIiIgQ2hlY2sgaWYgdGhlIGNvbXBvbmVudCBpcyBvbiBjYW52YXMgZnJvbSB0aHJlYWQuICIiIgogICAgICAgIGRlZiBfX2NoZWNrX2lmX2NvbXBvbmVudF9vbl9jYW52YXMoKToKICAgICAgICAgICAgaWYgZ2hlbnYuQ29tcG9uZW50Lk9uUGluZ0RvY3VtZW50KCkgaXMgTm9uZToKICAgICAgICAgICAgICAgIHNlbGYuX2NvbXBvbmVudF9vbl9jYW52YXMgPSBGYWxzZQogICAgICAgICAgICAgICAgcmV0dXJuIEZhbHNlCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBzZWxmLl9jb21wb25lbnRfb25fY2FudmFzID0gVHJ1ZQogICAgICAgICAgICAgICAgcmV0dXJuIFRydWUKICAgICAgICBhY3Rpb24gPSBTeXN0ZW0uQWN0aW9uKF9fY2hlY2tfaWZfY29tcG9uZW50X29uX2NhbnZhcykKICAgICAgICBSaGluby5SaGlub0FwcC5JbnZva2VPblVpVGhyZWFkKGFjdGlvbikKCiAgICBkZWYgX2NoZWNrX2lmX2NvbXBvbmVudF9lbmFibGVkKHNlbGYpOgogICAgICAgICIiIiBDaGVjayBpZiB0aGUgY29tcG9uZW50IGlzIGVuYWJsZWQgZnJvbSB0aHJlYWQuICIiIgogICAgICAgIGRlZiBfX2NoZWNrX2lmX2NvbXBvbmVudF9lbmFibGVkKCk6CiAgICAgICAgICAgIGlmIGdoZW52LkNvbXBvbmVudC5Mb2NrZWQ6CiAgICAgICAgICAgICAgICBzZWxmLl9jb21wb25lbnRfZW5hYmxlZCA9IEZhbHNlCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBzZWxmLl9jb21wb25lbnRfZW5hYmxlZCA9IFRydWUKICAgICAgICBhY3Rpb24gPSBTeXN0ZW0uQWN0aW9uKF9fY2hlY2tfaWZfY29tcG9uZW50X2VuYWJsZWQpCiAgICAgICAgUmhpbm8uUmhpbm9BcHAuSW52b2tlT25VaVRocmVhZChhY3Rpb24pCgogICAgZGVmIGV4cGlyZV9jb21wb25lbnRfc29sdXRpb24oc2VsZik6CiAgICAgICAgIiIiIEZpcmUgdGhlIHJlY2FsY3VsYXRpb24gb2YgdGhlIGNvbXBvbmVudCBzb2x1dGlvbiBmcm9tIHRocmVhZC4gIiIiCiAgICAgICAgZGVmIF9fZXhwaXJlX2NvbXBvbmVudF9zb2x1dGlvbigpOgogICAgICAgICAgICBnaGVudi5Db21wb25lbnQuUGFyYW1zLk91dHB1dFswXS5DbGVhckRhdGEoKSAgIyBjbGVhciB0aGUgb3V0cHV0CiAgICAgICAgICAgIGdoZW52LkNvbXBvbmVudC5FeHBpcmVTb2x1dGlvbihUcnVlKSAgIyBleHBpcmUgdGhlIGNvbXBvbmVudAogICAgICAgIGFjdGlvbiA9IFN5c3RlbS5BY3Rpb24oX19leHBpcmVfY29tcG9uZW50X3NvbHV0aW9uKQogICAgICAgIFJoaW5vLlJoaW5vQXBwLkludm9rZU9uVWlUaHJlYWQoYWN0aW9uKQoKICAgIGRlZiBjbGVhcl9jb21wb25lbnQoc2VsZik6CiAgICAgICAgIiIiIENsZWFyIHRoZSBjb21wb25lbnQgZnJvbSB0aHJlYWQuICIiIgogICAgICAgIGRlZiBfX2NsZWFyX2NvbXBvbmVudCgpOgogICAgICAgICAgICBnaGVudi5Db21wb25lbnQuQ2xlYXJEYXRhKCkKICAgICAgICBhY3Rpb24gPSBTeXN0ZW0uQWN0aW9uKF9fY2xlYXJfY29tcG9uZW50KQogICAgICAgIFJoaW5vLlJoaW5vQXBwLkludm9rZU9uVWlUaHJlYWQoYWN0aW9uKQoKICAgIGRlZiBhZGRfcnVudGltZV93YXJuaW5nKHNlbGYsIGV4Y2VwdGlvbiA6IHN0cik6CiAgICAgICAgIiIiIEFkZCBhIHdhcm5pbmcgdGFiIHRvIHRoZSBjb21wb25lbnQgZnJvbSBtYWluIHRocmVhZC4gIiIiCiAgICAgICAgYWN0aW9uID0gU3lzdGVtLkFjdGlvbigKICAgICAgICAgICAgbGFtYmRhOiBnaGVudi5Db21wb25lbnQuQWRkUnVudGltZU1lc3NhZ2UoUk1MLldhcm5pbmcsIGV4Y2VwdGlvbikKICAgICAgICApCiAgICAgICAgUmhpbm8uUmhpbm9BcHAuSW52b2tlT25VaVRocmVhZChhY3Rpb24pCgogICAgZGVmIGFkZF9ydW50aW1lX2Vycm9yKHNlbGYsIGV4Y2VwdGlvbiA6IHN0cik6CiAgICAgICAgIiIiIEFkZCBhbiBlcnJvciB0YWIgdG8gdGhlIGNvbXBvbmVudCBmcm9tIG1haW4gdGhyZWFkLiAiIiIKICAgICAgICBhY3Rpb24gPSBTeXN0ZW0uQWN0aW9uKAogICAgICAgICAgICBsYW1iZGE6IGdoZW52LkNvbXBvbmVudC5BZGRSdW50aW1lTWVzc2FnZShSTUwuRXJyb3IsIGV4Y2VwdGlvbikKICAgICAgICApCiAgICAgICAgUmhpbm8uUmhpbm9BcHAuSW52b2tlT25VaVRocmVhZChhY3Rpb24pCgogICAgZGVmIGFkZF9ydW50aW1lX3JlbWFyayhzZWxmLCBleGNlcHRpb24gOiBzdHIpOgogICAgICAgICIiIiBBZGQgYSBibGFuayB0YWIgdG8gdGhlIGNvbXBvbmVudCBmcm9tIG1haW4gdGhyZWFkLiAiIiIKICAgICAgICBhY3Rpb24gPSBTeXN0ZW0uQWN0aW9uKAogICAgICAgICAgICBsYW1iZGE6IGdoZW52LkNvbXBvbmVudC5BZGRSdW50aW1lTWVzc2FnZShSTUwuUmVtYXJrLCBleGNlcHRpb24pCiAgICAgICAgKQogICAgICAgIFJoaW5vLlJoaW5vQXBwLkludm9rZU9uVWlUaHJlYWQoYWN0aW9uKQoKICAgIEBwcm9wZXJ0eQogICAgZGVmIGNvbXBvbmVudF9lbmFibGVkKHNlbGYpOgogICAgICAgIHNlbGYuX2NoZWNrX2lmX2NvbXBvbmVudF9lbmFibGVkKCkKICAgICAgICByZXR1cm4gc2VsZi5fY29tcG9uZW50X2VuYWJsZWQKCiAgICBAcHJvcGVydHkKICAgIGRlZiBjb21wb25lbnRfb25fY2FudmFzKHNlbGYpOgogICAgICAgIHNlbGYuX2NoZWNrX2lmX2NvbXBvbmVudF9vbl9jYW52YXMoKQogICAgICAgIHJldHVybiBzZWxmLl9jb21wb25lbnRfb25fY2FudmFzCgpjbGFzcyBDbGllbnRUaHJlYWQoR0hUaHJlYWQpOgogICAgIiIiCiAgICBBIHRocmVhZCB0byBjb25uZWN0IHRvIHRoZSBWU0NvZGUgc2VydmVyLgogICAgIiIiCiAgICBkZWYgX19pbml0X18oc2VsZiwgdnNjb2RlX3NlcnZlcl9pcDogc3RyLCB2c2NvZGVfc2VydmVyX3BvcnQ6IGludCwgbmFtZTogc3RyLAogICAgICAgICAgICAgICAgIHF1ZXVlX21zZzogcXVldWUuUXVldWUgPSBOb25lLCBsb2NrX3F1ZXVlX21zZzogdGhyZWFkaW5nLkxvY2sgPSBOb25lLAogICAgICAgICAgICAgICAgIGV2ZW50X2ZpcmVfbXNnOiB0aHJlYWRpbmcuRXZlbnQgPSBOb25lKToKICAgICAgICBzdXBlcigpLl9faW5pdF9fKG5hbWU9bmFtZSkKICAgICAgICBzZWxmLnZzY29kZV9zZXJ2ZXJfaXAgPSB2c2NvZGVfc2VydmVyX2lwCiAgICAgICAgc2VsZi52c2NvZGVfc2VydmVyX3BvcnQgPSB2c2NvZGVfc2VydmVyX3BvcnQKICAgICAgICBzZWxmLmlzX2Nvbm5lY3RlZCA9IEZhbHNlCiAgICAgICAgc2VsZi5jb25uZWN0X3JlZnJlc2hfcmF0ZSA9IDEgICMgc2Vjb25kcwogICAgICAgIHNlbGYucXVldWVfbXNnID0gcXVldWVfbXNnCiAgICAgICAgc2VsZi5sb2NrX3F1ZXVlX21zZyA9IGxvY2tfcXVldWVfbXNnCiAgICAgICAgc2VsZi5ldmVudF9maXJlX21zZyA9IGV2ZW50X2ZpcmVfbXNnCiAgICAgICAgc2VsZi5jbGllbnRfc29ja2V0ID0gc29ja2V0LnNvY2tldChzb2NrZXQuQUZfSU5FVCwgc29ja2V0LlNPQ0tfU1RSRUFNKQoKICAgIGRlZiBydW4oc2VsZik6CiAgICAgICAgIiIiIFJ1biB0aGUgdGhyZWFkLiBTZW5kIHRoZSBtZXNzYWdlIHRvIHRoZSB2c2NvZGUgc2VydmVyLiIiIgogICAgICAgIHdoaWxlIHNlbGYuY29tcG9uZW50X29uX2NhbnZhcyBhbmQgc2VsZi5jb21wb25lbnRfZW5hYmxlZDoKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgaWYgbm90IHNlbGYuaXNfY29ubmVjdGVkOgogICAgICAgICAgICAgICAgICAgIHNlbGYuY29ubmVjdF90b192c2NvZGVfc2VydmVyKCkKICAgICAgICAgICAgICAgICAgICBzZWxmLmNsZWFyX2NvbXBvbmVudCgpCiAgICAgICAgICAgICAgICAgICAgc2VsZi5leHBpcmVfY29tcG9uZW50X3NvbHV0aW9uKCkKICAgICAgICAgICAgICAgICAgICBjb250aW51ZQoKICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRfZmlyZV9tc2cud2FpdCgpCiAgICAgICAgICAgICAgICBzZWxmLnNlbmRfbWVzc2FnZV9mcm9tX3F1ZXVlKCkKCiAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgICAgIHNlbGYuYWRkX3J1bnRpbWVfd2FybmluZyhmInNjcmlwdC1zeW5jOjpVbmtvd24gZXJyb3IgZnJvbSBydW46IHtzdHIoZSl9IikKICAgICAgICAgICAgICAgIHNlbGYuaXNfY29ubmVjdGVkID0gRmFsc2UKICAgICAgICAgICAgICAgIHNlbGYuY2xpZW50X3NvY2tldCA9IHNvY2tldC5zb2NrZXQoc29ja2V0LkFGX0lORVQsIHNvY2tldC5TT0NLX1NUUkVBTSkKCiAgICAgICAgc2VsZi5jbGllbnRfc29ja2V0LmNsb3NlKCkKCiAgICBkZWYgc2VuZF9tZXNzYWdlX2Zyb21fcXVldWUoc2VsZik6CiAgICAgICAgd2l0aCBzZWxmLmxvY2tfcXVldWVfbXNnOgogICAgICAgICAgICBpZiBzZWxmLnF1ZXVlX21zZyBhbmQgbm90IHNlbGYucXVldWVfbXNnLmVtcHR5KCk6CiAgICAgICAgICAgICAgICBtc2cgPSBzZWxmLnF1ZXVlX21zZy5nZXQoKQogICAgICAgICAgICAgICAgc2VsZi5xdWV1ZV9tc2cudGFza19kb25lKCkKICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRfZmlyZV9tc2cuc2V0KCkKICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRfZmlyZV9tc2cuY2xlYXIoKQogICAgICAgICAgICAgICAgc2VsZi5jbGllbnRfc29ja2V0LnNlbmQobXNnKQoKICAgIGRlZiBjb25uZWN0X3RvX3ZzY29kZV9zZXJ2ZXIoc2VsZik6CiAgICAgICAgIiIiIENvbm5lY3QgdG8gdGhlIFZTQ29kZSBzZXJ2ZXIuICIiIgogICAgICAgIHdoaWxlIHNlbGYuY29tcG9uZW50X29uX2NhbnZhcyBhbmQgbm90IHNlbGYuaXNfY29ubmVjdGVkOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBzZWxmLmNsaWVudF9zb2NrZXQuc2VuZChiIiIpCiAgICAgICAgICAgICAgICBzZWxmLmlzX2Nvbm5lY3RlZCA9IFRydWUKICAgICAgICAgICAgZXhjZXB0IHNvY2tldC5lcnJvcjoKICAgICAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgICAgICBzZWxmLmNsaWVudF9zb2NrZXQuY29ubmVjdCgoc2VsZi52c2NvZGVfc2VydmVyX2lwLCBzZWxmLnZzY29kZV9zZXJ2ZXJfcG9ydCkpCiAgICAgICAgICAgICAgICAgICAgc2VsZi5pc19jb25uZWN0ZWQgPSBUcnVlCiAgICAgICAgICAgICAgICBleGNlcHQgKENvbm5lY3Rpb25SZWZ1c2VkRXJyb3IsIENvbm5lY3Rpb25SZXNldEVycm9yLCBzb2NrZXQuZXJyb3IpIGFzIGU6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5oYW5kbGVfY29ubmVjdGlvbl9lcnJvcihlKQogICAgICAgICAgICBmaW5hbGx5OgogICAgICAgICAgICAgICAgdGltZS5zbGVlcChzZWxmLmNvbm5lY3RfcmVmcmVzaF9yYXRlKQoKICAgIGRlZiBoYW5kbGVfY29ubmVjdGlvbl9lcnJvcihzZWxmLCBlKToKICAgICAgICBlcnJvcl9tZXNzYWdlcyA9IHsKICAgICAgICAgICAgQ29ubmVjdGlvblJlZnVzZWRFcnJvcjogInNjcmlwdC1zeW5jOjpDb25uZWN0aW9uIHJlZnVzZWQgYnkgdGhlIHZzY29kZSIsCiAgICAgICAgICAgIENvbm5lY3Rpb25SZXNldEVycm9yOiAic2NyaXB0LXN5bmM6OkNvbm5lY3Rpb24gd2FzIGZvcmNpYmx5IGNsb3NlZCBieSB0aGUgdnNjb2RlIiwKICAgICAgICAgICAgc29ja2V0LmVycm9yOiBmInNjcmlwdC1zeW5jOjpFcnJvciBjb25uZWN0aW5nIHRvIHRoZSB2c2NvZGU6IHtzdHIoZSl9IgogICAgICAgIH0KICAgICAgICBzZWxmLmFkZF9ydW50aW1lX3dhcm5pbmcoZXJyb3JfbWVzc2FnZXNbdHlwZShlKV0pCiAgICAgICAgc2VsZi5pc19jb25uZWN0ZWQgPSBGYWxzZSBpZiB0eXBlKGUpICE9IHNvY2tldC5lcnJvciBvciBlLndpbmVycm9yICE9IDEwMDU2IGVsc2UgVHJ1ZQoKY2xhc3MgRmlsZUNoYW5nZWRUaHJlYWQoR0hUaHJlYWQpOgogICAgIiIiCiAgICAgICAgQSB0aHJlYWQgdG8gY2hlY2sgaWYgdGhlIGZpbGUgaGFzIGNoYW5nZWQgb24gZGlzay4KICAgICIiIgogICAgZGVmIF9faW5pdF9fKHNlbGYsCiAgICAgICAgICAgICAgICBwYXRoIDogc3RyLAogICAgICAgICAgICAgICAgbmFtZSA6IHN0cgogICAgICAgICAgICAgICAgKToKICAgICAgICBzdXBlcigpLl9faW5pdF9fKG5hbWU9bmFtZSkKICAgICAgICBzZWxmLnBhdGggPSBwYXRoCiAgICAgICAgc2VsZi5yZWZyZXNoX3JhdGUgPSAxMDAwICAjIG1pbGxpc2Vjb25kcwogICAgICAgIHNlbGYuX29uX2ZpbGVfY2hhbmdlZCA9IHRocmVhZGluZy5FdmVudCgpCgogICAgZGVmIHJ1bihzZWxmKToKICAgICAgICAiIiIKICAgICAgICAgICAgQ2hlY2sgaWYgdGhlIGZpbGUgaGFzIGNoYW5nZWQgb24gZGlzay4KICAgICAgICAiIiIKICAgICAgICBsYXN0X21vZGlmaWVkID0gb3MucGF0aC5nZXRtdGltZShzZWxmLnBhdGgpCiAgICAgICAgd2hpbGUgc2VsZi5jb21wb25lbnRfb25fY2FudmFzIGFuZCBub3Qgc2VsZi5fb25fZmlsZV9jaGFuZ2VkLmlzX3NldCgpOgogICAgICAgICAgICBTeXN0ZW0uVGhyZWFkaW5nLlRocmVhZC5TbGVlcChzZWxmLnJlZnJlc2hfcmF0ZSkKICAgICAgICAgICAgbGFzdF9tb2RpZmllZCA9IHNlbGYuaXNfZmlsZV9tb2RpZmllZChsYXN0X21vZGlmaWVkKQogICAgICAgIHNlbGYuX29uX2ZpbGVfY2hhbmdlZC5jbGVhcigpCiAgICAgICAgcmV0dXJuCgogICAgZGVmIHN0b3Aoc2VsZik6CiAgICAgICAgIiIiIFN0b3AgdGhlIHRocmVhZC4gIiIiCiAgICAgICAgc2VsZi5fb25fZmlsZV9jaGFuZ2VkLnNldCgpCgogICAgZGVmIGlzX2ZpbGVfbW9kaWZpZWQoc2VsZiwgbGFzdF9tb2RpZmllZCk6CiAgICAgICAgY3VycmVudF9tb2RpZmllZCA9IG9zLnBhdGguZ2V0bXRpbWUoc2VsZi5wYXRoKQogICAgICAgIGlmIGN1cnJlbnRfbW9kaWZpZWQgIT0gbGFzdF9tb2RpZmllZDoKICAgICAgICAgICAgc2VsZi5leHBpcmVfY29tcG9uZW50X3NvbHV0aW9uKCkKICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRfbW9kaWZpZWQKICAgICAgICByZXR1cm4gbGFzdF9tb2RpZmllZAoKCmNsYXNzIFNjcmlwdFN5bmNDUHkoY29tcG9uZW50KToKICAgIGRlZiBfX2luaXRfXyhzZWxmKToKICAgICAgICBzdXBlcihTY3JpcHRTeW5jQ1B5LCBzZWxmKS5fX2luaXRfXygpCiAgICAgICAgc2VsZi5fdmFyX291dHB1dCA9IFtdCgogICAgICAgIHNlbGYuaXNfc3VjY2VzcyA9IEZhbHNlCgogICAgICAgIHNlbGYuY2xpZW50X3RocmVhZF9uYW1lIDogc3RyID0gZiJzY3JpcHQtc3luYy1jbGllbnQtdGhyZWFkOjp7Z2hlbnYuQ29tcG9uZW50Lkluc3RhbmNlR3VpZH0iCiAgICAgICAgc2VsZi52c2NvZGVfc2VydmVyX2lwID0gIjEyNy4wLjAuMSIKICAgICAgICBzZWxmLnZzY29kZV9zZXJ2ZXJfcG9ydCA9IDU4MjYwCiAgICAgICAgc2VsZi5zdGRvdXQgPSBOb25lCiAgICAgICAgc2VsZi5xdWV1ZV9tc2cgPSBxdWV1ZS5RdWV1ZSgpCiAgICAgICAgc2VsZi5xdWV1ZV9tc2dfbG9jayA9IHRocmVhZGluZy5Mb2NrKCkKICAgICAgICBzZWxmLmV2ZW50X2ZpcmVfbXNnID0gdGhyZWFkaW5nLkV2ZW50KCkKCiAgICAgICAgc2VsZi5maWxlY2hhbmdlZF90aHJlYWRfbmFtZSA6IHN0ciA9IGYic2NyaXB0LXN5bmMtZmlsZUNoYW5nZWQtdGhyZWFkOjp7Z2hlbnYuQ29tcG9uZW50Lkluc3RhbmNlR3VpZH0iCiAgICAgICAgc2VsZi5fX3BhdGhfbmFtZV90YWJsZV92YWx1ZSA9ICJzY3JpcHQtc3luYzo6IiArICJwYXRoOjoiICsgc3RyKGdoZW52LkNvbXBvbmVudC5JbnN0YW5jZUd1aWQpCiAgICAgICAgaWYgc2VsZi5wYXRoIGlzIE5vbmU6CiAgICAgICAgICAgIGdoZW52LkNvbXBvbmVudC5NZXNzYWdlID0gInNlbGVjdC1zY3JpcHQiCgogICAgZGVmIFJlbW92ZWRGcm9tRG9jdW1lbnQoc2VsZiwgZG9jKToKICAgICAgICAiIiIgUmVtb3ZlIHRoZSBjb21wb25lbnQgZnJvbSB0aGUgZG9jdW1lbnQuICIiIgogICAgICAgIGlmIHNlbGYuY2xpZW50X3RocmVhZF9uYW1lIGluIFt0Lm5hbWUgZm9yIHQgaW4gdGhyZWFkaW5nLmVudW1lcmF0ZSgpXToKICAgICAgICAgICAgY2xpZW50X3RocmVhZCA9IFt0IGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKSBpZiB0Lm5hbWUgPT0gc2VsZi5jbGllbnRfdGhyZWFkX25hbWVdWzBdCiAgICAgICAgICAgIGNsaWVudF90aHJlYWQuam9pbigpCiAgICAgICAgaWYgc2VsZi5maWxlY2hhbmdlZF90aHJlYWRfbmFtZSBpbiBbdC5uYW1lIGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKV06CiAgICAgICAgICAgIGZpbGVjaGFuZ2VkX3RocmVhZCA9IFt0IGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKSBpZiB0Lm5hbWUgPT0gc2VsZi5maWxlY2hhbmdlZF90aHJlYWRfbmFtZV1bMF0KICAgICAgICAgICAgZmlsZWNoYW5nZWRfdGhyZWFkLmpvaW4oKQogICAgICAgIGlmIHNlbGYucXVldWVfbXNnIGlzIG5vdCBOb25lOgogICAgICAgICAgICBzZWxmLnF1ZXVlX21zZy5qb2luKCkKICAgICAgICBpZiBzZWxmLnF1ZXVlX21zZ19sb2NrIGlzIG5vdCBOb25lOgogICAgICAgICAgICBzZWxmLnF1ZXVlX21zZ19sb2NrLnJlbGVhc2UoKQogICAgICAgIGlmIHNlbGYuZXZlbnRfZmlyZV9tc2cgaXMgbm90IE5vbmU6CiAgICAgICAgICAgIHNlbGYuZXZlbnRfZmlyZV9tc2cuY2xlYXIoKQoKICAgICAgICAjIGNsZWFyIHRoZSBwYXRoIGZyb20gdGhlIHRhYmxlIHZpZXcKICAgICAgICBkZWwgc2VsZi5wYXRoCgogICAgZGVmIGluaXRfc2NyaXB0X3BhdGgoc2VsZiwgYnRuIDogYm9vbCA9IEZhbHNlKToKICAgICAgICAiIiIKICAgICAgICAgICAgQ2hlY2sgaWYgdGhlIGJ1dHRvbiBpcyBwcmVzc2VkIGFuZCBsb2FkL2NoYW5nZSBwYXRoIHNjcmlwdC4KICAgICAgICAgICAgCiAgICAgICAgICAgIDpwYXJhbSBidG46IEEgYm9vbGVhbiBvZiB0aGUgYnV0dG9uCiAgICAgICAgIiIiCiAgICAgICAgIyBjaGVjayBpZiBidXR0b24gaXMgcHJlc3NlZAogICAgICAgIGlmIGJ0biBpcyBUcnVlOgogICAgICAgICAgICBkaWFsb2cgPSBTeXN0ZW0uV2luZG93cy5Gb3Jtcy5PcGVuRmlsZURpYWxvZygpCiAgICAgICAgICAgIGRpYWxvZy5GaWx0ZXIgPSAiUHl0aG9uIGZpbGVzICgqLnB5KXwqLnB5IgogICAgICAgICAgICBkaWFsb2cuVGl0bGUgPSAiU2VsZWN0IGEgUHl0aG9uIGZpbGUiCiAgICAgICAgICAgIGRpYWxvZy5Jbml0aWFsRGlyZWN0b3J5ID0gb3MucGF0aC5kaXJuYW1lKCIiKQogICAgICAgICAgICBkaWFsb2cuRmlsZU5hbWUgPSAiIgogICAgICAgICAgICBkaWFsb2cuTXVsdGlzZWxlY3QgPSBGYWxzZQogICAgICAgICAgICBkaWFsb2cuQ2hlY2tGaWxlRXhpc3RzID0gVHJ1ZQogICAgICAgICAgICBkaWFsb2cuQ2hlY2tQYXRoRXhpc3RzID0gVHJ1ZQogICAgICAgICAgICBkaWFsb2cuUmVzdG9yZURpcmVjdG9yeSA9IFRydWUKICAgICAgICAgICAgaWYgZGlhbG9nLlNob3dEaWFsb2coKSA9PSBTeXN0ZW0uV2luZG93cy5Gb3Jtcy5EaWFsb2dSZXN1bHQuT0s6CiAgICAgICAgICAgICAgICBzZWxmLnBhdGggPSBkaWFsb2cuRmlsZU5hbWUKCiAgICAgICAgIyBkZWZhdWx0IGluaXQgc3RhdXRzCiAgICAgICAgaWYgc2VsZi5wYXRoIGlzIE5vbmU6CiAgICAgICAgICAgIHJhaXNlIEV4Y2VwdGlvbigic2NyaXB0LXN5bmM6OkZpbGUgbm90IHNlbGVjdGVkIikKCiAgICAgICAgIyBmaSBmaWxlIGlzIGluIHRhYmxlIHZpZXcgYmVmb3JlCiAgICAgICAgaWYgbm90IG9zLnBhdGguZXhpc3RzKHNlbGYucGF0aCk6CiAgICAgICAgICAgIHJhaXNlIEV4Y2VwdGlvbigic2NyaXB0LXN5bmM6OkZpbGUgZG9lcyBub3QgZXhpc3QiKQogICAgCiAgICBkZWYgcmVsb2FkX2FsbF9tb2R1bGVzKHNlbGYsIGRpcmVjdG9yeSk6CiAgICAgICAgZm9yIGZpbGVuYW1lIGluIG9zLmxpc3RkaXIoZGlyZWN0b3J5KToKICAgICAgICAgICAgaWYgZmlsZW5hbWUuZW5kc3dpdGgoJy5weScpIGFuZCBmaWxlbmFtZSAhPSAnX19pbml0X18ucHknOgogICAgICAgICAgICAgICAgbW9kdWxlX25hbWUgPSBmaWxlbmFtZVs6LTNdICAjIHJlbW92ZSAnLnB5JyBmcm9tIGZpbGVuYW1lCiAgICAgICAgICAgICAgICBpZiBtb2R1bGVfbmFtZSBpbiBzeXMubW9kdWxlczoKICAgICAgICAgICAgICAgICAgICBpbXBvcnRsaWIucmVsb2FkKHN5cy5tb2R1bGVzW21vZHVsZV9uYW1lXSkKCiAgICBkZWYgZ2V0X3JlbG9hZGFibGVfbW9kdWxlcyhzZWxmKToKICAgICAgICAiIiIKICAgICAgICAgICAgR2V0IGFsbCB0aGUgcmVsb2FkYWJsZSBtb2R1bGVzIGZyb20gdGhlIHN5cy5tb2R1bGVzLiBJdAogICAgICAgICAgICBtYWtlIHN1cmUgdG8gY2hlY2sgdGhlIG1vZHVsZSBzcGVjIGFuZCBsb2FkZXIgdG8gb25seSByZWxvYWQgbW9kdWxlcyAKICAgICAgICAgICAgdGhhdCBhcmUgYWN0dWFsbHkgbG9hZGVkIGZyb20gYSBmaWxlIG9yIGRpcmVjdG9yeQoKICAgICAgICAgICAgOnJldHVybjogVGhlIGxpc3Qgb2YgcmVsb2FkYWJsZSBtb2R1bGVzLgogICAgICAgICIiIgogICAgICAgIEJVSUxUSU5fT1JJR0lOUyA9IFsnYnVpbHQtaW4nLCAnZnJvemVuJ10KICAgICAgICByZWxvYWRhYmxlcyA9IFtdCiAgICAgICAgZm9yIG0gaW4gc3lzLm1vZHVsZXMudmFsdWVzKCk6CiAgICAgICAgICAgIGlmIGluc3BlY3QuaXNtb2R1bGUobSk6CiAgICAgICAgICAgICAgICBzcGVjID0gZ2V0YXR0cihtLCAiX19zcGVjX18iLCBOb25lKQogICAgICAgICAgICAgICAgaWYgc3BlYzoKICAgICAgICAgICAgICAgICAgICBpZiBzcGVjLm9yaWdpbiBpbiBCVUlMVElOX09SSUdJTlMgXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3IgaXNpbnN0YW5jZShzcGVjLmxvYWRlciwgaW1wb3J0bGliLm1hY2hpbmVyeS5Tb3VyY2VsZXNzRmlsZUxvYWRlcik6CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgICAgICByZWxvYWRhYmxlcy5hcHBlbmQobSkKCiAgICAgICAgcmV0dXJuIHJlbG9hZGFibGVzCgogICAgZGVmIHNhZmVfZXhlYyhzZWxmLCBwYXRoLCBnbG9iYWxzLCBsb2NhbHMsIHBhY2thZ2VzXzJfcmVsb2FkKToKICAgICAgICAiIiIKICAgICAgICAgICAgRXhlY3V0ZSBQeXRob24zIGNvZGUgc2FmZWx5LiBJdCByZWRpcmVjdHMgdGhlIG91dHB1dCBvZiB0aGUgY29kZQogICAgICAgICAgICB0byBhIHN0cmluZyBidWZmZXIgJ3N0ZG91dCcgdG8gb3V0cHV0IHRvIHRoZSBHSCBjb21wb25lbnQgcGFyYW0uCiAgICAgICAgICAgIEl0IGlzIHNlbmQgdG8gdGhlIHZzY29kZSBzZXJ2ZXIuCiAgICAgICAgICAgIAogICAgICAgICAgICA6cGFyYW0gcGF0aDogVGhlIHBhdGggb2YgdGhlIGZpbGUgdG8gZXhlY3V0ZS4KICAgICAgICAgICAgOnBhcmFtIGdsb2JhbHM6IFRoZSBnbG9iYWxzIGRpY3Rpb25hcnkuCiAgICAgICAgICAgIDpwYXJhbSBsb2NhbHM6IFRoZSBsb2NhbHMgZGljdGlvbmFyeS4KICAgICAgICAgICAgOnBhcmFtIHBhY2thZ2VzXzJfcmVsb2FkOiBUaGUgbGlzdCBvZiBwYWNrYWdlcyB0byByZWxvYWQsIHRoaXMgaXMgdXNlZCBmb3IgY3VzdG9tIHBhY2thZ2VzIGRldmVsb3BlbWVudC4KICAgICAgICAgICAgaW5zdGFsbGVkIG9uIHRoZSBzeXN0ZW0gdmlhIGFuIGVkaXRhYmxlIHBpcCBpbnN0YWxsYXRpb24gZm9yIGV4YW1wbGUuCiAgICAgICAgIiIiCiAgICAgICAgdHJ5OgogICAgICAgICAgICB3aXRoIG9wZW4ocGF0aCwgJ3InKSBhcyBmOgogICAgICAgICAgICAgICAgIyByZWxvYWQgdGhlIHNwZWNpZnllZCBwYWNrYWdlcwogICAgICAgICAgICAgICAgcGFja2FnZXNfMl9yZWxvYWQgPSBzZWxmLmdldF9yZWxvYWRhYmxlX21vZHVsZXMoKQogICAgICAgICAgICAgICAgIyBpZiBwYWNrYWdlc18yX3JlbG9hZCBpcyBub3QgTm9uZToKICAgICAgICAgICAgICAgICMgICAgIGlmIHBhY2thZ2VzXzJfcmVsb2FkLl9fbGVuX18oKSAhPSAwOgogICAgICAgICAgICAgICAgIyAgICAgICAgIGZvciBwYWNrYWdlIGluIHBhY2thZ2VzXzJfcmVsb2FkOgogICAgICAgICAgICAgICAgIyAgICAgICAgICAgICBmb3Iga2V5IGluIGxpc3Qoc3lzLm1vZHVsZXMua2V5cygpKToKICAgICAgICAgICAgICAgICMgICAgICAgICAgICAgICAgIGlmIHBhY2thZ2UgaW4ga2V5OgogICAgICAgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgIGltcG9ydGxpYi5yZWxvYWQoc3lzLm1vZHVsZXNba2V5XSkKCiAgICAgICAgICAgICAgICAjIGFkZCB0aGUgcGF0aCBhbmQgc3ViIGRpcmVjdG9yaWVzIHRvICB0aGUgc3lzIHBhdGgKICAgICAgICAgICAgICAgIHBhdGhfZGlyID0gb3MucGF0aC5kaXJuYW1lKHBhdGgpCiAgICAgICAgICAgICAgICBzdWJfZGlycyA9IFtdCiAgICAgICAgICAgICAgICBmb3Igcm9vdCwgZGlycywgZmlsZXMgaW4gb3Mud2FsayhwYXRoX2Rpcik6CiAgICAgICAgICAgICAgICAgICAgZm9yIGQgaW4gZGlyczoKICAgICAgICAgICAgICAgICAgICAgICAgc3ViX2RpcnMuYXBwZW5kKG9zLnBhdGguam9pbihyb290LCBkKSkKICAgICAgICAgICAgICAgIHN5cy5wYXRoLmV4dGVuZChbcGF0aF9kaXJdICsgc3ViX2RpcnMpCgogICAgICAgICAgICAgICAgIyByZWxvYWQgYWxsIHRoZSBtb2R1bGVzIGFsc28gb2YgdGhlIHN1YiBkaXJlY3RvcmllcwogICAgICAgICAgICAgICAgZm9yIHJvb3QsIGRpcnMsIGZpbGVzIGluIG9zLndhbGsocGF0aF9kaXIpOgogICAgICAgICAgICAgICAgICAgIGZvciBkIGluIGRpcnM6CiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucmVsb2FkX2FsbF9tb2R1bGVzKG9zLnBhdGguam9pbihyb290LCBkKSkKICAgICAgICAgICAgICAgIHNlbGYucmVsb2FkX2FsbF9tb2R1bGVzKHBhdGhfZGlyKQoKICAgICAgICAgICAgICAgICMgcmVmcmVzaCB0aGUgcHl0aG9uIGludGVycHJldGVyCiAgICAgICAgICAgICAgICBpbXBvcnRsaWIuaW52YWxpZGF0ZV9jYWNoZXMoKQoKICAgICAgICAgICAgICAgICMgcGFyc2UgdGhlIGNvZGUKICAgICAgICAgICAgICAgIGNvZGUgPSBjb21waWxlKGYucmVhZCgpLCBwYXRoLCAnZXhlYycpCiAgICAgICAgICAgICAgICBvdXRwdXQgPSBpby5TdHJpbmdJTygpCgogICAgICAgICAgICAgICAgIyBlbXB0eSB0aGUgcXVldWUgYW5kIGV2ZW50CiAgICAgICAgICAgICAgICB3aXRoIHNlbGYucXVldWVfbXNnX2xvY2s6CiAgICAgICAgICAgICAgICAgICAgd2hpbGUgbm90IHNlbGYucXVldWVfbXNnLmVtcHR5KCk6CiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucXVldWVfbXNnLmdldCgpCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucXVldWVfbXNnLnRhc2tfZG9uZSgpCiAgICAgICAgICAgICAgICBzZWxmLmV2ZW50X2ZpcmVfbXNnLmNsZWFyKCkKCiAgICAgICAgICAgICAgICAjIGV4ZWN1dGUgdGhlIGNvZGUKICAgICAgICAgICAgICAgIHdpdGggY29udGV4dGxpYi5yZWRpcmVjdF9zdGRvdXQob3V0cHV0KToKICAgICAgICAgICAgICAgICAgICBleGVjKGNvZGUsIGdsb2JhbHMsIGxvY2FscykKICAgICAgICAgICAgICAgIGxvY2Fsc1sic3Rkb3V0Il0gPSBvdXRwdXQuZ2V0dmFsdWUoKQoKICAgICAgICAgICAgICAgICMgc2VuZCB0aGUgbXNnIHRvIHRoZSB2c2NvZGUgc2VydmVyCiAgICAgICAgICAgICAgICBtc2dfanNvbiA9IGpzb24uZHVtcHMoeyJzY3JpcHRfcGF0aCI6IHBhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJndWlkIjogc3RyKGdoZW52LkNvbXBvbmVudC5JbnN0YW5jZUd1aWQpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibXNnIjogb3V0cHV0LmdldHZhbHVlKCl9KQogICAgICAgICAgICAgICAgbXNnX2pzb24gPSBtc2dfanNvbi5lbmNvZGUoJ3V0Zi04JykKICAgICAgICAgICAgICAgIHNlbGYucXVldWVfbXNnLnB1dChtc2dfanNvbikKICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRfZmlyZV9tc2cuc2V0KCkKCiAgICAgICAgICAgICAgICAjIHBhc3MgdGhlIHNjcmlwdCB2YXJpYWJsZXMgdG8gdGhlIEdIIGNvbXBvbmVudCBvdXRwdXRzCiAgICAgICAgICAgICAgICBvdXRwYXJhbSA9IGdoZW52LkNvbXBvbmVudC5QYXJhbXMuT3V0cHV0CiAgICAgICAgICAgICAgICBvdXRwYXJhbV9uYW1lcyA9IFtwLk5pY2tOYW1lIGZvciBwIGluIG91dHBhcmFtXQogICAgICAgICAgICAgICAgZm9yIG91dHAgaW4gb3V0cGFyYW1fbmFtZXM6CiAgICAgICAgICAgICAgICAgICAgaWYgb3V0cCBpbiBsb2NhbHMua2V5cygpOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl92YXJfb3V0cHV0LmFwcGVuZChsb2NhbHNbb3V0cF0pCiAgICAgICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fdmFyX291dHB1dC5hcHBlbmQoTm9uZSkKCiAgICAgICAgICAgICAgICBzeXMuc3Rkb3V0ID0gc3lzLl9fc3Rkb3V0X18KICAgICAgICAgICAgcmV0dXJuIGxvY2FscwoKICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CgogICAgICAgICAgICAjIHNlbmQgdGhlIGVycm9yIG1lc3NhZ2UgdG8gdGhlIHZzY29kZSBzZXJ2ZXIKICAgICAgICAgICAgZXJyX2pzb24gPSBqc29uLmR1bXBzKHsic2NyaXB0X3BhdGgiOiBwYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZ3VpZCI6IHN0cihnaGVudi5Db21wb25lbnQuSW5zdGFuY2VHdWlkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1zZyI6ICJlcnI6IiArIHN0cihlKX0pCiAgICAgICAgICAgIGVycl9qc29uID0gZXJyX2pzb24uZW5jb2RlKCd1dGYtOCcpCiAgICAgICAgICAgIHNlbGYucXVldWVfbXNnLnB1dChlcnJfanNvbikKICAgICAgICAgICAgc2VsZi5ldmVudF9maXJlX21zZy5zZXQoKQogICAgICAgICAgICAKICAgICAgICAgICAgc3lzLnN0ZG91dCA9IHN5cy5fX3N0ZG91dF9fCgogICAgICAgICAgICBlcnJfbXNnID0gZiJzY3JpcHQtc3luYzo6RXJyb3IgaW4gdGhlIGNvZGU6IHtzdHIoZSl9IgogICAgICAgICAgICByYWlzZSBFeGNlcHRpb24oZXJyX21zZykKCiAgICBkZWYgUnVuU2NyaXB0KHNlbGYsCiAgICAgICAgICAgIGJ0bjogYm9vbCwKICAgICAgICAgICAgcGFja2FnZXNfMl9yZWxvYWQ6IFN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLklMaXN0W29iamVjdF0sCiAgICAgICAgICAgIGlfZXhwb3J0X2RpciwKICAgICAgICAgICAgaV9icmVwczogU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuSUxpc3RbUmhpbm8uR2VvbWV0cnkuQnJlcF0sCiAgICAgICAgICAgIGlfYXNzZW1ibHlfbmFtZSwKICAgICAgICAgICAgaV9kdW1wOiBib29sKToKICAgICAgICAiIiIgVGhpcyBtZXRob2QgaXMgY2FsbGVkIHdoZW5ldmVyIHRoZSBjb21wb25lbnQgaGFzIHRvIGJlIHJlY2FsY3VsYXRlZCBpdCdzIHRoZSBzb2x2ZSBtYWluIGluc3RhbmNlLiAiIiIKICAgICAgICBzZWxmLmlzX3N1Y2Nlc3MgPSBGYWxzZQoKICAgICAgICAjIHNldCB0aGUgcGF0aCBpZiBidXR0b24gaXMgcHJlc3NlZAogICAgICAgIHNlbGYuaW5pdF9zY3JpcHRfcGF0aChidG4pCgogICAgICAgICMgZmlsZSBjaGFuZ2UgbGlzdGVuZXIgdGhyZWFkCiAgICAgICAgaWYgc2VsZi5maWxlY2hhbmdlZF90aHJlYWRfbmFtZSBub3QgaW4gW3QubmFtZSBmb3IgdCBpbiB0aHJlYWRpbmcuZW51bWVyYXRlKCldOgogICAgICAgICAgICBGaWxlQ2hhbmdlZFRocmVhZChzZWxmLnBhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuZmlsZWNoYW5nZWRfdGhyZWFkX25hbWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKS5zdGFydCgpCgogICAgICAgICMgc2V0IHVwIHRoZSB0Y3AgY2xpZW50IHRvIGNvbm5lY3QgdG8gdGhlIHZzY29kZSBzZXJ2ZXIKICAgICAgICBfID0gW3ByaW50KHQubmFtZSkgZm9yIHQgaW4gdGhyZWFkaW5nLmVudW1lcmF0ZSgpXQogICAgICAgIGlmIHNlbGYuY2xpZW50X3RocmVhZF9uYW1lIG5vdCBpbiBbdC5uYW1lIGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKV06CiAgICAgICAgICAgIENsaWVudFRocmVhZChzZWxmLnZzY29kZV9zZXJ2ZXJfaXAsCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYudnNjb2RlX3NlcnZlcl9wb3J0LAogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmNsaWVudF90aHJlYWRfbmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5xdWV1ZV9tc2csCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucXVldWVfbXNnX2xvY2ssCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRfZmlyZV9tc2cKICAgICAgICAgICAgICAgICAgICAgICAgKS5zdGFydCgpCgogICAgICAgICMgYWRkIHRvIHRoZSBnbG9iYWxzIGFsbCB0aGUgaW5wdXQgcGFyYW1ldGVycyBvZiB0aGUgY29tcG9uZW50ICh0aGUgbG9jYWxzKQogICAgICAgIGdsb2JhbHMoKS51cGRhdGUobG9jYWxzKCkpCgogICAgICAgIHJlcyA9IHNlbGYuc2FmZV9leGVjKHNlbGYucGF0aCwgTm9uZSwgZ2xvYmFscygpLCBwYWNrYWdlc18yX3JlbG9hZCkKICAgICAgICBzZWxmLmlzX3N1Y2Nlc3MgPSBUcnVlCiAgICAgICAgcmV0dXJuCgogICAgZGVmIEFmdGVyUnVuU2NyaXB0KHNlbGYpOgogICAgICAgICIiIgogICAgICAgICAgICBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgYXMgc29vbiBhcyB0aGUgY29tcG9uZW50IGhhcyBmaW5pc2hlZAogICAgICAgICAgICBpdHMgY2FsY3VsYXRpb24uIEl0IGlzIHVzZWQgdG8gbG9hZCB0aGUgR0hDb21wb25lbnQgb3V0cHV0cwogICAgICAgICAgICB3aXRoIHRoZSB2YWx1ZXMgY3JlYXRlZCBpbiB0aGUgc2NyaXB0LgogICAgICAgICIiIgogICAgICAgIGlmIG5vdCBzZWxmLmlzX3N1Y2Nlc3M6CiAgICAgICAgICAgIHJldHVybgogICAgICAgIG91dHBhcmFtID0gW3AgZm9yIHAgaW4gZ2hlbnYuQ29tcG9uZW50LlBhcmFtcy5PdXRwdXRdCiAgICAgICAgb3V0cGFyYW1fbmFtZXMgPSBbcC5OaWNrTmFtZSBmb3IgcCBpbiBvdXRwYXJhbV0KICAgICAgICAKICAgICAgICAjIFRPRE86IGFkZCB0aGUgY29udmVyc2lvbiB0byBkYXRhdHJlZSBmb3IgbmVzdGVkIGxpc3RzIGFuZCB0dXBsZXMKICAgICAgICBmb3IgaWR4LCBvdXRwIGluIGVudW1lcmF0ZShvdXRwYXJhbSk6CiAgICAgICAgICAgICMgZGV0ZWN0IGlmIHRoZSBvdXRwdXQgaXMgYSBsaXN0CiAgICAgICAgICAgIGlmIHR5cGUoc2VsZi5fdmFyX291dHB1dFtpZHhdKSA9PSBsaXN0IG9yIHR5cGUoc2VsZi5fdmFyX291dHB1dFtpZHhdKSA9PSB0dXBsZToKICAgICAgICAgICAgICAgIGdoZW52LkNvbXBvbmVudC5QYXJhbXMuT3V0cHV0W2lkeF0uVm9sYXRpbGVEYXRhLkNsZWFyKCkKICAgICAgICAgICAgICAgIGdoZW52LkNvbXBvbmVudC5QYXJhbXMuT3V0cHV0W2lkeF0uQWRkVm9sYXRpbGVEYXRhTGlzdChnaC5LZXJuZWwuRGF0YS5HSF9QYXRoKDApLCBzZWxmLl92YXJfb3V0cHV0W2lkeF0pCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBnaGVudi5Db21wb25lbnQuUGFyYW1zLk91dHB1dFtpZHhdLlZvbGF0aWxlRGF0YS5DbGVhcigpCiAgICAgICAgICAgICAgICBnaGVudi5Db21wb25lbnQuUGFyYW1zLk91dHB1dFtpZHhdLkFkZFZvbGF0aWxlRGF0YShnaC5LZXJuZWwuRGF0YS5HSF9QYXRoKDApLCAwLCBzZWxmLl92YXJfb3V0cHV0W2lkeF0pCiAgICAgICAgc2VsZi5fdmFyX291dHB1dC5jbGVhcigpCgogICAgQHByb3BlcnR5CiAgICBkZWYgcGF0aChzZWxmKToKICAgICAgICAiIiIgR2V0IHRoZSBwYXRoIG9mIHRoZSBmaWxlIGZyb20gdGhlIHRhYmxlIHZpZXcgdG8gYmUgc3RpY2tpbmcgYmV0d2VlbiB0aGUgc2Vzc2lvbnMuICIiIgogICAgICAgIHRhYmxlX3ZhbHVlID0gZ2hlbnYuQ29tcG9uZW50Lk9uUGluZ0RvY3VtZW50KCkuVmFsdWVUYWJsZS5HZXRWYWx1ZSgKICAgICAgICAgICAgc2VsZi5fX3BhdGhfbmFtZV90YWJsZV92YWx1ZSwgIm5vdF9mb3VuZCIKICAgICAgICApCiAgICAgICAgaWYgdGFibGVfdmFsdWUgIT0gIm5vdF9mb3VuZCI6CiAgICAgICAgICAgIHJldHVybiB0YWJsZV92YWx1ZQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHJldHVybiBOb25lCgogICAgQHBhdGguc2V0dGVyCiAgICBkZWYgcGF0aChzZWxmLCBwYXRoIDogc3RyKToKICAgICAgICAiIiIgU2V0IHRoZSBwYXRoIG9mIHRoZSBmaWxlIHRvIHRoZSB0YWJsZSB2aWV3IHRvIGJlIHN0aWNraW5nIGJldHdlZW4gdGhlIHNlc3Npb25zLiAiIiIKICAgICAgICBnaGVudi5Db21wb25lbnQuT25QaW5nRG9jdW1lbnQoKS5WYWx1ZVRhYmxlLlNldFZhbHVlKHNlbGYuX19wYXRoX25hbWVfdGFibGVfdmFsdWUsIHBhdGgpCgogICAgICAgIHNjcmlwdF9uYW1lID0gb3MucGF0aC5iYXNlbmFtZShwYXRoKQogICAgICAgIGdoZW52LkNvbXBvbmVudC5NZXNzYWdlID0gZiJ7c2NyaXB0X25hbWV9IgoKICAgICAgICBpZiBzZWxmLmZpbGVjaGFuZ2VkX3RocmVhZF9uYW1lIGluIFt0Lm5hbWUgZm9yIHQgaW4gdGhyZWFkaW5nLmVudW1lcmF0ZSgpXToKICAgICAgICAgICAgXyA9IFt0IGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKSBpZiB0Lm5hbWUgPT0gc2VsZi5maWxlY2hhbmdlZF90aHJlYWRfbmFtZV1bMF0uc3RvcCgpCgogICAgQHBhdGguZGVsZXRlcgogICAgZGVmIHBhdGgoc2VsZik6CiAgICAgICAgIiIiIERlbGV0ZSB0aGUgcGF0aCBvZiB0aGUgZmlsZSBmcm9tIHRoZSB0YWJsZSB2aWV3IGlmIHRoZSBvYmplY3QgaXMgZXJhc2VkLiAiIiIKICAgICAgICBnaGVudi5Db21wb25lbnQuT25QaW5nRG9jdW1lbnQoKS5WYWx1ZVRhYmxlLkRlbGV0ZVZhbHVlKHNlbGYuX19wYXRoX25hbWVfdGFibGVfdmFsdWUpCg== + S + + + + + *.*.python + 3.* + + + + + + + + + + + c9b2d725-6f87-4b07-af90-bd9aefef68eb + 066d0a87-236f-4eae-a0f4-9e42f5327962 + script-sync cpython + + + + + + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAABhmlDQ1BJQ0MgcHJvZmlsZQAAKM+VkTtIw1AUhv+mSkUqDhZ84JChCoIFURFHiWIRLJS2QqsOJjd9QZOGJMXFUXAtOPhYrDq4OOvq4CoIgg8QZwcnRRcp8dyk0CJU8MDlfvz3/j/nngsItRLTrI4JQNNtMxGVxHRmVQy8wodB9EPAmMwsI5ZcTKFtfd3Tbaq7CM/C/6pHzVoM8InEc8wwbeIN4plN2+C8TxxiBVklPiceN6lB4keuKx6/cc67LPDMkJlKzBOHiMV8CystzAqmRjxNHFY1nfKFtMcq5y3OWqnCGn3yFwaz+kqS67SGEcUSYohDhIIKiijBRoR2nRQLCTqX2viHXH+cXAq5imDkWEAZGmTXD/4Hv2dr5aYmvaSgBHS+OM7HCBDYBepVx/k+dpz6CeB/Bq70pr9cA2Y/Sa82tfAR0LsNXFw3NWUPuNwBBp4M2ZRdyU9LyOWA9zP6pgzQdwt0r3lza5zj9AFI0ayWb4CDQ2A0T9nrbd7d1Tq3P++484P0A3o2cqrMnZbPAAAACXBIWXMAAAsQAAALEAGtI711AAAAB3RJTUUH6AEZFwkM569AfQAABNpJREFUSEu9kntMU3cYhguoOOZ1ujmFXqQtBcEpIwoTxOGQolLwUp24OFS0sEqh0oIV0CIg1FLKsbTlNooFKhRF8TajziW6zYFxcckW9bhlm9uiLk6nAyuWy7tTc0iI4w9l2Z7k++/7nveX9xzGfw+LWMhgV4hd48Y2iN1ZBvEoFiH2ZOrFXkydeJzPvsn05ghhmxIZnCq4xo1TCXe2GaPZJniyKvAqi8AEps5Eb/4LOJVfDQZ4PAswYizLgHHMckxi6vqmeJfMpjdHCNscQgUMDAaMoQJeoQLGUwGTfXR43bvkM3pz5LhxzHXuVMAoqp4x7Ap4sfZT9ejxmk8ppnlrEDE142bCxA3k2vHryKSZYnJrcPxS+vTFcGMR09w55keuAFf/Xs/612OKjxZvepdAMF2NFROT8IHv+5CEroZskeiaJC7Cgz5/MTzYRsVg/64PPJFZhqlUwHTvYrBmFGBZsAybw9ZCGr0SyhXLoVobk0Gfvhju/CJPD2GnY7SwE57CDngJL2FCzBeYsuQC/OM/Rdiq45AsWQP5ygSoEpdi94fRDyslc6SWNH9pvVwgtWb7SQ/k8CfRumHY2ithpACD45YyAA9JP3ykPQiQdSNh4zlsS1gFZaIIuZuEKEx5DwZZKKyZAWhUCdC0i5o9fIK2Pcfm7gmMlIF7zwd4b3MiMMOBhdvvQLJ6C+TrV0CVvBz5qTEoTo+CThmBAzlBaNotgK3AD80av97mUt4s2joESX/ZULlr3pD2I1Deg/nKLiQmN0O2Xoys5HjsksaiUB6Nfcp3UZ67ANX5IThYRMn38dFSxoed4J+lrTRbngio1zuHyid9NABeei+CFQ5EZ91FcsZZyBTtUGUfRGFuLXRqAuaCEtQX51GvlqCllBLr+Wg18HDIzIO9xnc5baeQ9J0YKncNU9aPOYoeLNzZhXWZV5CiOI3MHW3Iy21AsboSRIEe1ZpCNGh3okUXjhaCkhspeRUPh2u5aLNwb1isM0a7Xi98Xj49rR8CuRPvqBxYtuNXbFKcR5rqBLLz7MjPt0BbZIRRo0WdLh82fRLs+/k4ZKLk1ZT4Yy6O1FPT6IujzTMzqT/HGUv1nzp0eOnO1JAsR+rinPuZiYrOPonqLOS57chRH8TevbUo01D16IrRSOSgwxCJK6ZgXK2ZjW/rZuGa1Q+kjYfvW7i40ep7ne5oeNbIL6mTsi9gW95pKNVtUBc1QKOpwn5dGarLC3GxYiN+Mkfgds183LcEo8sahB6bP3rtfAwc5qK3nbORVv0TUdpF1jplx+OtueeRvvskVIV2FJTUQ1tqgpHQotm4EzeMi3GrKhx36+bhgXUuum2B6LEL0NfGQ/8x38u0anhWbe/Yu0H1OZm66wyZuecomVfSRBZpa0h9OUGaK4rJL43rcbN6EX6xhOF3awge2mbjcWsAnrb5oe84F49PcUJp1ctz2SCM+64qGj/URuK3A6G4Z5uLR/YgONoEcB7jwXlqZiO9+vKcIaLHfG2KJa/VLMaPlnDcts3DHy1z8NfhQDxp96Pk3O77Z9gz6PWXp7MiTnG1MhbX66Lwc8MC3GkOwYNDb6GrPQA9J/lwnPbNo1dHRqdJFPVNbYyItEaKbjWFie62vi3680iQqPu4v+jpJzzRg3PssfTq/wGD8Tedsdp6457pjwAAAABJRU5ErkJggg== + + 6b67286b-4ffe-43c4-921e-806b10a83b8f + true + false + true + script-sync cpython + scsy-cpy + 1 + + false + false + false + + + + + + 236 + 527 + 173 + 124 + + + 351 + 589 + + + + + + 6 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + 2 + 08908df5-fa14-4982-9ab2-1aa0927566aa + 08908df5-fa14-4982-9ab2-1aa0927566aa + + + + + true + Connect a button to open a file dialog to select a cpython file to run. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAOsSURBVEhL1VU5S1xhFB0VB5Fx3x0Vl3Hf9w0VXEARVFQM2gmCgvgLBqIWBg0IoqWFdlaS0spGsIwiLmjhgoImRYKFZjSJnNxz5z0Rxy1VyIHLvHnLufeee77vs/wrOLy8vH7IL/4i3km8DX5+fp/n5+exvr6OtbU1rK6uYmVlBcvLy1hcXMTU1BQGBgbQ2tqK6upqpKamQgq6kE+tboYX4OPj0y4f/lpYWEB5eblGWVkZSkpKUFRUhPz8fOTk5CAjI0OJk5KSkJWVBZvNduXt7e00aJ6FNSgo6NvS0hK6urq0OkZVVZUmYpLCwkLk5uYqaVpaGlJSUjSSk5MhCa6Fw+6megK+vr4f+vv7f4+NjaGmpgZ1dXUavGYSdlJcXKxdZGdnIz09XckTExO1EynuVqT6ZNB5wBEdHX0zOzuLhoYGJa6vr0dLSwvm5uawu7sLE9vb25icnERBQQEcDocmiI+PR1xcHGfBLordlA8g2q91dnait7dXZWGCnp4eHB0dGbSeODg40HeZgOQxMTEICQm5kyQbBu09WsPDw10kpNaUg9UfHh4aVJ5wuVz6u7+/r8NmAlEACQkJEBdeCWefm1oGK9V/qaioAIODZJKZmRkleArn5+fo6OjA2dmZ/h8fH4fdbkdUVJQmYUfSxXfhtllk8u/DwsJcJOfwaEUmYftP4eLiAk1NTWrTkZERvbezs4PY2FhERkYiNDRUBy/XXKjTFsl0mZmZqd5mMAmteHNzox8/hEnO92lRDpmgXNQ/IiKCM9BEeXl5XN2XTDAt9rqmt81EvH6cgLKY5LQn3UMSggkojyiB4OBgfUdcxQ4+Slhs1Is+ZtsMLqKHtiQ5rctnrJzkfH9oaEifb21tafWUh51wvchc3TMw0Ge1Wq/4MR3B34mJCf2YnbS1tek9PqO+JGf1p6en+o7T6byvngYRibgW7l2koHepHZc8SVgtLUicnJxgeHhYW+f9wcFBHB8f67O9vT2tmuTsrLS09E7oPNYBUca9hBYzg84ykzwFknNmHCzl4YwCAwOpvedKJqSLT/LiLTvgwmFQjtHRUWxubhq0wMbGhspC77NyIVV7i2w/hebZvYiwswvqzb2Fi8YMuoQScpjUmxWL+xAQEKDPeTbIHF/eTQ04peVr7payfdyHSUo5zKrlDIC/v79uK9I1yV89DwirSPWVVq2srERtba0SUN/m5mattL29HdwYu7u7dUNsbGx8+4lmgOfr4zP3tXj7mfwfwWL5Ayn3+7H9F88PAAAAAElFTkSuQmCC + + f694cce9-2bb5-4c5e-a912-37ca1fe650c9 + btn + btn + true + 0 + true + 37a1fdbe-f895-4bf0-a740-19a73fe2889b + 1 + Connect a button to open a file dialog to select a cpython file to run. + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 238 + 529 + 98 + 20 + + + 288.5 + 539 + + + + + + + + 1 + true + Pass a list with the name of the custom packages you want to reload. This function is useful if you are developing a i.e. PyPI package and you want to reload the submodules after you modified something. The function will reload the package and all its submodules. If you want to reload the package and all its submodules, just pass the package name. If you want to reload only a submodule, pass the package name and the submodule name separated by a dot. If you want to reload multiple submodules, pass the package + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + 1facc5d0-c7a9-4cbb-95f5-7d3a7ef123b5 + packages_2_reload + packages_2_reload + true + 1 + true + 0 + Pass a list with the name of the custom packages you want to reload. This function is useful if you are developing a i.e. PyPI package and you want to reload the submodules after you modified something. The function will reload the package and all its submodules. If you want to reload the package and all its submodules, just pass the package name. If you want to reload only a submodule, pass the package name and the submodule name separated by a dot. If you want to reload multiple submodules, pass the package + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 238 + 549 + 98 + 20 + + + 288.5 + 559 + + + + + + + + true + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + 6ceb5c7a-499d-4deb-9d2c-d1a955effa73 + i_export_dir + i_export_dir + true + 0 + true + bee0b3ef-7bf0-49f6-8e1d-71c7765756d0 + 1 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 238 + 569 + 98 + 20 + + + 288.5 + 579 + + + + + + + + 1 + true + A generic x input. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAPkSURBVEhL1VVbKOV7FN7ITnK/RYNcNrkrx11SbokHuWQyb0ryRN5ocuLBKadELsktHuTywKBcXgiRUiYvJOVSknNw5LK3OWbO9J31/famOWfPGPN0OqtW+7/r9/vWWt/61vpp/ivTWVhY3MsvfsBfi7/MbGxstvr6+rC+vo7V1VUsLi5ifn4eExMTGBoaQnNzM8rLy5GXl4eUlBQEBQVBEjqTq1ojwjNmZWWVLxc/DQ4OIiEhQXl8fDxiY2MRExOD6OhoREREICQkRAH7+/sjLCwMdnZ2ektLy7cmmG+a1tHR8Y/R0VEUFRWp7OjJyclISkrC8PAwHh4ecHNzg4WFBeTm5iIwMFB5QEAAJIBBMF4Zob5i1tbWv5SVlf3V0NCA1NRUpKWlPTmpOjw8RHd3N3p7e7G0tITb21v138/PT1UiyT0IVe9McGam8/T0/LO9vR0ZGRkKND09HZmZmVhbW4Ner0dnZycmJydRUVGBqqoq1NfX4+joSPWHQby9vdkLVvGTEfILE+5XSUtpaamihQEIzkYT/PLyEgy+ubmJ2tpa1eiBgQG0trbi4OAAXV1d8PLygrOz82cJ8t4E+2R5bm5uH0pKSlRTyTkDPGZO8OPjY4yPj2Nubg4rKysKfHp6Wp3hN+li5b6+vhAV6gXzjRFaGivZ/5aYmAg61cKGkvMvwXd2dlT2LS0tODs7U98E39vbw/7+vurJ7OwshGZFl1RxJdh2Gun8z66urh8ITglSiiMjIzAYDGbgBBkbG0NHRwfOz89xcXGhztB6enpwfX0NFxcXpSp3d3cO6q8aiXQdGhqqtE1nEIJfXV2Zgc/MzIASZrMbGxsVVScnJ9jY2FDKYsXSA3h4eCAqKorTfc0ALSIvQ2RkJB4D3d/fq4tfA+/v70dbWxuamppQWVmJ6upq9X93d1cFcXJyUjjSC2MF5Il8UcecTjozOz09fRa8rq5OSZWS3draUvwLLUpJnHzpq7EHJnuj1Wr1wcHBavwLCgpwd3eH5eXlF4OTFmZPFco3Z+FJRcqkivc8xJFnk3iJFfwIuE6nQ1xc3GeBM5sDWjx3CSVGp6qoEMqVqnkOnI2lerKysuDg4EDuzSeZJlW8k4MPrIBjz3K5BqioqakpNcE1NTXY3t7+R+YCquQtyvkoMN/cRbRXrIK98PHxUUNDz87OVhNM+bI3XBlsqKgP9vb26gzfBunj89vUZG+lZEN4eDhkfTy5DKOigXQ8Zi1vAGxtbdVSlKoJ/t33gKYVqn7nI/K4kwhAfnNyclSm+fn5KCwsRHFxMbi/uBTlzsteNJPxff33m/s9f/mb/D8yjeZvU880QlAx2/0AAAAASUVORK5CYII= + + e86775bd-fb57-4402-a56b-9a1fa88b3782 + i_breps + i_breps + true + 1 + true + a126a588-53d2-4d08-977f-68deff6a42c2 + 1 + A generic x input. + 2ceb0405-fdfe-403d-a4d6-8786da45fb9d + + + + + + 238 + 589 + 98 + 20 + + + 288.5 + 599 + + + + + + + + true + rhinoscriptsyntax geometry + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + 99293e71-3a24-4bb0-a208-4748b642d47c + i_assembly_name + i_assembly_name + true + 0 + true + aedebb31-f342-420e-ac55-d80e788a157f + 1 + + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 238 + 609 + 98 + 20 + + + 288.5 + 619 + + + + + + + + true + Converts to collection of boolean values + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAOsSURBVEhL1VU5S1xhFB0VB5Fx3x0Vl3Hf9w0VXEARVFQM2gmCgvgLBqIWBg0IoqWFdlaS0spGsIwiLmjhgoImRYKFZjSJnNxz5z0Rxy1VyIHLvHnLufeee77vs/wrOLy8vH7IL/4i3km8DX5+fp/n5+exvr6OtbU1rK6uYmVlBcvLy1hcXMTU1BQGBgbQ2tqK6upqpKamQgq6kE+tboYX4OPj0y4f/lpYWEB5eblGWVkZSkpKUFRUhPz8fOTk5CAjI0OJk5KSkJWVBZvNduXt7e00aJ6FNSgo6NvS0hK6urq0OkZVVZUmYpLCwkLk5uYqaVpaGlJSUjSSk5MhCa6Fw+6megK+vr4f+vv7f4+NjaGmpgZ1dXUavGYSdlJcXKxdZGdnIz09XckTExO1EynuVqT6ZNB5wBEdHX0zOzuLhoYGJa6vr0dLSwvm5uawu7sLE9vb25icnERBQQEcDocmiI+PR1xcHGfBLordlA8g2q91dnait7dXZWGCnp4eHB0dGbSeODg40HeZgOQxMTEICQm5kyQbBu09WsPDw10kpNaUg9UfHh4aVJ5wuVz6u7+/r8NmAlEACQkJEBdeCWefm1oGK9V/qaioAIODZJKZmRkleArn5+fo6OjA2dmZ/h8fH4fdbkdUVJQmYUfSxXfhtllk8u/DwsJcJOfwaEUmYftP4eLiAk1NTWrTkZERvbezs4PY2FhERkYiNDRUBy/XXKjTFsl0mZmZqd5mMAmteHNzox8/hEnO92lRDpmgXNQ/IiKCM9BEeXl5XN2XTDAt9rqmt81EvH6cgLKY5LQn3UMSggkojyiB4OBgfUdcxQ4+Slhs1Is+ZtsMLqKHtiQ5rctnrJzkfH9oaEifb21tafWUh51wvchc3TMw0Ge1Wq/4MR3B34mJCf2YnbS1tek9PqO+JGf1p6en+o7T6byvngYRibgW7l2koHepHZc8SVgtLUicnJxgeHhYW+f9wcFBHB8f67O9vT2tmuTsrLS09E7oPNYBUca9hBYzg84ykzwFknNmHCzl4YwCAwOpvedKJqSLT/LiLTvgwmFQjtHRUWxubhq0wMbGhspC77NyIVV7i2w/hebZvYiwswvqzb2Fi8YMuoQScpjUmxWL+xAQEKDPeTbIHF/eTQ04peVr7payfdyHSUo5zKrlDIC/v79uK9I1yV89DwirSPWVVq2srERtba0SUN/m5mattL29HdwYu7u7dUNsbGx8+4lmgOfr4zP3tXj7mfwfwWL5Ayn3+7H9F88PAAAAAElFTkSuQmCC + + 5d5ec1f4-2789-47cb-b7e0-5f1023ada8b4 + i_dump + i_dump + true + 0 + true + 51a09241-6321-4d8b-bfc9-536b009c6410 + 1 + + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 238 + 629 + 98 + 20 + + + 288.5 + 639 + + + + + + + + false + The redirected standard output of the component scriptsync. + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + eba563ee-7094-4907-b35a-ee3a9d076495 + stdout + stdout + false + 0 + true + 0 + The redirected standard output of the component scriptsync. + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 366 + 529 + 41 + 60 + + + 386.5 + 559 + + + + + + + + false + Generic example output of the component + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAQTSURBVEhL1VVbKK1pGF7ISnI+s5zP5/NZzkQohUxcUS7cOCRXtiQ0MtqS5IILp8KNtitKKQmR7ERxISllz0wadrGszdAz3/Ot9a/sMXvbczXNW2/rb631P8/7Pu/zfp/qvwo/ExOTL+IT/yJ/EvljYWFh8XFiYgJbW1vY2NjA2toaVlZWsLi4iKmpKQwMDKChoQGlpaXIyMhAUFAQREG/ilfVeoTvhJmZWbl48c/JyUmkpKTITE5ORmJiIuLj4xETE4PIyEiEhoZKYD8/P4SHh8PKyurO1NT0nQHmm6G2tbX9Y35+HpWVlbI6Znp6uiQiSVxcHKKioiRocHAwAgICZPr7+0MQaAWGRg/1D2Fubv5zfX39U3d3NzIzM9HY2Ij+/n7Mzc1hc3MT09PTSEhIkF1EREQgJydH/ra6uora2lqI4h6EVB8McK/Cz83N7cvIyAjy8/ORm5uLuro6jI6O4urqCtfX1/KzrKwMsbGxKCwsxNHREc7Pz3F4eIjx8XF4enpyFuwiQQ/5IoT2GxUVFaipqZGyZGdnIy8vT+b+/j5ub29xf38vgZKSkrC9vY2FhQXQDMvLy1JSd3d32NvbPwuSjwZYY5Q6OTnpqqurpdbUnBKRhNnX1wedToeHhwecnJxIkra2NoSEhEj9fX19ZfVCAXh7e0O48E5g1uqhxWBF9b+lpqaCyUEqJMqQi4qKJMHT0xOen5+xtLT01ZB9fHyg0Wjg6uoqSUgourgW2FYqMfkuR0dHHcE5PFqRJLTmS5vu7e1JcEZPT89XNvXy8oKHhwdcXFzg4OAgScXzvSB4rxJMn8PCwqS3mSShFemWlzk8PGzsYH193Vi9Ig/1d3Z25gwkUXR0NLf7MwneC3tp6W2FiM8koluYfOYWcwaPj49y2CR9WT3lEUrAzs5O4ojv2cEvIlVW1It/ZttM6kufK111dXWht7cXp6enElyr1aKzs1MOlNqzY1ZPedgJJRVz1c/AELVqtfqObTNbWlowNjaG9vZ2DA0NYWZmRn4/ODiIm5sbuRPHx8eymJKSErS2thqr58yERNwFo4tk0LvUjtZrbm6WG8rDbnZ21mhHynJ2dobLy0tcXFzg4OAAPLNYPcEDAwO5I88C7tUeMJJ5lnBoWVlZ0udNTU3GQdKK1JuLuLu7i52dHXR0dCjLJeXhdtvY2FD715vMEF18EH98ICid8TKpNYdJQA6UVSuyCFBpb+GcRwHzzbOIoWEX1JvVcmmUJCglVIBZsXAfrK2t5e+8G8Qcv3+aGuKdaFlLF4njw5gKKOVQqhZ3ACwtLeV5Jbom+Jv3AUMtpPqdVk1LS5PzIAD1LS4ulpWWl5eDB2NVVRV4fhUUFPBo+MR39RBvB+/Xv9+5b+WP38n/o1Cp/gJAdKz5nm6ZIAAAAABJRU5ErkJggg== + + c98a3826-db80-4996-b56f-4d6ae964153a + a + a + false + 0 + true + 0 + Generic example output of the component + 1c282eeb-dd16-439f-94e4-7d92b542fe8b + + + + + + 366 + 589 + 41 + 60 + + + 386.5 + 619 + + + + + + + + + + false + ZnJvbSBnaHB5dGhvbmxpYi5jb21wb25lbnRiYXNlIGltcG9ydCBleGVjdXRpbmdjb21wb25lbnQgYXMgY29tcG9uZW50CgppbXBvcnQgU3lzdGVtCmltcG9ydCBTeXN0ZW0uRHJhd2luZwppbXBvcnQgU3lzdGVtLldpbmRvd3MuRm9ybXMKaW1wb3J0IFJoaW5vCmltcG9ydCBHcmFzc2hvcHBlcgppbXBvcnQgR3Jhc3Nob3BwZXIgYXMgZ2gKZnJvbSBHcmFzc2hvcHBlci5LZXJuZWwgaW1wb3J0IEdIX1J1bnRpbWVNZXNzYWdlTGV2ZWwgYXMgUk1MCmltcG9ydCBzeXMKaW1wb3J0IG9zCmltcG9ydCB0aW1lCgppbXBvcnQgY29udGV4dGxpYgppbXBvcnQgaW8KCmltcG9ydCBhYmMKaW1wb3J0IHNvY2tldAppbXBvcnQgdGhyZWFkaW5nCmltcG9ydCBxdWV1ZQppbXBvcnQganNvbgoKaW1wb3J0IGltcG9ydGxpYgppbXBvcnQgaW5zcGVjdAppbXBvcnQgc3lzCgoKY2xhc3MgR0hUaHJlYWQodGhyZWFkaW5nLlRocmVhZCwgbWV0YWNsYXNzPWFiYy5BQkNNZXRhKToKICAgICIiIgogICAgICAgIEEgYmFzZSBjbGFzcyBmb3IgR3Jhc3Nob3BwZXIgdGhyZWFkcy4KICAgICIiIgogICAgZGVmIF9faW5pdF9fKHNlbGYsIG5hbWUgOiBzdHIpOgogICAgICAgIHN1cGVyKCkuX19pbml0X18obmFtZT1uYW1lLCBkYWVtb249RmFsc2UpCiAgICAgICAgc2VsZi5fY29tcG9uZW50X29uX2NhbnZhcyA9IFRydWUKICAgICAgICBzZWxmLl9jb21wb25lbnRfZW5hYmxlZCA9IFRydWUKCiAgICBAYWJjLmFic3RyYWN0bWV0aG9kCiAgICBkZWYgcnVuKHNlbGYpOgogICAgICAgICIiIiBSdW4gdGhlIHRocmVhZC4gIiIiCiAgICAgICAgcGFzcwoKICAgIGRlZiBfY2hlY2tfaWZfY29tcG9uZW50X29uX2NhbnZhcyhzZWxmKToKICAgICAgICAiIiIgQ2hlY2sgaWYgdGhlIGNvbXBvbmVudCBpcyBvbiBjYW52YXMgZnJvbSB0aHJlYWQuICIiIgogICAgICAgIGRlZiBfX2NoZWNrX2lmX2NvbXBvbmVudF9vbl9jYW52YXMoKToKICAgICAgICAgICAgaWYgZ2hlbnYuQ29tcG9uZW50Lk9uUGluZ0RvY3VtZW50KCkgaXMgTm9uZToKICAgICAgICAgICAgICAgIHNlbGYuX2NvbXBvbmVudF9vbl9jYW52YXMgPSBGYWxzZQogICAgICAgICAgICAgICAgcmV0dXJuIEZhbHNlCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBzZWxmLl9jb21wb25lbnRfb25fY2FudmFzID0gVHJ1ZQogICAgICAgICAgICAgICAgcmV0dXJuIFRydWUKICAgICAgICBhY3Rpb24gPSBTeXN0ZW0uQWN0aW9uKF9fY2hlY2tfaWZfY29tcG9uZW50X29uX2NhbnZhcykKICAgICAgICBSaGluby5SaGlub0FwcC5JbnZva2VPblVpVGhyZWFkKGFjdGlvbikKCiAgICBkZWYgX2NoZWNrX2lmX2NvbXBvbmVudF9lbmFibGVkKHNlbGYpOgogICAgICAgICIiIiBDaGVjayBpZiB0aGUgY29tcG9uZW50IGlzIGVuYWJsZWQgZnJvbSB0aHJlYWQuICIiIgogICAgICAgIGRlZiBfX2NoZWNrX2lmX2NvbXBvbmVudF9lbmFibGVkKCk6CiAgICAgICAgICAgIGlmIGdoZW52LkNvbXBvbmVudC5Mb2NrZWQ6CiAgICAgICAgICAgICAgICBzZWxmLl9jb21wb25lbnRfZW5hYmxlZCA9IEZhbHNlCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBzZWxmLl9jb21wb25lbnRfZW5hYmxlZCA9IFRydWUKICAgICAgICBhY3Rpb24gPSBTeXN0ZW0uQWN0aW9uKF9fY2hlY2tfaWZfY29tcG9uZW50X2VuYWJsZWQpCiAgICAgICAgUmhpbm8uUmhpbm9BcHAuSW52b2tlT25VaVRocmVhZChhY3Rpb24pCgogICAgZGVmIGV4cGlyZV9jb21wb25lbnRfc29sdXRpb24oc2VsZik6CiAgICAgICAgIiIiIEZpcmUgdGhlIHJlY2FsY3VsYXRpb24gb2YgdGhlIGNvbXBvbmVudCBzb2x1dGlvbiBmcm9tIHRocmVhZC4gIiIiCiAgICAgICAgZGVmIF9fZXhwaXJlX2NvbXBvbmVudF9zb2x1dGlvbigpOgogICAgICAgICAgICBnaGVudi5Db21wb25lbnQuUGFyYW1zLk91dHB1dFswXS5DbGVhckRhdGEoKSAgIyBjbGVhciB0aGUgb3V0cHV0CiAgICAgICAgICAgIGdoZW52LkNvbXBvbmVudC5FeHBpcmVTb2x1dGlvbihUcnVlKSAgIyBleHBpcmUgdGhlIGNvbXBvbmVudAogICAgICAgIGFjdGlvbiA9IFN5c3RlbS5BY3Rpb24oX19leHBpcmVfY29tcG9uZW50X3NvbHV0aW9uKQogICAgICAgIFJoaW5vLlJoaW5vQXBwLkludm9rZU9uVWlUaHJlYWQoYWN0aW9uKQoKICAgIGRlZiBjbGVhcl9jb21wb25lbnQoc2VsZik6CiAgICAgICAgIiIiIENsZWFyIHRoZSBjb21wb25lbnQgZnJvbSB0aHJlYWQuICIiIgogICAgICAgIGRlZiBfX2NsZWFyX2NvbXBvbmVudCgpOgogICAgICAgICAgICBnaGVudi5Db21wb25lbnQuQ2xlYXJEYXRhKCkKICAgICAgICBhY3Rpb24gPSBTeXN0ZW0uQWN0aW9uKF9fY2xlYXJfY29tcG9uZW50KQogICAgICAgIFJoaW5vLlJoaW5vQXBwLkludm9rZU9uVWlUaHJlYWQoYWN0aW9uKQoKICAgIGRlZiBhZGRfcnVudGltZV93YXJuaW5nKHNlbGYsIGV4Y2VwdGlvbiA6IHN0cik6CiAgICAgICAgIiIiIEFkZCBhIHdhcm5pbmcgdGFiIHRvIHRoZSBjb21wb25lbnQgZnJvbSBtYWluIHRocmVhZC4gIiIiCiAgICAgICAgYWN0aW9uID0gU3lzdGVtLkFjdGlvbigKICAgICAgICAgICAgbGFtYmRhOiBnaGVudi5Db21wb25lbnQuQWRkUnVudGltZU1lc3NhZ2UoUk1MLldhcm5pbmcsIGV4Y2VwdGlvbikKICAgICAgICApCiAgICAgICAgUmhpbm8uUmhpbm9BcHAuSW52b2tlT25VaVRocmVhZChhY3Rpb24pCgogICAgZGVmIGFkZF9ydW50aW1lX2Vycm9yKHNlbGYsIGV4Y2VwdGlvbiA6IHN0cik6CiAgICAgICAgIiIiIEFkZCBhbiBlcnJvciB0YWIgdG8gdGhlIGNvbXBvbmVudCBmcm9tIG1haW4gdGhyZWFkLiAiIiIKICAgICAgICBhY3Rpb24gPSBTeXN0ZW0uQWN0aW9uKAogICAgICAgICAgICBsYW1iZGE6IGdoZW52LkNvbXBvbmVudC5BZGRSdW50aW1lTWVzc2FnZShSTUwuRXJyb3IsIGV4Y2VwdGlvbikKICAgICAgICApCiAgICAgICAgUmhpbm8uUmhpbm9BcHAuSW52b2tlT25VaVRocmVhZChhY3Rpb24pCgogICAgZGVmIGFkZF9ydW50aW1lX3JlbWFyayhzZWxmLCBleGNlcHRpb24gOiBzdHIpOgogICAgICAgICIiIiBBZGQgYSBibGFuayB0YWIgdG8gdGhlIGNvbXBvbmVudCBmcm9tIG1haW4gdGhyZWFkLiAiIiIKICAgICAgICBhY3Rpb24gPSBTeXN0ZW0uQWN0aW9uKAogICAgICAgICAgICBsYW1iZGE6IGdoZW52LkNvbXBvbmVudC5BZGRSdW50aW1lTWVzc2FnZShSTUwuUmVtYXJrLCBleGNlcHRpb24pCiAgICAgICAgKQogICAgICAgIFJoaW5vLlJoaW5vQXBwLkludm9rZU9uVWlUaHJlYWQoYWN0aW9uKQoKICAgIEBwcm9wZXJ0eQogICAgZGVmIGNvbXBvbmVudF9lbmFibGVkKHNlbGYpOgogICAgICAgIHNlbGYuX2NoZWNrX2lmX2NvbXBvbmVudF9lbmFibGVkKCkKICAgICAgICByZXR1cm4gc2VsZi5fY29tcG9uZW50X2VuYWJsZWQKCiAgICBAcHJvcGVydHkKICAgIGRlZiBjb21wb25lbnRfb25fY2FudmFzKHNlbGYpOgogICAgICAgIHNlbGYuX2NoZWNrX2lmX2NvbXBvbmVudF9vbl9jYW52YXMoKQogICAgICAgIHJldHVybiBzZWxmLl9jb21wb25lbnRfb25fY2FudmFzCgpjbGFzcyBDbGllbnRUaHJlYWQoR0hUaHJlYWQpOgogICAgIiIiCiAgICBBIHRocmVhZCB0byBjb25uZWN0IHRvIHRoZSBWU0NvZGUgc2VydmVyLgogICAgIiIiCiAgICBkZWYgX19pbml0X18oc2VsZiwgdnNjb2RlX3NlcnZlcl9pcDogc3RyLCB2c2NvZGVfc2VydmVyX3BvcnQ6IGludCwgbmFtZTogc3RyLAogICAgICAgICAgICAgICAgIHF1ZXVlX21zZzogcXVldWUuUXVldWUgPSBOb25lLCBsb2NrX3F1ZXVlX21zZzogdGhyZWFkaW5nLkxvY2sgPSBOb25lLAogICAgICAgICAgICAgICAgIGV2ZW50X2ZpcmVfbXNnOiB0aHJlYWRpbmcuRXZlbnQgPSBOb25lKToKICAgICAgICBzdXBlcigpLl9faW5pdF9fKG5hbWU9bmFtZSkKICAgICAgICBzZWxmLnZzY29kZV9zZXJ2ZXJfaXAgPSB2c2NvZGVfc2VydmVyX2lwCiAgICAgICAgc2VsZi52c2NvZGVfc2VydmVyX3BvcnQgPSB2c2NvZGVfc2VydmVyX3BvcnQKICAgICAgICBzZWxmLmlzX2Nvbm5lY3RlZCA9IEZhbHNlCiAgICAgICAgc2VsZi5jb25uZWN0X3JlZnJlc2hfcmF0ZSA9IDEgICMgc2Vjb25kcwogICAgICAgIHNlbGYucXVldWVfbXNnID0gcXVldWVfbXNnCiAgICAgICAgc2VsZi5sb2NrX3F1ZXVlX21zZyA9IGxvY2tfcXVldWVfbXNnCiAgICAgICAgc2VsZi5ldmVudF9maXJlX21zZyA9IGV2ZW50X2ZpcmVfbXNnCiAgICAgICAgc2VsZi5jbGllbnRfc29ja2V0ID0gc29ja2V0LnNvY2tldChzb2NrZXQuQUZfSU5FVCwgc29ja2V0LlNPQ0tfU1RSRUFNKQoKICAgIGRlZiBydW4oc2VsZik6CiAgICAgICAgIiIiIFJ1biB0aGUgdGhyZWFkLiBTZW5kIHRoZSBtZXNzYWdlIHRvIHRoZSB2c2NvZGUgc2VydmVyLiIiIgogICAgICAgIHdoaWxlIHNlbGYuY29tcG9uZW50X29uX2NhbnZhcyBhbmQgc2VsZi5jb21wb25lbnRfZW5hYmxlZDoKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgaWYgbm90IHNlbGYuaXNfY29ubmVjdGVkOgogICAgICAgICAgICAgICAgICAgIHNlbGYuY29ubmVjdF90b192c2NvZGVfc2VydmVyKCkKICAgICAgICAgICAgICAgICAgICBzZWxmLmNsZWFyX2NvbXBvbmVudCgpCiAgICAgICAgICAgICAgICAgICAgc2VsZi5leHBpcmVfY29tcG9uZW50X3NvbHV0aW9uKCkKICAgICAgICAgICAgICAgICAgICBjb250aW51ZQoKICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRfZmlyZV9tc2cud2FpdCgpCiAgICAgICAgICAgICAgICBzZWxmLnNlbmRfbWVzc2FnZV9mcm9tX3F1ZXVlKCkKCiAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgICAgIHNlbGYuYWRkX3J1bnRpbWVfd2FybmluZyhmInNjcmlwdC1zeW5jOjpVbmtvd24gZXJyb3IgZnJvbSBydW46IHtzdHIoZSl9IikKICAgICAgICAgICAgICAgIHNlbGYuaXNfY29ubmVjdGVkID0gRmFsc2UKICAgICAgICAgICAgICAgIHNlbGYuY2xpZW50X3NvY2tldCA9IHNvY2tldC5zb2NrZXQoc29ja2V0LkFGX0lORVQsIHNvY2tldC5TT0NLX1NUUkVBTSkKCiAgICAgICAgc2VsZi5jbGllbnRfc29ja2V0LmNsb3NlKCkKCiAgICBkZWYgc2VuZF9tZXNzYWdlX2Zyb21fcXVldWUoc2VsZik6CiAgICAgICAgd2l0aCBzZWxmLmxvY2tfcXVldWVfbXNnOgogICAgICAgICAgICBpZiBzZWxmLnF1ZXVlX21zZyBhbmQgbm90IHNlbGYucXVldWVfbXNnLmVtcHR5KCk6CiAgICAgICAgICAgICAgICBtc2cgPSBzZWxmLnF1ZXVlX21zZy5nZXQoKQogICAgICAgICAgICAgICAgc2VsZi5xdWV1ZV9tc2cudGFza19kb25lKCkKICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRfZmlyZV9tc2cuc2V0KCkKICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRfZmlyZV9tc2cuY2xlYXIoKQogICAgICAgICAgICAgICAgc2VsZi5jbGllbnRfc29ja2V0LnNlbmQobXNnKQoKICAgIGRlZiBjb25uZWN0X3RvX3ZzY29kZV9zZXJ2ZXIoc2VsZik6CiAgICAgICAgIiIiIENvbm5lY3QgdG8gdGhlIFZTQ29kZSBzZXJ2ZXIuICIiIgogICAgICAgIHdoaWxlIHNlbGYuY29tcG9uZW50X29uX2NhbnZhcyBhbmQgbm90IHNlbGYuaXNfY29ubmVjdGVkOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBzZWxmLmNsaWVudF9zb2NrZXQuc2VuZChiIiIpCiAgICAgICAgICAgICAgICBzZWxmLmlzX2Nvbm5lY3RlZCA9IFRydWUKICAgICAgICAgICAgZXhjZXB0IHNvY2tldC5lcnJvcjoKICAgICAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgICAgICBzZWxmLmNsaWVudF9zb2NrZXQuY29ubmVjdCgoc2VsZi52c2NvZGVfc2VydmVyX2lwLCBzZWxmLnZzY29kZV9zZXJ2ZXJfcG9ydCkpCiAgICAgICAgICAgICAgICAgICAgc2VsZi5pc19jb25uZWN0ZWQgPSBUcnVlCiAgICAgICAgICAgICAgICBleGNlcHQgKENvbm5lY3Rpb25SZWZ1c2VkRXJyb3IsIENvbm5lY3Rpb25SZXNldEVycm9yLCBzb2NrZXQuZXJyb3IpIGFzIGU6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5oYW5kbGVfY29ubmVjdGlvbl9lcnJvcihlKQogICAgICAgICAgICBmaW5hbGx5OgogICAgICAgICAgICAgICAgdGltZS5zbGVlcChzZWxmLmNvbm5lY3RfcmVmcmVzaF9yYXRlKQoKICAgIGRlZiBoYW5kbGVfY29ubmVjdGlvbl9lcnJvcihzZWxmLCBlKToKICAgICAgICBlcnJvcl9tZXNzYWdlcyA9IHsKICAgICAgICAgICAgQ29ubmVjdGlvblJlZnVzZWRFcnJvcjogInNjcmlwdC1zeW5jOjpDb25uZWN0aW9uIHJlZnVzZWQgYnkgdGhlIHZzY29kZSIsCiAgICAgICAgICAgIENvbm5lY3Rpb25SZXNldEVycm9yOiAic2NyaXB0LXN5bmM6OkNvbm5lY3Rpb24gd2FzIGZvcmNpYmx5IGNsb3NlZCBieSB0aGUgdnNjb2RlIiwKICAgICAgICAgICAgc29ja2V0LmVycm9yOiBmInNjcmlwdC1zeW5jOjpFcnJvciBjb25uZWN0aW5nIHRvIHRoZSB2c2NvZGU6IHtzdHIoZSl9IgogICAgICAgIH0KICAgICAgICBzZWxmLmFkZF9ydW50aW1lX3dhcm5pbmcoZXJyb3JfbWVzc2FnZXNbdHlwZShlKV0pCiAgICAgICAgc2VsZi5pc19jb25uZWN0ZWQgPSBGYWxzZSBpZiB0eXBlKGUpICE9IHNvY2tldC5lcnJvciBvciBlLndpbmVycm9yICE9IDEwMDU2IGVsc2UgVHJ1ZQoKY2xhc3MgRmlsZUNoYW5nZWRUaHJlYWQoR0hUaHJlYWQpOgogICAgIiIiCiAgICAgICAgQSB0aHJlYWQgdG8gY2hlY2sgaWYgdGhlIGZpbGUgaGFzIGNoYW5nZWQgb24gZGlzay4KICAgICIiIgogICAgZGVmIF9faW5pdF9fKHNlbGYsCiAgICAgICAgICAgICAgICBwYXRoIDogc3RyLAogICAgICAgICAgICAgICAgbmFtZSA6IHN0cgogICAgICAgICAgICAgICAgKToKICAgICAgICBzdXBlcigpLl9faW5pdF9fKG5hbWU9bmFtZSkKICAgICAgICBzZWxmLnBhdGggPSBwYXRoCiAgICAgICAgc2VsZi5yZWZyZXNoX3JhdGUgPSAxMDAwICAjIG1pbGxpc2Vjb25kcwogICAgICAgIHNlbGYuX29uX2ZpbGVfY2hhbmdlZCA9IHRocmVhZGluZy5FdmVudCgpCgogICAgZGVmIHJ1bihzZWxmKToKICAgICAgICAiIiIKICAgICAgICAgICAgQ2hlY2sgaWYgdGhlIGZpbGUgaGFzIGNoYW5nZWQgb24gZGlzay4KICAgICAgICAiIiIKICAgICAgICBsYXN0X21vZGlmaWVkID0gb3MucGF0aC5nZXRtdGltZShzZWxmLnBhdGgpCiAgICAgICAgd2hpbGUgc2VsZi5jb21wb25lbnRfb25fY2FudmFzIGFuZCBub3Qgc2VsZi5fb25fZmlsZV9jaGFuZ2VkLmlzX3NldCgpOgogICAgICAgICAgICBTeXN0ZW0uVGhyZWFkaW5nLlRocmVhZC5TbGVlcChzZWxmLnJlZnJlc2hfcmF0ZSkKICAgICAgICAgICAgbGFzdF9tb2RpZmllZCA9IHNlbGYuaXNfZmlsZV9tb2RpZmllZChsYXN0X21vZGlmaWVkKQogICAgICAgIHNlbGYuX29uX2ZpbGVfY2hhbmdlZC5jbGVhcigpCiAgICAgICAgcmV0dXJuCgogICAgZGVmIHN0b3Aoc2VsZik6CiAgICAgICAgIiIiIFN0b3AgdGhlIHRocmVhZC4gIiIiCiAgICAgICAgc2VsZi5fb25fZmlsZV9jaGFuZ2VkLnNldCgpCgogICAgZGVmIGlzX2ZpbGVfbW9kaWZpZWQoc2VsZiwgbGFzdF9tb2RpZmllZCk6CiAgICAgICAgY3VycmVudF9tb2RpZmllZCA9IG9zLnBhdGguZ2V0bXRpbWUoc2VsZi5wYXRoKQogICAgICAgIGlmIGN1cnJlbnRfbW9kaWZpZWQgIT0gbGFzdF9tb2RpZmllZDoKICAgICAgICAgICAgc2VsZi5leHBpcmVfY29tcG9uZW50X3NvbHV0aW9uKCkKICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRfbW9kaWZpZWQKICAgICAgICByZXR1cm4gbGFzdF9tb2RpZmllZAoKCmNsYXNzIFNjcmlwdFN5bmNDUHkoY29tcG9uZW50KToKICAgIGRlZiBfX2luaXRfXyhzZWxmKToKICAgICAgICBzdXBlcihTY3JpcHRTeW5jQ1B5LCBzZWxmKS5fX2luaXRfXygpCiAgICAgICAgc2VsZi5fdmFyX291dHB1dCA9IFtdCgogICAgICAgIHNlbGYuaXNfc3VjY2VzcyA9IEZhbHNlCgogICAgICAgIHNlbGYuY2xpZW50X3RocmVhZF9uYW1lIDogc3RyID0gZiJzY3JpcHQtc3luYy1jbGllbnQtdGhyZWFkOjp7Z2hlbnYuQ29tcG9uZW50Lkluc3RhbmNlR3VpZH0iCiAgICAgICAgc2VsZi52c2NvZGVfc2VydmVyX2lwID0gIjEyNy4wLjAuMSIKICAgICAgICBzZWxmLnZzY29kZV9zZXJ2ZXJfcG9ydCA9IDU4MjYwCiAgICAgICAgc2VsZi5zdGRvdXQgPSBOb25lCiAgICAgICAgc2VsZi5xdWV1ZV9tc2cgPSBxdWV1ZS5RdWV1ZSgpCiAgICAgICAgc2VsZi5xdWV1ZV9tc2dfbG9jayA9IHRocmVhZGluZy5Mb2NrKCkKICAgICAgICBzZWxmLmV2ZW50X2ZpcmVfbXNnID0gdGhyZWFkaW5nLkV2ZW50KCkKCiAgICAgICAgc2VsZi5maWxlY2hhbmdlZF90aHJlYWRfbmFtZSA6IHN0ciA9IGYic2NyaXB0LXN5bmMtZmlsZUNoYW5nZWQtdGhyZWFkOjp7Z2hlbnYuQ29tcG9uZW50Lkluc3RhbmNlR3VpZH0iCiAgICAgICAgc2VsZi5fX3BhdGhfbmFtZV90YWJsZV92YWx1ZSA9ICJzY3JpcHQtc3luYzo6IiArICJwYXRoOjoiICsgc3RyKGdoZW52LkNvbXBvbmVudC5JbnN0YW5jZUd1aWQpCiAgICAgICAgaWYgc2VsZi5wYXRoIGlzIE5vbmU6CiAgICAgICAgICAgIGdoZW52LkNvbXBvbmVudC5NZXNzYWdlID0gInNlbGVjdC1zY3JpcHQiCgogICAgZGVmIFJlbW92ZWRGcm9tRG9jdW1lbnQoc2VsZiwgZG9jKToKICAgICAgICAiIiIgUmVtb3ZlIHRoZSBjb21wb25lbnQgZnJvbSB0aGUgZG9jdW1lbnQuICIiIgogICAgICAgIGlmIHNlbGYuY2xpZW50X3RocmVhZF9uYW1lIGluIFt0Lm5hbWUgZm9yIHQgaW4gdGhyZWFkaW5nLmVudW1lcmF0ZSgpXToKICAgICAgICAgICAgY2xpZW50X3RocmVhZCA9IFt0IGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKSBpZiB0Lm5hbWUgPT0gc2VsZi5jbGllbnRfdGhyZWFkX25hbWVdWzBdCiAgICAgICAgICAgIGNsaWVudF90aHJlYWQuam9pbigpCiAgICAgICAgaWYgc2VsZi5maWxlY2hhbmdlZF90aHJlYWRfbmFtZSBpbiBbdC5uYW1lIGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKV06CiAgICAgICAgICAgIGZpbGVjaGFuZ2VkX3RocmVhZCA9IFt0IGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKSBpZiB0Lm5hbWUgPT0gc2VsZi5maWxlY2hhbmdlZF90aHJlYWRfbmFtZV1bMF0KICAgICAgICAgICAgZmlsZWNoYW5nZWRfdGhyZWFkLmpvaW4oKQogICAgICAgIGlmIHNlbGYucXVldWVfbXNnIGlzIG5vdCBOb25lOgogICAgICAgICAgICBzZWxmLnF1ZXVlX21zZy5qb2luKCkKICAgICAgICBpZiBzZWxmLnF1ZXVlX21zZ19sb2NrIGlzIG5vdCBOb25lOgogICAgICAgICAgICBzZWxmLnF1ZXVlX21zZ19sb2NrLnJlbGVhc2UoKQogICAgICAgIGlmIHNlbGYuZXZlbnRfZmlyZV9tc2cgaXMgbm90IE5vbmU6CiAgICAgICAgICAgIHNlbGYuZXZlbnRfZmlyZV9tc2cuY2xlYXIoKQoKICAgICAgICAjIGNsZWFyIHRoZSBwYXRoIGZyb20gdGhlIHRhYmxlIHZpZXcKICAgICAgICBkZWwgc2VsZi5wYXRoCgogICAgZGVmIGluaXRfc2NyaXB0X3BhdGgoc2VsZiwgYnRuIDogYm9vbCA9IEZhbHNlKToKICAgICAgICAiIiIKICAgICAgICAgICAgQ2hlY2sgaWYgdGhlIGJ1dHRvbiBpcyBwcmVzc2VkIGFuZCBsb2FkL2NoYW5nZSBwYXRoIHNjcmlwdC4KICAgICAgICAgICAgCiAgICAgICAgICAgIDpwYXJhbSBidG46IEEgYm9vbGVhbiBvZiB0aGUgYnV0dG9uCiAgICAgICAgIiIiCiAgICAgICAgIyBjaGVjayBpZiBidXR0b24gaXMgcHJlc3NlZAogICAgICAgIGlmIGJ0biBpcyBUcnVlOgogICAgICAgICAgICBkaWFsb2cgPSBTeXN0ZW0uV2luZG93cy5Gb3Jtcy5PcGVuRmlsZURpYWxvZygpCiAgICAgICAgICAgIGRpYWxvZy5GaWx0ZXIgPSAiUHl0aG9uIGZpbGVzICgqLnB5KXwqLnB5IgogICAgICAgICAgICBkaWFsb2cuVGl0bGUgPSAiU2VsZWN0IGEgUHl0aG9uIGZpbGUiCiAgICAgICAgICAgIGRpYWxvZy5Jbml0aWFsRGlyZWN0b3J5ID0gb3MucGF0aC5kaXJuYW1lKCIiKQogICAgICAgICAgICBkaWFsb2cuRmlsZU5hbWUgPSAiIgogICAgICAgICAgICBkaWFsb2cuTXVsdGlzZWxlY3QgPSBGYWxzZQogICAgICAgICAgICBkaWFsb2cuQ2hlY2tGaWxlRXhpc3RzID0gVHJ1ZQogICAgICAgICAgICBkaWFsb2cuQ2hlY2tQYXRoRXhpc3RzID0gVHJ1ZQogICAgICAgICAgICBkaWFsb2cuUmVzdG9yZURpcmVjdG9yeSA9IFRydWUKICAgICAgICAgICAgaWYgZGlhbG9nLlNob3dEaWFsb2coKSA9PSBTeXN0ZW0uV2luZG93cy5Gb3Jtcy5EaWFsb2dSZXN1bHQuT0s6CiAgICAgICAgICAgICAgICBzZWxmLnBhdGggPSBkaWFsb2cuRmlsZU5hbWUKCiAgICAgICAgIyBkZWZhdWx0IGluaXQgc3RhdXRzCiAgICAgICAgaWYgc2VsZi5wYXRoIGlzIE5vbmU6CiAgICAgICAgICAgIHJhaXNlIEV4Y2VwdGlvbigic2NyaXB0LXN5bmM6OkZpbGUgbm90IHNlbGVjdGVkIikKCiAgICAgICAgIyBmaSBmaWxlIGlzIGluIHRhYmxlIHZpZXcgYmVmb3JlCiAgICAgICAgaWYgbm90IG9zLnBhdGguZXhpc3RzKHNlbGYucGF0aCk6CiAgICAgICAgICAgIHJhaXNlIEV4Y2VwdGlvbigic2NyaXB0LXN5bmM6OkZpbGUgZG9lcyBub3QgZXhpc3QiKQogICAgCiAgICBkZWYgcmVsb2FkX2FsbF9tb2R1bGVzKHNlbGYsIGRpcmVjdG9yeSk6CiAgICAgICAgIiIiCiAgICAgICAgICAgIFJlbG9hZCBhbGwgdGhlIG1vZHVsZXMgKGxvY2FsIGZpbGVzKSBpbiB0aGUgZGlyZWN0b3J5IG9mIHRoZSBzY3JpcHQuCgogICAgICAgICAgICA6cGFyYW0gZGlyZWN0b3J5OiBUaGUgZGlyZWN0b3J5IG9mIHRoZSBzY3JpcHQuCiAgICAgICAgIiIiCiAgICAgICAgZm9yIGZpbGVuYW1lIGluIG9zLmxpc3RkaXIoZGlyZWN0b3J5KToKICAgICAgICAgICAgaWYgZmlsZW5hbWUuZW5kc3dpdGgoJy5weScpIGFuZCBmaWxlbmFtZSAhPSAnX19pbml0X18ucHknOgogICAgICAgICAgICAgICAgbW9kdWxlX25hbWUgPSBmaWxlbmFtZVs6LTNdICAjIHJlbW92ZSAnLnB5JyBmcm9tIGZpbGVuYW1lCiAgICAgICAgICAgICAgICBpZiBtb2R1bGVfbmFtZSBpbiBzeXMubW9kdWxlczoKICAgICAgICAgICAgICAgICAgICBpbXBvcnRsaWIucmVsb2FkKHN5cy5tb2R1bGVzW21vZHVsZV9uYW1lXSkKCiAgICBkZWYgZ2V0X3JlbG9hZGFibGVfcGFja2FnZXMoc2VsZik6CiAgICAgICAgIiIiCiAgICAgICAgICAgIEdldCBhbGwgdGhlIHJlbG9hZGFibGUgbW9kdWxlcyBmcm9tIHRoZSBzeXMubW9kdWxlcy4gSXQKICAgICAgICAgICAgbWFrZSBzdXJlIHRvIGNoZWNrIHRoZSBtb2R1bGUgc3BlYyBhbmQgbG9hZGVyIHRvIG9ubHkgcmVsb2FkIG1vZHVsZXMgCiAgICAgICAgICAgIHRoYXQgYXJlIGFjdHVhbGx5IGxvYWRlZCBmcm9tIGEgZmlsZSBvciBkaXJlY3RvcnkKCiAgICAgICAgICAgIDpyZXR1cm46IFRoZSBsaXN0IG9mIHJlbG9hZGFibGUgbW9kdWxlcy4KICAgICAgICAiIiIKICAgICAgICBCVUlMVElOX09SSUdJTlMgPSBbJ2J1aWx0LWluJywgJ2Zyb3plbiddCiAgICAgICAgcmVsb2FkYWJsZXMgPSBbXQogICAgICAgIGZvciBtIGluIHN5cy5tb2R1bGVzLnZhbHVlcygpOgogICAgICAgICAgICBpZiBpbnNwZWN0LmlzbW9kdWxlKG0pOgogICAgICAgICAgICAgICAgc3BlYyA9IGdldGF0dHIobSwgIl9fc3BlY19fIiwgTm9uZSkKICAgICAgICAgICAgICAgIGlmIHNwZWM6CiAgICAgICAgICAgICAgICAgICAgaWYgc3BlYy5vcmlnaW4gaW4gQlVJTFRJTl9PUklHSU5TIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yIGlzaW5zdGFuY2Uoc3BlYy5sb2FkZXIsIGltcG9ydGxpYi5tYWNoaW5lcnkuU291cmNlbGVzc0ZpbGVMb2FkZXIpOgogICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICAgICAgcmVsb2FkYWJsZXMuYXBwZW5kKG0pCgogICAgICAgIHJldHVybiByZWxvYWRhYmxlcwoKICAgIGRlZiBzYWZlX2V4ZWMoc2VsZiwgcGF0aCwgZ2xvYmFscywgbG9jYWxzLCBwYWNrYWdlc18yX3JlbG9hZCk6CiAgICAgICAgIiIiCiAgICAgICAgICAgIEV4ZWN1dGUgUHl0aG9uMyBjb2RlIHNhZmVseS4gSXQgcmVkaXJlY3RzIHRoZSBvdXRwdXQgb2YgdGhlIGNvZGUKICAgICAgICAgICAgdG8gYSBzdHJpbmcgYnVmZmVyICdzdGRvdXQnIHRvIG91dHB1dCB0byB0aGUgR0ggY29tcG9uZW50IHBhcmFtLgogICAgICAgICAgICBJdCBpcyBzZW5kIHRvIHRoZSB2c2NvZGUgc2VydmVyLgogICAgICAgICAgICAKICAgICAgICAgICAgOnBhcmFtIHBhdGg6IFRoZSBwYXRoIG9mIHRoZSBmaWxlIHRvIGV4ZWN1dGUuCiAgICAgICAgICAgIDpwYXJhbSBnbG9iYWxzOiBUaGUgZ2xvYmFscyBkaWN0aW9uYXJ5LgogICAgICAgICAgICA6cGFyYW0gbG9jYWxzOiBUaGUgbG9jYWxzIGRpY3Rpb25hcnkuCiAgICAgICAgICAgIDpwYXJhbSBwYWNrYWdlc18yX3JlbG9hZDogVGhlIGxpc3Qgb2YgcGFja2FnZXMgdG8gcmVsb2FkLCB0aGlzIGlzIHVzZWQgZm9yIGN1c3RvbSBwYWNrYWdlcyBkZXZlbG9wZW1lbnQuCiAgICAgICAgICAgIGluc3RhbGxlZCBvbiB0aGUgc3lzdGVtIHZpYSBhbiBlZGl0YWJsZSBwaXAgaW5zdGFsbGF0aW9uIGZvciBleGFtcGxlLgogICAgICAgICIiIgogICAgICAgIHRyeToKICAgICAgICAgICAgd2l0aCBvcGVuKHBhdGgsICdyJykgYXMgZjoKICAgICAgICAgICAgICAgICMgcmVsb2FkIHRoZSBzcGVjaWZ5ZWQgcGFja2FnZXMKICAgICAgICAgICAgICAgICMgcmVsb2FkYWJsZXMgPSBzZWxmLmdldF9yZWxvYWRhYmxlX3BhY2thZ2VzKCkKICAgICAgICAgICAgICAgICMgIyBpZiBwYWNrYWdlc18yX3JlbG9hZCBpcyBub3QgTm9uZToKICAgICAgICAgICAgICAgICMgIyAgICAgaWYgcGFja2FnZXNfMl9yZWxvYWQuX19sZW5fXygpICE9IDA6CiAgICAgICAgICAgICAgICAjICMgICAgICAgICBmb3IgcGFja2FnZSBpbiBwYWNrYWdlc18yX3JlbG9hZDoKICAgICAgICAgICAgICAgICMgIyAgICAgICAgICAgICBpZiBwYWNrYWdlIGluIHJlbG9hZGFibGVzOgogICAgICAgICAgICAgICAgIyAjICAgICAgICAgICAgICAgICBpbXBvcnRsaWIucmVsb2FkKHBhY2thZ2UpCiAgICAgICAgICAgICAgICAjIGZvciBwYWNrYWdlIGluIHBhY2thZ2VzXzJfcmVsb2FkOgogICAgICAgICAgICAgICAgIyAgICAgaWYgcGFja2FnZSBpbiByZWxvYWRhYmxlczoKICAgICAgICAgICAgICAgICMgICAgICAgICBpbXBvcnRsaWIucmVsb2FkKHBhY2thZ2UpCgogICAgICAgICAgICAgICAgIyBhZGQgdGhlIHBhdGggYW5kIHN1YiBkaXJlY3RvcmllcyB0byAgdGhlIHN5cyBwYXRoCiAgICAgICAgICAgICAgICBwYXRoX2RpciA9IG9zLnBhdGguZGlybmFtZShwYXRoKQogICAgICAgICAgICAgICAgc3ViX2RpcnMgPSBbXQogICAgICAgICAgICAgICAgZm9yIHJvb3QsIGRpcnMsIGZpbGVzIGluIG9zLndhbGsocGF0aF9kaXIpOgogICAgICAgICAgICAgICAgICAgIGZvciBkIGluIGRpcnM6CiAgICAgICAgICAgICAgICAgICAgICAgIHN1Yl9kaXJzLmFwcGVuZChvcy5wYXRoLmpvaW4ocm9vdCwgZCkpCiAgICAgICAgICAgICAgICBzeXMucGF0aC5leHRlbmQoW3BhdGhfZGlyXSArIHN1Yl9kaXJzKQoKICAgICAgICAgICAgICAgICMgcmVsb2FkIGFsbCB0aGUgbW9kdWxlcyBhbHNvIG9mIHRoZSBzdWIgZGlyZWN0b3JpZXMKICAgICAgICAgICAgICAgIGZvciByb290LCBkaXJzLCBmaWxlcyBpbiBvcy53YWxrKHBhdGhfZGlyKToKICAgICAgICAgICAgICAgICAgICBmb3IgZCBpbiBkaXJzOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnJlbG9hZF9hbGxfbW9kdWxlcyhvcy5wYXRoLmpvaW4ocm9vdCwgZCkpCiAgICAgICAgICAgICAgICBzZWxmLnJlbG9hZF9hbGxfbW9kdWxlcyhwYXRoX2RpcikKCiAgICAgICAgICAgICAgICAjIHJlZnJlc2ggdGhlIHB5dGhvbiBpbnRlcnByZXRlcgogICAgICAgICAgICAgICAgaW1wb3J0bGliLmludmFsaWRhdGVfY2FjaGVzKCkKCiAgICAgICAgICAgICAgICAjIHBhcnNlIHRoZSBjb2RlCiAgICAgICAgICAgICAgICBjb2RlID0gY29tcGlsZShmLnJlYWQoKSwgcGF0aCwgJ2V4ZWMnKQogICAgICAgICAgICAgICAgb3V0cHV0ID0gaW8uU3RyaW5nSU8oKQoKICAgICAgICAgICAgICAgICMgZW1wdHkgdGhlIHF1ZXVlIGFuZCBldmVudAogICAgICAgICAgICAgICAgd2l0aCBzZWxmLnF1ZXVlX21zZ19sb2NrOgogICAgICAgICAgICAgICAgICAgIHdoaWxlIG5vdCBzZWxmLnF1ZXVlX21zZy5lbXB0eSgpOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnF1ZXVlX21zZy5nZXQoKQogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnF1ZXVlX21zZy50YXNrX2RvbmUoKQogICAgICAgICAgICAgICAgc2VsZi5ldmVudF9maXJlX21zZy5jbGVhcigpCgogICAgICAgICAgICAgICAgIyBleGVjdXRlIHRoZSBjb2RlCiAgICAgICAgICAgICAgICB3aXRoIGNvbnRleHRsaWIucmVkaXJlY3Rfc3Rkb3V0KG91dHB1dCk6CiAgICAgICAgICAgICAgICAgICAgZXhlYyhjb2RlLCBnbG9iYWxzLCBsb2NhbHMpCiAgICAgICAgICAgICAgICBsb2NhbHNbInN0ZG91dCJdID0gb3V0cHV0LmdldHZhbHVlKCkKCiAgICAgICAgICAgICAgICAjIHNlbmQgdGhlIG1zZyB0byB0aGUgdnNjb2RlIHNlcnZlcgogICAgICAgICAgICAgICAgbXNnX2pzb24gPSBqc29uLmR1bXBzKHsic2NyaXB0X3BhdGgiOiBwYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZ3VpZCI6IHN0cihnaGVudi5Db21wb25lbnQuSW5zdGFuY2VHdWlkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1zZyI6IG91dHB1dC5nZXR2YWx1ZSgpfSkKICAgICAgICAgICAgICAgIG1zZ19qc29uID0gbXNnX2pzb24uZW5jb2RlKCd1dGYtOCcpCiAgICAgICAgICAgICAgICBzZWxmLnF1ZXVlX21zZy5wdXQobXNnX2pzb24pCiAgICAgICAgICAgICAgICBzZWxmLmV2ZW50X2ZpcmVfbXNnLnNldCgpCgogICAgICAgICAgICAgICAgIyBwYXNzIHRoZSBzY3JpcHQgdmFyaWFibGVzIHRvIHRoZSBHSCBjb21wb25lbnQgb3V0cHV0cwogICAgICAgICAgICAgICAgb3V0cGFyYW0gPSBnaGVudi5Db21wb25lbnQuUGFyYW1zLk91dHB1dAogICAgICAgICAgICAgICAgb3V0cGFyYW1fbmFtZXMgPSBbcC5OaWNrTmFtZSBmb3IgcCBpbiBvdXRwYXJhbV0KICAgICAgICAgICAgICAgIGZvciBvdXRwIGluIG91dHBhcmFtX25hbWVzOgogICAgICAgICAgICAgICAgICAgIGlmIG91dHAgaW4gbG9jYWxzLmtleXMoKToKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fdmFyX291dHB1dC5hcHBlbmQobG9jYWxzW291dHBdKQogICAgICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3Zhcl9vdXRwdXQuYXBwZW5kKE5vbmUpCgogICAgICAgICAgICAgICAgc3lzLnN0ZG91dCA9IHN5cy5fX3N0ZG91dF9fCiAgICAgICAgICAgIHJldHVybiBsb2NhbHMKCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoKICAgICAgICAgICAgIyBzZW5kIHRoZSBlcnJvciBtZXNzYWdlIHRvIHRoZSB2c2NvZGUgc2VydmVyCiAgICAgICAgICAgIGVycl9qc29uID0ganNvbi5kdW1wcyh7InNjcmlwdF9wYXRoIjogcGF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImd1aWQiOiBzdHIoZ2hlbnYuQ29tcG9uZW50Lkluc3RhbmNlR3VpZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtc2ciOiAiZXJyOiIgKyBzdHIoZSl9KQogICAgICAgICAgICBlcnJfanNvbiA9IGVycl9qc29uLmVuY29kZSgndXRmLTgnKQogICAgICAgICAgICBzZWxmLnF1ZXVlX21zZy5wdXQoZXJyX2pzb24pCiAgICAgICAgICAgIHNlbGYuZXZlbnRfZmlyZV9tc2cuc2V0KCkKICAgICAgICAgICAgCiAgICAgICAgICAgIHN5cy5zdGRvdXQgPSBzeXMuX19zdGRvdXRfXwoKICAgICAgICAgICAgZXJyX21zZyA9IGYic2NyaXB0LXN5bmM6OkVycm9yIGluIHRoZSBjb2RlOiB7c3RyKGUpfSIKICAgICAgICAgICAgcmFpc2UgRXhjZXB0aW9uKGVycl9tc2cpCgogICAgZGVmIFJ1blNjcmlwdChzZWxmLAogICAgICAgICAgICBidG46IGJvb2wsCiAgICAgICAgICAgIHBhY2thZ2VzXzJfcmVsb2FkOiBTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5JTGlzdFtvYmplY3RdLAogICAgICAgICAgICBpX2V4cG9ydF9kaXIsCiAgICAgICAgICAgIGlfYnJlcHM6IFN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLklMaXN0W1JoaW5vLkdlb21ldHJ5LkJyZXBdLAogICAgICAgICAgICBpX2Fzc2VtYmx5X25hbWUsCiAgICAgICAgICAgIGlfZHVtcDogYm9vbCk6CiAgICAgICAgIiIiIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCB3aGVuZXZlciB0aGUgY29tcG9uZW50IGhhcyB0byBiZSByZWNhbGN1bGF0ZWQgaXQncyB0aGUgc29sdmUgbWFpbiBpbnN0YW5jZS4gIiIiCiAgICAgICAgc2VsZi5pc19zdWNjZXNzID0gRmFsc2UKCiAgICAgICAgIyBzZXQgdGhlIHBhdGggaWYgYnV0dG9uIGlzIHByZXNzZWQKICAgICAgICBzZWxmLmluaXRfc2NyaXB0X3BhdGgoYnRuKQoKICAgICAgICAjIGZpbGUgY2hhbmdlIGxpc3RlbmVyIHRocmVhZAogICAgICAgIGlmIHNlbGYuZmlsZWNoYW5nZWRfdGhyZWFkX25hbWUgbm90IGluIFt0Lm5hbWUgZm9yIHQgaW4gdGhyZWFkaW5nLmVudW1lcmF0ZSgpXToKICAgICAgICAgICAgRmlsZUNoYW5nZWRUaHJlYWQoc2VsZi5wYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmZpbGVjaGFuZ2VkX3RocmVhZF9uYW1lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkuc3RhcnQoKQoKICAgICAgICAjIHNldCB1cCB0aGUgdGNwIGNsaWVudCB0byBjb25uZWN0IHRvIHRoZSB2c2NvZGUgc2VydmVyCiAgICAgICAgXyA9IFtwcmludCh0Lm5hbWUpIGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKV0KICAgICAgICBpZiBzZWxmLmNsaWVudF90aHJlYWRfbmFtZSBub3QgaW4gW3QubmFtZSBmb3IgdCBpbiB0aHJlYWRpbmcuZW51bWVyYXRlKCldOgogICAgICAgICAgICBDbGllbnRUaHJlYWQoc2VsZi52c2NvZGVfc2VydmVyX2lwLAogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnZzY29kZV9zZXJ2ZXJfcG9ydCwKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5jbGllbnRfdGhyZWFkX25hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucXVldWVfbXNnLAogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnF1ZXVlX21zZ19sb2NrLAogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmV2ZW50X2ZpcmVfbXNnCiAgICAgICAgICAgICAgICAgICAgICAgICkuc3RhcnQoKQoKICAgICAgICAjIGFkZCB0byB0aGUgZ2xvYmFscyBhbGwgdGhlIGlucHV0IHBhcmFtZXRlcnMgb2YgdGhlIGNvbXBvbmVudCAodGhlIGxvY2FscykKICAgICAgICBnbG9iYWxzKCkudXBkYXRlKGxvY2FscygpKQoKICAgICAgICByZXMgPSBzZWxmLnNhZmVfZXhlYyhzZWxmLnBhdGgsIE5vbmUsIGdsb2JhbHMoKSwgcGFja2FnZXNfMl9yZWxvYWQpCiAgICAgICAgc2VsZi5pc19zdWNjZXNzID0gVHJ1ZQogICAgICAgIHJldHVybgoKICAgIGRlZiBBZnRlclJ1blNjcmlwdChzZWxmKToKICAgICAgICAiIiIKICAgICAgICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIGFzIHNvb24gYXMgdGhlIGNvbXBvbmVudCBoYXMgZmluaXNoZWQKICAgICAgICAgICAgaXRzIGNhbGN1bGF0aW9uLiBJdCBpcyB1c2VkIHRvIGxvYWQgdGhlIEdIQ29tcG9uZW50IG91dHB1dHMKICAgICAgICAgICAgd2l0aCB0aGUgdmFsdWVzIGNyZWF0ZWQgaW4gdGhlIHNjcmlwdC4KICAgICAgICAiIiIKICAgICAgICBpZiBub3Qgc2VsZi5pc19zdWNjZXNzOgogICAgICAgICAgICByZXR1cm4KICAgICAgICBvdXRwYXJhbSA9IFtwIGZvciBwIGluIGdoZW52LkNvbXBvbmVudC5QYXJhbXMuT3V0cHV0XQogICAgICAgIG91dHBhcmFtX25hbWVzID0gW3AuTmlja05hbWUgZm9yIHAgaW4gb3V0cGFyYW1dCiAgICAgICAgCiAgICAgICAgIyBUT0RPOiBhZGQgdGhlIGNvbnZlcnNpb24gdG8gZGF0YXRyZWUgZm9yIG5lc3RlZCBsaXN0cyBhbmQgdHVwbGVzCiAgICAgICAgZm9yIGlkeCwgb3V0cCBpbiBlbnVtZXJhdGUob3V0cGFyYW0pOgogICAgICAgICAgICAjIGRldGVjdCBpZiB0aGUgb3V0cHV0IGlzIGEgbGlzdAogICAgICAgICAgICBpZiB0eXBlKHNlbGYuX3Zhcl9vdXRwdXRbaWR4XSkgPT0gbGlzdCBvciB0eXBlKHNlbGYuX3Zhcl9vdXRwdXRbaWR4XSkgPT0gdHVwbGU6CiAgICAgICAgICAgICAgICBnaGVudi5Db21wb25lbnQuUGFyYW1zLk91dHB1dFtpZHhdLlZvbGF0aWxlRGF0YS5DbGVhcigpCiAgICAgICAgICAgICAgICBnaGVudi5Db21wb25lbnQuUGFyYW1zLk91dHB1dFtpZHhdLkFkZFZvbGF0aWxlRGF0YUxpc3QoZ2guS2VybmVsLkRhdGEuR0hfUGF0aCgwKSwgc2VsZi5fdmFyX291dHB1dFtpZHhdKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZ2hlbnYuQ29tcG9uZW50LlBhcmFtcy5PdXRwdXRbaWR4XS5Wb2xhdGlsZURhdGEuQ2xlYXIoKQogICAgICAgICAgICAgICAgZ2hlbnYuQ29tcG9uZW50LlBhcmFtcy5PdXRwdXRbaWR4XS5BZGRWb2xhdGlsZURhdGEoZ2guS2VybmVsLkRhdGEuR0hfUGF0aCgwKSwgMCwgc2VsZi5fdmFyX291dHB1dFtpZHhdKQogICAgICAgIHNlbGYuX3Zhcl9vdXRwdXQuY2xlYXIoKQoKICAgIEBwcm9wZXJ0eQogICAgZGVmIHBhdGgoc2VsZik6CiAgICAgICAgIiIiIEdldCB0aGUgcGF0aCBvZiB0aGUgZmlsZSBmcm9tIHRoZSB0YWJsZSB2aWV3IHRvIGJlIHN0aWNraW5nIGJldHdlZW4gdGhlIHNlc3Npb25zLiAiIiIKICAgICAgICB0YWJsZV92YWx1ZSA9IGdoZW52LkNvbXBvbmVudC5PblBpbmdEb2N1bWVudCgpLlZhbHVlVGFibGUuR2V0VmFsdWUoCiAgICAgICAgICAgIHNlbGYuX19wYXRoX25hbWVfdGFibGVfdmFsdWUsICJub3RfZm91bmQiCiAgICAgICAgKQogICAgICAgIGlmIHRhYmxlX3ZhbHVlICE9ICJub3RfZm91bmQiOgogICAgICAgICAgICByZXR1cm4gdGFibGVfdmFsdWUKICAgICAgICBlbHNlOgogICAgICAgICAgICByZXR1cm4gTm9uZQoKICAgIEBwYXRoLnNldHRlcgogICAgZGVmIHBhdGgoc2VsZiwgcGF0aCA6IHN0cik6CiAgICAgICAgIiIiIFNldCB0aGUgcGF0aCBvZiB0aGUgZmlsZSB0byB0aGUgdGFibGUgdmlldyB0byBiZSBzdGlja2luZyBiZXR3ZWVuIHRoZSBzZXNzaW9ucy4gIiIiCiAgICAgICAgZ2hlbnYuQ29tcG9uZW50Lk9uUGluZ0RvY3VtZW50KCkuVmFsdWVUYWJsZS5TZXRWYWx1ZShzZWxmLl9fcGF0aF9uYW1lX3RhYmxlX3ZhbHVlLCBwYXRoKQoKICAgICAgICBzY3JpcHRfbmFtZSA9IG9zLnBhdGguYmFzZW5hbWUocGF0aCkKICAgICAgICBnaGVudi5Db21wb25lbnQuTWVzc2FnZSA9IGYie3NjcmlwdF9uYW1lfSIKCiAgICAgICAgaWYgc2VsZi5maWxlY2hhbmdlZF90aHJlYWRfbmFtZSBpbiBbdC5uYW1lIGZvciB0IGluIHRocmVhZGluZy5lbnVtZXJhdGUoKV06CiAgICAgICAgICAgIF8gPSBbdCBmb3IgdCBpbiB0aHJlYWRpbmcuZW51bWVyYXRlKCkgaWYgdC5uYW1lID09IHNlbGYuZmlsZWNoYW5nZWRfdGhyZWFkX25hbWVdWzBdLnN0b3AoKQoKICAgIEBwYXRoLmRlbGV0ZXIKICAgIGRlZiBwYXRoKHNlbGYpOgogICAgICAgICIiIiBEZWxldGUgdGhlIHBhdGggb2YgdGhlIGZpbGUgZnJvbSB0aGUgdGFibGUgdmlldyBpZiB0aGUgb2JqZWN0IGlzIGVyYXNlZC4gIiIiCiAgICAgICAgZ2hlbnYuQ29tcG9uZW50Lk9uUGluZ0RvY3VtZW50KCkuVmFsdWVUYWJsZS5EZWxldGVWYWx1ZShzZWxmLl9fcGF0aF9uYW1lX3RhYmxlX3ZhbHVlKQo= + S + + + + + *.*.python + 3.* + + + + + + + + + + + a8b97322-2d53-47cd-905e-b932c3ccd74e + Button + + + + + Button object with two values + False + True + 37a1fdbe-f895-4bf0-a740-19a73fe2889b + Button + + false + 0 + + + + + + 133 + 510 + 66 + 22 + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + d9f12976-f7f0-40a9-a06e-c4e80b19529d + Panel + + false + 0 + 0 + diffCheck + + + + + + -20 + 551 + 113 + 38 + + 0 + 0 + 0 + + -19.14932 + 551.1913 + + + + + + + 255;213;217;232 + + true + true + false + false + false + true + + + + + + + + + 06953bda-1d37-4d58-9b38-4b3c74e54c8f + File Path + + + + + Contains a collection of file paths + false + All files|*.* + bee0b3ef-7bf0-49f6-8e1d-71c7765756d0 + File Path + Path + false + 0 + + + + + + 135 + 582 + 50 + 24 + + + 160.70218 + 594.44104 + + + + + + 1 + + + + + 1 + {0} + + + + + false + F:\diffCheck\temp\ + + + + + + + + + + + + + 919e146f-30ae-4aae-be34-4d72f555e7da + Brep + + + + + Contains a collection of Breps (Boundary REPresentations) + true + a126a588-53d2-4d08-977f-68deff6a42c2 + Brep + Brep + false + 0 + + + + + + 136 + 613 + 50 + 24 + + + 161.0756 + 625.8681 + + + + + + 1 + + + + + 1 + {0} + + + + + 5981a85d-0063-489b-8bd7-7a1ebe1453a7 + + + + + + + + + + + + + a8b97322-2d53-47cd-905e-b932c3ccd74e + Button + + + + + Button object with two values + False + True + 51a09241-6321-4d8b-bfc9-536b009c6410 + Button + dump! + false + 0 + + + + + + 88 + 674 + 102 + 22 + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + aedebb31-f342-420e-ac55-d80e788a157f + Panel + + false + 0 + 0 + AssemblyTest + + + + + + 91 + 649 + 102 + 20 + + 0 + 0 + 0 + + 91.80564 + 649.3606 + + + + + + + 255;213;217;232 + + true + true + true + false + false + true + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + dbcb817b-1342-4c31-96a8-a828fd3f41e1 + Panel + + false + 1 + eba563ee-7094-4907-b35a-ee3a9d076495 + 1 + Double click to edit panel content… + + + + + + 509 + 403 + 494 + 251 + + 0 + 0 + 0 + + 509.25073 + 403.22205 + + + + + + + 255;213;217;232 + + true + true + true + false + false + true + + + + + + + + + + + + + + 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 + + + + + \ No newline at end of file diff --git a/src/gh/util/componentizer_cpy.py b/src/gh/util/componentizer_cpy.py new file mode 100644 index 00000000..cdffe828 --- /dev/null +++ b/src/gh/util/componentizer_cpy.py @@ -0,0 +1,408 @@ +import argparse +import base64 +import json +import os +import re +import sys +import tempfile +import urllib.request, urllib.parse, urllib.error +import zipfile +from io import BytesIO + +import clr +import System +import System.IO + + +SCRIPT_COMPONENT_GUID = System.Guid("c9b2d725-6f87-4b07-af90-bd9aefef68eb") +CPY_VER = "3.-1" +TEMPLATE_VER = re.compile("{{version}}") +TEMPLATE_NAME = re.compile("{{name}}") +TEMPLATE_GHUSER_NAME = re.compile("{{ghuser_name}}") + +TYPES_MAP = dict( + none="6a184b65-baa3-42d1-a548-3915b401de53", + ghdoc="1c282eeb-dd16-439f-94e4-7d92b542fe8b", + float="9d51e32e-c038-4352-9554-f4137ca91b9a", + bool="d60527f5-b5af-4ef6-8970-5f96fe412559", + int="48d01794-d3d8-4aef-990e-127168822244", + complex="309690df-6229-4774-91bb-b1c9c0bfa54d", + str="3aceb454-6dbd-4c5b-9b6b-e71f8c1cdf88", + datetime="09bcf900-fe83-4efa-8d32-33d89f7a3e66", + guid="5325b8e1-51d7-4d36-837a-d98394626c35", + color="24b1d1a3-ab79-498c-9e44-c5b14607c4d3", + point="e1937b56-b1da-4c12-8bd8-e34ee81746ef", + vector="15a50725-e3d3-4075-9f7c-142ba5f40747", + plane="3897522d-58e9-4d60-b38c-978ddacfedd8", + interval="589748aa-e558-4dd9-976f-78e3ab91fc77", + uvinterval="74c906f3-db02-4cea-bd58-de375cb5ae73", + box="f29cb021-de79-4e63-9f04-fc8e0df5f8b6", + transform="c4b38e4c-21ff-415f-a0d1-406d282428dd", + line="f802a8cd-e699-4a94-97ea-83b5406271de", + circle="3c5409a1-3293-4181-a6fa-c24c37fc0c32", + arc="9c80ec18-b48c-41b0-bc6e-cd93d9c916aa", + polyline="66fa617b-e3e8-4480-9f1e-2c0688c1d21b", + rectangle="83da014b-a550-4bf5-89ff-16e54225bd5d", + curve="9ba89ec2-5315-435f-a621-b66c5fa2f301", + mesh="794a1f9d-21d5-4379-b987-9e8bbf433912", + surface="f4070a37-c822-410f-9057-100d2e22a22d", + subd="20f4ca9c-6c90-4fd6-ba8a-5bf9ca79db08", + brep="2ceb0405-fdfe-403d-a4d6-8786da45fb9d", + geometrybase="c37956f4-d39c-49c7-af71-1e87f8031b26" +) + +EXPOSURE = dict(valid=set([-1, 2, 4, 8, 16, 32, 64, 128]), default=2) +ACCESS = dict(valid=set([0, 1, 2]), map=dict(item=0, list=1, tree=2), default=0) +PARAM_TYPE = dict( + valid=set(TYPES_MAP.values()), map=TYPES_MAP, default=TYPES_MAP["ghdoc"] +) +WIRE_DISPLAY = dict( + valid=set([0, 1, 2]), map=dict(default=0, faint=1, hidden=2), default=0 +) + + +def fetch_ghio_lib(target_folder="temp"): + """Fetch the GH_IO.dll library from the NuGet packaging system.""" + ghio_dll = "GH_IO.dll" + filename = "lib/net48/" + ghio_dll + + response = urllib.request.urlopen("https://www.nuget.org/api/v2/package/Grasshopper/") + dst_file = os.path.join(target_folder, ghio_dll) + zip_file = zipfile.ZipFile(BytesIO(response.read())) + + with zip_file.open(filename, "r") as zipped_dll: + with open(dst_file, "wb") as fp: + fp.write(zipped_dll.read()) + + return dst_file + + +def find_ghio_assembly(libdir): + for root, _dirs, files in os.walk(libdir): + for basename in files: + if basename.upper() == "GH_IO.DLL": + filename = os.path.join(root, basename) + return filename + + +def bitmap_from_image_path(image_path): + with open(image_path, "rb") as imageFile: + # Ensure img_string is a string, not a bytes object + img_string = base64.b64encode(imageFile.read()) + if isinstance(img_string, bytes): + img_string = img_string.decode() + + # Now you can pass img_string to the FromBase64String method + return System.Convert.FromBase64String(img_string) + # return System.Convert.FromBase64String(img_string) + + +def validate_source_bundle(source): + icon = os.path.join(source, "icon.png") + code = os.path.join(source, "code.py") + data = os.path.join(source, "metadata.json") + + if not os.path.exists(icon): + raise ValueError( + "icon missing, make sure icon.png is present in the source bundle: {}".format( + source + ) + ) + if not os.path.exists(code): + raise ValueError( + "code missing, make sure code.py is present in the source bundle: {}".format( + source + ) + ) + if not os.path.exists(data): + raise ValueError( + "metadata missing, make sure metadata.json is present in the source bundle: {}".format( + source + ) + ) + + icon = bitmap_from_image_path(icon) + + with open(code, "r") as f: + python_code = f.read() + + with open(data, "r") as f: + data = json.load(f) + + if "exposure" not in data: + data["exposure"] = EXPOSURE["default"] + + if data["exposure"] not in EXPOSURE["valid"]: + raise ValueError( + "Invalid exposure value. Accepted values are {}".format( + sorted(EXPOSURE["valid"]) + ) + ) + + ghpython = data.get("ghpython") + + if r'"""' not in python_code: + python_code = r'"""{}"""{}{}'.format( + data.get("description", "Generated by Componentizer"), + os.linesep, + python_code, + ) + + return icon, python_code, data + + +def parse_param_access(access): + try: + access = int(access) + except ValueError: + # Maybe string? + access = ACCESS["map"].get(access) + + if access not in ACCESS["valid"]: + raise ValueError( + "Invalid param access value. Valid values are {}".format( + sorted(ACCESS["valid"]) + ) + ) + + return access + + +def parse_wire_display(wire_display): + try: + wire_display = int(wire_display) + except ValueError: + wire_display = WIRE_DISPLAY["map"].get(wire_display) + + if wire_display not in WIRE_DISPLAY["valid"]: + raise ValueError( + "Invalid wire display value. Valid values are {}".format( + sorted(WIRE_DISPLAY["valid"]) + ) + ) + + return wire_display + + +def parse_param_type_hint(type_hint_id): + type_hint_id = type_hint_id or PARAM_TYPE["default"] + + if type_hint_id in TYPES_MAP: + type_hint_id = TYPES_MAP[type_hint_id] + + if type_hint_id not in PARAM_TYPE["valid"]: + raise ValueError( + 'Invalid param type hint ID ("{}"). Valid values are {}'.format( + type_hint_id, sorted(PARAM_TYPE["valid"]) + ) + ) + + try: + type_hint_id = System.Guid.Parse(type_hint_id) + except SystemError: + raise ValueError("Unable to parse type hint ID: {}".format(type_hint_id)) + + return type_hint_id + + +def replace_templates(code, version, name, ghuser_name): + if version: + code = TEMPLATE_VER.sub(version, code) + + code = TEMPLATE_NAME.sub(name, code) + code = TEMPLATE_GHUSER_NAME.sub(ghuser_name, code) + + return code + + +def create_ghuser_component(source, target, version=None, prefix=None): + from GH_IO.Serialization import GH_LooseChunk + + icon, code, data = validate_source_bundle(source) + + code = replace_templates(code, version, data["name"], os.path.basename(target)) + + instance_guid = data.get("instanceGuid") + if not instance_guid: + instance_guid = System.Guid.NewGuid() + else: + instance_guid = System.Guid.Parse(instance_guid) + + prefix = prefix or "" + + root = GH_LooseChunk("UserObject") + root.SetGuid("BaseID", SCRIPT_COMPONENT_GUID) + root.SetString("Name", prefix + data["name"]) + root.SetString("NickName", data["nickname"]) + root.SetString("Description", data.get("description", "")) + root.SetString("ToolTip", data.get("description", "")) + root.SetInt32("Exposure", data.get("exposure", EXPOSURE["default"])) + root.SetString("Category", data["category"]) + root.SetString("SubCategory", data["subcategory"]) + root.SetGuid("InstanceGuid", instance_guid) + root.SetByteArray("Icon", icon) + + ghpython_data = data["ghpython"] + + ghpython_root = GH_LooseChunk("UserObject") + ghpython_root.SetString("Description", data.get("description", "")) + bitmap_icon = System.Drawing.Bitmap.FromStream(System.IO.MemoryStream(icon)) + ghpython_root.SetDrawingBitmap("IconOverride", bitmap_icon) + ghpython_root.SetBoolean("UsingLibraryInputParam", False) + ghpython_root.SetBoolean("UsingScriptInputParam", False) + ghpython_root.SetBoolean("UsingStandardOutputParam", False) + ghpython_root.SetInt32("IconDisplay", ghpython_data.get("iconDisplay", 0)) + ghpython_root.SetString("Name", data["name"]) + ghpython_root.SetString("NickName", data["nickname"]) + ghpython_root.SetBoolean("MarshalGuids", ghpython_data.get("marshalGuids", True)) + + # ghpython_root.CreateChunk('Attributes') + # for mf in ('Bounds', 'Pivot', 'Selected'): + + params = ghpython_root.CreateChunk("ParameterData") + inputParam = ghpython_data.get("inputParameters", []) + outputParam = ghpython_data.get("outputParameters", []) + + params.SetInt32("InputCount", len(inputParam)) + for i, _pi in enumerate(inputParam): + params.SetGuid( + "InputId", i, System.Guid.Parse("08908df5-fa14-4982-9ab2-1aa0927566aa") + ) + params.SetInt32("OutputCount", len(outputParam)) + for i, _po in enumerate(outputParam): + params.SetGuid( + "OutputId", i, System.Guid.Parse("08908df5-fa14-4982-9ab2-1aa0927566aa") + ) + + for i, pi in enumerate(inputParam): + input_instance_guid = System.Guid.NewGuid() + pi_chunk = params.CreateChunk("InputParam", i) + pi_chunk.SetString("Name", pi["name"]) + pi_chunk.SetString("NickName", pi.get("nickname") or pi["name"]) + pi_chunk.SetString("Description", pi.get("description")) + pi_chunk.SetBoolean("Optional", pi.get("optional", True)) + pi_chunk.SetString("ToolTip", pi.get("description", "")) + pi_chunk.SetBoolean("AllowTreeAccess", pi.get("allowTreeAccess", True)) + pi_chunk.SetBoolean("ShowTypeHints", pi.get("showTypeHints", True)) + pi_chunk.SetInt32( + "ScriptParamAccess", + parse_param_access(pi.get("scriptParamAccess", ACCESS["default"])), + ) + pi_chunk.SetInt32("SourceCount", pi.get("sourceCount", 0)) + pi_chunk.SetGuid("InstanceGuid", input_instance_guid) + pi_chunk.SetGuid("TypeHintID", parse_param_type_hint(pi.get("typeHintID"))) + pi_chunk.SetInt32( + "WireDisplay", + parse_wire_display(pi.get("wireDisplay", WIRE_DISPLAY["default"])), + ) + pi_chunk.SetBoolean("ReverseData", pi.get("reverse", False)) + pi_chunk.SetBoolean("SimplifyData", pi.get("simplify", False)) + if pi.get("flatten", False): + pi_chunk.SetInt32("Mapping", 1) + elif pi.get("graft", False): + pi_chunk.SetInt32("Mapping", 2) + + for i, po in enumerate(outputParam): + output_instance_guid = System.Guid.NewGuid() + po_chunk = params.CreateChunk("OutputParam", i) + po_chunk.SetString("Name", po["name"]) + po_chunk.SetString("NickName", po.get("nickname") or po["name"]) + po_chunk.SetString("Description", po.get("description")) + po_chunk.SetBoolean("Optional", po.get("optional", False)) + po_chunk.SetString("ToolTip", po.get("description", "")) + po_chunk.SetInt32("SourceCount", po.get("sourceCount", 0)) + po_chunk.SetGuid("InstanceGuid", output_instance_guid) + po_chunk.SetBoolean("ReverseData", po.get("reverse", False)) + po_chunk.SetBoolean("SimplifyData", po.get("simplify", False)) + if po.get("flatten", False): + po_chunk.SetInt32("Mapping", 1) + elif po.get("graft", False): + po_chunk.SetInt32("Mapping", 2) + + script = ghpython_root.CreateChunk("Script") + + code_base64 = base64.b64encode(code.encode("utf-8")) + code_base64 = str(code_base64)[2:-1] + script.SetString("Text", code_base64) + script.SetString("Title", "S") + language_spec = script.CreateChunk("LanguageSpec") + language_spec.SetString("Taxon", "*.*.python") + language_spec.SetString("Version", CPY_VER) + + # xml_serialized = ghpython_root.Serialize_Xml() + root.SetByteArray("Object", ghpython_root.Serialize_Binary()) + System.IO.File.WriteAllBytes(target, root.Serialize_Binary()) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Create GHUser components out of python code." + ) + parser.add_argument( + "source", + type=str, + help="Source directory where code for all components is stored", + ) + parser.add_argument("target", type=str, help="Target directory for ghuser files") + parser.add_argument( + "--ghio", + type=str, + required=False, + help="Folder where the GH_IO.dll assembly is located. Defaults to ./lib", + ) + parser.add_argument( + "--version", type=str, required=False, help="Version to tag components" + ) + parser.add_argument( + "--prefix", + type=str, + required=False, + help="Add this prefix to the name of each generated component", + ) + args = parser.parse_args() + + sourcedir = args.source + if not os.path.isabs(sourcedir): + sourcedir = os.path.abspath(sourcedir) + + targetdir = args.target + if not os.path.isabs(targetdir): + targetdir = os.path.abspath(targetdir) + + if args.ghio is None: + libdir = tempfile.mkdtemp("ghio") + fetch_ghio_lib(libdir) + else: + libdir = os.path.abspath(args.ghio) + gh_io = find_ghio_assembly(libdir) + source_bundles = [ + d + for d in os.listdir(sourcedir) + if os.path.isdir(os.path.join(sourcedir, d)) + and d not in ("__pycache__", ".git") + ] + + print("GHPython componentizer") + print("======================") + + print("[x] Source: {} ({} components)".format(sourcedir, len(source_bundles))) + print("[ ] Target: {}\r".format(targetdir), end="") + if not os.path.exists(targetdir): + os.mkdir(targetdir) + print("[x]") + + if not gh_io: + print("[-] Cannot find GH_IO Assembly! Aborting.") + sys.exit(-1) + + clr.AddReference(os.path.splitext(gh_io)[0]) + + print("[x] GH_IO assembly: {}".format(gh_io)) + + print("Processing component bundles:") + for d in source_bundles: + source = os.path.join(sourcedir, d) + target = os.path.join(targetdir, d + ".ghuser") + print(" [ ] {}\r".format(d), end="") + create_ghuser_component(source, target, args.version, args.prefix) + print(" [x] {} => {}".format(d, target)) \ No newline at end of file