compas-masonry 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- compas_masonry-0.2.1/LICENSE +21 -0
- compas_masonry-0.2.1/PKG-INFO +135 -0
- compas_masonry-0.2.1/README.md +70 -0
- compas_masonry-0.2.1/pyproject.toml +144 -0
- compas_masonry-0.2.1/requirements-dev.txt +7 -0
- compas_masonry-0.2.1/requirements.txt +10 -0
- compas_masonry-0.2.1/setup.cfg +4 -0
- compas_masonry-0.2.1/src/compas_masonry/__init__.py +3 -0
- compas_masonry-0.2.1/src/compas_masonry/__main__.py +2 -0
- compas_masonry-0.2.1/src/compas_masonry/forms/__init__.py +0 -0
- compas_masonry-0.2.1/src/compas_masonry/forms/settings.py +203 -0
- compas_masonry-0.2.1/src/compas_masonry/scene/__init__.py +13 -0
- compas_masonry-0.2.1/src/compas_masonry/scene/envelopeobject.py +94 -0
- compas_masonry-0.2.1/src/compas_masonry/scene/formobject.py +509 -0
- compas_masonry-0.2.1/src/compas_masonry/session.py +10 -0
- compas_masonry-0.2.1/src/compas_masonry/settings.py +53 -0
- compas_masonry-0.2.1/src/compas_masonry/splash.py +44 -0
- compas_masonry-0.2.1/src/compas_masonry.egg-info/PKG-INFO +135 -0
- compas_masonry-0.2.1/src/compas_masonry.egg-info/SOURCES.txt +22 -0
- compas_masonry-0.2.1/src/compas_masonry.egg-info/dependency_links.txt +1 -0
- compas_masonry-0.2.1/src/compas_masonry.egg-info/not-zip-safe +1 -0
- compas_masonry-0.2.1/src/compas_masonry.egg-info/requires.txt +18 -0
- compas_masonry-0.2.1/src/compas_masonry.egg-info/top_level.txt +1 -0
- compas_masonry-0.2.1/tests/test_placeholder.py +2 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
ETH Zurich - Block Research Group
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: compas_masonry
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: COMPAS Masonry is a masonry assessment toolbox for Rhino based on the COMPAS framework.
|
|
5
|
+
Author-email: tom van mele <tom.v.mele@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
ETH Zurich - Block Research Group
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://blockresearchgroup.github.io/compas_masonry
|
|
29
|
+
Project-URL: Documentation, https://blockresearchgroup.github.io/compas_masonry
|
|
30
|
+
Project-URL: Repository, https://github.com/blockresearchgroup/compas_masonry
|
|
31
|
+
Project-URL: Changelog, https://github.com/blockresearchgroup/compas_masonry/blob/main/CHANGELOG.md
|
|
32
|
+
Project-URL: Issues, https://github.com/blockresearchgroup/compas_masonry/issues
|
|
33
|
+
Project-URL: Forum, https://forum.compas-framework.org/
|
|
34
|
+
Classifier: Development Status :: 4 - Beta
|
|
35
|
+
Classifier: Topic :: Scientific/Engineering
|
|
36
|
+
Classifier: Operating System :: Unix
|
|
37
|
+
Classifier: Operating System :: POSIX
|
|
38
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
39
|
+
Classifier: Programming Language :: Python
|
|
40
|
+
Classifier: Programming Language :: Python :: 3
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
43
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
44
|
+
Requires-Python: >=3.9
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
License-File: LICENSE
|
|
47
|
+
Requires-Dist: cvxpy
|
|
48
|
+
Requires-Dist: compas>=2.14.1
|
|
49
|
+
Requires-Dist: compas_cgal>=0.9.1
|
|
50
|
+
Requires-Dist: compas_dem>=0.4
|
|
51
|
+
Requires-Dist: compas_libigl>=0.7.6
|
|
52
|
+
Requires-Dist: compas_rui>=0.6
|
|
53
|
+
Requires-Dist: compas_session>=0.7
|
|
54
|
+
Requires-Dist: compas_tna>=0.7
|
|
55
|
+
Requires-Dist: compas_tno>=0.3
|
|
56
|
+
Provides-Extra: dev
|
|
57
|
+
Requires-Dist: bump-my-version; extra == "dev"
|
|
58
|
+
Requires-Dist: compas_invocations2; extra == "dev"
|
|
59
|
+
Requires-Dist: invoke>=0.14; extra == "dev"
|
|
60
|
+
Requires-Dist: ruff; extra == "dev"
|
|
61
|
+
Requires-Dist: sphinx_compas2_theme; extra == "dev"
|
|
62
|
+
Requires-Dist: twine; extra == "dev"
|
|
63
|
+
Requires-Dist: wheel; extra == "dev"
|
|
64
|
+
Dynamic: license-file
|
|
65
|
+
|
|
66
|
+
# COMPAS Masonry
|
|
67
|
+
|
|
68
|
+
> [!WARNING]
|
|
69
|
+
> This plugin is under active development,
|
|
70
|
+
> and its functionality will frequently change.
|
|
71
|
+
|
|
72
|
+

