From 0e3c24b711a251fe8f6840bb85ed5bb8e1d80ebb Mon Sep 17 00:00:00 2001 From: tomvanmele Date: Mon, 9 Sep 2024 21:06:04 +0200 Subject: [PATCH] base plugin --- plugin/COMPAS-Masonry.rhproj | 123 +++++++++++++++++++++++++++++++++ plugin/Masonry.py | 26 +++++++ plugin/Masonry_reqs_check.py | 99 ++++++++++++++++++++++++++ plugin/Masonry_reqs_install.py | 9 +++ plugin/Masonry_scene_clear.py | 32 +++++++++ plugin/Masonry_scene_redraw.py | 24 +++++++ plugin/Masonry_session_open.py | 33 +++++++++ plugin/Masonry_session_redo.py | 29 ++++++++ plugin/Masonry_session_save.py | 23 ++++++ plugin/Masonry_session_undo.py | 29 ++++++++ plugin/Masonry_settings.py | 74 ++++++++++++++++++++ 11 files changed, 501 insertions(+) create mode 100644 plugin/COMPAS-Masonry.rhproj create mode 100644 plugin/Masonry.py create mode 100644 plugin/Masonry_reqs_check.py create mode 100644 plugin/Masonry_reqs_install.py create mode 100644 plugin/Masonry_scene_clear.py create mode 100644 plugin/Masonry_scene_redraw.py create mode 100644 plugin/Masonry_session_open.py create mode 100644 plugin/Masonry_session_redo.py create mode 100644 plugin/Masonry_session_save.py create mode 100644 plugin/Masonry_session_undo.py create mode 100644 plugin/Masonry_settings.py diff --git a/plugin/COMPAS-Masonry.rhproj b/plugin/COMPAS-Masonry.rhproj new file mode 100644 index 0000000..53cc7d1 --- /dev/null +++ b/plugin/COMPAS-Masonry.rhproj @@ -0,0 +1,123 @@ +{ + "id": "4384e04f-2997-429b-b3fc-53e7fe78703e", + "identity": { + "name": "COMPAS-Masonry", + "version": "0.1.1", + "publisher": { + "email": "tom.v.mele@gmail.com", + "name": "Tom Van Mele", + "company": "Block Research Group", + "url": "https://brg.ethz.ch/" + }, + "description": "COMPAS Masonry is a plugin for Rhino for the assessment of masonry structures. The current version of this plugin is based on COMPAS 2 and is available for Rhino 8.", + "copyright": "ETH Zurich - Block Research Group", + "license": "MIT", + "url": "https://blockresearchgroup.gitbook.io/compas-Masonry" + }, + "settings": { + "buildPath": "build/", + "buildTarget": { + "appName": "Rhino3D", + "appVersion": { + "major": 8 + }, + "title": "Rhino3D (8.*)", + "slug": "rh8" + }, + "publishTarget": { + "title": "McNeel Yak Server" + } + }, + "codes": [ + { + "id": "68ad7331-a5f2-4bc3-a368-67c1dfa79746", + "language": { + "id": "*.*.python", + "version": "3.*.*" + }, + "title": "Masonry", + "uri": "Masonry.py" + }, + { + "id": "04447f90-ccb1-40dd-b091-723956a0b949", + "language": { + "id": "*.*.python", + "version": "3.*.*" + }, + "title": "Masonry_settings", + "uri": "Masonry_settings.py" + }, + { + "id": "11d055d9-c869-4ad1-acad-19db4f69bfd2", + "language": { + "id": "*.*.python", + "version": "3.*.*" + }, + "title": "Masonry_session_undo", + "uri": "Masonry_session_undo.py" + }, + { + "id": "028d81bf-d395-4dd2-988c-40874e5220bc", + "language": { + "id": "*.*.python", + "version": "3.*.*" + }, + "title": "Masonry_session_redo", + "uri": "Masonry_session_redo.py" + }, + { + "id": "74a633fe-af2c-44bd-b016-fbe62eb881bf", + "language": { + "id": "*.*.python", + "version": "3.*.*" + }, + "title": "Masonry_scene_clear", + "uri": "Masonry_scene_clear.py" + }, + { + "id": "13557fa6-ae2f-401c-9d5b-9a911f47cd94", + "language": { + "id": "*.*.python", + "version": "3.*.*" + }, + "title": "Masonry_scene_redraw", + "uri": "Masonry_scene_redraw.py" + }, + { + "id": "7deeda3f-df3f-4050-ad10-dc9a61184889", + "language": { + "id": "*.*.python", + "version": "3.*.*" + }, + "title": "Masonry_session_open", + "uri": "Masonry_session_open.py" + }, + { + "id": "bd5e519e-c996-4751-9ba7-084e38836173", + "language": { + "id": "*.*.python", + "version": "3.*.*" + }, + "title": "Masonry_session_save", + "uri": "Masonry_session_save.py" + }, + { + "id": "f1693b65-203f-4795-8bf5-73e1e8c0083c", + "language": { + "id": "*.*.python", + "version": "3.*.*" + }, + "title": "Masonry_reqs_check", + "uri": "Masonry_reqs_check.py" + }, + { + "id": "2022efd3-8405-43e9-8164-2997356d8408", + "language": { + "id": "*.*.python", + "version": "3.*.*" + }, + "title": "Masonry_reqs_install", + "uri": "Masonry_reqs_install.py" + } + ] +} \ No newline at end of file diff --git a/plugin/Masonry.py b/plugin/Masonry.py new file mode 100644 index 0000000..4079b49 --- /dev/null +++ b/plugin/Masonry.py @@ -0,0 +1,26 @@ +#! python3 + +import compas_masonry +from compas_rui.forms import AboutForm + + +def RunCommand(is_interactive): + + form = AboutForm( + title=compas_masonry.title, + description=compas_masonry.description, + version=compas_masonry.__version__, + website=compas_masonry.website, + copyright=compas_masonry.__copyright__, + license=compas_masonry.__license__, + ) + + form.show() + + +# ============================================================================= +# Run as main +# ============================================================================= + +if __name__ == "__main__": + RunCommand(True) diff --git a/plugin/Masonry_reqs_check.py b/plugin/Masonry_reqs_check.py new file mode 100644 index 0000000..54aa984 --- /dev/null +++ b/plugin/Masonry_reqs_check.py @@ -0,0 +1,99 @@ +#! python3 + +try: + import compas +except ModuleNotFoundError: + compas = False + +try: + import compas_assembly +except ModuleNotFoundError: + compas_assembly = False + +try: + import compas_cra +except ModuleNotFoundError: + compas_cra = False + +try: + import compas_model +except ModuleNotFoundError: + compas_model = False + +try: + import compas_rui +except ModuleNotFoundError: + compas_rui = False + InfoForm = False +else: + from compas_rui.forms import InfoForm + +try: + import compas_session +except ModuleNotFoundError: + compas_session = False + +if not InfoForm: + import Eto.Drawing # type: ignore + import Eto.Forms # type: ignore + import Rhino # type: ignore + import Rhino.UI # type: ignore + + class InfoForm(Eto.Forms.Dialog[bool]): + def __init__(self, text, title="Info", width=800, height=500): + + super().__init__() + + self.Title = title + self.Padding = Eto.Drawing.Padding(0) + self.Resizable = True + self.MinimumSize = Eto.Drawing.Size(0.5 * width, 0.5 * height) + self.ClientSize = Eto.Drawing.Size(width, height) + textarea = Eto.Forms.TextArea() + textarea.Text = text + textarea.ReadOnly = True + layout = Eto.Forms.DynamicLayout() + layout.BeginVertical(Eto.Drawing.Padding(12, 12, 12, 0), Eto.Drawing.Size(0, 0), True, True) + layout.AddRow(textarea) + layout.EndVertical() + layout.BeginVertical(Eto.Drawing.Padding(12, 12, 12, 18), Eto.Drawing.Size(6, 0), False, False) + layout.AddRow(None, self.ok) + layout.EndVertical() + self.Content = layout + + @property + def ok(self): + self.DefaultButton = Eto.Forms.Button(Text="OK") + self.DefaultButton.Click += self.on_ok + return self.DefaultButton + + def on_ok(self, sender, event): + self.Close(True) + + def show(self): + return self.ShowModal(Rhino.UI.RhinoEtoApp.MainWindow) + + +def RunCommand(interactive): + + width = len("compas_session") + 1 + + lines = [ + "compas is not installed" if not compas else f"{compas.__name__:<{width}}: {compas.__version__}", + "compas_assembly is not installed" if not compas_assembly else f"{compas_assembly.__name__:<{width}}: {compas_assembly.__version__}", + "compas_cra is not installed" if not compas_cra else f"{compas_cra.__name__:<{width}}: {compas_cra.__version__}", + "compas_model is not installed" if not compas_model else f"{compas_model.__name__:<{width}}: {compas_model.__version__}", + "compas_rui is not installed" if not compas_rui else f"{compas_rui.__name__:<{width}}: {compas_rui.__version__}", + "compas_session is not installed" if not compas_session else f"{compas_session.__name__:<{width}}: {compas_session.__version__}", + ] + + form = InfoForm(text="\n".join(lines), title="Verify Installation") + form.show() + + +# ============================================================================= +# Run as main +# ============================================================================= + +if __name__ == "__main__": + RunCommand(True) diff --git a/plugin/Masonry_reqs_install.py b/plugin/Masonry_reqs_install.py new file mode 100644 index 0000000..1acb4f2 --- /dev/null +++ b/plugin/Masonry_reqs_install.py @@ -0,0 +1,9 @@ +#! python3 +# r: compas compas_ags compas_fd compas_rui compas_session compas_tna + +import compas # noqa: F401 +import compas_assembly # noqa: F401 +import compas_cra # noqa: F401 +import compas_model # noqa: F401 +import compas_rui # noqa: F401 +import compas_session # noqa: F401 diff --git a/plugin/Masonry_scene_clear.py b/plugin/Masonry_scene_clear.py new file mode 100644 index 0000000..d989436 --- /dev/null +++ b/plugin/Masonry_scene_clear.py @@ -0,0 +1,32 @@ +#! python3 + +import rhinoscriptsyntax as rs # type: ignore + +import compas_masonry.settings +from compas_session.namedsession import NamedSession + + +def RunCommand(is_interactive): + + session = NamedSession(name="COMPAS-Masonry") + scene = session.scene() + + result = rs.MessageBox( + "Note that this will remove all COMPAS Masonry data and objects. Do you wish to proceed?", + buttons=4 | 32 | 256 | 0, + title="Clear COMPAS Masonry", + ) + + if result == 6: + scene.clear() + + if compas_masonry.settings.SETTINGS["Session"]["autosave.events"]: + session.record(eventname="Clear") + + +# ============================================================================= +# Run as main +# ============================================================================= + +if __name__ == "__main__": + RunCommand(True) diff --git a/plugin/Masonry_scene_redraw.py b/plugin/Masonry_scene_redraw.py new file mode 100644 index 0000000..b617430 --- /dev/null +++ b/plugin/Masonry_scene_redraw.py @@ -0,0 +1,24 @@ +#! python3 + +import rhinoscriptsyntax as rs # type: ignore + +from compas_session.namedsession import NamedSession + + +def RunCommand(is_interactive): + + session = NamedSession(name="COMPAS-Masonry") + scene = session.scene() + + rs.EnableRedraw(False) + scene.redraw() + rs.EnableRedraw(True) + rs.Redraw() + + +# ============================================================================= +# Run as main +# ============================================================================= + +if __name__ == "__main__": + RunCommand(True) diff --git a/plugin/Masonry_session_open.py b/plugin/Masonry_session_open.py new file mode 100644 index 0000000..5611bb7 --- /dev/null +++ b/plugin/Masonry_session_open.py @@ -0,0 +1,33 @@ +#! python3 + +import compas_masonry.settings +from compas_rui.forms import FileForm +from compas_session.namedsession import NamedSession + + +def RunCommand(is_interactive): + + session = NamedSession(name="COMPAS-Masonry") + + filepath = FileForm.open(session.basedir) + if not filepath: + return + + scene = session.scene() + scene.clear() + + session.open(filepath) + + scene = session.scene() + scene.draw() + + if compas_masonry.settings.SETTINGS["Session"]["autosave.events"]: + session.record(eventname="Open Session") + + +# ============================================================================= +# Run as main +# ============================================================================= + +if __name__ == "__main__": + RunCommand(True) diff --git a/plugin/Masonry_session_redo.py b/plugin/Masonry_session_redo.py new file mode 100644 index 0000000..5a91922 --- /dev/null +++ b/plugin/Masonry_session_redo.py @@ -0,0 +1,29 @@ +#! python3 + +import rhinoscriptsyntax as rs # type: ignore + +from compas_session.namedsession import NamedSession + + +def RunCommand(is_interactive): + + session = NamedSession(name="COMPAS-Masonry") + + scene = session.scene() + + if session.redo(): + scene.clear() + scene = session.scene() + + rs.EnableRedraw(False) + scene.draw() + rs.EnableRedraw(True) + rs.Redraw() + + +# ============================================================================= +# Run as main +# ============================================================================= + +if __name__ == "__main__": + RunCommand(True) diff --git a/plugin/Masonry_session_save.py b/plugin/Masonry_session_save.py new file mode 100644 index 0000000..bf35a08 --- /dev/null +++ b/plugin/Masonry_session_save.py @@ -0,0 +1,23 @@ +#! python3 + +from compas_rui.forms import FileForm +from compas_session.namedsession import NamedSession + + +def RunCommand(is_interactive): + + session = NamedSession(name="COMPAS-Masonry") + + filepath = FileForm.save(session.basedir, "COMPAS-Masonry.json") + if not filepath: + return + + session.save(filepath) + + +# ============================================================================= +# Run as main +# ============================================================================= + +if __name__ == "__main__": + RunCommand(True) diff --git a/plugin/Masonry_session_undo.py b/plugin/Masonry_session_undo.py new file mode 100644 index 0000000..9fd0549 --- /dev/null +++ b/plugin/Masonry_session_undo.py @@ -0,0 +1,29 @@ +#! python3 + +import rhinoscriptsyntax as rs # type: ignore + +from compas_session.namedsession import NamedSession + + +def RunCommand(is_interactive): + + session = NamedSession(name="COMPAS-Masonry") + + scene = session.scene() + + if session.undo(): + scene.clear() + scene = session.scene() + + rs.EnableRedraw(False) + scene.draw() + rs.EnableRedraw(True) + rs.Redraw() + + +# ============================================================================= +# Run as main +# ============================================================================= + +if __name__ == "__main__": + RunCommand(True) diff --git a/plugin/Masonry_settings.py b/plugin/Masonry_settings.py new file mode 100644 index 0000000..f1d4226 --- /dev/null +++ b/plugin/Masonry_settings.py @@ -0,0 +1,74 @@ +#! python3 + +import compas_masonry.settings +from compas_rui.forms import SettingsForm +from compas_masonry.datastructures import ForceDiagram +from compas_masonry.datastructures import FormDiagram +from compas_masonry.datastructures import ThrustDiagram +from compas_masonry.scene import RhinoForceObject +from compas_masonry.scene import RhinoFormObject +from compas_masonry.scene import RhinoThrustObject +from compas_session.namedsession import NamedSession + + +def RunCommand(is_interactive): + + session = NamedSession(name="COMPAS-Masonry") + scene = session.scene() + + form: RhinoFormObject = scene.find_by_itemtype(itemtype=FormDiagram) + force: RhinoForceObject = scene.find_by_itemtype(itemtype=ForceDiagram) + thrust: RhinoThrustObject = scene.find_by_itemtype(itemtype=ThrustDiagram) + + if form: + if "FormDiagram" in compas_masonry.settings.SETTINGS: + for key, value in compas_masonry.settings.SETTINGS["FormDiagram"].items(): + name = "_".join(key.split(".")) + if hasattr(form, name): + value.set(getattr(form, name)) + + if force: + if "ForceDiagram" in compas_masonry.settings.SETTINGS: + for key, value in compas_masonry.settings.SETTINGS["ForceDiagram"].items(): + name = "_".join(key.split(".")) + if hasattr(force, name): + value.set(getattr(force, name)) + + if thrust: + if "ThrustDiagram" in compas_masonry.settings.SETTINGS: + for key, value in compas_masonry.settings.SETTINGS["ThrustDiagram"].items(): + name = "_".join(key.split(".")) + if hasattr(thrust, name): + value.set(getattr(thrust, name)) + + settingsform = SettingsForm(settings=compas_masonry.settings.SETTINGS, use_tab=True) + if settingsform.show(): + + if form: + if "FormDiagram" in compas_masonry.settings.SETTINGS: + for key, value in compas_masonry.settings.SETTINGS["FormDiagram"].items(): + name = "_".join(key.split(".")) + setattr(form, name, value.value) + + if force: + if "ForceDiagram" in compas_masonry.settings.SETTINGS: + for key, value in compas_masonry.settings.SETTINGS["ForceDiagram"].items(): + name = "_".join(key.split(".")) + setattr(force, name, value.value) + + if thrust: + if "ThrustDiagram" in compas_masonry.settings.SETTINGS: + for key, value in compas_masonry.settings.SETTINGS["ThrustDiagram"].items(): + name = "_".join(key.split(".")) + setattr(thrust, name, value.value) + + if compas_masonry.settings.SETTINGS["Session"]["autosave.events"]: + session.record(eventname="Update Settings") + + +# ============================================================================= +# Run as main +# ============================================================================= + +if __name__ == "__main__": + RunCommand(True)