|
|
73
|
+
|
|
74
|
+
COMPAS Masonry is a plugin for Rhino for the assessment of masonry structures,
|
|
75
|
+
and for the stability analsis of Discrete Element Models in general.
|
|
76
|
+
|
|
77
|
+
The current version of this plugin is based on COMPAS 2 and is available for Rhino 8.
|
|
78
|
+
|
|
79
|
+
## Installation
|
|
80
|
+
|
|
81
|
+
To install COMPAS-Masonry, use Rhino's package manager Yak.
|
|
82
|
+
To open Yak, type `PackageManager` on the Rhino command line.
|
|
83
|
+
|
|
84
|
+

|
|
85
|
+
|
|
86
|
+
## COMPAS Packages
|
|
87
|
+
|
|
88
|
+
COMPAS-Masonry uses the following COMPAS packages:
|
|
89
|
+
|
|
90
|
+
* [compas](https://github.com/compas-dev/compas)
|
|
91
|
+
* [compas_assembly](https://github.com/blockresearchgroup/compas_assembly)
|
|
92
|
+
* [compas_model](https://github.com/blockresearchgroup/compas_model)
|
|
93
|
+
* [compas_rui](https://github.com/blockresearchgroup/compas_rui)
|
|
94
|
+
* [compas_session](https://github.com/blockresearchgroup/compas_session)
|
|
95
|
+
|
|
96
|
+
After installing RhinoVAULT with Yak, these requirements will be installed automatically if necessary.
|
|
97
|
+
The tool might be unresponsive during this process, which might take up to 1 or 2 mins.
|
|
98
|
+
The packages are installed in a separate virtual environment named `COMPAS-Masonry`.
|
|
99
|
+
|
|
100
|
+
> [!NOTE]
|
|
101
|
+
> Note that COMPAS-Masonry currently doesn't include any solvers
|
|
102
|
+
> (such as [compas_cra](https://github.com/blockresearchgroup/compas_cra)) yet.
|
|
103
|
+
> This is because they have dependencies that are still difficult to install in Rhino.
|
|
104
|
+
|
|
105
|
+
## User Interface
|
|
106
|
+
|
|
107
|
+
COMPAS-Masonry defines the following Rhino commands:
|
|
108
|
+
|
|
109
|
+
* `Masonry`
|
|
110
|
+
* `Masonry_session_undo`
|
|
111
|
+
* `Masonry_session_redo`
|
|
112
|
+
* `Masonry_session_open`
|
|
113
|
+
* `Masonry_session_save`
|
|
114
|
+
* `Masonry_scene_clear`
|
|
115
|
+
* `Masonry_scene_redraw`
|
|
116
|
+
* `Masonry_settings`
|
|
117
|
+
|
|
118
|
+
These commands can be executed using the Rhino command line (simply start typing the command name),
|
|
119
|
+
or with the corresponding buttons of the COMPAS-Masonry toolbar.
|
|
120
|
+
|
|
121
|
+

|
|
122
|
+
|
|
123
|
+
If the toolbar is not visible after installing COMPAS-Masonry,
|
|
124
|
+
you can load it from the "Toolbars" page.
|
|
125
|
+
To open the "Toolbars" page, type `Toolbar` on the Rhino command line...
|
|
126
|
+
|
|
127
|
+

|
|
128
|
+
|
|
129
|
+
## Documentation
|
|
130
|
+
|
|
131
|
+
For further "getting started" instructions, a tutorial, examples, and an detailed description of the individual commands and the user interface, please check out the online documentation here: [COMPAS-Masonry Gitbook](https://blockresearchgroup.gitbook.io/COMPAS-Masonry)
|
|
132
|
+
|
|
133
|
+
## Issues
|
|
134
|
+
|
|
135
|
+
Please report problems using the issue tracker of the github repo: <https://github.com/blockresearchgroup/compas-Masonry/issues>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# COMPAS Masonry
|
|
2
|
+
|
|
3
|
+
> [!WARNING]
|
|
4
|
+
> This plugin is under active development,
|
|
5
|
+
> and its functionality will frequently change.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
COMPAS Masonry is a plugin for Rhino for the assessment of masonry structures,
|
|
10
|
+
and for the stability analsis of Discrete Element Models in general.
|
|
11
|
+
|
|
12
|
+
The current version of this plugin is based on COMPAS 2 and is available for Rhino 8.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
To install COMPAS-Masonry, use Rhino's package manager Yak.
|
|
17
|
+
To open Yak, type `PackageManager` on the Rhino command line.
|
|
18
|
+
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+
## COMPAS Packages
|
|
22
|
+
|
|
23
|
+
COMPAS-Masonry uses the following COMPAS packages:
|
|
24
|
+
|
|
25
|
+
* [compas](https://github.com/compas-dev/compas)
|
|
26
|
+
* [compas_assembly](https://github.com/blockresearchgroup/compas_assembly)
|
|
27
|
+
* [compas_model](https://github.com/blockresearchgroup/compas_model)
|
|
28
|
+
* [compas_rui](https://github.com/blockresearchgroup/compas_rui)
|
|
29
|
+
* [compas_session](https://github.com/blockresearchgroup/compas_session)
|
|
30
|
+
|
|
31
|
+
After installing RhinoVAULT with Yak, these requirements will be installed automatically if necessary.
|
|
32
|
+
The tool might be unresponsive during this process, which might take up to 1 or 2 mins.
|
|
33
|
+
The packages are installed in a separate virtual environment named `COMPAS-Masonry`.
|
|
34
|
+
|
|
35
|
+
> [!NOTE]
|
|
36
|
+
> Note that COMPAS-Masonry currently doesn't include any solvers
|
|
37
|
+
> (such as [compas_cra](https://github.com/blockresearchgroup/compas_cra)) yet.
|
|
38
|
+
> This is because they have dependencies that are still difficult to install in Rhino.
|
|
39
|
+
|
|
40
|
+
## User Interface
|
|
41
|
+
|
|
42
|
+
COMPAS-Masonry defines the following Rhino commands:
|
|
43
|
+
|
|
44
|
+
* `Masonry`
|
|
45
|
+
* `Masonry_session_undo`
|
|
46
|
+
* `Masonry_session_redo`
|
|
47
|
+
* `Masonry_session_open`
|
|
48
|
+
* `Masonry_session_save`
|
|
49
|
+
* `Masonry_scene_clear`
|
|
50
|
+
* `Masonry_scene_redraw`
|
|
51
|
+
* `Masonry_settings`
|
|
52
|
+
|
|
53
|
+
These commands can be executed using the Rhino command line (simply start typing the command name),
|
|
54
|
+
or with the corresponding buttons of the COMPAS-Masonry toolbar.
|
|
55
|
+
|
|
56
|
+

|
|
57
|
+
|
|
58
|
+
If the toolbar is not visible after installing COMPAS-Masonry,
|
|
59
|
+
you can load it from the "Toolbars" page.
|
|
60
|
+
To open the "Toolbars" page, type `Toolbar` on the Rhino command line...
|
|
61
|
+
|
|
62
|
+

|
|
63
|
+
|
|
64
|
+
## Documentation
|
|
65
|
+
|
|
66
|
+
For further "getting started" instructions, a tutorial, examples, and an detailed description of the individual commands and the user interface, please check out the online documentation here: [COMPAS-Masonry Gitbook](https://blockresearchgroup.gitbook.io/COMPAS-Masonry)
|
|
67
|
+
|
|
68
|
+
## Issues
|
|
69
|
+
|
|
70
|
+
Please report problems using the issue tracker of the github repo: <https://github.com/blockresearchgroup/compas-Masonry/issues>
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=66.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
# ============================================================================
|
|
6
|
+
# project info
|
|
7
|
+
# ============================================================================
|
|
8
|
+
|
|
9
|
+
[project]
|
|
10
|
+
name = "compas_masonry"
|
|
11
|
+
description = "COMPAS Masonry is a masonry assessment toolbox for Rhino based on the COMPAS framework."
|
|
12
|
+
keywords = []
|
|
13
|
+
authors = [{ name = "tom van mele", email = "tom.v.mele@gmail.com" }]
|
|
14
|
+
license = { file = "LICENSE" }
|
|
15
|
+
readme = "README.md"
|
|
16
|
+
requires-python = ">=3.9"
|
|
17
|
+
dynamic = ['dependencies', 'optional-dependencies', 'version']
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 4 - Beta",
|
|
20
|
+
"Topic :: Scientific/Engineering",
|
|
21
|
+
"Operating System :: Unix",
|
|
22
|
+
"Operating System :: POSIX",
|
|
23
|
+
"Operating System :: Microsoft :: Windows",
|
|
24
|
+
"Programming Language :: Python",
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Programming Language :: Python :: 3.9",
|
|
27
|
+
"Programming Language :: Python :: 3.10",
|
|
28
|
+
"Programming Language :: Python :: 3.11",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://blockresearchgroup.github.io/compas_masonry"
|
|
33
|
+
Documentation = "https://blockresearchgroup.github.io/compas_masonry"
|
|
34
|
+
Repository = "https://github.com/blockresearchgroup/compas_masonry"
|
|
35
|
+
Changelog = "https://github.com/blockresearchgroup/compas_masonry/blob/main/CHANGELOG.md"
|
|
36
|
+
Issues = "https://github.com/blockresearchgroup/compas_masonry/issues"
|
|
37
|
+
Forum = "https://forum.compas-framework.org/"
|
|
38
|
+
|
|
39
|
+
# ============================================================================
|
|
40
|
+
# scripts
|
|
41
|
+
# ============================================================================
|
|
42
|
+
|
|
43
|
+
# ============================================================================
|
|
44
|
+
# setuptools config
|
|
45
|
+
# ============================================================================
|
|
46
|
+
|
|
47
|
+
[tool.setuptools]
|
|
48
|
+
package-dir = { "" = "src" }
|
|
49
|
+
include-package-data = true
|
|
50
|
+
zip-safe = false
|
|
51
|
+
|
|
52
|
+
[tool.setuptools.dynamic]
|
|
53
|
+
version = { attr = "compas_masonry.__version__" }
|
|
54
|
+
dependencies = { file = "requirements.txt" }
|
|
55
|
+
optional-dependencies = { dev = { file = "requirements-dev.txt" } }
|
|
56
|
+
|
|
57
|
+
[tool.setuptools.packages.find]
|
|
58
|
+
where = ["src"]
|
|
59
|
+
|
|
60
|
+
# ============================================================================
|
|
61
|
+
# replace pytest.ini
|
|
62
|
+
# ============================================================================
|
|
63
|
+
|
|
64
|
+
[tool.pytest.ini_options]
|
|
65
|
+
minversion = "6.0"
|
|
66
|
+
testpaths = ["tests", "src/compas_masonry"]
|
|
67
|
+
python_files = ["test_*.py", "*_test.py", "test.py"]
|
|
68
|
+
addopts = [
|
|
69
|
+
"-ra",
|
|
70
|
+
"--strict-markers",
|
|
71
|
+
"--doctest-glob=*.rst",
|
|
72
|
+
"--tb=short",
|
|
73
|
+
"--import-mode=importlib",
|
|
74
|
+
]
|
|
75
|
+
doctest_optionflags = [
|
|
76
|
+
"NORMALIZE_WHITESPACE",
|
|
77
|
+
"IGNORE_EXCEPTION_DETAIL",
|
|
78
|
+
"ALLOW_UNICODE",
|
|
79
|
+
"ALLOW_BYTES",
|
|
80
|
+
"NUMBER",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
# ============================================================================
|
|
84
|
+
# replace bumpversion.cfg
|
|
85
|
+
# ============================================================================
|
|
86
|
+
|
|
87
|
+
[tool.bumpversion]
|
|
88
|
+
current_version = "0.2.1"
|
|
89
|
+
message = "Bump version to {new_version}"
|
|
90
|
+
commit = true
|
|
91
|
+
tag = true
|
|
92
|
+
|
|
93
|
+
[[tool.bumpversion.files]]
|
|
94
|
+
filename = "src/compas_masonry/__init__.py"
|
|
95
|
+
search = "{current_version}"
|
|
96
|
+
replace = "{new_version}"
|
|
97
|
+
|
|
98
|
+
[[tool.bumpversion.files]]
|
|
99
|
+
filename = "CHANGELOG.md"
|
|
100
|
+
search = "Unreleased"
|
|
101
|
+
replace = "[{new_version}] {now:%Y-%m-%d}"
|
|
102
|
+
|
|
103
|
+
# ============================================================================
|
|
104
|
+
# replace setup.cfg
|
|
105
|
+
# ============================================================================
|
|
106
|
+
|
|
107
|
+
[tool.black]
|
|
108
|
+
line-length = 179
|
|
109
|
+
|
|
110
|
+
[tool.ruff]
|
|
111
|
+
line-length = 179
|
|
112
|
+
indent-width = 4
|
|
113
|
+
target-version = "py39"
|
|
114
|
+
|
|
115
|
+
[tool.ruff.lint]
|
|
116
|
+
select = ["E", "F", "I"]
|
|
117
|
+
|
|
118
|
+
[tool.ruff.lint.per-file-ignores]
|
|
119
|
+
"__init__.py" = ["I001"]
|
|
120
|
+
"tests/*" = ["I001"]
|
|
121
|
+
"tasks.py" = ["I001"]
|
|
122
|
+
|
|
123
|
+
[tool.ruff.lint.isort]
|
|
124
|
+
force-single-line = true
|
|
125
|
+
known-first-party = [
|
|
126
|
+
"compas",
|
|
127
|
+
"compas_session",
|
|
128
|
+
"compas_rui",
|
|
129
|
+
"compas_masonry",
|
|
130
|
+
"compas_tna",
|
|
131
|
+
"compas_tno",
|
|
132
|
+
"compas_dem",
|
|
133
|
+
"compas_rhino",
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
[tool.ruff.lint.pydocstyle]
|
|
137
|
+
convention = "numpy"
|
|
138
|
+
|
|
139
|
+
[tool.ruff.lint.pycodestyle]
|
|
140
|
+
max-doc-length = 179
|
|
141
|
+
|
|
142
|
+
[tool.ruff.format]
|
|
143
|
+
docstring-code-format = true
|
|
144
|
+
docstring-code-line-length = "dynamic"
|
|
File without changes
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#! python3
|
|
2
|
+
# venv: brg-csd
|
|
3
|
+
# r: compas_masonry
|
|
4
|
+
|
|
5
|
+
from typing import Union
|
|
6
|
+
|
|
7
|
+
import Eto.Drawing as drawing # type: ignore
|
|
8
|
+
import Eto.Forms as forms # type: ignore
|
|
9
|
+
import Rhino # type: ignore
|
|
10
|
+
import Rhino.UI # type: ignore
|
|
11
|
+
from pydantic import BaseModel
|
|
12
|
+
from pydantic import Field
|
|
13
|
+
|
|
14
|
+
from compas.colors import Color
|
|
15
|
+
from compas_session.settings import Settings
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def field_ge(field):
|
|
19
|
+
"""Get the 'greater than or equal to' constraint from a Pydantic field.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
field : ModelField
|
|
24
|
+
The Pydantic model field.
|
|
25
|
+
|
|
26
|
+
Returns
|
|
27
|
+
-------
|
|
28
|
+
float or int or None
|
|
29
|
+
The 'greater than or equal to' constraint if it exists, otherwise None.
|
|
30
|
+
|
|
31
|
+
"""
|
|
32
|
+
ge = None
|
|
33
|
+
for m in field.metadata:
|
|
34
|
+
if hasattr(m, "ge"):
|
|
35
|
+
ge = m.ge
|
|
36
|
+
break
|
|
37
|
+
return ge
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def field_le(field):
|
|
41
|
+
"""Get the 'less than or equal to' constraint from a Pydantic field.
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
field : ModelField
|
|
46
|
+
The Pydantic model field.
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
float or int or None
|
|
51
|
+
The 'less than or equal to' constraint if it exists, otherwise None.
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
le = None
|
|
55
|
+
for m in field.metadata:
|
|
56
|
+
if hasattr(m, "le"):
|
|
57
|
+
le = m.le
|
|
58
|
+
break
|
|
59
|
+
return le
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class SettingsForm(forms.Dialog[bool]):
|
|
63
|
+
"""A dynamic form for editing Pydantic models.
|
|
64
|
+
|
|
65
|
+
Parameters
|
|
66
|
+
----------
|
|
67
|
+
model_cls : Type[BaseModel]
|
|
68
|
+
The Pydantic model class to create the form for.
|
|
69
|
+
width : int, optional
|
|
70
|
+
The width of the form, by default 400.
|
|
71
|
+
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
def __init__(self, model: Union[Settings, BaseModel], title: str = "Settings", width: int = 400):
|
|
75
|
+
super().__init__()
|
|
76
|
+
self.ClientSize = drawing.Size(width, -1)
|
|
77
|
+
self.model = model
|
|
78
|
+
self.model_cls = type(model)
|
|
79
|
+
self.controls = {}
|
|
80
|
+
self.Title = title
|
|
81
|
+
|
|
82
|
+
self.Content = self._build_layout()
|
|
83
|
+
|
|
84
|
+
self.DefaultButton = self.ok_button
|
|
85
|
+
self.AbortButton = self.cancel_button
|
|
86
|
+
|
|
87
|
+
def _build_layout(self):
|
|
88
|
+
layout = forms.DynamicLayout()
|
|
89
|
+
layout.Padding = drawing.Padding(10)
|
|
90
|
+
layout.Spacing = drawing.Size(10, 10)
|
|
91
|
+
|
|
92
|
+
for name, field in self.model_cls.model_fields.items():
|
|
93
|
+
if issubclass(field.annotation, BaseModel): # type: ignore
|
|
94
|
+
continue
|
|
95
|
+
|
|
96
|
+
text = field.title or name.replace("_", " ").capitalize()
|
|
97
|
+
label = forms.Label()
|
|
98
|
+
label.Text = text
|
|
99
|
+
control = self._create_control(name, field, field.default)
|
|
100
|
+
self.controls[name] = control
|
|
101
|
+
layout.AddRow(label, control)
|
|
102
|
+
|
|
103
|
+
layout.AddRow(None)
|
|
104
|
+
|
|
105
|
+
self.ok_button = forms.Button()
|
|
106
|
+
self.ok_button.Text = "OK"
|
|
107
|
+
self.ok_button.Click += self._on_ok
|
|
108
|
+
|
|
109
|
+
self.cancel_button = forms.Button()
|
|
110
|
+
self.cancel_button.Text = "Cancel"
|
|
111
|
+
self.cancel_button.Click += self._on_cancel
|
|
112
|
+
|
|
113
|
+
layout.AddRow(None, self.ok_button, self.cancel_button)
|
|
114
|
+
return layout
|
|
115
|
+
|
|
116
|
+
def _create_control(self, name, field, default):
|
|
117
|
+
if field.annotation is str:
|
|
118
|
+
value = getattr(self.model, name, default) or ""
|
|
119
|
+
control = forms.TextBox()
|
|
120
|
+
control.Text = value
|
|
121
|
+
|
|
122
|
+
elif field.annotation is int:
|
|
123
|
+
value = getattr(self.model, name, default) or 0
|
|
124
|
+
control = forms.NumericUpDown()
|
|
125
|
+
control.Value = value
|
|
126
|
+
control.MinValue = field_ge(field)
|
|
127
|
+
control.MaxValue = field_le(field)
|
|
128
|
+
|
|
129
|
+
elif field.annotation is float:
|
|
130
|
+
value = getattr(self.model, name, default) or 0.0
|
|
131
|
+
control = forms.NumericUpDown()
|
|
132
|
+
control.Value = value
|
|
133
|
+
control.DecimalPlaces = 3
|
|
134
|
+
control.MinValue = field_ge(field)
|
|
135
|
+
control.MaxValue = field_le(field)
|
|
136
|
+
|
|
137
|
+
elif field.annotation is bool:
|
|
138
|
+
value = getattr(self.model, name, default) or False
|
|
139
|
+
control = forms.CheckBox()
|
|
140
|
+
control.Checked = value
|
|
141
|
+
|
|
142
|
+
elif (
|
|
143
|
+
field.annotation is tuple
|
|
144
|
+
and hasattr(field, "default")
|
|
145
|
+
and isinstance(field.default, tuple)
|
|
146
|
+
and len(field.default) == 4
|
|
147
|
+
and all(isinstance(x, int) for x in field.default)
|
|
148
|
+
):
|
|
149
|
+
value = getattr(self.model, name, default) or (255, 255, 255, 255)
|
|
150
|
+
color = drawing.Color.FromArgb(*value)
|
|
151
|
+
control = forms.ColorPicker()
|
|
152
|
+
control.Value = color
|
|
153
|
+
|
|
154
|
+
else:
|
|
155
|
+
value = getattr(self.model, name, default) or ""
|
|
156
|
+
control = forms.TextBox()
|
|
157
|
+
control.Text = str(value)
|
|
158
|
+
|
|
159
|
+
return control
|
|
160
|
+
|
|
161
|
+
def _on_ok(self, sender, e):
|
|
162
|
+
values = {}
|
|
163
|
+
for name, control in self.controls.items():
|
|
164
|
+
if isinstance(control, forms.TextBox):
|
|
165
|
+
values[name] = control.Text
|
|
166
|
+
elif isinstance(control, forms.NumericUpDown):
|
|
167
|
+
values[name] = control.Value
|
|
168
|
+
elif isinstance(control, forms.CheckBox):
|
|
169
|
+
values[name] = control.Checked
|
|
170
|
+
elif isinstance(control, forms.ColorPicker):
|
|
171
|
+
c = control.Value
|
|
172
|
+
values[name] = (c.R, c.G, c.B, c.A)
|
|
173
|
+
try:
|
|
174
|
+
for key, value in values.items():
|
|
175
|
+
setattr(self.model, key, value)
|
|
176
|
+
self.Close(True)
|
|
177
|
+
except Exception as ex:
|
|
178
|
+
forms.MessageBox.Show(str(ex), "Validation Error")
|
|
179
|
+
|
|
180
|
+
def _on_cancel(self, sender, e):
|
|
181
|
+
self.Close(False)
|
|
182
|
+
|
|
183
|
+
def show(self):
|
|
184
|
+
return self.ShowModal(Rhino.UI.RhinoEtoApp.MainWindow)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
# =============================================================================
|
|
188
|
+
# Run as main
|
|
189
|
+
# =============================================================================
|
|
190
|
+
|
|
191
|
+
if __name__ == "__main__":
|
|
192
|
+
|
|
193
|
+
class TestSettings(BaseModel):
|
|
194
|
+
name: str = Field("Default", title="Name", description="Enter your name")
|
|
195
|
+
age: int = Field(30, title="Age", ge=0, le=120)
|
|
196
|
+
is_active: bool = Field(True, title="Active")
|
|
197
|
+
color: tuple = Field(Color.white().rgba255, title="Color", description="Pick a color")
|
|
198
|
+
|
|
199
|
+
settings = TestSettings(name="Alice", age=28, is_active=True, color=Color.red().rgba255)
|
|
200
|
+
dialog = SettingsForm(settings) # type: ignore
|
|
201
|
+
|
|
202
|
+
if dialog.ShowModal(Rhino.UI.RhinoEtoApp.MainWindow):
|
|
203
|
+
print(dialog.model)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from compas.plugins import plugin
|
|
2
|
+
from compas.scene.context import register
|
|
3
|
+
|
|
4
|
+
from compas_tna.diagrams import FormDiagram
|
|
5
|
+
from .formobject import RhinoFormDiagramObject
|
|
6
|
+
|
|
7
|
+
# this clashes with TNA and/or RV
|
|
8
|
+
# we need a strategy for this
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@plugin(category="factories", pluggable_name="register_scene_objects", requires=["Rhino"])
|
|
12
|
+
def register_scene_objects_rhino():
|
|
13
|
+
register(FormDiagram, RhinoFormDiagramObject, context="Rhino")
|