Compare commits

..

561 Commits

Author SHA1 Message Date
Dion Moult 8b8af680bc Merge branch 'v0.8.0' into webui_updates 2024-08-29 09:55:41 +10:00
Dion Moult 8a57a52949 Bump IOS 2024-08-29 09:20:32 +10:00
Jean-Marc Couffin 720eda51c3 Update README.md with new blenderBMI branding - BONSAI 2024-08-29 08:35:24 +10:00
Bruno Perdigão 01a701007e Fix b74811b3f 2024-08-28 19:02:06 -03:00
Bruno Perdigão ec5368224f Fix after fbcb19fdb 2024-08-28 18:58:11 -03:00
Bruno Perdigão 56e9488d3e A few updates on Snap and Raycast to improve the snap feel. 2024-08-28 16:52:35 -03:00
Bruno Perdigão 23ec2fc48e Adds intersect_edges_v2 to Cad tools.
This function uses another method to calculate the closest points in two edges that are not parallel.
The `intersect_line_line` from mathutils were not getting good results when using orthogonal view.
2024-08-28 16:52:35 -03:00
Bruno Perdigão fbcb19fdbb Improved snap "stickiness".
Added more control on how the snapping system selects the snapping point, and "M" key now updates the input panel.

Added `intersect_edge_2` to Cad tool

Revert "Improved snap "stickiness"."

This reverts commit 85e67d3996ab8002b4cef7c0b859e9da251d39bf.

A few snap and raycast changes to improve the snap feel
2024-08-28 16:52:35 -03:00
Andrej730 d9f3c9d012 bim.activate_model to hide all annotations #5232 2024-08-28 23:54:17 +05:00
Yassine Oualid 91e236c42c Display and Load Work Schedules from webUI 2024-08-28 18:57:40 +01:00
Yassine Oualid 03ab88b5bb First Draft Cost Schedule Web UI:
- display cost schedules
	- load cost items
	- Add cost items
	- Edit cost item names
2024-08-28 18:54:18 +01:00
Andrej730 42ef06aae1 typing 2024-08-28 18:47:23 +05:00
Andrej730 691dfb45f0 bim.activate_model to unhide all objects #5232
Restore old behaviour (new behaviour was introduced by accident in 786b796) where it would unhide all objects instead of keeping only objects in the current drawing.
2024-08-28 18:42:10 +05:00
Andrej730 760816b7f0 Show occurrences in spatial manager decomposed elements
Example - https://imgur.com/a/PNFUbv0
2024-08-28 17:57:19 +05:00
Andrej730 fc04c6e41e Remove unused property 2024-08-28 17:53:13 +05:00
Andrej730 99e67d528f Remove duplicated then decorator from b9855b2
'then the object name is selected' were already defined in then_the_object_name_is_selected
2024-08-28 16:42:55 +05:00
Andrej730 c113061742 Preserve visibility status for non-ifc objects when drawing is activated
Mentioned in #3402
2024-08-28 16:37:26 +05:00
Andrej730 174ff00a6d Fix errors trying to setup decorations running tests 2024-08-28 16:37:26 +05:00
Andrej730 84a2d4266d Autodocument hotkeys in the BIM tool hotkeys descriptions
Addition to #5223

Example - https://i.imgur.com/vGVHNPL.png
2024-08-28 15:41:50 +05:00
Andrej730 64cba98c3d Fix #5235 2024-08-28 14:37:58 +05:00
Andrej730 1aed2a6b3c Fix error not excluding annotations from other drawings after 3848a21
Mentioned in #5233

Also some refactor:
- checking IfcProduct instead of IfcProject. Not sure when this issue occur in general but if it occurs then it might fail for other non-IfcProducts too, not just IfcProject
- small performance optimization
2024-08-28 12:35:47 +05:00
Andrej730 4e1a956830 Fix #5233 2024-08-28 12:35:47 +05:00
Andrej730 747a39b440 48f0dc6a00 to pass on unix too 2024-08-28 11:29:39 +05:00
Andrej730 1b49515d9f Replace ordered_set with orderly_set
deepdiff deprecated use of ordered_set and switched to orderly_set (ordered_set fork), so we switch too
see https://github.com/seperman/deepdiff/releases/tag/8.0.0
2024-08-28 11:14:52 +05:00
Bruno Perdigão dabb85c466 Fix polytool input for distance zero 2024-08-27 19:59:55 -03:00
Bruno Perdigão b74811b3f4 Polytool, changed decorator order to show created polyline first. 2024-08-27 19:53:03 -03:00
Bruno Perdigão 79eaf895f7 Fix polyline to work only with walls.
This is temporary until we enable polyline to work with other tools.
2024-08-27 19:05:30 -03:00
Bruno Perdigão 994c85a05a black format 2024-08-27 18:22:43 -03:00
Bruno Perdigão 0faacccf6d Raycast now filters objects that are not in the active local view. 2024-08-27 18:20:06 -03:00
Bruno Perdigão 89d27bdf5f Fixed edge snap.
The `intersect_line_line` were returning points that were outside
the object edges, so it was added a function to check if the point
return is on the object edge.
2024-08-27 18:20:06 -03:00
Bruno Perdigão 76853db32c Fix mixed snap for Polytool 2024-08-27 18:20:06 -03:00
Andrej730 002c50e29d black format 2024-08-27 18:25:30 +05:00
Andrej730 d2efb2ab78 operator to toggle container elements
Example - https://imgur.com/a/Sy83Tnz
2024-08-27 18:25:30 +05:00
Andrej730 8bb78959ef h5 cache - improve logs
Now there are logs when cache was successfully loaded/created/failed to load.
2024-08-27 18:25:30 +05:00
Andrej730 48f0dc6a00 bim.purge_hdf5_cache to skip currently loaded cache
Previously it would fail with:
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'bonsai\\bim\\data\\cache\\988c190483ae6bab7cf6b00cee78694d.h5'
2024-08-27 18:25:30 +05:00
Andrej730 27aee31adf typing 2024-08-27 18:25:29 +05:00
Bruno Perdigão 24aaefb927 Polytool, fixed error with setting the plane method 2024-08-27 10:03:02 -03:00
Bruno Perdigão 7daec25454 Polytool, fixed decorator to show the mouse snapping point on top. 2024-08-27 10:03:02 -03:00
Andrej730 8309b13db0 reveal element filters and drawing underlay panels just if drawing is active
Those two panels were requiring drawing's camera to be active object which was a bit confusing since "Active Drawing" section above worked fine without selecting camera explicitly.

https://i.imgur.com/wcmA73Z.png
2024-08-27 17:55:44 +05:00
Andrej730 5e95985d19 Fix error setting integer properties in bim tests 2024-08-27 11:33:58 +05:00
Andrej730 fefe325ece Fix workflow for tests requiring Sun Position extension 2024-08-27 11:33:21 +05:00
Bruno Perdigão b717abf639 Polytool: small fix for Z axis line decorator 2024-08-26 17:11:20 -03:00
Bruno Perdigão 32ae12b45a Polytool: added on screen snap information. 2024-08-26 17:11:19 -03:00
Bruno Perdigão 48b74ebb76 Polytool: creates a decorator to show instructions on the screen. 2024-08-26 17:11:19 -03:00
Bruno Perdigão 197d0b3258 Fixed issue with X, Y and Z input for polytool.
This issue was caused by the change to X, Y, Z keys for lock axis.
2024-08-26 17:11:19 -03:00
Bruno Perdigão 2a1bc30f19 Polytool improved axis lock and mixed snapping
You can now lock into an axis while snapping to an object.
The result will be to closer point. In the future, there should
be a way for the user to select between different points.
2024-08-26 17:11:19 -03:00
Bruno Perdigão 6dcbd98769 Fixed error for measure tool when working with top or side view. 2024-08-26 17:11:19 -03:00
Bruno Perdigão 1be025ed86 Fixed typo 2024-08-26 17:11:19 -03:00
Bruno Perdigão 6fa87a16ab Polytool refactor for selecting plane and axis snap.
User can now select X, Y, Z to lock to an axis, and
S-X, S-Y and S-Z to lock to a plane.
2024-08-26 17:11:19 -03:00
Ziad-I 8c19b695ea fix drawings and sheets paths not being normalized
which lead to the paths sometimes having both / and \\
2024-08-26 20:07:50 +03:00
Ziad-I 5831c56380 remove left over print :) 2024-08-26 16:29:09 +03:00
Andrej730 3dde1b80b9 Fix errors initializing hdf5 cache #4832 2024-08-26 17:33:23 +05:00
Andrej730 08dd8f87ff Operator to select document related objects
https://i.imgur.com/4gXAram.png
2024-08-26 17:15:44 +05:00
Andrej730 1c3cf44122 get_referenced_elements to support IfcExternalInformation 2024-08-26 17:15:44 +05:00
Andrej730 868454c011 delete brick.ttl (added in d1d9db3) 2024-08-26 17:15:44 +05:00
Andrej730 edcfcd8850 Fix error if user hit shift-a in Annotation Tool without any drawing active 2024-08-26 15:47:00 +05:00
Andrej730 33bbf9fc53 remove debug print in collector.assign 2024-08-26 15:47:00 +05:00
Andrej730 286e90e299 Add annotation by default to the active drawing #5216
Approach in 358c834 didn't worked out because annotations are assigned to the drawing after assign_class and we can't check in assign_class whether it's going to be part of the drawing.
2024-08-26 15:46:59 +05:00
Bruno Perdigão 5aa7758795 Small fix in angle input for polytool 2024-08-25 21:36:11 -03:00
Bruno Perdigão 6c47baf0de Small fix in polytool with angle input when working with millimeters units 2024-08-25 19:13:27 -03:00
Bruno Perdigão 51018177cd Added option for wall_from_to_points not round the length and angle.
This function was hard coded to round length angle, now it has an option.
I assume it was originally built like this because it was supposed to
work only with Grease Pencil.
2024-08-25 19:07:50 -03:00
Bruno Perdigão be9719f5ca Fixed issue with creating duplicated points in polytool 2024-08-25 18:53:53 -03:00
Bruno Perdigão 9193ff7252 Fixed error with raycast in orthogonal view 2024-08-25 18:42:00 -03:00
Bruno Perdigão 53c3019b73 Small fix 2024-08-25 18:36:20 -03:00
Bruno Perdigão 6bbf3d3917 Refactor snapping functions and allow to choose snapping point.
By pressing "M", the user can now cycle through active snapping points when
there are many options close to each other. Still lacks a text to give
information about the active point.
2024-08-25 18:27:10 -03:00
Ziad-I 47a15011f6 add button to drawings panel to open documentation web ui page
might need a different icon since the URL icon is used by the open_drawing button
2024-08-25 21:38:15 +03:00
Ziad-I f26f6dfe5e fix broken display for multiple spreadsheets due to absolute position
removed absolute positioning as it made spreadsheets on top of each other
and made the spreadsheet's width and height as full screen as possible. also, add a separating margin between two spreadsheets.
2024-08-25 20:30:20 +03:00
Ziad-I 1745a4fd39 fix theme data not being sent when all Bonsai's are disconnected 2024-08-25 17:50:26 +03:00
Dion Moult fcaac3787b Continuing work to update docs 2024-08-25 22:15:12 +10:00
Thomas Krijnen 2d3adce59e Compatibility fix for v0.8 wrapper instances 2024-08-25 10:51:10 +02:00
Thomas Krijnen 7e6607adcf black 2024-08-25 10:39:57 +02:00
Thomas Krijnen 46c62d7cdb Add no-parallel-mapping setting to type literal 2024-08-25 10:33:54 +02:00
Thomas Krijnen c521892ca2 ::impl to make msvc17 a bit happier 2024-08-25 09:54:44 +02:00
Dion Moult d4a0dd1527 Split header and panel tool UI into two functions. Align related tool buttons together. 2024-08-25 15:43:55 +10:00
Dion Moult 527cdd3304 General interface docs 2024-08-25 14:55:21 +10:00
tim 31e836cfb4 png icons added 2024-08-25 14:54:30 +10:00
tim 86f123b6b0 Icons to header & sidebar 2024-08-25 14:54:30 +10:00
Thomas Krijnen fea8e3a5c9 Perform similar face bound lenciency in cgal kernel 2024-08-24 20:03:44 +02:00
Thomas Krijnen 3137904055 Perform mapping in parallel (or --no-parallel-mapping) 2024-08-24 20:03:44 +02:00
Bruno Perdigão f89dee7668 Fixed angle input for imperial units in polyline wall and measure tool. 2024-08-24 15:02:22 -03:00
Ziad-I c042d1afe5 make container padding/margin consistent over all pages 2024-08-24 18:48:58 +03:00
Ziad-I 42fc72bd4f add favicon to web UI 2024-08-24 18:12:13 +03:00
Bruno Perdigão f72c128ba6 Improved validation for inputs in polyline wall and measure tool. 2024-08-24 11:48:39 -03:00
Bruno Perdigão 3ceeaa739f Small fix on format_distance to show zero like 0'. 2024-08-24 11:48:39 -03:00
Thomas Krijnen 7a2e58944e clang (rightfully) complains about missing include 2024-08-24 15:00:49 +02:00
Dion Moult b9855b289f More qto and spatial tests. Tests can now select items in a UIList. 2024-08-24 22:48:37 +10:00
Dion Moult c7a8fd9309 More Qto tests and you can now spy on UILists and enum items 2024-08-24 21:39:46 +10:00
Thomas Krijnen daa6b31c5d msvc17 workaround 2024-08-24 13:24:23 +02:00
Dion Moult cd411e1f14 Add smoke tests for colour by property feature 2024-08-24 14:20:13 +10:00
Dion Moult 7a168069f7 Add solar analysis panel UI tests 2024-08-24 13:34:40 +10:00
Bruno Perdigão 97d2e08286 Initial implementation of unit handling for wall polyline tool.
The input panel now works with meters, millimeters and imperial units.
2024-08-23 17:33:34 -03:00
Thomas Krijnen f440a3ca17 Revert OCCT version to 7.5.3 due to HLR poly/edge behaviour 2024-08-23 20:54:06 +02:00
Thomas Krijnen 81bdb551ab SvgSerializer fix: Z == 2 2024-08-23 20:43:27 +02:00
Thomas Krijnen 5fdad744d3 Cgal kernel: Fail boolean op altogether when part conversion to Nef fails 2024-08-23 20:42:32 +02:00
Thomas Krijnen ab6f408db4 Unify edge orientation logic among kernels 2024-08-23 20:41:42 +02:00
Thomas Krijnen cdf8b9c038 Cgal kernel: taxonomy::line is intended to run along local Z 2024-08-23 20:41:17 +02:00
Thomas Krijnen 918fb41a7e Unify face bound counting logic among kernels 2024-08-23 20:39:20 +02:00
Thomas Krijnen 1d8e39e55f NB! For now let's use Epick for cgal-simple instead of actually Simple_cartesian 2024-08-23 20:38:38 +02:00
Thomas Krijnen b0b65e550c dispatch_curve_creation based on template magic instead of dynamic casting 2024-08-23 20:36:47 +02:00
Thomas Krijnen a1527a7e31 --use-material-names no longer in serializer_settings 2024-08-23 20:35:01 +02:00
Ziad-I 2ca3f86fc9 add RMB context menu to tables to set top calc type 2024-08-23 21:30:21 +03:00
Thomas Krijnen d80bcd1a94 Unify variant storage (#5118) 2024-08-23 20:29:07 +02:00
Ziad-I 60a06138d2 edit index.css for color consistency 2024-08-23 19:34:15 +03:00
Andrej730 e2001e82dd fix (hopefully) last failing test in github workflow 2024-08-23 17:25:10 +05:00
Andrej730 92f4cb0ffa fix error reloading camera representation
After 4b4ede7 it was leading to non-existing code
2024-08-23 17:25:10 +05:00
Andrej730 9f00e8aef0 Use Point RepresentationType for point clouds in ifc4x3
PointCloud representation type marked as deprecated in ifc4x3, see https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcShapeRepresentation.htm
2024-08-23 17:25:10 +05:00
Andrej730 638d200a27 fix error switching to point cloud representation
Previously it wasn't handled and would always result in errors. It seems the only way to load point cloud representation to BBIM was by loading IFC file and only if this is the only representation of the element.
2024-08-23 17:25:10 +05:00
Andrej730 59717d6e92 fix tests after a4a2497f33 2024-08-23 17:25:10 +05:00
Andrej730 009795f7dc More reliable way to get bbim package name #5214
See #5214 for details, can't rely on 'bpy.context.preferences.addons' as it may contain a missing addons too (if addon was manually uninstalled and it won't be able to load but it will still appear in 'addons').
2024-08-23 17:25:10 +05:00
Andrej730 a0792a4b93 typing 2024-08-23 17:25:09 +05:00
Ziad-I 8534b6e154 fix first demo message not showing 2024-08-23 19:34:35 +10:00
Ziad-I 7910a68028 add more details in demo page 2024-08-23 19:34:35 +10:00
Ziad-I d44ee9874b Bonsai web ui templates 2024-08-23 19:34:35 +10:00
Ziad-I 8cd86581ff handle operators from demo page 2024-08-23 19:34:35 +10:00
Ziad-I 0a5b6a41b0 add demo html/css/js 2024-08-23 19:34:35 +10:00
Ziad-I 7bac468151 add demo endpoint and event listener 2024-08-23 19:34:35 +10:00
Ziad-I b375579dcd add new webui demo panel in demo module 2024-08-23 19:34:35 +10:00
Dion Moult d3d1ca0169 Fix bug where select similar property didn't work 2024-08-23 15:29:19 +10:00
Dion Moult 2b0572af10 New feature to filter pset / qto quickly in the panel
Ever work regularly with models that have 30 or more properties per element?
2024-08-23 15:20:47 +10:00
Dion Moult ed6365b292 You can now filter spatial containers by name, long name, or class 2024-08-23 14:27:22 +10:00
Dion Moult e3b1e0773f Show grouping panel by default 2024-08-23 14:20:37 +10:00
Dion Moult 3d38068b90 Unindent project in spatial tree to save space 2024-08-23 14:20:32 +10:00
Dion Moult a4a2497f33 You can now filter and search in the spatial decomposition panel 2024-08-23 13:49:45 +10:00
Dion Moult 1ef2fb89af Show annotations and hide openings in spatial decomposition element filter 2024-08-23 13:48:19 +10:00
Bruno Perdigão 902d777574 Fix removing the dimension decorator in measure tool. 2024-08-22 17:44:48 -03:00
Bruno Perdigão 3bd0caade1 Fixed Polyline Wall after changes in Measure tool input 2024-08-22 16:11:22 -03:00
Bruno Perdigão 301cb4bbdc Small fix in TAB behavior for measure and polyline tool 2024-08-22 15:55:05 -03:00
Bruno Perdigão f0338ffdda Measure tools now shows decorator for the dimension of every line and the angles between them. Area calculation was removed and will be introduced in another operator 2024-08-22 15:54:11 -03:00
Dion Moult 2100528cbe Rebrand to Bonsai in IOS-Python docs 2024-08-23 00:12:11 +10:00
Dion Moult ae4f681f73 Remove superseded test 2024-08-22 23:58:15 +10:00
Dion Moult 53d7624fc4 Work in progress starting to restructure docs in preparation for next release 2024-08-22 23:56:59 +10:00
Andrej730 951b2b76a6 small fix for 94f5137684 2024-08-22 18:34:13 +05:00
Andrej730 e9b4b6560e drawing.create_camera not to assign camera to the scene collection
Noticed that added drawing camera was linked to the scene collection and after collector.assign it was linked to the 2 collections instead of just 1 - it's own drawing collection and the scene collection.
2024-08-22 18:34:13 +05:00
Andrej730 cabffdc549 fix tests after 4e48c35425 2024-08-22 18:33:21 +05:00
Andrej730 7ea60742d6 fix typo 2024-08-22 18:28:50 +05:00
Andrej730 358c834427 fix bim tests after 143e094
drawings and annotations that are part of some drawing don't need to be added to the spatial hierarchy
2024-08-22 18:28:50 +05:00
Andrej730 5d6655cbc7 fix issue adding drawing representation after ef04402ed8 2024-08-22 18:28:50 +05:00
Andrej730 4d122d77dc load_from_memory prop - add description 2024-08-22 17:20:48 +05:00
Dion Moult d4e863ed3b Replace BlenderBIM branding with Bonsai in docs 2024-08-22 21:02:19 +10:00
Dion Moult b6ccf505e7 Fix #5177. Refresh georeferencing viz data after data purged. 2024-08-22 20:18:13 +10:00
Dion Moult ce9842983b Fix #5037. Remove deprecated pie menu. 2024-08-22 19:59:55 +10:00
Dion Moult eb19b26a6e Revert xlsx feature, just csv for now
Don't want another dep
2024-08-22 17:24:43 +10:00
Dion Moult 06602d0e39 Download CSV/XLSX from web 2024-08-22 17:22:38 +10:00
Dion Moult 00279b63de Show sum of columns on web spreadsheet, really useful for qto 2024-08-22 17:22:29 +10:00
Dion Moult 6418353119 You can now filter headers in web spreadsheets 2024-08-22 17:22:09 +10:00
Dion Moult 3afbbe51d2 Make spreadsheets fullscreen
Spreadsheets from multiple sessions need to be redesigned to perhaps use tabs or split windows or something else
2024-08-22 17:21:48 +10:00
Dion Moult ddb767674b Fix bug where there would be missing data in web spreadsheets
See https://github.com/olifolkerd/tabulator/issues/3135
2024-08-22 15:37:04 +10:00
Bruno Perdigão 5575ea8296 Polyline and Measure tool now use right-click to confirm input 2024-08-21 23:01:06 -03:00
Bruno Perdigão e8a7a032aa Changed the order of the input panel for Polyline and Measure tool. Distance and Angle now come first. 2024-08-21 22:56:12 -03:00
Bruno Perdigão f23e419685 Fixed bug in Polyline and Measure tool. The input calculation was wrong when you had only one point in the polyline 2024-08-21 22:56:12 -03:00
Bruno Perdigão b87e8136af Raycast and Snap refactor. Snap now works with objects with no faces 2024-08-21 22:56:12 -03:00
Bruno Postle 473d0ae888 Remove Association op cleans blenderbim & bonsai
The remove *.ifc Association removes any stale Linux BlenderBIM
associations as well as Bonsai associations, this should now give a
clean upgrade path. Closes #5212
2024-08-21 21:11:11 +01:00
Andrej730 94f5137684 fix poll error messages addressing empty enum 2024-08-21 18:36:12 +05:00
Andrej730 4e75945435 add surface styles preview (based on their blender materials)
Example - https://i.imgur.com/jH9q7iF.png
2024-08-21 18:36:11 +05:00
Andrej730 e31019eb67 fix issue adding bcf topic viewpoints
missed the set statement which is requirement to make it work for all cases
2024-08-21 18:36:11 +05:00
Andrej730 c505630a20 fix error removing bcf topic comment 2024-08-21 18:36:11 +05:00
Andrej730 860fa81f73 bonsai bcf - activate comment's viewpoint
Example - https://imgur.com/a/iUMgpVm
2024-08-21 18:36:11 +05:00
Andrej730 847b5d226e bim.add_bcf_comment - poll message 2024-08-21 18:36:11 +05:00
Andrej730 ad77d09916 fix bug in bonsai bcf v3 api
it wasn't setting reference links / document references / labels if Topic container for them wasn't created before
2024-08-21 18:36:11 +05:00
Andrej730 9b12cae8b4 bcf bonsai - create bcf v3 projects and display loaded bcf version
Example - https://imgur.com/a/3ZSGtw7
2024-08-21 18:36:11 +05:00
Andrej730 84a8c5dfeb bim.convert_to_blender to ignore linked files 2024-08-21 18:36:11 +05:00
Andrej730 12a7b8a79e bim.convert_to_blender to avoid types without mesh properties 2024-08-21 18:36:11 +05:00
Andrej730 ef04402ed8 Fix Image empty interpreted as Mesh #5194
Apparently we can't trust `obj.data == None` to identify empties since in Blender there are empties that can use `bpy.types.Image` as their `obj.data`.
2024-08-21 18:36:10 +05:00
Andrej730 45fed747c2 fix failing test in model module
it was failing because type object was hidden in viewport and was unselectable
2024-08-21 18:36:10 +05:00
Dion Moult 85229fc865 Fix #5204. Bug where you could attempt to add IFC objects in edit mode which isn't allowed. 2024-08-21 22:22:46 +10:00
tim 916f854905 Update ifccsv.rst
BlenderBIM to Bonsai changes
2024-08-21 22:06:08 +10:00
tim 1915541d20 Update ifcconvert.rst
Changed BlenderBIM Add-on to Bonsai
2024-08-21 22:05:48 +10:00
tim e37b84a95a Update introduction.rst
Replaced BlenderBIM with Bonsai
2024-08-21 22:05:34 +10:00
tim bcb2a37ce0 Removed Linux defaults to not confuse mac users 2024-08-21 22:05:14 +10:00
tim 018d6847a0 Update blenderbim.rst
replaced BlenderBim text with Bonsai
2024-08-21 22:04:44 +10:00
Dion Moult 35918265d0 Fix bug on Linux where INBETWEEN_MOUSEMOVE is fired for measure tool 2024-08-21 21:47:41 +10:00
Dion Moult 4e48c35425 Remove old dumb stair, superseded by new clever stair (now just called stair) 2024-08-21 21:19:27 +10:00
Dion Moult d985fe9240 Fix #5205. Regression in creating walls / slabs / profiles / products with potentially no default container. 2024-08-21 21:09:29 +10:00
Dion Moult 7c00021aaa You can now toggle flat shading when showing colourschemes 2024-08-21 20:55:35 +10:00
Andrej730 d2dc8b519f fix for ef835e43b8 2024-08-21 15:14:15 +05:00
Andrej730 25fe025354 bonsai file association files #5212 2024-08-21 15:13:59 +05:00
Andrej730 1aae710286 Restore file association files removed by accident #5212 2024-08-21 15:13:59 +05:00
Andrej730 38e8130793 stop ignoring src/bonsai/bonsai/libs
After #4373 with new folder structure 'libs' is no longer used to store dependencies and there is no need to ignore it.
2024-08-21 15:13:58 +05:00
Dion Moult 7e94388074 You can select a colourscheme key via search / dropdown now rather than typing a query 2024-08-21 18:50:55 +10:00
Andrej730 ef835e43b8 bim.save_uv_to_style - support saving uv to objects without a style
There was a problem with assigning uv workflow if object wasn't originally from IFC - saving uv requires object to have IfcSurfaceStyle but assigning IfcSurfaceStyle would reload representation discarding UV.

So, the current workflow for saving non-ifc objects uv to ifc:
1) Assign class to ifc object
2) Create IfcSurfaceStyle with a texture (currently also requires a rendering style)
3) Use "Save UV To Style"

Example - https://imgur.com/a/GZqo38M
2024-08-21 12:33:25 +05:00
Andrej730 e5d0eb13bf Show in UI if representation item has UV mapping / colour map
Example - https://i.imgur.com/bWV4dRj.png
2024-08-21 12:33:25 +05:00
Andrej730 4fcf23319f Show in UI an operator for saving UV
It was lost when we deprecated style UI in materials tab.
Button location - https://i.imgur.com/V57MKU2.png

Also added some minor tweaks.
2024-08-21 12:33:25 +05:00
Dion Moult 99154afdb1 You can now specify custom min/max for quantitative legends 2024-08-21 16:34:10 +10:00
Dion Moult e83eb68fe1 Add seaborn colour palletes for tab10, paired, rocket, mako, spectral, and coolwarm
This covers three usecases: qualitative, quantitative min->max, and quantitative middle with low/high
2024-08-21 15:27:21 +10:00
Dion Moult e4a4a33920 Add support for colouring by quantitative colour legend, not just qualitative categories 2024-08-21 14:02:41 +10:00
Dion Moult e8848c9701 Natsort is now a dependency. We'll be using it to do better sorting everywhere. 2024-08-21 14:01:32 +10:00
Bruno Perdigão cfd8044cb3 Fixed bug related to pressing shift for plane selection 2024-08-20 17:47:02 -03:00
Bruno Perdigão 2d7866570e Fixed bug for x, y, z calculation 2024-08-20 17:47:02 -03:00
Bruno Perdigão eb0ed7fe6b Fixed bugs related to shift and added Z as input option 2024-08-20 17:47:02 -03:00
Bruno Perdigão 67733c4449 Improved calculation for coordinates from distance and angle 2024-08-20 17:47:02 -03:00
Bruno Perdigão b3940cdc45 Minor refactor and clean up 2024-08-20 17:47:02 -03:00
Bruno Perdigão 94e75aebb0 Added area calculation to the input panel 2024-08-20 17:47:02 -03:00
Bruno Perdigão ff203b2a13 Changed decorator name to PolylineDecorator 2024-08-20 17:47:02 -03:00
Bruno Perdigão 10616df494 black format 2024-08-20 17:47:02 -03:00
Bruno Perdigão 1dc6d4935e Polyline tool: improved plane selection method and decorators 2024-08-20 17:47:02 -03:00
Bruno Perdigão 04088af2b6 small fix 2024-08-20 17:47:02 -03:00
Bruno Perdigão c477173096 Improved plane selection for Measure tool 2024-08-20 17:47:02 -03:00
Bruno Perdigão 2f4093f958 Fixed decorator for mixed snaping 2024-08-20 17:47:02 -03:00
Bruno Perdigão 95fc51da76 Created function to mix snap point with axis lock in polyline tool 2024-08-20 17:47:02 -03:00
Bruno Perdigão 50e629c02c Removed code after refactor 2024-08-20 17:47:02 -03:00
Bruno Perdigão 4a178fca58 Fixed error in polyline tool, when two points where add at the same location sequentially 2024-08-20 17:47:02 -03:00
Bruno Perdigão aff5b238d9 WIP: Added possibility to change plane intersection method 2024-08-20 17:47:02 -03:00
Bruno Perdigão 315b6060b0 WIP: Changed coordinates, distance and angles calculations to allow for 3d vectors 2024-08-20 17:47:02 -03:00
Bruno Perdigão b137197586 Changed input validantion to Snap tool 2024-08-20 17:47:02 -03:00
Bruno Perdigão d1d9db3ed8 WIP: started refactoring to develop the measure tool with most of the logic from polyline wall 2024-08-20 17:47:02 -03:00
Andrej730 736b50c6fa bonsai bcf - fix issue when viewpoints were not reloaded
when new bcf file was loaded
2024-08-20 18:39:09 +05:00
Andrej730 64b96633c2 bonsai bcf v3 - support working with viewpoints #2790
Also fixed a bug when removing viewpoint always removed the last viewpoint
2024-08-20 18:39:09 +05:00
Andrej730 8eae997053 bcf v3, bonsai bcf v3 - support extracting files #2790
extracting files in general is also improved - now it's possible to extract a file that was just added to bcf in memory and not yet saved to the disk.

Update model.py
2024-08-20 18:39:09 +05:00
Andrej730 fee56fc120 bonsai bcf - remove "bim.edit_bcf_author"
bcfxml doesn't actually have "author" field - this field is not stored in bcf, it's just needed as an UI for author for newly added comments and topics.
2024-08-20 18:39:09 +05:00
Andrej730 d1f87d5467 fix bug in 71ddc6384a 2024-08-20 18:39:09 +05:00
Andrej730 7539404c27 bcf v3 & bonsai bcf v3 - support adding/removing header files #2790
Also removed unnecessary read in AddBcfDocumentReference.
2024-08-20 18:39:08 +05:00
Andrej730 71ddc6384a bonsai bcf v3 - support adding/removing related topics #2790
Not entirely sure about TopicHandler.guid typing, just made it consistent with v2 for now.
2024-08-19 18:44:33 +05:00
Andrej730 4b402f8ea5 bonsai bcf - dropdown for related topics
Previously you had to type in exactly manually.
Besides the dropdown it should also show now a topic description in the dropdown items tooltips.
Removed "bim.add_bcf_related_topic" poll as it should be now covered by the enum.

Example - https://imgur.com/a/xhgcGWI
2024-08-19 18:44:33 +05:00
Andrej730 c39fa80e09 bonsai bcf v3 - support working with topics #2790 2024-08-19 18:44:33 +05:00
Andrej730 c89ad8c7da related topic - poll message set 2024-08-19 18:44:33 +05:00
Andrej730 6dfe46d9bd bonsai bcf - add default project for bcf v3, fix small possible issue with bcf v2
In theory in bcf v2 there could be a project with project info but without project.
2024-08-19 18:44:33 +05:00
Andrej730 1de51ecf77 bonsai bcf - fix bim snippet ui issue
schema is optional field in bcf v2 and it was unreliable to use it to detect whether bim snippet is present or not
2024-08-19 18:44:33 +05:00
Andrej730 8a55f18c95 bonsai bcf - poll message for adding bim snippet 2024-08-19 18:44:32 +05:00
Andrej730 7a1976cfc1 bonsai bcf - show info message when project is saved/loaded
to make ui more responsive
2024-08-19 18:44:32 +05:00
Andrej730 78c6401453 bonsai bcf v3 - support working with bim snippets 2024-08-19 18:44:32 +05:00
Andrej730 e12838d93e bonsai bcf v3 - support working with comments #2790 2024-08-19 18:44:32 +05:00
Andrej730 7aa5b71a6a bcf - comments setter api 2024-08-19 18:44:32 +05:00
Andrej730 2ef3af5e1b bonsai bcf - make document reference uneditable
as this data is not really editable and won't be saved
2024-08-19 18:44:32 +05:00
Andrej730 d399f7c6b7 bonsai bcf - add save current project button
Now there are two separate buttons - "save project" and "save project as".
Example - https://i.imgur.com/1vuVfgi.png
2024-08-19 18:44:32 +05:00
Andrej730 beb7f75368 bonsai - bcf v3 document references #2790 2024-08-19 18:44:32 +05:00
Andrej730 dc6fdc2a98 typing 2024-08-19 12:26:49 +05:00
Thomas Krijnen 45be17c25a Remove duplicate UseMaterialNames setting binding #5191 2024-08-19 09:15:49 +02:00
Dion Moult 4f11b19b3d Update install instructions for Bonsai 2024-08-18 22:22:21 +10:00
Ryan Schultz f646cf4372 Removes the style from all selected objects 2024-08-17 13:36:10 -05:00
Ziad-I 538859f60a make has_started check for both pid and port
this solves the issue when a user has not killed a previous server so the port of that server wasn't removed from the pid file, which would make has_started return true even if server hasn't started yet.
2024-08-16 20:52:39 +10:00
Ziad-I 75da994faf fix gantt display when there are no dependencies 2024-08-16 20:52:39 +10:00
Ziad-I 99827df89a fix setting color-scheme css property 2024-08-16 20:52:39 +10:00
Ziad-I 054a900779 edit names of pages and paths for them 2024-08-16 20:52:39 +10:00
Ziad-I e800f8b93d docstrings and formating 2024-08-16 20:52:39 +10:00
Ziad-I 7163697362 add open different web UI pages on starting it up 2024-08-16 20:52:39 +10:00
Ziad-I 29600711ae make webui default for work schedules and simplfy condition 2024-08-16 20:52:39 +10:00
Ziad-I 1d0ee61ba7 fix dependency display bug
dependency was not being displayed correctly due to calling draw on Gantt before appending it to the DOM, I think?
2024-08-16 20:52:39 +10:00
Ziad-I fb909ace1a edit condition if user tries to export to web with no server
previously it was just checking if there was a server running but not if blender was connected to a server, this was being handled in the operator itself which isn't the best.
2024-08-16 20:52:39 +10:00
Ziad-I 6ae5dbacf4 make web default format when exporting 2024-08-16 20:52:39 +10:00
Ziad-I 52bffa7f9c handle edge case not covered by last commit 2024-08-16 20:52:39 +10:00
Ziad-I e9a502ccec fix error when exporting an empty csv 2024-08-16 20:52:39 +10:00
Ziad-I f3d4eed19e split addGanttElement function into smaller functions
for code organization and readability
2024-08-16 20:52:39 +10:00
Ziad-I d260298ab2 fix printing when there is multiple gantt charts 2024-08-16 20:52:39 +10:00
Ziad-I c7d0cff300 edit or commented left over console.log 2024-08-16 20:52:39 +10:00
Ziad-I 631deeb094 fix connected list appearing in printing 2024-08-16 20:52:39 +10:00
Ziad-I 953a49f9ae add different bg color for work schedule table rows 2024-08-16 20:52:39 +10:00
Ziad-I 2e94a7c3f1 move outdated gantt warning into connected list 2024-08-16 20:52:39 +10:00
Ziad-I 68f10e1502 move outdated data warning into connected list for csv page 2024-08-16 20:52:39 +10:00
Ziad-I 625a57c6de change used text color for warnings 2024-08-16 20:52:39 +10:00
Andrej730 4348b9bff9 bonsai - bcf v3 referenced links support #2790 2024-08-15 18:18:11 +05:00
Andrej730 28ee1a7781 bonsai - dropdown for new bcf topic labels (same as f1db51df1a) 2024-08-15 18:18:11 +05:00
Andrej730 d40119d617 bonsai - more bcf v3 support and lots of todos #2790 2024-08-15 18:18:11 +05:00
Andrej730 774533911c bonsai - fix issues loading bcf v3 #2790 2024-08-15 18:18:10 +05:00
Andrej730 7597b1b29c bonsai, ifcopenshell - append IfcSurfaceStyles from other projects
And other IfcPresentationStyles, though they are not currently supported by bonsai.

Example - https://imgur.com/a/AHlvowp
2024-08-15 18:18:05 +05:00
Andrej730 bd8a2736d4 typing 2024-08-15 18:18:05 +05:00
Andrej730 aafb4b6147 fix missing import in 2066ebcc11 2024-08-14 19:54:45 +05:00
Andrej730 2066ebcc11 bbim, bcf - add simple operator to quickly load ifc file from bcf header
Example - https://imgur.com/a/rieFwNI
2024-08-14 18:44:53 +05:00
Andrej730 795ebc0ac1 remove uninstall/update instructions from preferences
Since 06c8a9e there's no longer issue with loaded binaries preventing to reload the addon on Windows, which works for 4.2.0 and in 4.2.1 we'll have https://projects.blender.org/blender/blender/issues/125049 which essentially does the same, moves the binaries out of the way.

Upgrade also works fine and we have a warning from 3d4c85c to indicate that user should restart Blender after upgrade.
2024-08-14 17:16:25 +05:00
Andrej730 7612cf92c0 remove donate button from bonsai preferences #4373
As per Blender request, see https://extensions.blender.org/approval-queue/bonsai/#activity-2480
2024-08-14 17:03:43 +05:00
Andrej730 db1f4d126a bonsai web module #5178
Ping @Ziad-I just in case
2024-08-14 16:49:34 +05:00
Andrej730 b15820dd10 bonsai libs/desktop #5178 2024-08-14 16:49:34 +05:00
Andrej730 f8f7884278 bonsai other scripts #5178 2024-08-14 16:49:34 +05:00
Andrej730 3318de7f6d bonsai main extension files #5178 2024-08-14 16:49:34 +05:00
Andrej730 726bf40d58 bonsai core module imports #5178 2024-08-14 16:49:34 +05:00
Andrej730 3860884db3 bonsai other ifcopenshell packages #5178 2024-08-14 16:49:34 +05:00
Andrej730 5784e3103d bonsai assets #5178 2024-08-14 16:49:34 +05:00
Andrej730 2a1d1d6e10 bonsaibim urls #5178 2024-08-14 16:49:34 +05:00
Andrej730 485643863f bonsai bim module imports #5178 2024-08-14 16:49:34 +05:00
Andrej730 c03777cfe6 bonsai tool module imports #5178 2024-08-14 16:49:34 +05:00
Andrej730 be442ff1be bonsai copyrights #5178 2024-08-14 16:49:34 +05:00
Andrej730 95e7910f69 bonsai .gitignore #5178 2024-08-14 16:49:34 +05:00
Andrej730 d5592ed2eb fix ifc4d copyright license 2024-08-14 16:49:34 +05:00
Andrej730 a29806ef9e bonsai dev_environment scripts #5178 2024-08-14 16:49:34 +05:00
Andrej730 3a9d79dcd3 bonsai makefile #5178 2024-08-14 16:49:34 +05:00
Andrej730 b9c2e312e3 black format 2024-08-14 16:49:34 +05:00
Andrej730 f1db51df1a blenderbim, bcf - add tooltips for topic attributes based on extensions
Example - https://imgur.com/a/mYiXqXn
2024-08-13 18:53:11 +05:00
Andrej730 312a58ddce bcf - readme note about code structure 2024-08-13 18:53:11 +05:00
Andrej730 1e71708aba bcf v2 - extensions support #3220
The api is the same as for bcf v3 though for bcf v2 they are currently available only in read-only mode.
2024-08-13 18:53:11 +05:00
Andrej730 ad6e00571e bcf v3 - add extensions tests 2024-08-13 18:53:11 +05:00
Dion Moult c8d05951b0 Rename choco dir 2024-08-13 23:47:26 +10:00
Dion Moult 0f8c3b3c83 Name change in workflows dir 2024-08-13 23:21:30 +10:00
Dion Moult 25071dfec6 Rename source dir 2024-08-13 23:09:50 +10:00
Dion Moult cc28f5a92b Search replace in test dir 2024-08-13 15:47:27 +10:00
Dion Moult a57a7041ac Search replace BlenderBIM with Bonsai 2024-08-13 15:45:33 +10:00
Dion Moult 17b90c3241 Search replace BlenderBIM Add-on with Bonsai 2024-08-13 15:40:54 +10:00
Dion Moult 90089f91c6 Minor fix 2024-08-13 15:28:03 +10:00
Dion Moult 37dd2a5607 G'day Bonsai! 2024-08-13 13:38:10 +10:00
Bruno Perdigão bc70130123 Polyline wall - you now can press 'C' to close the polyline 2024-08-12 16:01:25 -03:00
Bruno Perdigão 8d53141d5a Fix polyline wall generator for open polylines 2024-08-12 15:53:42 -03:00
Bruno Perdigão 0ffc62fbf3 lowered the threshold for the polyline snap to axis 2024-08-12 15:39:38 -03:00
Bruno Perdigão 4350e3df82 added shadow to polyline input panel text 2024-08-12 15:38:27 -03:00
Andrej730 2ad601ed34 bcf - fix make models after 237cd99 2024-08-12 18:04:45 +05:00
Andrej730 f9e8d6d478 bcf - fix issues with unexpected reloads from zip
It wasn't considering that self._topics could be an empty dict because there are no topics and it would also reload it. Now we have None value to distinguish when it actually wasn't loaded before.

Same for viewpoints, reference files and document references.

I've also imade mplementations identical/more similar between v2 and v3.
2024-08-12 17:31:52 +05:00
Andrej730 65cc5bf4c1 bbim bcf - fix issues setting visibility exceptions
1) bpy.ops.object.hide_view_set doesn't actually work with context provided selected objects - it's checking whether they're actually selected
2) bpy.ops.object.hide_view_clear wasn't using select=False, selecting revealed objects which might get in the way later.
3) used new api for getting visibility settings
2024-08-12 16:29:10 +05:00
Andrej730 73e5985777 bcf + bbim - set/get selected/visible elements #4857
1) added more high level api for getting/setting selected/visible elements in bcf
2) in bbim when you add a new viewpoint it will remember currently selected and visible objects:
https://imgur.com/a/2pZ79Z2
2024-08-12 16:29:10 +05:00
Andrej730 de14e92720 poll message 2024-08-12 16:29:10 +05:00
Andrej730 09ad47d11b remove debug prints 2024-08-12 16:29:10 +05:00
Andrej730 debe63c1af fix typo 2024-08-12 16:29:10 +05:00
Andrej730 6f2eb6c54a typing 2024-08-12 16:29:10 +05:00
Andrej730 56ca431965 bbim - load bcf files using drag'n'drop
Example - https://imgur.com/a/aK62slh
2024-08-12 16:29:10 +05:00
Andrej730 74e8b80fb4 bbim, bcf - expose topic attributes to edit from bbim #3026
Previously they weren't editable if they were not defined in .bcf already, so previously it was kind of requiring them to be defined by some other software, not BBIM.

Also changed couple prop names to make them more clear to users.
2024-08-12 16:25:41 +05:00
Andrej730 7ecfe372ad fix #5175 after 1626dd8 2024-08-12 15:19:02 +05:00
Andrej730 b017ab7596 black format after #5172 2024-08-12 15:19:01 +05:00
Junzhe Ren bd3905fe76 Update supported VS version installation.rst (#5174)
* Update installation.rst

2022 is now supported by dependency CMake

* Update installation.rst

Updates on Compiling on Windows (Visual Studio)
2024-08-12 15:17:08 +05:00
Bruno Perdigão 0c8048c14d Walls from polyline are now joined when generated 2024-08-11 21:57:16 -03:00
Bruno Perdigão 77f72ecdfa renamed the tools to Snap and Raycast 2024-08-11 21:57:16 -03:00
Bruno Perdigão 723701f1b8 Points are now added relative to default container Z value. 2024-08-11 21:57:16 -03:00
Bruno Perdigão bf96c63f7d moved raycasting functions to Raycasting module 2024-08-11 21:57:16 -03:00
Bruno Perdigão cef8251458 minor refactors 2024-08-11 21:57:16 -03:00
Bruno Perdigão 547981f32c Temporary solution for wall generation with polyline 2024-08-11 21:57:16 -03:00
Bruno Perdigão a3cc0245ca Started a system to lock on axis 2024-08-11 21:57:16 -03:00
Bruno Perdigão 5d934a2baa Improvements on how it handles the numbers input 2024-08-11 21:57:16 -03:00
Bruno Perdigão 4409a35441 small fix related to polyline decorator 2024-08-11 21:57:16 -03:00
Bruno Perdigão f637ef8016 black format 2024-08-11 21:57:16 -03:00
Bruno Perdigão 5e2cefee12 small change on input from keyboard 2024-08-11 21:57:16 -03:00
Bruno Perdigão 67b01dcd0f black format 2024-08-11 21:57:16 -03:00
Bruno Perdigão bc0efd7389 Added snaping to polyline points 2024-08-11 21:57:16 -03:00
Bruno Perdigão 4b4e6fa7e2 adds decorator to angle snap axis 2024-08-11 21:57:16 -03:00
Bruno Perdigão 17a0face6e Now the mouse snaps in angle axis in 30 degree intervals 2024-08-11 21:57:16 -03:00
Bruno Perdigão a3b2860789 added highlight color to the input panel 2024-08-11 21:57:16 -03:00
Bruno Perdigão f8f22257b4 fixed backspace for number input 2024-08-11 21:57:16 -03:00
Bruno Perdigão 8284ed0cdb Fix to allow calculations to work when no point was added yet 2024-08-11 21:57:16 -03:00
Bruno Perdigão d995e010cf WIP: calculates x and y based on distance and angle. Accepts negative input 2024-08-11 21:57:16 -03:00
Bruno Perdigão fcfc070825 WIP: Input panel receives x and y inputs from the keyboard 2024-08-11 21:57:16 -03:00
Bruno Perdigão 55552770a6 Input panel now shows coordinates, distance and angle 2024-08-11 21:57:16 -03:00
Bruno Perdigão 350df4eee5 WIP: Started the input system 2024-08-11 21:57:16 -03:00
Bruno Perdigão 04a273c720 Fixed problem with event type by using event value 2024-08-11 21:57:16 -03:00
Bruno Perdigão 61641acf56 Added 'Backspace' event to remove last polyline point 2024-08-11 21:57:16 -03:00
Bruno Perdigão 10035662dd Basic polyline implementation 2024-08-11 21:57:16 -03:00
Bruno Perdigão 056df7758b Improved performance. Objects are first select by their 2d bounding box related to the view. Then, just the objects close to the mouse use ray cast. 2024-08-11 21:57:16 -03:00
Bruno Perdigão 0522adac63 Added simple snap decorator 2024-08-11 21:57:16 -03:00
Bruno Perdigão 1f781e5cab added mouse offset for raycast 2024-08-11 21:57:16 -03:00
Bruno Perdigão a30fd7cab4 enabled snaping to ground plane 2024-08-11 21:57:16 -03:00
Bruno Perdigão 94ca2423e9 First implementation. Two types of raycast and basic snaping for faces,
edges and edge center.
2024-08-11 21:57:16 -03:00
Ryan Schultz 2938c1fd0b small tweak to the previous commits 2024-08-11 18:32:07 -05:00
Ryan Schultz ab8710bd1e schedule's background fill driven by .ods/xlsx, if it exists.
also added `.border` class to default schedule css.
2024-08-11 12:14:55 -05:00
Ryan Schultz a791abe23e fixes #4780: added preference for default location for schedule's css.
Also added a `border` class to style the schedule's border with css.  That is `fill`, `stroke-width`, and `stroke` are no longer hard-coded.
2024-08-11 11:53:58 -05:00
Chirag Singh e70122f354 Ran Black Formatting 2024-08-11 10:40:10 +10:00
Chirag Singh 96fdced471 1. Added a Json File having SpectralDB Materials. 2. Implemented UIList: Lists down the materials to be mapped with. 3. By default Not mapped material is white. 4. Added a Drop down for category and Subcategory from where the user can select the material from spectralDB 5. Corrected hardcoded render123.hdr as highlighted by Manu in #5033 2024-08-11 10:40:10 +10:00
Andrej730 1c95f6cc3f bcf - remove lru_cache in build_viewpoint #4857
disabling it as it currently won't allows users to create a different viewpoint for the same IFC element (in the same or other bcf file) and also entity position can change between `build_viewpoint` calls
2024-08-09 19:00:10 +05:00
Andrej730 0f03e412c3 bcf - port 3c17718 to v3
According to docs bcf is using meters as their length unit - https://github.com/BuildingSMART/BCF-XML/tree/release_3_0/Documentation

We should create some kind of common code folder to keep this sane...
2024-08-09 19:00:10 +05:00
Thomas Krijnen 6ca3e2a6db Attempt fix #5168 - Update release.yml 2024-08-09 15:54:41 +02:00
Thomas Krijnen 079446a4b6 Attempt fix #5168 - Update Dockerfile 2024-08-09 15:54:32 +02:00
Andrej730 e706e568bd bcf - option to provide snapshot filename + save warnings #4453
Example warning:
WARNING. Snapshot with viewpoint guid '6aff8c6e-216c-48c9-8120-3101816def3e' won't be saved to bcf. Only snapshot data (VisualizationInfoHandler.snapshot) is provided and snapshot filename (ViewPoint.snapshot) is missing.
2024-08-09 16:42:33 +05:00
Andrej730 526a2a6a80 bcf - return added viewpoint in add_visinfo_handler #4453 2024-08-09 16:42:33 +05:00
Andrej730 3e7a2c1b83 bcf - fix inconsistent return types in add_viewpoint #4887 2024-08-09 15:12:41 +05:00
Andrej730 9bb04d3ffc small fix for bcf docs
bcfxml.get_topic actually returns topichandler, not topic
2024-08-09 14:58:10 +05:00
Andrej730 7c4d45ab32 ci - fix ifcdiff dependencies 2024-08-09 14:29:38 +05:00
Andrej730 dafec70097 black format 2024-08-08 18:13:31 +05:00
Andrej730 eca1d47d06 typing 2024-08-08 18:12:45 +05:00
Andrej730 9671be1734 add a couple poll messages 2024-08-08 18:11:00 +05:00
Andrej730 644f32d11c Fix errors appending assets when projects are using georeferencing #5110 2024-08-08 18:11:00 +05:00
Andrej730 1626dd85f4 fix opening recent project showing file browser 2024-08-08 15:43:19 +05:00
Andrej730 3c0103b4da fix issues toggling EDIT mode
1) it was throwing errors if object was linked

2) bim.override_mode_set_edit wasn't considering that toggle_edit_mode might not work out and was changing BIMGeometryProperties.mode though it wasn't needed.
2024-08-08 15:12:57 +05:00
Dion Moult f9c4b6a98f Improve QTO of segment lengths
Previous method uses bounding box which could be wrong if the app (Revit) doesn't extrude in +Z and has a slope (e.g. most pipes). Also Revit tends to use rectangle profiles not for the cross section, but instead for the footprint which is crazy.
2024-08-08 15:13:34 +10:00
Dion Moult b01e93161e Use vertex buffer for more efficient centroids 2024-08-08 08:24:12 +10:00
Andrej730 ffbd3e50c5 typing 2024-08-07 20:27:21 +05:00
Andrej730 98c4a1d110 ifcdiff - add simple tests 2024-08-07 17:33:10 +05:00
Andrej730 e2c4bcb217 blenderbim - hide json output file and some operators if current ifc file is not used
It was misleading since those operators only worked with the current model and had no effect if it wasn't used in ifcdiff.
2024-08-07 17:33:10 +05:00
Andrej730 7e60b6888e ifcopenshell v0.8 fixes #5156 #4832 2024-08-07 17:33:10 +05:00
ArturTomczak bbf8ebcb52 add user-agent header to bSDD calls
As explained in: https://github.com/buildingSMART/bSDD/blob/master/Documentation/bSDD%20API.md#http-header-x-user-agent
2024-08-07 21:12:49 +10:00
Tim c1936b871e Renamed tools #3527 2024-08-07 21:12:29 +10:00
Ziad-I 31d67b5e62 fix bootstrap css conflict by adding dummy class in navbar a tags 2024-08-07 21:11:44 +10:00
Ziad-I 683e168ca1 add border radius to all pages 2024-08-07 21:11:44 +10:00
Ziad-I cbc0b4837f add icons to navbar and make it smaller 2024-08-07 21:11:44 +10:00
Ziad-I 02ff6c00ef add button colors 2024-08-07 21:11:44 +10:00
Ziad-I 78f664e892 fix CSS inconsistency and small errors 2024-08-07 21:11:44 +10:00
Ziad-I d745265048 fix footer for drawings page 2024-08-07 21:11:44 +10:00
Ziad-I 917991feab only ask for updates from specific blender using blender ID 2024-08-07 21:11:44 +10:00
Ziad-I 4877ab4426 add updating and removing of drawings/sheets 2024-08-07 21:11:44 +10:00
Ziad-I 48c5100d3b add blender generated theme for drawings page 2024-08-07 21:11:44 +10:00
Ziad-I 72caf7525e fix highlighting for better visibility 2024-08-07 21:11:44 +10:00
Ziad-I 242d91bc17 small css change 2024-08-07 21:11:44 +10:00
Ziad-I afb22ce7d5 add blender generated theme to gantt page
and some small edits in extracted colors and index page
2024-08-07 21:11:44 +10:00
Ziad-I e45a670ff5 add csv page uses blender theme css variables 2024-08-07 21:11:44 +10:00
Ziad-I 45042aa5e0 index.css uses blender css variables if they are defined 2024-08-07 21:11:44 +10:00
Ziad-I 07aec0730f update title in all pages 2024-08-07 21:11:44 +10:00
Ziad-I 7e6da3edb3 add mix colors function as blender mixes two colors...
blender mixes two colors to get the panel background final color :)
2024-08-07 21:11:44 +10:00
Ziad-I 4f0eafa92d fix blender css variables names 2024-08-07 21:11:44 +10:00
Ziad-I de75eded09 add theme_data listeners in web ui 2024-08-07 21:11:44 +10:00
Ziad-I f2b4bea4de add getting and sending theme data from blender 2024-08-07 21:11:44 +10:00
Ziad-I 4f28b2506d add theme data listeners in sioserver 2024-08-07 21:11:44 +10:00
Ziad-I 281da8ed77 add docstring to has_started and indentation edits 2024-08-07 21:11:44 +10:00
Ziad-I bdf4258895 add footer to drawings page 2024-08-07 21:11:44 +10:00
Ziad-I 385d9b9df7 connected clients list now works correctly with all pages 2024-08-07 21:11:44 +10:00
Ziad-I 0e40df4fa3 now correctly gets drawings and sheets data to send to web ui 2024-08-07 21:11:44 +10:00
Ziad-I b0c132f73a fix when sending csv or gantt data it is saved in the WebData
due to load not always being called as sometimes WebData is loaded before
2024-08-07 21:11:44 +10:00
Dion Moult 4fd802bf3d More efficient shape bbox and average vertex centroid function 2024-08-07 17:21:49 +10:00
Andrej730 e461040e17 bim.pip_install - fix for Blender 4.2 2024-08-06 18:22:35 +05:00
Andrej730 43b574011e fix choco releases 2024-08-06 17:14:43 +05:00
Andrej730 9bae914b51 ci-blenderbim-choco - rename for consistency, add workflow_dispatch
workflow_dispatch allows running workflow manually if needed
2024-08-06 16:52:30 +05:00
Andrej730 945070bdff blenderbim daily releases - add a note about autoupdates 2024-08-06 15:13:50 +05:00
Andrej730 d2b4afe1be blenderbim tests github action 2024-08-06 15:09:47 +05:00
Andrej730 3760f8fafe setup daily builds extensions repo 2024-08-06 15:09:47 +05:00
Andrej730 b9e5cefddf Another fix for #5134 2024-08-06 10:56:36 +05:00
Andrej730 9f5f757ccf Fix #5134 2024-08-05 18:33:03 +05:00
Andrej730 3a147d7f62 Remove Python 3.10 build from bbim builds
Reverts 8514a42, removes python 3.10 from bbim builds as it's not suppored by Blender 4.2+ (https://github.com/gentoo/gentoo/pull/37671)
2024-08-05 16:37:16 +05:00
Andrej730 9f1d14e5a7 black format 2024-08-05 13:59:33 +05:00
Dion Moult bce71f3797 See #5087. See #5114. Skip trying to test shapes that obviously don't have a representation to prevent false positives 2024-08-05 14:18:54 +10:00
Bruno Postle 253dca730d Fix misplaced section/elevation symbols
Looks like a simple typo, closes #5131
2024-08-04 17:30:30 +01:00
Ryan Schultz e0f33a56ec shift+click, to quickly switch the drawing view without turning anything on or off in the scene. as discussed: https://community.osarch.org/discussion/2196/quick-way-to-switch-between-drawing-views#latest
shift+click, to quickly switch the drawing view without turning anything on or off in the scene.
as discussed: https://community.osarch.org/discussion/2196/quick-way-to-switch-between-drawing-views#latest
2024-08-04 10:02:31 -05:00
Dion Moult 2287931e9c Rewrite georeference tests actually test UI effects 2024-08-04 21:23:02 +10:00
Dion Moult 1f7a498606 Fix #4958. Add UI spy class in feature tests to allow more natural BDD tests 2024-08-04 21:23:02 +10:00
Ryan Schultz a9e366b238 Assure text 'wraps' in CloseError 2024-08-03 14:30:06 -05:00
Ryan Schultz 1ca0dfb1e0 Make sure drawings are loaded when calling bim.activate_drawing from sheets UI.
related: c11ba23a3d
2024-08-03 14:09:15 -05:00
Ryan Schultz c11ba23a3d Fix #3728 - Be able to bim.activate_drawing a drawing listed in the sheets UI, as well. 2024-08-03 11:01:31 -05:00
Dion Moult 556c769b40 Sun position add-on is now detected in the current session instead of needing to restart Blender 2024-08-03 23:21:31 +10:00
Dion Moult 78173dd546 Add basic tests for new web module 2024-08-03 23:12:21 +10:00
Dion Moult 2196c16097 Fix failing georeference and spatial core/tool/bim tests and clean dead code 2024-08-03 23:08:35 +10:00
Dion Moult 7af5db7cd4 Collector now unassigns from old ifc collections 2024-08-03 22:04:38 +10:00
Dion Moult c58672cc25 Allow selecting a container object when changing spatial container 2024-08-03 19:29:06 +10:00
Dion Moult 85e022d76e IfcTester now groups results by types to make long failure lists more useful 2024-08-02 23:58:01 +10:00
Andrej730 872f40933f remove Python 3.9 from bbim makefile since a31051a93 2024-08-02 18:54:37 +05:00
Andrej730 4491018f5e fix tool surveyor test 2024-08-02 18:54:37 +05:00
Andrej730 a21c440b5b fix tool geometry tests 2024-08-02 18:54:37 +05:00
Andrej730 143e094db8 assign default container on assigning IfcAnnotation class
Currently if you create a IfcAnnotation it might just get lost as it's not assigned anywhere. Also noticed this since previously we allowed using bim.add_reference_image without any specific drawings.
2024-08-02 18:54:37 +05:00
Andrej730 94e9e945d7 fix system/qto tool tests after e6ac012 2024-08-02 18:54:36 +05:00
Andrej730 5e56115050 typing 2024-08-02 18:54:36 +05:00
Andrej730 1ad654aab3 Fix Ifc tool tests after #4843 and unlinking changes 2024-08-02 18:54:36 +05:00
Andrej730 596ffb093b dev environment script - keep it possible to run the script without any changes
by default it assumes it's executed from ifcopenshell repo directory
2024-08-02 18:54:36 +05:00
Andrej730 3576362fd8 blenderbim make test - run all tests but return error code at the end 2024-08-02 18:11:25 +05:00
Andrej730 2c949bb39a blenderbim "make test" - run tool and bim tests even if some core tests failed 2024-08-02 17:20:29 +05:00
Andrej730 34faa0617b fix running core tests on python 3.10 2024-08-02 17:05:28 +05:00
Dion Moult 15f6b3803f Fix #4986. IfcTester now determines whether a spec is relevant to the ifc version 2024-08-02 22:02:56 +10:00
Andrej730 8514a426bb fix potential blenderbim issues for python 3.10
tomllib was added to python 3.11, tomli can be used for the previous versions.

Though it is a bit questionable since internally Blender is using just tomllib and because of that I'm not sure anymore if Blender still supports Python 3.10.
2024-08-02 16:00:49 +05:00
Andrej730 2062324294 prevent issues importing blenderbim for core test
initialize_bbim_semver was possible breaking on running core tests if system python was missing tomllib
2024-08-02 16:00:49 +05:00
Dion Moult 90c6218210 Fix #5115. Members (e.g. stringers) can now have a stair modifier applied as they may be used to support stairs 2024-08-02 16:34:30 +10:00
Dion Moult 321bb7178d See #5110. Minor fix when appending linked elements. 2024-08-02 16:29:14 +10:00
Dion Moult 42dda0a07a Run black on light 2024-08-02 16:00:45 +10:00
Dion Moult adb17d91f9 Dedicated doc section for blend open/save issue 2024-08-02 15:57:17 +10:00
Dion Moult 646cc59687 Update live install script on linux/mac and merge system support docs into dev setup docs 2024-08-02 15:57:17 +10:00
Dion Moult 38759348cd Document new install location on 4.2 2024-08-02 15:57:17 +10:00
Dion Moult ff44f4f395 Show warning if a blend file is used alongside an ifc 2024-08-02 15:57:17 +10:00
Dion Moult a31051a937 Drop py39 from build matrix for BBIM as we now only support Blender >=4.2 2024-08-02 15:57:17 +10:00
Chirag Singh 5cfd69f337 Merge branch 'v0.8.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.8.0 2024-08-02 11:23:09 +05:30
Chirag Singh f4100f7951 Added HDR support 2024-08-02 11:22:40 +05:30
Thomas Krijnen 785d5118d0 installation.rst - minor enhancement 2024-08-02 05:02:20 +02:00
Thomas Krijnen fddd85817a installation.rst - minor doc enhancements 2024-08-02 04:59:09 +02:00
Thomas Krijnen a689fc6377 Consistency TopExp_Explorer::Current() 2024-08-02 04:50:06 +02:00
Augustin Trancart 8e5a7ed24e improve json lib discovery for cmake 2024-08-02 03:31:17 +02:00
Dion Moult 788217c73c Use loader to get name instead of hardcoding when loading IFCs. See #4517. 2024-08-02 09:31:15 +10:00
Blender Defender 1abc3a1422 feat: Update the patch UI of ResetAbsoluteCoordinates
Instead of specifying parameters `a`, `b`, `c` and `d`, more meaningful parameters have been introduced (`threshold`, `automatic_offset_point`, `x`, `y` and `z`), which allow to do the same operations in a more understandable way.
2024-08-02 08:26:14 +10:00
Richard Brice c31c34b7d2 reimplements piecewise_function using PIMPL idiom
PIMPL idiom allows implementaiton of piecewise_function to evolve without envoking systemwide recompile (unless the class definition changes)
2024-08-01 12:34:49 -07:00
Richard Brice b22ecba179 Implements mutually exclusive access to mapping cache with a mutex 2024-08-01 07:15:22 -07:00
Chirag Singh 22bc98b48b Merge branch 'v0.8.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.8.0 2024-08-01 19:29:48 +05:30
Chirag Singh cf70026570 Gensky corrected and output in .tiff format 2024-08-01 19:29:02 +05:30
Andrej730 3c4a865e0b ci.yml - also run tests for other ifcopenshell packages 2024-08-01 18:01:59 +05:00
Andrej730 8523bb317a bcf, bsdd - add "make test" 2024-08-01 18:01:59 +05:00
Andrej730 4b00b268c0 fix core geometry trests after c4ae957 and 698c648 2024-08-01 18:01:58 +05:00
Andrej730 f0ca34d107 fix core project tests after 0dc084d and e3cb811 2024-08-01 18:01:58 +05:00
Andrej730 3834ecb06a fix core root test after e3cb811 2024-08-01 18:01:58 +05:00
Andrej730 047c9e3ee9 fix core aggregate module test after 6eb3c48 2024-08-01 18:01:58 +05:00
Andrej730 786b796f37 fix breaking bim.activate_model for new collections structure 2024-08-01 18:01:58 +05:00
Andrej730 3fd8be72c2 refresh_ui_data note 2024-08-01 18:01:58 +05:00
Andrej730 cb80081473 fix covering test and fix bug adding coverings in non-meters projects
Noticed that adding a covering in millimeters project didn't worked - the reason was that shapely was using tolerance in ifc project units when get_obj_base_points was returning points in si (blender always operates in meters internally).
I've changed get_obj_base_points to return data in project units and get_bmesh_from_polygon to convert it back to meters for Blender.
It's probably would be better to always operate in si until we need to save data to ifc but I'm not that familiar with that module to just change it everywhere.

Ping @maxfb87 just in case.
2024-08-01 18:01:58 +05:00
Andrej730 5ac84e2be7 covering - more detailed poll messages 2024-08-01 18:01:58 +05:00
Andrej730 c8466e0606 typing 2024-08-01 18:01:58 +05:00
Thomas Krijnen db5167bbaf Prevent infinite recursion 2024-08-01 07:59:23 +02:00
Thomas Krijnen 7d6e26bfd5 Add revolve as top-level item in occt kernel 2024-08-01 07:48:42 +02:00
Thomas Krijnen 2fd339ac6b Hack/workaround for #5064 2024-08-01 07:48:28 +02:00
Dion Moult 6f6dc08696 Minor typo fixes 2024-08-01 14:58:23 +10:00
Andrej730 6cb063ebd2 fix bim drawing module test after 47704b1 2024-07-31 19:00:34 +05:00
Andrej730 fb95e3eb51 fix enabling sverchok as legacy addon on Blender 4.2
It was failing when BBIM is installed as an extension
2024-07-31 19:00:34 +05:00
Andrej730 17a061f917 fix bim test after e6ac012
when Types collection was renamed to IfcTypeProduct
2024-07-31 19:00:34 +05:00
Andrej730 51db65b868 fix resource bim tests after c399eb2
IfcLaborResource doesn't actually support IfcQuantityArea quantities
2024-07-31 19:00:34 +05:00
Andrej730 faab9e04a3 fix resource bim tests after 1a4e467
operator prop was deprecated a long time ago in e2d4a3a
2024-07-31 19:00:34 +05:00
Andrej730 bea92455dd clean up bim tests from trailing spaces 2024-07-31 19:00:34 +05:00
Andrej730 6be1b80a82 fix container operators after a9a4b0c + mention a limitation
If you would select container1 + obj1 with intention to copy obj1 to container1 - running bim.copy_to_container would also copy container1.
Similar issue for referencing/dereferncing structures in other structures in ifc4x3.
2024-07-31 19:00:34 +05:00
Andrej730 2927eadada Display referenced structured elements during container edit for more responsive ui
Before - https://imgur.com/a/m5qtDUn
After - https://imgur.com/a/TFlUNTa
2024-07-31 19:00:33 +05:00
Andrej730 4c5e90dc77 fix bim tests after collections no longer represent spatial hierarchy 2024-07-31 19:00:33 +05:00
Andrej730 f860973172 fix spatial module bim tests after a9a4b0c 2024-07-31 19:00:33 +05:00
Andrej730 94ed0cd59c fix bim.assign_container uses after a9a4b0c + add TODOs 2024-07-31 19:00:33 +05:00
Andrej730 93ea1f98ac fix qto tests after 8c3d10a 2024-07-31 19:00:33 +05:00
Andrej730 b68a92f251 remove bim.assign_objects_base_qto from tests (removed in 8c3d10a) 2024-07-31 19:00:33 +05:00
Andrej730 902da2e720 remove bim.pie_update_container
as we no longer rely on collections for container assignment
2024-07-31 19:00:33 +05:00
Andrej730 d384aaeb9c fix tests after a9a4b0c 2024-07-31 19:00:33 +05:00
Andrej730 133494af97 remove bimtester from bbim (related to 7157590) 2024-07-31 19:00:32 +05:00
Andrej730 64fc9462b6 fix bim attribute tests after 9122f00 2024-07-31 19:00:32 +05:00
Andrej730 3d86e5fff3 fix bim geometry tests after fccf56d 2024-07-31 19:00:32 +05:00
Andrej730 a24bb069aa fix bim tests after changes in quantities calculations 2024-07-31 19:00:32 +05:00
Andrej730 159355d63a typing 2024-07-31 19:00:32 +05:00
Andrej730 598cf4ba79 bim.perform_quantity_take_off description + info message 2024-07-31 19:00:32 +05:00
Andrej730 c86a4c88a9 fix broken search test after 410fff6 2024-07-31 19:00:32 +05:00
Jonathan Gan 6a9e76c2af Documentation: Added getting started documentation for ifcopenshell core (#4965)
* Added getting started documentation for ifcopenshell core

* Apply suggestions from code review

Co-authored-by: Thomas Krijnen <t.krijnen@gmail.com>

* Updated code snippet to use ->as instead of dynamic_cast based on feedback

* Missed out two dynamic casts

* Using preprocessor macros instead of chaining if-else

---------

Co-authored-by: Jonathan Gan <jonathan.gan@inspacion.com>
Co-authored-by: Thomas Krijnen <t.krijnen@gmail.com>
2024-07-31 07:28:25 +10:00
Andrej730 2070071c49 fix bbim builds... 2024-07-30 21:20:14 +05:00
Andrej730 9bbf3bcaba mention supported formats in export window
as currently there is no other ui to indicate that other formats besides .ifc are supported and I guess we just expect users to change extension in the saved filename

https://i.imgur.com/Qa6OlmR.png
2024-07-30 20:47:48 +05:00
Andrej730 0395c0c6c7 fix ifcjson export support #4832
Bumped the version, so Blender would recognize the updated wheel.

Related https://github.com/IFCJSON-Team/IFC2JSON_python/pull/3
2024-07-30 20:47:47 +05:00
Andrej730 a175ec4d28 fix bim tests after d4b055a 2024-07-30 20:46:16 +05:00
Andrej730 139627b6ec fix bim tests after b9f76042b 2024-07-30 20:46:16 +05:00
Andrej730 6f2eb0a116 fix bim tests after a156864 2024-07-30 20:46:16 +05:00
Andrej730 d26561acee fix for bim style module test 2024-07-30 20:46:16 +05:00
Andrej730 de0374bdbd fix error purging unused types in 75f8e75 2024-07-30 20:46:16 +05:00
Ziad-I 51463ab674 fix pid file not there on first run so exception was thrown and not caught
when the user ran the web ui for the first time. the running_pid file was not created yet by the server so it threw an exception due to with open not inside the try block
2024-07-30 18:18:35 +03:00
Dion Moult 6012695cfe Use a tolerance when detecting project norths heuristically 2024-07-30 23:57:54 +10:00
Dion Moult 081b3fcf33 Remove misleading load project button in new project wizard.
Previously there were subtle differences and two ways to load projects which is bad UX.
2024-07-30 23:57:54 +10:00
Dion Moult 27a2c94b4a Fix #5065. Restore "Import IFC" menu item for those wishing to purely work with IFC geometry instead of native ifc 2024-07-30 23:57:54 +10:00
Dion Moult b9f76042bb Remove deprecated export IFC operator ID 2024-07-30 23:57:54 +10:00
Andrej730 e7ef307984 remove redundant indent in bdc5a7a
Co-Authored-By: Adi Shavit <1814800+adishavit@users.noreply.github.com>
2024-07-30 18:56:02 +05:00
Andrej730 1f68e52ac2 black format - exclude 'mvd' and reformat pyproject.toml for readibility 2024-07-30 18:49:10 +05:00
Dion Moult 87dfb75c21 Merge pull request #5103 from IfcOpenShell/webui_drawings
Web UI drawings page
2024-07-30 23:12:04 +10:00
Blender Defender 8afb1b8b30 feat: Display float properties as string properties for more precision in the patch panel
This change affects the following recipes: `OffsetObjectPlacements`, `OffsetStoreyElevations`, `SetFalseOrigin`, `SetRefElevation` and `SetWorldCoordinateSystem`
2024-07-30 23:05:44 +10:00
Blender Defender 5572991a7c style: Run black on geom/occ_utils.py 2024-07-30 23:04:58 +10:00
Blender Defender 653b9288c0 feat: Allow merging multiple ifc projects at once with the MergeProject recipe 2024-07-30 23:04:58 +10:00
Chirag Singh 233b0856af Implemented gensky and fixed executable flag error as mentioned by Manu in #5033 2024-07-30 13:51:20 +05:30
Dion Moult ec29e3d60b Send sigkill not sigterm because aiohttp swallows sigterm and takes a long time
I'm not smart enough to know exactly why
2024-07-30 17:54:28 +10:00
Dion Moult 70bc32b3df Check for PID file prior to connecting to newly started web socket server 2024-07-30 17:28:35 +10:00
Ziad-I ca781655b0 add displaying of svgs in drawings page 2024-07-29 23:35:28 +03:00
Ziad-I 03e2cb70bb remove unnecessary padding 2024-07-29 22:45:35 +03:00
Chirag Singh c7c95e1f9d Implemented gensky (Values Hardcoded) 2024-07-29 23:15:31 +05:30
Chirag Singh b040c5e25b Pulled changes 2024-07-29 23:13:21 +05:30
Richard Brice 60b007d28a Fixes domain of vertical and cant pwf (Issue #5072) 2024-07-29 09:48:15 -07:00
Andrej730 52130a3eb6 fix materials / styles bim tests #4843 2024-07-29 18:53:12 +05:00
Andrej730 5e849d7b81 update core.tool.Material to fix tests 2024-07-29 18:53:12 +05:00
Andrej730 a7a28f613b Fix errors in tests and scripts removing styles
remove_style relies on style_type which is using StylesData to get the enum of it's values and StylesData will fail to load on `material = tool.Ifc.get_object(ifc_file.by_id(style.ifc_definition_id))` as ifc_definition_id was removed but not yet removed as an item from styles ui.

This issue doesn't occur when user is working from UI since StylesData precached when they load styles UI but if they run a script (as we do in bim tests) StylesData is not precached and will be loaded when get_active_style_type() is called leading to errors.
2024-07-29 18:53:12 +05:00
Andrej730 46b3bfecd1 fix issues assigning material sets and material lists 2024-07-29 18:53:12 +05:00
Andrej730 11b62a0fdc fix console errors adding new style and changing it's color
1) As adding new styles means it's not assigned anywhere, there is no need to keep graph up to date.
2) Removed Ifc Operator super class from couple operators that do not write ifc data
3) Moved common code to tool.Style
2024-07-29 18:53:11 +05:00
Andrej730 732bb93826 fix duplicated lines in 2575348 2024-07-29 18:53:11 +05:00
Andrej730 a0bda1afd3 typing 2024-07-29 18:53:11 +05:00
Dion Moult e0790601df Black 2024-07-29 22:38:55 +10:00
Dion Moult a9a4b0ccf0 Deprecate "duplicate" spatial tree browser in favour of regular object selection 2024-07-29 22:29:44 +10:00
Blender Defender f8848051ca style: Run black formatter on spatial/ui.py 2024-07-29 21:37:29 +10:00
Blender Defender b81031eecf fix: Remove the "animatable" option from the "engine" and "format" property in BIMFMProperties 2024-07-29 21:37:29 +10:00
Blender Defender 95a7ea8dce refactor: Create property group MultipleFileSelect
To easier create and display properties that allow one or more files as input, a `MultipleFileSelect` property group has been extracted, together with an operator for selecting the files and the code for displaying the property.
2024-07-29 21:37:29 +10:00
Dion Moult 98edb5a34c Display the default container in the UI when creating new types 2024-07-29 19:50:21 +10:00
Dion Moult 8ca2a55616 Implement filtered selection in new spatial decomposition panel 2024-07-29 18:09:08 +10:00
Dion Moult 74141bec73 Sort pset names and properties alphabetically
Can't believe it took this long to get around to doing this
2024-07-29 10:43:15 +10:00
Dion Moult f60c4fd3c5 Forgot to commit these files for the georeferencing updates 2024-07-29 10:42:37 +10:00
Ziad-I d9ee3522bc empty panels before adding names 2024-07-28 22:28:20 +03:00
Ziad-I 2538c47d01 fix display of list items 2024-07-28 22:01:13 +03:00
Ziad-I ec3dc71c0e add showing of drawings' and sheets' names 2024-07-28 21:04:16 +03:00
Ziad-I e5edd9a34d add retrieving drawings data from blender to web ui 2024-07-28 15:09:55 +03:00
Ziad-I f72359918d use blenderbim version instead of blender version 2024-07-27 22:12:14 +03:00
Kurt Battisti dfd505a794 Fix. Docs Georeferencing URL (#5096)
use users/advanced/georeferencing.html
2024-07-28 00:14:50 +10:00
Blender Defender 4a311fe4de fix: Remove the "ifc_patch_args" property (#5095)
* fix: Remove the "ifc_patch_args" property

This property has been removed, because patch recipes with arguments other than the boilerplate arguments automatically display these arguments as properties, and patch recipes that don't allow more arguments than the boilerplate arguments fail, if "ifc_patch_args" is not None or "[]". The test cases have been adjusted accordingly.

* style: run the black formatter to fix failing checks
2024-07-27 22:58:48 +10:00
Ziad-I 9d4493e1da add footer to index and gantt page 2024-07-27 15:52:49 +03:00
Andrej730 a1d8fbdbe9 Fix missing materials from sets #5093 #4832
Regression in ifcopenshell 0.8 - missing materials and styles from IfcMaterialProfileSets, IfcMaterialProfileSetUsages, IfcMaterialLayerSet.
2024-07-27 15:38:22 +05:00
Andrej730 952abde48e fix console errors related to material rename from ui
1) update_material_name was triggered for categories and failed since ifc id in that case = 0
2) update_material_name was triggered for materials when they were still incomplete and ifc id was still 0
3) moved setting material.name before settings ifc_id to avoid triggering unnecessary changes in ifc
2024-07-27 15:24:05 +05:00
Andrej730 168718063f fix regression #5092 after be7661a83 2024-07-27 15:24:01 +05:00
Dion Moult 4abcbbb4f9 Georeferencing calculator can now calculate blender offsets too 2024-07-27 19:54:12 +10:00
Dion Moult 1ac1b289c1 Map coords always visualise using map units, visualise IFC local origin, and don't show blender coords if no blender offset 2024-07-27 19:53:45 +10:00
Ziad-I c25173aa12 add event listeners and joining of room in drawings page 2024-07-26 22:43:10 +03:00
Andrej730 ea8d303883 fix some test-bim errors in Blender 4.2 2024-07-26 21:23:39 +05:00
Ziad-I 9d79337fa7 edit drawings html/css/js 2024-07-26 17:29:39 +03:00
Blender Defender 82a6ddb01c feat: Make sql_type an enum property in the Ifc2Sql recipe
Since there is a limited number of choices, a string property wouldn't be very helpful. Use a dynamic enum property (which is adjusted according to which types of SQL are available) instead.
2024-07-26 23:35:02 +10:00
Blender Defender a7152bdef0 feat: Convert argument names into prettier looking property names in the IFC Patch Panel
Inspired by #4721
2024-07-26 23:29:41 +10:00
Andrej730 6484a529b0 black format 2024-07-26 18:29:18 +05:00
Andrej730 6e1e653ceb fix tests to use release version of ifc4x3 (ci was failing) 2024-07-26 16:29:46 +05:00
Andrej730 0488e4cccb bcfp numpy 2.0+ support #5080
`np.float_` is deprecated, it was just an alias for `np.float64`
2024-07-26 16:29:26 +05:00
Andrej730 3cf92fd508 bsddclassification - remove description prop as unused 2024-07-26 16:29:26 +05:00
Andrej730 fb2bb7554e bsdd - add buttons to open URIs in browser
Examples:
- https://i.imgur.com/zSvU9vp.png
- https://imgur.com/a/WkbTiVa
2024-07-26 16:29:26 +05:00
Andrej730 be7661a83b remove duplicated operator bim.open_webbrowser
it did exactly the same as bim.open_uri
2024-07-26 16:29:25 +05:00
Andrej730 9684e21d93 bsdd - hide domain selection operator for the active domain
Example - https://imgur.com/a/SkpECro
2024-07-26 16:29:25 +05:00
Andrej730 ee5c401823 bsdd - expose bsdd props descriptions to ui
Example - https://imgur.com/a/xUUeuF5
2024-07-26 16:29:25 +05:00
Andrej730 4aa3ffb765 bsdd - check keyword length only in tool
just to make it more straightforward and remove unused output
2024-07-26 16:29:25 +05:00
Dion Moult c9affcc622 Update README.md 2024-07-26 20:09:26 +10:00
Ziad-I bddb8d1e56 add initial page layout 2024-07-26 02:19:55 +03:00
Ziad-I c4d3dad639 add page setup functions 2024-07-25 15:35:08 +03:00
Ziad-I adbf9093d3 add initial drawings page 2024-07-25 15:12:37 +03:00
Ziad-I c8defbb77f add connected list to gantt chart page 2024-07-25 14:59:56 +03:00
Ziad-I a14fc0a7f5 edit css rules 2024-07-25 14:25:44 +03:00
Ziad-I 8d2717d25b add connected blender list for index page 2024-07-24 23:26:43 +03:00
1257 changed files with 141970 additions and 155123 deletions
-85
View File
@@ -1,85 +0,0 @@
name: ci-blenderbim-daily
on:
push:
paths:
- '.github/workflows/ci-blenderbim-daily.yml'
- 'src/blenderbim/**'
- 'src/ifcopenshell-python/ifcopenshell/**'
- 'src/bcf/bcf/**'
- 'src/ifcclash/ifcclash/**'
- 'src/ifccobie/**'
- 'src/ifcdiff/**'
- 'src/ifccsv/**'
- 'src/ifcpatch/ifcpatch/**'
- 'src/ifc4d/ifc4d/**'
- 'src/ifc5d/ifc5d/**'
- 'src/ifccityjson/**'
branches:
- v0.8.0
workflow_dispatch:
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
name: ${{ matrix.config.name }}-${{ matrix.pyver }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
pyver: [py39, py310, py311, py312]
config:
- {
name: "Windows Build",
short_name: win,
}
- {
name: "Linux Build",
short_name: linux,
}
- {
name: "MacOS Build",
short_name: macos,
}
- {
name: "MacOS ARM Build",
short_name: macosm1,
}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
with:
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
python-version: '3.11'
- name: Get current version
id: version
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
- name: Get current date
id: date
run: echo "date=$(date +'%y%m%d')" >> $GITHUB_OUTPUT
- name: Compile
run: |
cd src/blenderbim && make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }}
- name: Find zip file name
id: find_zip
run: |
filepath=$(ls src/blenderbim/dist/blenderbim_*.zip)
echo "filepath=$filepath" >> $GITHUB_OUTPUT
echo "filename=$(basename $filepath)" >> $GITHUB_OUTPUT
- name: Upload zip file to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.find_zip.outputs.filepath }}
asset_name: ${{ steps.find_zip.outputs.filename }}
release_name: "blenderbim-${{steps.version.outputs.version}}-alpha${{steps.date.outputs.date}} (unstable)"
tag: "blenderbim-${{steps.version.outputs.version}}-alpha${{steps.date.outputs.date}}"
overwrite: true
@@ -1,4 +1,4 @@
name: Publish-blenderbim-chocolatey package
name: ci-bonsai-choco
on:
schedule:
@@ -9,11 +9,12 @@ on:
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# * * * * *
- cron: "30 0 * * *" # 30min past utc midnight
workflow_dispatch:
env:
major: 0
minor: 0
name: blenderbim
name: bonsai
choco_version: 1.1.0
CHOCO_TOKEN: ${{ secrets.CHOCO_TOKEN }}
@@ -41,5 +42,6 @@ jobs:
- name: Check in release tags if we should do a choco release and perform the release if needed
id: do_choco_release
run: |
cd /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/ &&
pip install pygithub
cd /home/runner/work/IfcOpenShell/IfcOpenShell/choco/bonsai/ &&
python3 choco_release.py
+155
View File
@@ -0,0 +1,155 @@
name: ci-bonsai-daily
on:
push:
paths:
- '.github/workflows/ci-bonsai-daily.yml'
- 'src/bonsai/**'
- 'src/ifcopenshell-python/ifcopenshell/**'
- 'src/bcf/bcf/**'
- 'src/ifcclash/ifcclash/**'
- 'src/ifccobie/**'
- 'src/ifcdiff/**'
- 'src/ifccsv/**'
- 'src/ifcpatch/ifcpatch/**'
- 'src/ifc4d/ifc4d/**'
- 'src/ifc5d/ifc5d/**'
- 'src/ifccityjson/**'
branches:
- v0.8.0
workflow_dispatch:
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
name: ${{ matrix.config.name }}-${{ matrix.pyver }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
pyver: [py311, py312]
config:
- {
name: "Windows Build",
short_name: win,
}
- {
name: "Linux Build",
short_name: linux,
}
- {
name: "MacOS Build",
short_name: macos,
}
- {
name: "MacOS ARM Build",
short_name: macosm1,
}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
with:
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
python-version: '3.11'
- name: Get current version
id: version
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
- name: Get current date
id: date
run: echo "date=$(date +'%y%m%d')" >> $GITHUB_OUTPUT
- name: Compile
run: |
cd src/bonsai && make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }}
- name: Find zip file name
id: find_zip
run: |
filepath=$(ls src/bonsai/dist/bonsai_*.zip)
echo "filepath=$filepath" >> $GITHUB_OUTPUT
echo "filename=$(basename $filepath)" >> $GITHUB_OUTPUT
- name: Upload zip file to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.find_zip.outputs.filepath }}
asset_name: ${{ steps.find_zip.outputs.filename }}
release_name: "bonsai-${{steps.version.outputs.version}}-alpha${{steps.date.outputs.date}} (unstable)"
tag: "bonsai-${{steps.version.outputs.version}}-alpha${{steps.date.outputs.date}}"
overwrite: true
body: "See README in https://github.com/IfcOpenShell/bonsai_unstable_repo/ on how to setup autoupdates for daily Bonsai builds."
update-extensions-repo-and-run-tests:
needs: [build]
runs-on: ubuntu-latest
steps:
- name: Checkout bonsai_unstable_repo repository
uses: actions/checkout@v2
with:
repository: IfcOpenShell/bonsai_unstable_repo
token: ${{ secrets.IOS_TO_BLENDER_REPO }}
path: bonsai_unstable_repo
- name: Update index.json on extensions repo
run: |
set -x -e
# Download Blender.
wget -q -O blender.tar.xz https://ftp.nluug.nl/pub/graphics/blender/release/Blender4.2/blender-4.2.0-linux-x64.tar.xz
tar -xf blender.tar.xz
# Setup Blender.
BLENDER_PATH=$(find blender-*/ -maxdepth 0 -exec readlink -f {} \;)
export PATH="$PATH:$BLENDER_PATH"
blender --version
cd bonsai_unstable_repo
pip install -r requirements.txt
python setup_extensions_repo.py --last-tag
git config --global user.name 'IfcOpenBot'
git config --global user.email 'IfcOpenBot@users.noreply.github.com'
git add index.json
git add readme.md
git commit -m "Update index.json"
git push
- name: Run bonsai tests
run: |
set -x -e
BLENDER_PATH=$(find blender-*/ -maxdepth 0 -exec readlink -f {} \;)
export PATH="$PATH:$BLENDER_PATH"
bonsai_zip="$(pwd)/$(ls bonsai_unstable_repo/bonsai_py311*-linux-x64.zip)"
blender --version
blender --command extension install-file -r user_default -e $bonsai_zip
blender --command extension list
wget -q -O sverchok.zip https://github.com/nortikin/sverchok/archive/refs/heads/master.zip
# ifcsverchok expecting sverchok to be named "sverchok" and not "sverchok-master".
unzip -q sverchok.zip
mv sverchok-master sverchok
zip -q -r sverchok.zip sverchok
rm -r sverchok
blender --command extension install-file -r user_default sverchok.zip
git clone https://github.com/IfcOpenShell/IfcOpenShell.git IfcOpenShell
cd IfcOpenShell/src/ifcsverchok
make dist
sverchok_zip="$(pwd)/dist/$(ls dist)"
blender --command extension install-file -r user_default $sverchok_zip
# Install Sun Position extension.
blender --online-mode --command extension sync
blender --online-mode --background --python-expr "import bpy; \
bpy.ops.extensions.package_install(repo_index=0, pkg_id='sun_position'); \
bpy.ops.preferences.addon_enable(module='bl_ext.blender_org.sun_position'); bpy.ops.wm.save_userpref()"
cd ../bonsai
pip install pytest-blender
blender --background --python scripts/setup_pytest.py
blender --python-expr "import bonsai; print(bonsai.bbim_semver); import ifcopenshell; print(ifcopenshell.version)" --background
make test
@@ -1,6 +1,6 @@
name: ci-blenderbim
name: ci-bonsai
# Differences from ci-blenderbim-daily.yml:
# Differences from ci-bonsai-daily.yml:
# - make has IS_STABLE=TRUE
# - action is never triggered and executed only manually
# - doesn't add a current date to the release and tag
@@ -24,7 +24,7 @@ jobs:
strategy:
fail-fast: false
matrix:
pyver: [py39, py310, py311, py312]
pyver: [py310, py311, py312]
config:
- {
name: "Windows Build",
@@ -53,12 +53,12 @@ jobs:
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
- name: Compile
run: |
cd src/blenderbim &&
cd src/bonsai &&
make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }} IS_STABLE=TRUE
- name: Find zip file name
id: find_zip
run: |
filepath=$(ls src/blenderbim/dist/blenderbim_*.zip)
filepath=$(ls src/bonsai/dist/bonsai_*.zip)
echo "filepath=$filepath" >> $GITHUB_OUTPUT
echo "filename=$(basename $filepath)" >> $GITHUB_OUTPUT
- name: Upload zip file to release
@@ -67,6 +67,6 @@ jobs:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.find_zip.outputs.filepath }}
asset_name: ${{ steps.find_zip.outputs.filename }}
release_name: "blenderbim-${{steps.version.outputs.version}}"
tag: "blenderbim-${{steps.version.outputs.version}}"
release_name: "bonsai-${{steps.version.outputs.version}}"
tag: "bonsai-${{steps.version.outputs.version}}"
overwrite: true
+10 -2
View File
@@ -47,6 +47,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install xmlschema xsdata numpy lxml pytest isodate lark networkx tabulate python-dateutil shapely
pip install mathutils
pip install src/bcf --no-deps
pip install https://github.com/Andrej730/aud/archive/refs/heads/master-reduced-size.zip
@@ -106,7 +107,7 @@ jobs:
- name: Run IfcConvert on Sample files
run: |
(find test/input src/blenderbim/test/files -name '*.ifc' | while read i; do \
(find test/input src/bonsai/test/files -name '*.ifc' | while read i; do \
echo $i | tee -a log; \
timeout 1m "$(which IfcConvert)" -yv "$i" "$i.obj" --validate >> log 2>&1; \
echo $i $? >> statuses; \
@@ -125,4 +126,11 @@ jobs:
python tests.py
cd ../src/ifcopenshell-python
mv ifcopenshell ifcopenshell-local # Force testing on installed module
make test-safe
make test
cd ../bcf && make test
pip install requests
cd ../bsdd && make test
pip install deepdiff
cd ../ifcdiff && make test
cd ../ifcpatch && make test
cd ../ifctester && make test
+4 -4
View File
@@ -8,12 +8,12 @@ on:
jobs:
activate:
if: github.repository == 'IfcOpenShell/IfcOpenShell'
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- run: echo ok go
build:
needs: activate
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -52,8 +52,8 @@ jobs:
-DOCC_INCLUDE_DIR=/usr/include/opencascade \
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 \
-DPYTHON_INCLUDE_DIR:PATH=/usr/include/python3.8 \
-DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.8.so \
-DPYTHON_INCLUDE_DIR:PATH=/usr/include/python3.10 \
-DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.10.so \
-DLIBXML2_INCLUDE_DIR=/usr/include/libxml2 \
-DLIBXML2_LIBRARIES=/usr/lib/x86_64-linux-gnu/libxml2.so \
-DGLTF_SUPPORT=On \
+9 -12
View File
@@ -73,19 +73,16 @@ src/ifcopenshell-python/test/build
# mypy cache
.mypy_cache
# blenderbim libs
src/blenderbim/blenderbim/libs
# bonsai i18n
src/bonsai/bonsai/translations.py
# blenderbim i18n
src/blenderbim/blenderbim/translations.py
# bonsai test temp files
src/bonsai/test/files/temp
src/bonsai/test/files/basic.ifc.cache.blend
src/bonsai/test/files/basic.ifc.cache.sqlite
# blenderbim test temp files
src/blenderbim/test/files/temp
src/blenderbim/test/files/basic.ifc.cache.blend
src/blenderbim/test/files/basic.ifc.cache.sqlite
src/blenderbim/drawings
src/blenderbim/layouts
src/bonsai/drawings
src/bonsai/layouts
# ifcopenshell swig and compiled files
src/ifcopenshell-python/ifcopenshell/_ifcopenshell_wrapper.so
@@ -100,4 +97,4 @@ src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.py
.cache
# Brickschema
src/blenderbim/blenderbim/bim/schema/Brick.ttl
src/bonsai/bonsai/bim/schema/Brick.ttl
+2 -2
View File
@@ -1,6 +1,6 @@
# -*- mode: Dockerfile -*-
FROM ubuntu:focal
FROM ubuntu:22.04
ARG CHANNEL
ENV CHANNEL=${CHANNEL:-latest}
@@ -23,7 +23,7 @@ RUN echo "deb http://archive.ubuntu.com/ubuntu focal-proposed main restricted" |
echo "deb http://archive.ubuntu.com/ubuntu focal-proposed multiverse" | tee -a /etc/apt/sources.list; \
apt-get -qq update; \
apt-get -y install tzdata dos2unix rsync; \
apt-get -y install python3 libxml2 libpython3.8 \
apt-get -y install python3 libxml2 libpython3.10 \
libboost-all-dev \
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev \
libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
+8 -8
View File
@@ -12,7 +12,7 @@ is implemented for the IFC releases [IFC2x3 TC1] and [IFC4 Add2 TC1]. Extending
is possible at compile-time when using C++ and at run-time when using Python.
In addition to a C++ and Python API, IfcOpenShell comes with an ecosystem of tools, notably including IfcConvert (an application
to convert IFC models to other formats), the BlenderBIM Add-on (an add-on to Blender providing a graphical IFC authoring platform),
to convert IFC models to other formats), the ~~BlenderBIM~~ Bonsai Add-on (an add-on to Blender providing a graphical IFC authoring platform),
and many other libraries, CLI apps, and more. Support is also provided for auxiliary standards such as BCF and IDS.
For more information, see:
@@ -22,10 +22,10 @@ For more information, see:
* [IfcOpenShell C++ Installation](https://docs.ifcopenshell.org/ifcopenshell/installation.html)
* [IfcOpenShell Python Installation](https://docs.ifcopenshell.org/ifcopenshell-python/installation.html)
* [IfcOpenShell Python Hello World Tutorial](https://docs.ifcopenshell.org/ifcopenshell-python/hello_world.html)
* [BlenderBIM Add-on Website](https://blenderbim.org)
* [BlenderBIM Add-on Documentation](https://docs.blenderbim.org/index.html)
* [Add-on Installation](https://docs.blenderbim.org/users/installation.html)
* [Exploring an IFC model](https://docs.blenderbim.org/users/exploring_an_ifc_model.html)
* [Bonsai Website](https://bonsaibim.org)
* [Bonsai Documentation](https://docs.bonsaibim.org/index.html)
* [Add-on Installation](https://docs.bonsaibim.org/users/installation.html)
* [Exploring an IFC model](https://docs.bonsaibim.org/users/exploring_an_ifc_model.html)
Development is sponsored through your generous donations!
@@ -37,7 +37,7 @@ Contents
| Name | Description | License | Service |
| ------------------------- | --------------------------------------------------------------------- | ------------------- | ------- |
| bcf | Library to read and write BCF-XML and query OpenCDE BCF-API modules | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/bcf-client?label=PyPI&color=006dad)](https://pypi.org/project/bcf-client/) |
| blenderbim | Add-on to Blender providing a graphical native IFC authoring platform | GPL-3.0-or-later | [![Official](https://img.shields.io/badge/BlenderBIM.org-Download-70ba35)](https://blenderbim.org/download.html) [![GitHub Unstable](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=blenderbim-*&label=GitHub-Unstable&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=blenderbim&expanded=true) [![Chocolatey](https://img.shields.io/chocolatey/v/blenderbim-nightly?label=Chocolatey&color=5c9fd8)](https://community.chocolatey.org/packages/blenderbim-nightly/) |
| ~~blenderbim~~ Bonsai | Add-on to Blender providing a graphical native IFC authoring platform | GPL-3.0-or-later | [![Official](https://img.shields.io/badge/BonsaiBIM.org-Download-70ba35)](https://bonsaibim.org/download.html) [![GitHub Unstable](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=blenderbim-*&label=GitHub-Unstable&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=blenderbim&expanded=true) [![Chocolatey](https://img.shields.io/chocolatey/v/blenderbim-nightly?label=Chocolatey&color=5c9fd8)](https://community.chocolatey.org/packages/blenderbim-nightly/) |
| bsdd | Library to query the bSDD API | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/bsdd?label=PyPI&color=006dad)](https://pypi.org/project/bsdd/) |
| ifc2ca | Utility to convert IFC structural analysis models to Code_Aster | LGPL-3.0-or-later |
| ifc4d | Convert to and from IFC and project management software | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifc4d?label=PyPI&color=006dad)](https://pypi.org/project/ifc4d/) |
@@ -46,12 +46,12 @@ Contents
| ifcblender | Historic Blender IFC import add-on | LGPL-3.0-or-later\* |
| ifccityjson | Convert CityJSON to IFC | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifccityjson?label=PyPI&color=006dad)](https://pypi.org/project/ifccityjson/) |
| ifcclash | Clash detection library and CLI app | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcclash?label=PyPI&color=006dad)](https://pypi.org/project/ifcclash/) |
| ifcconvert | CLI app to convert IFC to many other formats | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcconvert/installation.html)
| ifcconvert | CLI app to convert IFC to many other formats | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcconvert/installation.html) [![GitHub](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcconvert-*&label=GitHub&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcconvert&expanded=true)
| ifccsv | Library and CLI app to export and import schedules from IFC | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifccsv?label=PyPI&color=006dad)](https://pypi.org/project/ifccsv/) |
| ifcdiff | Compare changes between IFC models | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcdiff?label=PyPI&color=006dad)](https://pypi.org/project/ifcdiff/) |
| ifcfm | Extract IFC data for FM handover requirements | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcfm?label=PyPI&color=006dad)](https://pypi.org/project/ifcfm/) |
| ifcmax | Historic extension for IFC support in 3DS Max | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcmax.html)
| ifcopenshell-python | Python library for IFC manipulation | LGPL-3.0-or-later\* | [![GitHub](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcopenshell-python-*&label=GitHub&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcopenshell-python&expanded=true) [![PyPI](https://img.shields.io/pypi/v/ifcopenshell?label=PyPI&color=006dad)](https://pypi.org/project/ifcopenshell/) [![Anaconda](https://img.shields.io/conda/vn/conda-forge/ifcopenshell?label=Anaconda&color=43b02a)](https://anaconda.org/conda-forge/ifcopenshell) [![Anaconda](https://img.shields.io/conda/vn/ifcopenshell/ifcopenshell?label=Anaconda-Unstable&color=43b02a)](https://anaconda.org/ifcopenshell/ifcopenshell) [![Docker](https://img.shields.io/docker/pulls/aecgeeks/ifcopenshell?label=Docker&color=1D63ED)](https://hub.docker.com/r/aecgeeks/ifcopenshell) [![AUR](https://img.shields.io/aur/version/ifcopenshell?label=AUR&color=1793d1)](https://aur.archlinux.org/packages/ifcopenshell) [![AUR Unstable](https://img.shields.io/aur/version/ifcopenshell-git?label=AUR-Unstable&color=1793d1)](https://aur.archlinux.org/packages/ifcopenshell-git) |
| ifcopenshell-python | Python library for IFC manipulation | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcopenshell-python/installation.html) [![GitHub](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcopenshell-python-*&label=GitHub&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcopenshell-python&expanded=true) [![PyPI](https://img.shields.io/pypi/v/ifcopenshell?label=PyPI&color=006dad)](https://pypi.org/project/ifcopenshell/) [![Anaconda](https://img.shields.io/conda/vn/conda-forge/ifcopenshell?label=Anaconda&color=43b02a)](https://anaconda.org/conda-forge/ifcopenshell) [![Anaconda](https://img.shields.io/conda/vn/ifcopenshell/ifcopenshell?label=Anaconda-Unstable&color=43b02a)](https://anaconda.org/ifcopenshell/ifcopenshell) [![Docker](https://img.shields.io/docker/pulls/aecgeeks/ifcopenshell?label=Docker&color=1D63ED)](https://hub.docker.com/r/aecgeeks/ifcopenshell) [![AUR](https://img.shields.io/aur/version/ifcopenshell?label=AUR&color=1793d1)](https://aur.archlinux.org/packages/ifcopenshell) [![AUR Unstable](https://img.shields.io/aur/version/ifcopenshell-git?label=AUR-Unstable&color=1793d1)](https://aur.archlinux.org/packages/ifcopenshell-git) |
| ifcpatch | Utility to run pre-packaged scripts to manipulate IFCs | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcpatch?label=PyPI&color=006dad)](https://pypi.org/project/ifcpatch/) |
| ifcsverchok | Blender Add-on for visual node programming with IFC | GPL-3.0-or-later | [![GitHub Unstable](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcsverchok-*.*.*.*&label=GitHub-Unstable&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcsverchok&expanded=true)
| ifctester | Library, CLI and webapp for IDS model auditing | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifctester?label=PyPI&color=006dad)](https://pypi.org/project/ifctester/) |
@@ -15,7 +15,7 @@
<licenseUrl>https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.8.0/COPYING</licenseUrl>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<projectSourceUrl>https://github.com/IfcOpenShell/IfcOpenShell</projectSourceUrl>
<docsUrl>https://docs.blenderbim.org/</docsUrl>
<docsUrl>https://docs.bonsaibim.org/</docsUrl>
<!--<mailingListUrl></mailingListUrl>-->
<bugTrackerUrl>https://github.com/IfcOpenShell/IfcOpenShell/issues</bugTrackerUrl>
<tags>blender bim blenderbim ifc python opensource foss</tags>

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

@@ -14,9 +14,11 @@ import os
import pathlib
import re
from urllib import request
from github import Github
from typing import NoReturn
def get_repo_tag_names():
def get_repo_tag_names() -> list[str]:
git_return = os.popen("git tag -l").read()
tag_names = [tag_name for tag_name in git_return.split("\n") if tag_name]
print(f"{len(tag_names)} tag_names found in repo")
@@ -43,7 +45,7 @@ def get_latest_choco_blender_version() -> list:
return re.findall(RE_BLENDER_VERSION_MIN_MAJ_PAT, html_txt)
def get_file_sha256_hash(file_path):
def get_file_sha256_hash(file_path: str) -> str:
BLOCKSIZE = 65536
hasher = hashlib.sha256()
@@ -56,16 +58,29 @@ def get_file_sha256_hash(file_path):
return hasher.hexdigest()
def quit_with_error_message(message: str):
def quit_with_error_message(message: str) -> NoReturn:
print(f"ERROR: {message}")
quit(0)
def get_release_zip(tag: str) -> tuple[str, str]:
g = Github()
repo = g.get_repo("IfcOpenShell/IfcOpenShell")
release = repo.get_release(tag)
for asset in release.get_assets():
asset_name = asset.name
if python_version not in asset_name:
continue
if TARGET_OS not in asset_name:
continue
return (asset_name, asset.browser_download_url)
raise Exception(f"Couldn't find the release matching '{python_version}' and '{TARGET_OS}' in tag '{tag}'.")
start = datetime.datetime.now()
URL_CHOCO_PACKAGE = "https://community.chocolatey.org/packages/blender"
URL_BLENDER_CMAKE = "https://raw.githubusercontent.com/blender/blender/{}/build_files/cmake/Modules/FindPythonLibsUnix.cmake"
URL_IFCOS_RELEASES = "https://github.com/IfcOpenShell/IfcOpenShell/releases/download/"
RE_BLENDER_VERSION_MIN_MAJ = r"Latest Version.+<span>Blender (\d+\.\d+)\..+</span>"
RE_BLENDER_VERSION_MIN_MAJ_PAT = r"Latest Version.+<span>Blender (\d+\.\d+\.\d+)</span>"
RE_BLENDER_PYTHON_VERSION_MAJ_MIN = r"\(_PYTHON_VERSION_SUPPORTED (\d+\.\d+)\)"
@@ -79,7 +94,7 @@ os.chdir(BLENDERBIM_DIR)
blenderbim_date_yesterday = (datetime.datetime.now() - datetime.timedelta(days=1)).strftime("%y%m%d")
should_release = False
target_release_tag = ""
target_os = "win"
TARGET_OS = "windows-x64"
git_status = os.popen("git status").read()
print(git_status)
@@ -130,10 +145,7 @@ print(f"{python_version=}")
blenderbim_build_version = target_release_tag.replace("blenderbim-", "")
# url_blenderbim_py3x_win_zip
release_zip_file_name = f"{target_release_tag}-{python_version}-{target_os}.zip"
# download release
url_blenderbim_py3x_win_zip = f"{URL_IFCOS_RELEASES}{target_release_tag}/{release_zip_file_name}"
release_zip_file_name, url_blenderbim_py3x_win_zip = get_release_zip(target_release_tag)
os.popen(f"wget {url_blenderbim_py3x_win_zip} --no-verbose").read()
# sha256sum_blenderbim_py310_win_zip
+4 -3
View File
@@ -221,10 +221,11 @@ endif()
if(GLTF_SUPPORT OR CITYJSON_SUPPORT)
UNIFY_ENVVARS_AND_CACHE(JSON_INCLUDE_DIR)
find_file(json_hpp "json.hpp" ${JSON_INCLUDE_DIR}/nlohmann)
find_path(json_header_path "nlohmann/json.hpp" HINTS ${JSON_INCLUDE_DIR})
set(JSON_INCLUDE_DIR ${json_header_path})
if(json_hpp)
message(STATUS "JSON for Modern C++ header file found")
if(json_header_path)
message(STATUS "JSON for Modern C++ header file found in ${JSON_INCLUDE_DIR}")
else()
message(FATAL_ERROR "Unable to find JSON for Modern C++ header file, aborting")
endif()
+8 -8
View File
@@ -76,14 +76,14 @@ about:
For more information, see:
* [IfcOpenShell Website](http://ifcopenshell.org)
* [IfcOpenShell Documentation](http://blenderbim.org/docs-python)
* [IfcOpenShell C++ Installation](https://blenderbim.org/docs-python/ifcopenshell/installation.html)
* [IfcOpenShell Python Installation](https://blenderbim.org/docs-python/ifcopenshell-python/installation.html)
* [IfcOpenShell Python Hello World Tutorial](https://blenderbim.org/docs-python/ifcopenshell-python/hello_world.html)
* [BlenderBIM Add-on Website](https://blenderbim.org)
* [BlenderBIM Add-on Documentation](http://blenderbim.org/docs)
* [Add-on Installation](https://blenderbim.org/docs/users/installation.html)
* [Exploring an IFC model](https://blenderbim.org/docs/users/exploring_an_ifc_model.html)
* [IfcOpenShell Documentation](http://bonsaibim.org/docs-python)
* [IfcOpenShell C++ Installation](https://bonsaibim.org/docs-python/ifcopenshell/installation.html)
* [IfcOpenShell Python Installation](https://bonsaibim.org/docs-python/ifcopenshell-python/installation.html)
* [IfcOpenShell Python Hello World Tutorial](https://bonsaibim.org/docs-python/ifcopenshell-python/hello_world.html)
* [Bonsai Website](https://bonsaibim.org)
* [Bonsai Documentation](http://bonsaibim.org/docs)
* [Add-on Installation](https://bonsaibim.org/docs/users/installation.html)
* [Exploring an IFC model](https://bonsaibim.org/docs/users/exploring_an_ifc_model.html)
<table>
<thead>
+1 -1
View File
@@ -81,7 +81,7 @@ ADD_COMMIT_SHA = os.getenv("ADD_COMMIT_SHA")
PYTHON_VERSIONS = ["3.9.11", "3.10.3", "3.11.8", "3.12.1"]
JSON_VERSION = "v3.6.1"
OCE_VERSION = "0.18.3"
OCCT_VERSION = "7.7.1"
OCCT_VERSION = "7.5.3"
BOOST_VERSION = "1.80.0"
PCRE_VERSION = "8.41"
LIBXML2_VERSION = "2.9.11"
+29 -2
View File
@@ -1,7 +1,34 @@
[tool.black]
line-length = 120
include = 'src/(bcf|bcfserver|blenderbim|bsdd|foundationserver|ifc2ca|ifc4d|ifc5d|ifcbimtester|ifcblender|ifccityjson|ifcclash|ifccsv|ifcdiff|ifcfm|ifcpatch|ifctester|ifcopenshell-python|ifcsverchok|opencdeserver)/.*.py$'
extend-exclude = '(src/ifcopenshell-python/ifcopenshell/express/*|src/ifc2ca/templates/*)'
include = '''
src/(
bcf
|bcfserver
|blenderbim
|bsdd
|foundationserver
|ifc2ca
|ifc4d
|ifc5d
|ifcbimtester
|ifcblender
|ifccityjson
|ifcclash
|ifccsv
|ifcdiff
|ifcfm
|ifcpatch
|ifctester
|ifcopenshell-python
|ifcsverchok
|opencdeserver
)/.*.py$
'''
extend-exclude = '''
src/ifcopenshell-python/ifcopenshell/express/*
|src/ifcopenshell-python/ifcopenshell/mvd/*
|src/ifc2ca/templates/*
'''
[tool.pyright]
reportInvalidTypeForm = false
+6 -2
View File
@@ -30,8 +30,12 @@ license:
# TODO: make this based on xsd file presence
.PHONY: models
models:
cd src && xsdata generate -p bcf.v2.model --unnest-classes --kw-only --slots -ds Google bcf/v2/xsd
cd src && xsdata generate -p bcf.v3.model --unnest-classes --kw-only --slots -ds Google bcf/v3/xsd
xsdata generate -p bcf.v2.model --unnest-classes --kw-only --slots -ds Google bcf/v2/xsd
xsdata generate -p bcf.v3.model --unnest-classes --kw-only --slots -ds Google bcf/v3/xsd
.PHONY: test
test:
pytest -p no:pytest-blender tests
# .PHONY
# api:
+4
View File
@@ -3,3 +3,7 @@
A simple Python implementation of the BCF standard. Manipulation of BCF-XML is
available via `bcfxml.py` and manipulation of BCF-API is available via
`bcfapi.py`.
Python files in 'model' folder are automatically generated from .xsd files (located in 'xsd' folder).
To regenerate them you can use `make models`.
The only exception is 'v2/model/extensions.py', see it's note for the details.
+28
View File
@@ -0,0 +1,28 @@
import bcf.v2.model.extensions
import bcf.v3.model.extensions
from typing import NamedTuple, Union
from dataclasses import fields
class AttributeData(NamedTuple):
attr_type: type
subattr_name: str
subattr_xsd_name: str
Extensions = Union[bcf.v2.model.extensions.Extensions, bcf.v3.model.extensions.Extensions]
def get_extensions_attributes(extensions: Extensions) -> dict[str, AttributeData]:
"""Return mapping of xsd attribute name to a tuple that consists of:
- Extensions attribute name
- Extensions attribute type type
- subattribute name"""
possible_attributes = {}
for field in fields(type(extensions)):
field_type = field.type.__args__[0] # type: ignore [reportAttributeAccessIssue]
subfield = next(iter(fields(field_type)))
xsd_name = subfield.metadata["name"]
possible_attributes[field.name] = AttributeData(field_type, subfield.name, xsd_name)
return possible_attributes
+10
View File
@@ -0,0 +1,10 @@
import bcf.v2.model
import bcf.v3.model
from typing import Union
BimSnippet = Union[bcf.v2.model.BimSnippet, bcf.v3.model.BimSnippet]
BitMap = Union[bcf.v2.model.VisualizationInfoBitmap, bcf.v3.model.Bitmap]
DocumentReference = Union[bcf.v2.model.TopicDocumentReference, bcf.v3.model.DocumentReference]
HeaderFile = Union[bcf.v2.model.HeaderFile, bcf.v3.model.File]
Topic = Union[bcf.v2.model.Topic, bcf.v3.model.Topic]
ViewPoint = Union[bcf.v2.model.ViewPoint, bcf.v3.model.ViewPoint]
+101
View File
@@ -0,0 +1,101 @@
import tempfile
import bcf.v2.bcfxml
import bcf.v2.model
import bcf.v2.topic
import bcf.v3.bcfxml
import bcf.v3.model
import bcf.v3.topic
import bcf.agnostic.model as mdl
from pathlib import Path
from typing import Union, Optional
from typing_extensions import assert_never
TopicHandler = Union[bcf.v2.topic.TopicHandler, bcf.v3.topic.TopicHandler]
def extract_file(
topic: TopicHandler,
entity: Union[mdl.HeaderFile, mdl.BimSnippet, mdl.DocumentReference, mdl.BitMap],
bcfxml: Optional[Union[bcf.v2.bcfxml.BcfXml, bcf.v3.bcfxml.BcfXml]] = None,
outfile: Optional[Path] = None,
) -> Union[Path, str, None]:
"""Extracts an element with a file into a temporary directory
These include header files, bim snippets, document references, and
viewpoint bitmaps. External reference are not downloaded. Instead, the
URI reference is returned.
:param entity: The entity with a file reference to extract
:param outfile: If provided, save the header file to that location.
Otherwise, a temporary directory is created and the filename is
derived from the header's original filename.
:param bcfxml: The BCF XML file to use for resolving document references files.
Required only for BCF v3 document references (in BCF v3 internal documents
are stored at BCF root, not in the topic).
:return: The filepath of the extracted file. It may be a URL if the
header file is external.
"""
if isinstance(entity, mdl.DocumentReference):
if isinstance(entity, bcf.v2.model.TopicDocumentReference):
reference = entity.referenced_document
else:
reference = entity.document_guid
else:
reference = entity.reference
if not reference:
return None
# For v3 document references external documents are detected by empty document_guid.
# External bitmaps are not supported by bcf.
if not isinstance(entity, (bcf.v3.model.DocumentReference, mdl.BitMap)) and entity.is_external:
return reference
if isinstance(entity, bcf.v3.model.DocumentReference):
# Extract document reference filename and contents.
if not bcfxml:
raise TypeError("bcfxml is required for BCF v3 document references.")
assert isinstance(bcfxml, bcf.v3.bcfxml.BcfXml)
error_msg = f"BCF XML is missing document with guid '{reference}'."
if not bcfxml.documents:
raise Exception(error_msg)
definition_docs = bcfxml.documents.definition.documents
if not definition_docs:
raise Exception(error_msg)
docs = next((doc for doc in definition_docs.document if doc.guid == reference), None)
if not docs:
raise Exception(error_msg)
filename = docs.filename
bytes_data = bcfxml.documents.documents[filename]
else:
if isinstance(entity, mdl.BimSnippet):
bytes_data = topic.bim_snippet
assert isinstance(bytes_data, bytes)
elif isinstance(entity, mdl.HeaderFile):
bytes_data = topic.reference_files[reference]
elif isinstance(entity, mdl.BitMap):
bytes_data = next(
byte_data
for vp in topic.viewpoints.values()
for data_reference, byte_data in vp.bitmaps.items()
if data_reference == reference
)
elif isinstance(entity, bcf.v2.model.TopicDocumentReference):
assert isinstance(topic, bcf.v2.topic.TopicHandler)
bytes_data = topic.document_references[reference]
else:
assert_never(entity)
# We don't really need it if 'outfile' is None, just keeping type checker happy.
if isinstance(entity, mdl.HeaderFile) and entity.filename:
filename = entity.filename
else:
filename = Path(reference).name
if not outfile:
outfile = Path(tempfile.mkdtemp()) / filename
with open(outfile, "wb") as f:
f.write(bytes_data)
return outfile
+5
View File
@@ -0,0 +1,5 @@
import bcf.v2.visinfo
import bcf.v3.visinfo
from typing import Union
VisualizationInfoHandler = Union[bcf.v2.visinfo.VisualizationInfoHandler, bcf.v3.visinfo.VisualizationInfoHandler]
+4 -3
View File
@@ -30,9 +30,10 @@ from bcf.v3.model import Version as Version3
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
def load(
filepath: Path, xml_handler: Optional[AbstractXmlParserSerializer] = None
) -> Optional[Union[BcfXml2, BcfXml3]]:
BcfXml = Union[BcfXml2, BcfXml3]
def load(filepath: Path, xml_handler: Optional[AbstractXmlParserSerializer] = None) -> Optional[BcfXml]:
"""
Load a BCF file.
+5 -5
View File
@@ -5,8 +5,8 @@ from numpy.typing import NDArray
def camera_vectors_from_element_placement(
elem_placement: NDArray[np.float_],
) -> tuple[NDArray[np.float_], NDArray[np.float_], NDArray[np.float_]]:
elem_placement: NDArray[np.float64],
) -> tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.float64]]:
"""
Calculate the vectors of a camera pointing to an element.
@@ -21,8 +21,8 @@ def camera_vectors_from_element_placement(
def camera_vectors_from_target_position(
target_position: NDArray[np.float_], offset: Optional[NDArray[np.float_]] = None
) -> tuple[NDArray[np.float_], NDArray[np.float_], NDArray[np.float_]]:
target_position: NDArray[np.float64], offset: Optional[NDArray[np.float64]] = None
) -> tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.float64]]:
"""
Calculate the vectors of a camera pointing to a target point.
@@ -50,7 +50,7 @@ def camera_vectors_from_target_position(
# return camera_position, -mat[:3, 2], mat[:3, 1]
def unit_vector(v: NDArray[np.float_]) -> NDArray[np.float_]:
def unit_vector(v: NDArray[np.float64]) -> NDArray[np.float64]:
"""
Return the unit vector of a vector.
+50 -8
View File
@@ -6,7 +6,9 @@ import zipfile
from pathlib import Path
from typing import Any, NoReturn, Optional, TypeVar
import bcf.agnostic.extensions
import bcf.v2.model as mdl
import bcf.v2.model.extensions as mdl_extensions
from bcf.inmemory_zipfile import InMemoryZipFile, ZipFileInterface
from bcf.v2.topic import TopicHandler
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
@@ -24,7 +26,8 @@ class BcfXml:
self._xml_handler = xml_handler or XmlParserSerializer()
self._version: Optional[mdl.Version] = None
self._project_info: Optional[mdl.ProjectExtension] = None
self._topics: dict[str, TopicHandler] = {}
self._extensions: Optional[mdl_extensions.Extensions] = None
self._topics: Optional[dict[str, TopicHandler]] = None
self._extension_schema: Optional[bytes] = None
self._zip_file = self._load_zip_file()
@@ -85,24 +88,63 @@ class BcfXml:
def extension_schema(self, value: bytes) -> None:
self._extension_schema = value
@property
def extensions(self) -> Optional[mdl_extensions.Extensions]:
"""BCF extensions."""
if not self._extensions and self.extension_schema:
import io
from xml.etree import ElementTree as etree
extensions = mdl_extensions.Extensions()
xs = "{http://www.w3.org/2001/XMLSchema}"
root = etree.parse(io.BytesIO((self.extension_schema)))
attrs = bcf.agnostic.extensions.get_extensions_attributes(extensions)
xsd_to_attrs = {v.subattr_xsd_name: k for k, v in attrs.items()}
for node in root.findall(f".//{xs}restriction"):
attr_type = node.attrib.get("base")
if not attr_type:
continue
attr_name = xsd_to_attrs.get(attr_type)
if attr_name is None:
continue
values = []
for enum in node.findall(f".//{xs}enumeration"):
values.append(enum.attrib["value"])
if not values:
continue
attr_data = attrs[attr_name]
attr = attr_data.attr_type()
setattr(attr, attr_data.subattr_name, values)
setattr(extensions, attr_name, attr)
self._extensions = extensions
return self._extensions
@extensions.setter
def extensions(self, value: Optional[mdl_extensions.Extensions]) -> None:
self._extensions = value
@property
def topics(self) -> dict[str, TopicHandler]:
"""BCF topics."""
if not self._topics and self._zip_file:
self._topics = self._load_topics(self._zip_file, self._xml_handler)
if self._topics is None:
self._topics = self._load_topics()
return self._topics
def _load_topics(
self, zip_file: zipfile.ZipFile, xml_handler: AbstractXmlParserSerializer
) -> dict[str, TopicHandler]:
def _load_topics(self) -> dict[str, TopicHandler]:
topics = {}
for topic_dir in zipfile.Path(zip_file).iterdir():
if self._zip_file is None:
return topics
for topic_dir in zipfile.Path(self._zip_file).iterdir():
if not topic_dir.is_dir():
continue
markup_path = topic_dir.joinpath("markup.bcf")
if not markup_path.exists():
continue
topics[topic_dir.name] = TopicHandler(topic_dir, xml_handler)
topics[topic_dir.name] = TopicHandler(topic_dir, self._xml_handler)
return topics
@classmethod
+197
View File
@@ -0,0 +1,197 @@
# NOTE: This file is not generated from
# https://github.com/buildingSMART/BCF-XML/blob/release_2_1/Extension%20Schemas/extensions.xsd
# because in bcf 2.1 there is no extensions.xml - I guess, the schema assumes that each .bcf
# will use their own schema patched by it's own extensions.xsd.
#
# To make things simpler we just mimic extensions structures from bcf 3, so they'll have common API,
# and parse extensions.xsd inside .bcf as .xml and fill our structures.
#
# Preferably if we could generate some kind of extensions.xml from extensions.xsd
# and leave all the handling to xsdata.
#
# We also don't add it to __init__.py not to mess with generator.
#
# Currently extensions support for v2 is only read-only.
from dataclasses import dataclass, field, fields
from typing import List, NamedTuple, Optional
@dataclass(slots=True, kw_only=True)
class ExtensionsPriorities:
class Meta:
global_type = False
priority: List[str] = field(
default_factory=list,
metadata={
"name": "Priority",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
},
)
@dataclass(slots=True, kw_only=True)
class ExtensionsSnippetTypes:
class Meta:
global_type = False
snippet_type: List[str] = field(
default_factory=list,
metadata={
"name": "SnippetType",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
},
)
@dataclass(slots=True, kw_only=True)
class ExtensionsStages:
class Meta:
global_type = False
stage: List[str] = field(
default_factory=list,
metadata={
"name": "Stage",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
},
)
@dataclass(slots=True, kw_only=True)
class ExtensionsTopicLabels:
class Meta:
global_type = False
topic_label: List[str] = field(
default_factory=list,
metadata={
"name": "TopicLabel",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
},
)
@dataclass(slots=True, kw_only=True)
class ExtensionsTopicStatuses:
class Meta:
global_type = False
topic_status: List[str] = field(
default_factory=list,
metadata={
"name": "TopicStatus",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
},
)
@dataclass(slots=True, kw_only=True)
class ExtensionsTopicTypes:
class Meta:
global_type = False
topic_type: List[str] = field(
default_factory=list,
metadata={
"name": "TopicType",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
},
)
@dataclass(slots=True, kw_only=True)
class ExtensionsUsers:
class Meta:
global_type = False
user: List[str] = field(
default_factory=list,
metadata={
"name": "UserIdType",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
},
)
@dataclass(slots=True, kw_only=True)
class Extensions:
topic_types: Optional[ExtensionsTopicTypes] = field(
default=None,
metadata={
"name": "TopicTypes",
"type": "Element",
"namespace": "",
},
)
topic_statuses: Optional[ExtensionsTopicStatuses] = field(
default=None,
metadata={
"name": "TopicStatuses",
"type": "Element",
"namespace": "",
},
)
priorities: Optional[ExtensionsPriorities] = field(
default=None,
metadata={
"name": "Priorities",
"type": "Element",
"namespace": "",
},
)
topic_labels: Optional[ExtensionsTopicLabels] = field(
default=None,
metadata={
"name": "TopicLabels",
"type": "Element",
"namespace": "",
},
)
users: Optional[ExtensionsUsers] = field(
default=None,
metadata={
"name": "Users",
"type": "Element",
"namespace": "",
},
)
snippet_types: Optional[ExtensionsSnippetTypes] = field(
default=None,
metadata={
"name": "SnippetTypes",
"type": "Element",
"namespace": "",
},
)
stages: Optional[ExtensionsStages] = field(
default=None,
metadata={
"name": "Stages",
"type": "Element",
"namespace": "",
},
)
+46 -64
View File
@@ -5,7 +5,7 @@ import tempfile
import uuid
import zipfile
from pathlib import Path
from typing import Any, NoReturn, Optional
from typing import Any, NoReturn, Optional, Union
import numpy as np
from ifcopenshell import entity_instance
@@ -27,9 +27,9 @@ class TopicHandler:
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> None:
self._markup: Optional[mdl.Markup] = None
self._viewpoints: dict[str, VisualizationInfoHandler] = {}
self._reference_files: dict[str, bytes] = {}
self._document_references: dict[str, bytes] = {}
self._viewpoints: Optional[dict[str, VisualizationInfoHandler]] = None
self._reference_files: Optional[dict[str, bytes]] = None
self._document_references: Optional[dict[str, bytes]] = None
self._bim_snippet: Optional[bytes] = None
self._xml_handler = xml_handler or XmlParserSerializer()
self._topic_dir = topic_dir
@@ -63,11 +63,21 @@ class TopicHandler:
"""Return the header of the topic."""
return self.markup.header if self.markup else None
@header.setter
def header(self, header: mdl.Header) -> None:
"""Set the header of the topic."""
self.markup.header = header
@property
def comments(self) -> list[mdl.Comment]:
"""Return the comments of the topic."""
return self.markup.comment if self.markup else []
@comments.setter
def comments(self, comments: list[mdl.Comment]) -> None:
assert self.markup
self.markup.comment = comments
@property
def bim_snippet(self) -> Optional[bytes]:
if not self._bim_snippet and self._topic_dir:
@@ -80,14 +90,24 @@ class TopicHandler:
@property
def viewpoints(self) -> dict[str, VisualizationInfoHandler]:
if not self._viewpoints and self._topic_dir:
if self._viewpoints is None:
self._viewpoints = self._load_viewpoints()
return self._viewpoints
def _load_viewpoints(self) -> dict[str, VisualizationInfoHandler]:
if self._topic_dir and self.markup and (viewpoints := self.markup.viewpoints):
return VisualizationInfoHandler.from_topic_viewpoints(self._topic_dir, viewpoints)
return {}
@property
def reference_files(self) -> dict[str, bytes]:
if self._reference_files or not self.header:
if self._reference_files is not None:
return self._reference_files
self._reference_files = {}
if not self.header:
return self._reference_files
for ref in self.header.file:
if ref.is_external:
continue
@@ -99,8 +119,13 @@ class TopicHandler:
@property
def document_references(self) -> dict[str, bytes]:
if self._document_references or not self.topic:
if self._document_references is not None:
return self._document_references
self._document_references = {}
if not self.topic:
return self._document_references
for doc in self.topic.document_reference:
if doc.is_external or not doc.referenced_document:
continue
@@ -118,11 +143,6 @@ class TopicHandler:
return bim_snippet_path.read_bytes()
return None
def _load_viewpoints(self) -> dict[str, VisualizationInfoHandler]:
if self.markup and (viewpoints := self.markup.viewpoints):
return VisualizationInfoHandler.from_topic_viewpoints(self._topic_dir, viewpoints)
return {}
@classmethod
def create_new(
cls,
@@ -220,55 +240,7 @@ class TopicHandler:
real_path = real_path.parent if path_part == ".." else real_path.joinpath(path_part)
destination_zip.writestr(real_path.at, self.document_references[doc.referenced_document])
def extract_file(self, entity, outfile: Optional[Path] = None) -> Path:
"""Extracts an element with a file into a temporary directory
These include header files, bim snippets, document references, and
viewpoint bitmaps. External reference are not downloaded. Instead, the
URI reference is returned.
:param entity: The entity with a file reference to extract
:type entity: bcf.v2.model.HeaderFile,bcf.v2.model.BimSnippet,bcf.v2.model.TopicDocumentReference
:param outfile: If provided, save the header file to that location.
Otherwise, a temporary directory is created and the filename is
derived from the header's original filename.
:type outfile: pathlib.Path,optional
:return: The filepath of the extracted file. It may be a URL if the
header file is external.
:rtype: Path
"""
if hasattr(entity, "reference"):
reference = entity.reference
else:
reference = entity.referenced_document
if not reference:
return
if getattr(entity, "is_external", False):
return entity.reference
resolved_reference = self._topic_dir
for part in Path(reference).parts:
if part == "..":
resolved_reference = resolved_reference.parent
else:
resolved_reference = resolved_reference.joinpath(part)
if not outfile:
if getattr(entity, "filename", None):
filename = entity.filename
else:
filename = resolved_reference.name
outfile = Path(tempfile.mkdtemp()) / filename
with open(outfile, "wb") as f:
f.write(resolved_reference.read_bytes())
return outfile
def add_viewpoint(self, element: entity_instance) -> None:
def add_viewpoint(self, element: entity_instance) -> VisualizationInfoHandler:
"""Add a viewpoint pointed at the placement of an IFC element to the topic.
Args:
@@ -278,7 +250,9 @@ class TopicHandler:
self.add_visinfo_handler(new_viewpoint)
return new_viewpoint
def add_viewpoint_from_point_and_guids(self, position: NDArray[np.float_], *guids: str) -> None:
def add_viewpoint_from_point_and_guids(
self, position: NDArray[np.float64], *guids: str
) -> VisualizationInfoHandler:
"""Add a viewpoint pointing at an XYZ point in space
Args:
@@ -291,9 +265,17 @@ class TopicHandler:
self.add_visinfo_handler(vi_handler)
return vi_handler
def add_visinfo_handler(self, new_viewpoint: VisualizationInfoHandler) -> None:
def add_visinfo_handler(
self, new_viewpoint: VisualizationInfoHandler, snapshot_filename: Optional[str] = None
) -> mdl.ViewPoint:
self.viewpoints[new_viewpoint.guid + ".bcfv"] = new_viewpoint
self.markup.viewpoints.append(mdl.ViewPoint(viewpoint=new_viewpoint.guid + ".bcfv", guid=new_viewpoint.guid))
viewpoint = mdl.ViewPoint(
viewpoint=new_viewpoint.guid + ".bcfv",
snapshot=snapshot_filename,
guid=new_viewpoint.guid,
)
self.markup.viewpoints.append(viewpoint)
return viewpoint
def __eq__(self, other: object) -> bool | NoReturn:
return (
+115 -10
View File
@@ -1,7 +1,6 @@
import uuid
import zipfile
from functools import lru_cache
from typing import Any, Iterable, Optional
from typing import Any, Iterable, Optional, Literal, Union
import numpy as np
from ifcopenshell import entity_instance
@@ -134,6 +133,15 @@ class VisualizationInfoHandler:
self._save_bitmaps(bcf_zip, topic_dir)
def _save_snapshot(self, bcf_zip: ZipFileInterface, topic_dir: str, filename: Optional[str]) -> None:
if bool(self.snapshot) ^ bool(filename):
data = ["data (VisualizationInfoHandler.snapshot)", "filename (ViewPoint.snapshot)"]
provided_data, missing_data = data if self.snapshot else data[::-1]
print(
f"WARNING. Snapshot with viewpoint guid '{self.guid}' won't be saved to bcf. "
f"Only snapshot {provided_data} is provided but snapshot {missing_data} is missing."
)
return
if self.snapshot and filename:
bcf_zip.writestr(f"{topic_dir}/{filename}", self.snapshot)
@@ -176,7 +184,7 @@ class VisualizationInfoHandler:
@classmethod
def create_from_point_and_guids(
cls,
position: NDArray[np.float_],
position: NDArray[np.float64],
*guids: str,
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> "VisualizationInfoHandler":
@@ -196,13 +204,110 @@ class VisualizationInfoHandler:
visualization_info=build_viewpoint_from_position_and_guids(position, *guids), xml_handler=xml_handler
)
def get_selected_guids(self) -> Union[list[str], None]:
"""
Return viewpoint selected elements IFC guids.
Returns:
If viewpoint has no selection settings, return `None`.
Otherwise return a list of selected elements IFC guids.
"""
visualization_info = self.visualization_info
components = visualization_info.components
if not components:
return None
selection = components.selection
if not selection:
return None
return [guid for c in selection.component if (guid := c.ifc_guid)]
def set_selected_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
visualization_info = self.visualization_info
guids = [e.GlobalId for e in elements]
components = visualization_info.components
if not components:
visibility = mdl.ComponentVisibility(default_visibility=True)
components = mdl.Components(visibility=visibility)
visualization_info.components = components
selection = components.selection
components_list = [mdl.Component(ifc_guid=guid) for guid in guids]
if not selection:
selection = mdl.ComponentSelection()
components.selection = selection
selection.component = components_list
def set_visible_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
self.set_visibility(elements, elements_visibility="VISIBLE")
def set_hidden_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
self.set_visibility(elements, elements_visibility="HIDDEN")
def set_visibility(
self, elements: list[ifcopenshell.entity_instance], elements_visibility: Literal["VISIBLE", "HIDDEN"]
) -> None:
visualization_info = self.visualization_info
default_visibility = elements_visibility == "HIDDEN"
guids = [e.GlobalId for e in elements]
components_list = [mdl.Component(ifc_guid=guid) for guid in guids]
components = visualization_info.components
if not components:
visibility = mdl.ComponentVisibility(default_visibility=default_visibility)
components = mdl.Components(visibility=visibility)
visualization_info.components = components
visibility = components.visibility
if not visibility:
visibility = mdl.ComponentVisibility(default_visibility=default_visibility)
components.visibility = visibility
elif visibility.default_visibility != default_visibility:
visibility.default_visibility = default_visibility
exceptions = visibility.exceptions
if not exceptions:
exceptions = mdl.ComponentVisibilityExceptions()
visibility.exceptions = exceptions
exceptions.component = components_list
def get_elements_visibility(self) -> Union[tuple[bool, list[str]], None]:
"""
Return viewpoint elements visibility settings.
Returns:
If viewpoint has no visibility settings, return `None`.
Otherwise return a tuple containing the default visibility
and a list of IFC element GUIDs listed as exceptions.
If default visibility is `True`, all elements are visible except the exceptions.
If default visibility is `False`, all elements are hidden except the exceptions.
"""
visualization_info = self.visualization_info
components = visualization_info.components
if not components:
return None
visibility = components.visibility
if not visibility:
return None
default_visibility = visibility.default_visibility or False
exceptions = visibility.exceptions
if not exceptions:
return default_visibility, []
guids = [guid for c in exceptions.component if (guid := c.ifc_guid)]
return default_visibility, guids
@lru_cache(maxsize=None)
def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
"""
Return a BCF viewpoint of an IFC element.
This function is cached to speedudp the creation of multiple BCF topics regarding the same element.
This function is cached to speed up the creation of multiple BCF topics regarding the same element.
Args:
element: The IFC element to point at.
@@ -224,11 +329,11 @@ def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
)
def build_viewpoint_from_position_and_guids(position: NDArray[np.float_], *guids: str) -> mdl.VisualizationInfo:
def build_viewpoint_from_position_and_guids(position: NDArray[np.float64], *guids: str) -> mdl.VisualizationInfo:
"""
Return a BCF viewpoint of an IFC element.
This function is cached to speedudp the creation of multiple BCF topics regarding the same element.
This function is cached to speed up the creation of multiple BCF topics regarding the same element.
Args:
position: target point coordinates.
@@ -249,7 +354,7 @@ def build_components(*guids: str) -> mdl.Components:
Return the BCF components from an IFC element GUID.
Args:
*guids: One or more IFC element GUID.
*guids: One or more selected IFC element GUID.
Returns:
The BCF components definition.
@@ -261,7 +366,7 @@ def build_components(*guids: str) -> mdl.Components:
)
def build_camera(elem_placement: NDArray[np.float_]) -> mdl.PerspectiveCamera:
def build_camera(elem_placement: NDArray[np.float64]) -> mdl.PerspectiveCamera:
"""
Return a BCF camera for an IFC element placement matrix.
@@ -275,7 +380,7 @@ def build_camera(elem_placement: NDArray[np.float_]) -> mdl.PerspectiveCamera:
def build_camera_from_vectors(
camera_position: NDArray[np.float_], camera_dir: NDArray[np.float_], camera_up: NDArray[np.float_]
camera_position: NDArray[np.float64], camera_dir: NDArray[np.float64], camera_up: NDArray[np.float64]
) -> mdl.PerspectiveCamera:
"""
Return a BCF camera for an IFC element placement matrix.
+9 -5
View File
@@ -26,7 +26,7 @@ class BcfXml:
self._version: Optional[mdl.Version] = None
self._project_info: Optional[mdl.ProjectInfo] = None
self._extensions: Optional[mdl.Extensions] = None
self._topics: dict[str, TopicHandler] = {}
self._topics: Optional[dict[str, TopicHandler]] = None
self._documents: Optional[DocumentsHandler] = None
self._zip_file = self._load_zip_file()
@@ -91,18 +91,22 @@ class BcfXml:
@property
def topics(self) -> dict[str, TopicHandler]:
"""BCF topics."""
if not self._topics and self._zip_file:
self._load_topics()
if self._topics is None:
self._topics = self._load_topics()
return self._topics
def _load_topics(self) -> None:
def _load_topics(self) -> dict[str, TopicHandler]:
topics = {}
if self._zip_file is None:
return topics
for topic_dir in zipfile.Path(self._zip_file).iterdir():
if not topic_dir.is_dir():
continue
markup_path = topic_dir.joinpath("markup.bcf")
if not markup_path.exists():
continue
self._topics[topic_dir.name] = TopicHandler(topic_dir, self._xml_handler)
topics[topic_dir.name] = TopicHandler(topic_dir, self._xml_handler)
return topics
@property
def documents(self) -> Optional[DocumentsHandler]:
+75 -15
View File
@@ -26,7 +26,8 @@ class TopicHandler:
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> None:
self._markup: Optional[mdl.Markup] = None
self._viewpoints: dict[str, VisualizationInfoHandler] = {}
self._viewpoints: Optional[dict[str, VisualizationInfoHandler]] = None
self._reference_files: Optional[dict[str, bytes]] = None
self._bim_snippet: Optional[bytes] = None
self._xml_handler = xml_handler or XmlParserSerializer()
self._topic_dir = topic_dir
@@ -49,22 +50,36 @@ class TopicHandler:
return self.markup.topic
@property
def guid(self) -> Optional[str]:
def guid(self) -> str:
"""Return the GUID of the topic."""
if self._markup:
return self.topic.guid
return self._topic_dir.name if self._topic_dir else None
return self._topic_dir.name if self._topic_dir else ""
@property
def header(self) -> Optional[mdl.Header]:
"""Return the header of the topic."""
return self.markup.header
@header.setter
def header(self, header: mdl.Header) -> None:
"""Set the header of the topic."""
self.markup.header = header
@property
def comments(self) -> list[mdl.Comment]:
"""Return the comments of the topic."""
return self.topic.comments.comment if self.topic.comments else []
@comments.setter
def comments(self, comments: list[mdl.Comment]) -> None:
topic_comments = self.topic.comments
if topic_comments is None:
if not comments:
return
self.topic.comments = (topic_comments := mdl.TopicComments())
topic_comments.comment = comments
@property
def bim_snippet(self) -> Optional[bytes]:
if not self._bim_snippet and self._topic_dir:
@@ -77,15 +92,15 @@ class TopicHandler:
@property
def viewpoints(self) -> dict[str, "VisualizationInfoHandler"]:
if (
not self._viewpoints
and self._topic_dir
and self.topic.viewpoints
and (viewpoints := self.topic.viewpoints.view_point)
):
self._viewpoints = VisualizationInfoHandler.from_topic_viewpoints(self._topic_dir, viewpoints)
if self._viewpoints is None:
self._viewpoints = self._load_viewpoints()
return self._viewpoints
def _load_viewpoints(self) -> dict[str, "VisualizationInfoHandler"]:
if self._topic_dir and self.topic.viewpoints and (viewpoints := self.topic.viewpoints.view_point):
return VisualizationInfoHandler.from_topic_viewpoints(self._topic_dir, viewpoints)
return {}
def _load_bim_snippet(self) -> Optional[bytes]:
bim_snippet_obj = self.topic.bim_snippet
if bim_snippet_obj and not bim_snippet_obj.is_external and self._topic_dir:
@@ -94,6 +109,27 @@ class TopicHandler:
return bim_snippet_path.read_bytes()
return None
@property
def reference_files(self) -> dict[str, bytes]:
if self._reference_files is not None:
return self._reference_files
self._reference_files = {}
if not self.header:
return self._reference_files
if not self.header.files:
return self._reference_files
for ref in self.header.files.file:
if ref.is_external:
continue
real_path = self._topic_dir
for path_part in ref.reference.split("/"):
real_path = real_path.parent if path_part == ".." else real_path.joinpath(path_part)
self._reference_files[ref.reference] = real_path.read_bytes()
return self._reference_files
@classmethod
def create_new(
cls,
@@ -145,6 +181,7 @@ class TopicHandler:
self._save_xml(destination_zip, self._markup, "markup.bcf")
self._save_viewpoints(destination_zip, topic_dir)
self._save_bim_snippet(destination_zip)
self._save_reference_files(destination_zip)
def _save_viewpoints(self, destination_zip: ZipFileInterface, topic_dir: str) -> None:
if not self.topic.viewpoints or not (viewpoints := self.topic.viewpoints.view_point):
@@ -165,7 +202,20 @@ class TopicHandler:
if self.bim_snippet:
destination_zip.writestr(f"{self.topic.guid}/{ref_filename}", self.bim_snippet)
def add_viewpoint(self, element: entity_instance) -> None:
def _save_reference_files(self, destination_zip: ZipFileInterface) -> None:
if not self.header:
return
if not self.header.files:
return
for ref in self.header.files.file:
if ref.is_external or not ref.reference:
continue
real_path = self._topic_dir
for path_part in ref.reference.split("/"):
real_path = real_path.parent if path_part == ".." else real_path.joinpath(path_part)
destination_zip.writestr(real_path.at, self.reference_files[ref.reference])
def add_viewpoint(self, element: entity_instance) -> VisualizationInfoHandler:
"""
Add a viewpoint tergeting an IFC element to the topic.
@@ -174,8 +224,11 @@ class TopicHandler:
"""
new_viewpoint = VisualizationInfoHandler.create_new(element, self._xml_handler)
self.add_visinfo_handler(new_viewpoint)
return new_viewpoint
def add_viewpoint_from_point_and_guids(self, position: NDArray[np.float_], *guids: str) -> None:
def add_viewpoint_from_point_and_guids(
self, position: NDArray[np.float64], *guids: str
) -> VisualizationInfoHandler:
"""
Add a viewpoint tergeting an IFC element to the topic.
@@ -186,14 +239,21 @@ class TopicHandler:
position, *guids, xml_handler=self._xml_handler
)
self.add_visinfo_handler(vi_handler)
return vi_handler
def add_visinfo_handler(self, new_viewpoint: VisualizationInfoHandler) -> None:
def add_visinfo_handler(
self, new_viewpoint: VisualizationInfoHandler, snapshot_filename: Optional[str] = None
) -> mdl.ViewPoint:
self.viewpoints[new_viewpoint.guid + ".bcfv"] = new_viewpoint
if self.topic.viewpoints is None:
self.topic.viewpoints = mdl.TopicViewpoints()
self.topic.viewpoints.view_point.append(
mdl.ViewPoint(viewpoint=new_viewpoint.guid + ".bcfv", guid=new_viewpoint.guid)
viewpoint = mdl.ViewPoint(
viewpoint=new_viewpoint.guid + ".bcfv",
snapshot=snapshot_filename,
guid=new_viewpoint.guid,
)
self.topic.viewpoints.view_point.append(viewpoint)
return viewpoint
def __eq__(self, other: object) -> bool | NoReturn:
return (
+123 -12
View File
@@ -1,11 +1,11 @@
import uuid
import zipfile
from functools import lru_cache
from typing import Any, Iterable, Optional
from typing import Any, Iterable, Optional, Literal, Union
import numpy as np
from ifcopenshell import entity_instance
from ifcopenshell.util import placement
import ifcopenshell.util.unit
import ifcopenshell.util.placement
from numpy.typing import NDArray
import bcf.v3.model as mdl
@@ -133,6 +133,15 @@ class VisualizationInfoHandler:
self._save_bitmaps(bcf_zip, topic_dir)
def _save_snapshot(self, bcf_zip: ZipFileInterface, topic_dir: str, filename: Optional[str]) -> None:
if bool(self.snapshot) ^ bool(filename):
data = ["data (VisualizationInfoHandler.snapshot)", "filename (ViewPoint.snapshot)"]
provided_data, missing_data = data if self.snapshot else data[::-1]
print(
f"WARNING. Snapshot with viewpoint guid '{self.guid}' won't be saved to bcf. "
f"Only snapshot {provided_data} is provided but snapshot {missing_data} is missing."
)
return
if self.snapshot and filename:
bcf_zip.writestr(f"{topic_dir}/{filename}", self.snapshot)
@@ -175,7 +184,7 @@ class VisualizationInfoHandler:
@classmethod
def create_from_point_and_guids(
cls,
position: NDArray[np.float_],
position: NDArray[np.float64],
*guids: str,
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> "VisualizationInfoHandler":
@@ -195,13 +204,110 @@ class VisualizationInfoHandler:
visualization_info=build_viewpoint_from_position_and_guids(position, *guids), xml_handler=xml_handler
)
def get_selected_guids(self) -> Union[list[str], None]:
"""
Return viewpoint selected elements IFC guids.
Returns:
If viewpoint has no selection settings, return `None`.
Otherwise return a list of selected elements IFC guids.
"""
visualization_info = self.visualization_info
components = visualization_info.components
if not components:
return None
selection = components.selection
if not selection:
return None
return [guid for c in selection.component if (guid := c.ifc_guid)]
def set_selected_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
visualization_info = self.visualization_info
guids = [e.GlobalId for e in elements]
components = visualization_info.components
if not components:
visibility = mdl.ComponentVisibility(default_visibility=True)
components = mdl.Components(visibility=visibility)
visualization_info.components = components
selection = components.selection
components_list = [mdl.Component(ifc_guid=guid) for guid in guids]
if not selection:
selection = mdl.ComponentSelection()
components.selection = selection
selection.component = components_list
def set_visible_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
self.set_visibility(elements, elements_visibility="VISIBLE")
def set_hidden_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
self.set_visibility(elements, elements_visibility="HIDDEN")
def set_visibility(
self, elements: list[ifcopenshell.entity_instance], elements_visibility: Literal["VISIBLE", "HIDDEN"]
) -> None:
visualization_info = self.visualization_info
default_visibility = elements_visibility == "HIDDEN"
guids = [e.GlobalId for e in elements]
components_list = [mdl.Component(ifc_guid=guid) for guid in guids]
components = visualization_info.components
if not components:
visibility = mdl.ComponentVisibility(default_visibility=default_visibility)
components = mdl.Components(visibility=visibility)
visualization_info.components = components
visibility = components.visibility
if not visibility:
visibility = mdl.ComponentVisibility(default_visibility=default_visibility)
components.visibility = visibility
elif visibility.default_visibility != default_visibility:
visibility.default_visibility = default_visibility
exceptions = visibility.exceptions
if not exceptions:
exceptions = mdl.ComponentVisibilityExceptions()
visibility.exceptions = exceptions
exceptions.component = components_list
def get_elements_visibility(self) -> Union[tuple[bool, list[str]], None]:
"""
Return viewpoint elements visibility settings.
Returns:
If viewpoint has no visibility settings, return `None`.
Otherwise return a tuple containing the default visibility
and a list of IFC element GUIDs listed as exceptions.
If default visibility is `True`, all elements are visible except the exceptions.
If default visibility is `False`, all elements are hidden except the exceptions.
"""
visualization_info = self.visualization_info
components = visualization_info.components
if not components:
return None
visibility = components.visibility
if not visibility:
return None
default_visibility = visibility.default_visibility or False
exceptions = visibility.exceptions
if not exceptions:
return default_visibility, []
guids = [guid for c in exceptions.component if (guid := c.ifc_guid)]
return default_visibility, guids
@lru_cache(maxsize=None)
def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
"""
Return a BCF viewpoint of an IFC element.
This function is cached to speedudp the creation of multiple BCF topics regarding the same element.
This function is cached to speed up the creation of multiple BCF topics regarding the same element.
Args:
element: The IFC element to point at.
@@ -209,7 +315,12 @@ def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
Returns:
The BCF viewpoint definition.
"""
elem_placement = placement.get_local_placement(element.ObjectPlacement)
ifc_file = element.wrapped_data.file
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
elem_placement = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement)
elem_placement[0][3] *= unit_scale
elem_placement[1][3] *= unit_scale
elem_placement[2][3] *= unit_scale
return mdl.VisualizationInfo(
guid=str(uuid.uuid4()),
@@ -218,11 +329,11 @@ def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
)
def build_viewpoint_from_position_and_guids(position: NDArray[np.float_], *guids: str) -> mdl.VisualizationInfo:
def build_viewpoint_from_position_and_guids(position: NDArray[np.float64], *guids: str) -> mdl.VisualizationInfo:
"""
Return a BCF viewpoint of an IFC element.
This function is cached to speedudp the creation of multiple BCF topics regarding the same element.
This function is cached to speed up the creation of multiple BCF topics regarding the same element.
Args:
position: target point coordinates.
@@ -243,7 +354,7 @@ def build_components(*guids: str) -> mdl.Components:
Return the BCF components from an IFC element GUID.
Args:
*guids: One or more IFC element GUID.
*guids: One or more selected IFC element GUID.
Returns:
The BCF components definition.
@@ -255,7 +366,7 @@ def build_components(*guids: str) -> mdl.Components:
)
def build_camera(elem_placement: NDArray[np.float_]) -> mdl.PerspectiveCamera:
def build_camera(elem_placement: NDArray[np.float64]) -> mdl.PerspectiveCamera:
"""
Return a BCF camera for an IFC element placement matrix.
@@ -269,7 +380,7 @@ def build_camera(elem_placement: NDArray[np.float_]) -> mdl.PerspectiveCamera:
def build_camera_from_vectors(
camera_position: NDArray[np.float_], camera_dir: NDArray[np.float_], camera_up: NDArray[np.float_]
camera_position: NDArray[np.float64], camera_dir: NDArray[np.float64], camera_up: NDArray[np.float64]
) -> mdl.PerspectiveCamera:
"""
Return a BCF camera for an IFC element placement matrix.
+23
View File
@@ -55,9 +55,32 @@ def test_save_maximum_information() -> None:
def assert_everything_in_place(bcf: BcfXml):
assert bcf.version.version_id == "2.1"
assert bcf.project
assert bcf.project.name == "BCF API Implementation"
assert bcf.project_info
assert bcf.project_info.extension_schema == "extensions.xsd"
assert bcf.extensions
assert bcf.extensions.topic_types
assert bcf.extensions.topic_types.topic_type == ["Architecture", "Hidden Type", "Structural"]
assert bcf.extensions.topic_statuses
assert bcf.extensions.topic_statuses.topic_status == ["Finished status", "Open", "Closed"]
assert bcf.extensions.priorities
assert bcf.extensions.priorities.priority == ["Low", "High", "Medium"]
assert bcf.extensions.topic_labels
assert bcf.extensions.topic_labels.topic_label == [
"Architecture",
"IT Development",
"Management",
"Mechanical",
"Structural",
]
assert bcf.extensions.users
assert bcf.extensions.users.user == ["dangl@iabi.eu", "linhard@iabi.eu"]
assert bcf.extensions.snippet_types
assert bcf.extensions.snippet_types.snippet_type == ["IFC2X3", "PDF", "XLSX"]
assert bcf.extensions.stages is None
assert len(bcf.topics) == 2
assert_first_topic_handler(bcf.topics["7ddc3ef0-0ab7-43f1-918a-45e38b42369c"])
second_th = bcf.topics["d1068c81-af04-4546-b63c-348810f6c716"]
+16
View File
@@ -39,6 +39,22 @@ def assert_everything_in_place(bcf: BcfXml):
assert bcf.project.name == "BCF 3.0 test cases"
assert bcf.project.project_id == "de894a86-3a08-4ea0-b2d1-6c222b5602d1"
assert bcf.extensions
assert bcf.extensions.topic_types
assert bcf.extensions.topic_types.topic_type == ["ERROR", "WARNING", "INFORMATION", "CLASH", "OTHER"]
assert bcf.extensions.topic_statuses
assert bcf.extensions.topic_statuses.topic_status == ["OPEN", "IN_PROGRESS", "SOLVED", "CLOSED"]
assert bcf.extensions.priorities
assert bcf.extensions.priorities.priority == ["LOW", "MEDIUM", "HIGH", "CRITICAL"]
assert bcf.extensions.topic_labels
assert bcf.extensions.topic_labels.topic_label == []
assert bcf.extensions.users
assert bcf.extensions.users.user == ["Architect@example.com", "Engineer@example.com", "MEPDesigner@example.com"]
assert bcf.extensions.snippet_types
assert bcf.extensions.snippet_types.snippet_type == []
assert bcf.extensions.stages
assert bcf.extensions.stages.stage == []
assert len(bcf.topics) == 1
topic_handler = bcf.topics["8ac9822a-761a-4deb-9f39-f61286acbf6a"]
-5
View File
@@ -1,5 +0,0 @@
# BlenderBIM Add-on
An add-on to Blender to allow BIM functionality.
More information on the [BlenderBIM Add-on website](https://blenderbim.org).
@@ -1,147 +0,0 @@
import sys
import os
import webbrowser
blenderbim_lib_path = os.environ.get("blenderbim_lib_path")
if blenderbim_lib_path:
sys.path.insert(0, blenderbim_lib_path)
import argparse
from aiohttp import web
import socketio
import pystache
import json
sio_port = 8080 # default port
sio = socketio.AsyncServer(
cors_allowed_origins="*",
async_mode="aiohttp",
)
# sio.instrument(
# auth={
# "username": "admin",
# "password": "admin",
# }
# )
app = web.Application()
sio.attach(app)
# represents a caching for blender messages
blender_messages = {}
# Web namespace
class WebNamespace(socketio.AsyncNamespace):
def __init__(self, namespace):
super().__init__(namespace)
async def on_connect(self, sid, environ):
print(f"Web client connected: {sid}")
if blender_messages:
await self.send_cached_messages(sid)
async def on_disconnect(self, sid):
print(f"Web client disconnected: {sid}")
async def on_web_operator(self, sid, data):
await sio.emit(
"web_operator",
data,
namespace="/blender",
room=data["blenderId"],
)
async def send_cached_messages(self, sid):
# Send cached messages to the connected web client
for blenderId, messages in blender_messages.items():
if "csv_data" in messages:
await self.emit("csv_data", {"blenderId": blenderId, "data": messages["csv_data"]}, room=sid)
if "gantt_data" in messages:
await self.emit("gantt_data", {"blenderId": blenderId, "data": messages["gantt_data"]}, room=sid)
# Blender namespace
class BlenderNamespace(socketio.AsyncNamespace):
def __init__(self, namespace):
super().__init__(namespace)
async def on_connect(self, sid, environ):
print(f"Blender client connected: {sid}")
# Notify web client about new connection
blender_messages[sid] = {}
await sio.emit("blender_connect", sid, namespace="/web")
async def on_disconnect(self, sid):
print(f"Blender client disconnected: {sid}")
# Remove client message and notify web client about disconnection
if sid in blender_messages:
del blender_messages[sid]
await sio.emit("blender_disconnect", sid, namespace="/web")
async def on_data(self, sid, data):
print(f"Data from Blender client {sid}")
# blender_messages[sid]["default_data"] = data
await sio.emit("default_data", {"blenderId": sid, "data": data}, namespace="/web")
async def on_csv_data(self, sid, data):
print(f"CSV data from Blender client {sid}")
# Store the message and forward it to the web client
blender_messages[sid]["csv_data"] = data
await sio.emit("csv_data", {"blenderId": sid, "data": data}, namespace="/web")
async def on_gantt_data(self, sid, data):
print(f"Gant Chart data from Blender client {sid}")
blender_messages[sid]["gantt_data"] = data
await sio.emit("gantt_data", {"blenderId": sid, "data": data}, namespace="/web")
# Attach namespaces
sio.register_namespace(WebNamespace("/web"))
sio.register_namespace(BlenderNamespace("/blender"))
# Define a route to render the index.html template
async def index(request):
with open("templates/index.html", "r") as f:
template = f.read()
html_content = pystache.render(template, {"port": sio_port})
return web.Response(text=html_content, content_type="text/html")
async def gantt(request):
with open("templates/gantt.html", "r") as f:
template = f.read()
html_content = pystache.render(template, {"port": sio_port})
return web.Response(text=html_content, content_type="text/html")
async def open_web_browser(app):
webbrowser.open(f"http://127.0.0.1:{sio_port}/")
app.router.add_get("/", index)
app.router.add_get("/gantt", gantt)
app.router.add_static("/jsgantt/", path="../gantt", name="jsgantt")
app.router.add_static("/static/", path="./static", name="static")
app.on_startup.append(open_web_browser)
def main():
global sio_port
parser = argparse.ArgumentParser(description="SocketIO server")
parser.add_argument("--host", type=str, default="127.0.0.1", help="Host to run the server on")
parser.add_argument("--port", type=int, default=8080, help="Port to run the server on")
args = parser.parse_args()
sio_port = args.port
web.run_app(app, host=args.host, port=sio_port)
if __name__ == "__main__":
main()
# web.run_app(app, host="127.0.0.1", port=sio_port)
@@ -1,319 +0,0 @@
:root {
--font-family: Arial, sans-serif;
--margin-small: 0.625rem;
--margin-medium: 1.25rem;
--margin-large: 2.5rem;
--padding-small: 0.125rem;
--padding-medium: 1rem;
--font-size-small: 1rem;
--font-size-large: 1.2rem;
--logo-height: 2.5rem;
--folder-collapse-font-size: 0.75rem;
--folder-collapse-font-family: Courier, "Courier New", monospace;
--box-shadow: 0 0 0.7rem #5f5f5f66;
}
:root.dark {
color-scheme: dark;
--bg-color: #252525;
--primary-text-color: #e0e0e0;
--secondary-text-color: #c7c7c7;
--nav-bg-color: #121212;
--nav-border-color: #25682a;
--nav-link-color: #fff;
--nav-link-hover-color: #3fb449;
--warning-color: #FFDB8F;
--border-color: #464444;
--hover-bg-color: #3a3a3a;
--highlight-color: #009136;
--task-complete-bg-color: #777777;
--milestone-border-color: #ffffff;
--group-item-bg-color: #4b4b4b;
--input-bg-color: #3b3b3b;
--input-border-color: #000;
}
:root.light {
color-scheme: light;
--bg-color: #ffffff;
--primary-text-color: #000000;
--nav-bg-color: #f8f8f8;
--nav-border-color: #cccccc;
--nav-link-color: #000000;
--nav-link-hover-color: #38a63d;
--warning-color: #FF4500;
}
html {
font-size: var(--base-font-size);
}
body {
background-color: var(--bg-color);
color: var(--primary-text-color);
margin: 0;
font-family: var(--font-family);
}
#container {
margin-top: var(--margin-medium);
margin-left: var(--margin-small);
margin-right: var(--margin-small);
margin-bottom: var(--margin-medium);
}
h3 {
margin-top: 0;
}
nav {
background-color: var(--nav-bg-color);
padding: var(--padding-medium) 0;
display: flex;
align-items: center;
position: relative;
border-bottom: 2px solid var(--nav-border-color);
}
nav .logo {
margin-left: var(--margin-large);
height: var(--logo-height);
}
nav ul {
list-style-type: none;
margin: 0;
margin-left: 0.0625rem;
display: flex;
flex-grow: 1;
justify-content: center;
}
nav ul li {
margin-right: 3.125rem;
}
nav ul li a {
text-decoration: none;
color: var(--nav-link-color);
font-size: var(--font-size-large);
}
nav ul li a:hover,
nav ul li a.active {
color: var(--nav-link-hover-color);
}
.warning {
color: var(--warning-color);
margin-bottom: var(--margin-small);
padding: var(--padding-small);
display: none;
}
.table-description {
margin-bottom: var(--margin-medium);
width: 50%;
background-color: transparent;
border-collapse: collapse;
border-spacing: 0;
border-color: var(--border-color);
border: 1px solid var(--border-color);
border-radius: 0.25rem;
box-shadow: var(--box-shadow);
text-align: center;
}
.table-description tr {
display: table-row;
border-bottom: 1px solid var(--border-color);
}
#toggle-theme {
border: none;
background: none;
cursor: pointer;
font-size: var(--font-size-large);
margin-right: var(--margin-medium);
}
#toggle-theme:focus {
outline: none;
}
.gantt-info {
margin: 0.5rem;
font-size: var(--font-size-small);
font-weight: bold;
}
.btn {
margin: 0.5rem;
font-size: var(--font-size-small);
cursor: pointer;
}
@media print {
.no-print {
display: none;
}
}
/* ------------ Overwriting JSGantt CSS rules ------------ */
:root.dark div.gantt {
background-color: var(--bg-color);
color: var(--secondary-text-color);
}
:root.dark .gantt table,
:root.dark .gantt td {
border-color: var(--border-color);
}
/* Headings and cell defaults */
:root.dark .gmajorheading,
:root.dark .gminorheading,
:root.dark .gminorheadingwkend,
:root.dark .gtaskcell,
:root.dark .gtaskcellcurrent,
:root.dark .gtaskcellwkend,
:root.dark .gname,
:root.dark .ggroupitem,
:root.dark .gtaskheading {
background-color: var(--bg-color);
border-color: var(--border-color);
}
:root.dark .gtaskheading,
:root.dark .gname,
:root.dark .gtaskname,
:root.dark .gres,
:root.dark .gdur,
:root.dark .gcomp,
:root.dark .gstartdate,
:root.dark .gplanstartdate,
:root.dark .gplanenddate,
:root.dark .gcost,
:root.dark .gchartlbl,
:root.dark .gcontainercol,
:root.dark .genddate {
color: var(--secondary-text-color);
border-color: var(--border-color);
}
:root.dark .gtaskname>div {
color: var(--secondary-text-color);
}
:root.dark .gtaskbarcontainer.gplan,
:root.dark .gchartlbl.gcontainercol {
background: var(--bg-color);
border-color: var(--border-color);
}
:root.dark .gtaskname div,
:root.dark .gtaskheading div,
:root.dark .gtaskname span {
color: var(--secondary-text-color);
}
:root.dark .gtasklist,
:root.dark .gadditional {
border: var(--border-color) 1px solid;
}
:root.dark .gchartgrid {
background-color: var(--bg-color);
}
:root.dark .glistgrid,
:root.dark .glistlbl {
background-color: var(--bg-color);
border-color: var(--border-color);
}
/* .gTaskInfo {
background-color: #2e2e2e;
color: #c7c7c7;
border-color: #c7c7c7;;
} */
/* Dark mode scrollbar */
:root.dark .frame::-webkit-scrollbar-thumb,
:root.dark .frame::-webkit-scrollbar-track {
background-color: var(--bg-color);
}
/* Highlight row */
:root.dark .gitemhighlight td {
background-color: var(--highlight-color);
color: var(--nav-link-color);
}
/* Differentiate Group, Milestone and Ordinary task items (applied to row) */
:root.dark .ggroupitem {
background-color: var(--bg-color);
font-weight: bold;
border-color: var(--border-color);
}
:root.dark .gmileitem,
:root.dark .glineitem {
background-color: var(--bg-color);
}
/* Task bar caption text styles */
:root.dark .gmilecaption,
:root.dark .ggroupcaption,
:root.dark .gcaption {
color: var(--nav-link-color);
}
/* Task complete %age bar */
:root.dark .gtaskcomplete {
background-color: var(--task-complete-bg-color);
}
/* Milestones */
:root.dark .gmdtop,
:root.dark .gmdbottom {
border-bottom: 5px solid var(--milestone-border-color);
}
:root.dark .gfoldercollapse {
color: var(--secondary-text-color);
cursor: pointer;
font-weight: bold;
font-size: var(--folder-collapse-font-size);
font-family: var(--folder-collapse-font-family);
}
/* Highlight for collapsible row */
:root.dark .gname.ggroupitem {
background-color: var(--group-item-bg-color);
}
/* Form label and selected highlighting */
:root.dark .gformlabel {
background-color: var(--formlabel-bg-color);
color: var(--secondary-text-color);
border: var(--formlabel-border-color) 1px solid;
}
:root.dark span.gformlabel:hover {
background-color: var(--hover-bg-color);
border-color: var(--border-color);
}
:root.dark span.gselected {
background-color: var(--formlabel-selected-bg-color);
border-color: var(--task-complete-bg-color);
color: var(--nav-link-color);
}
:root.dark .gantt-inputtable {
background-color: var(--input-bg-color);
box-sizing: border-box;
border: 1px solid var(--input-border-color);
color: var(--secondary-text-color);
}
@@ -1,132 +0,0 @@
:root {
--font-family: Arial, sans-serif;
--margin-small: 0.625rem;
--margin-medium: 1.25rem;
--margin-large: 2.5rem;
--padding-small: 0.125rem;
--padding-medium: 1rem;
--font-size-large: 1.2rem;
--logo-height: 2.5rem;
}
:root.dark {
color-scheme: dark;
--bg-color: #252525;
--text-color: #e0e0e0;
--nav-bg-color: #121212;
--nav-border-color: #25682a;
--nav-link-color: #fff;
--nav-link-hover-color: #3fb449;
--warning-color: #FFDB8F;
}
:root.light {
color-scheme: light;
--bg-color: #ffffff;
--text-color: #000000;
--nav-bg-color: #f8f8f8;
--nav-border-color: #cccccc;
--nav-link-color: #000000;
--nav-link-hover-color: #38a63d;
--warning-color: #FF4500;
}
html {
font-size: var(--base-font-size);
}
body {
background-color: var(--bg-color);
color: var(--text-color);
margin: 0;
font-family: var(--font-family);
}
#container {
margin-top: var(--margin-medium);
margin-left: var(--margin-small);
margin-right: var(--margin-small);
margin-bottom: var(--margin-medium);
}
.table-container {
margin-bottom: var(--margin-large);
}
.csv-table {
margin-top: var(--margin-small);
}
h3 {
margin-top: 0;
}
nav {
background-color: var(--nav-bg-color);
padding: var(--padding-medium) 0;
display: flex;
align-items: center;
position: relative;
border-bottom: 2px solid var(--nav-border-color);
}
nav .logo {
margin-left: var(--margin-large);
height: var(--logo-height);
}
nav ul {
list-style-type: none;
margin: 0;
margin-left: 0.0625rem;
display: flex;
flex-grow: 1;
justify-content: center;
}
nav ul li {
margin-right: 3.125rem;
}
nav ul li a {
text-decoration: none;
color: var(--nav-link-color);
font-size: var(--font-size-large);
}
nav ul li a:hover,
nav ul li a.active {
color: var(--nav-link-hover-color);
}
.warning {
color: var(--warning-color);
margin-bottom: var(--margin-small);
padding: var(--padding-small);
display: none;
}
#toggle-theme {
border: none;
background: none;
cursor: pointer;
font-size: var(--font-size-large);
margin-right: var(--margin-medium);
}
#toggle-theme:focus {
outline: none;
}
/* ------------ Overwriting Tabulator CSS rules ------------ */
:root.light .tabulator-header,
:root.light .tabulator .tabulator-header .tabulator-col {
background: var(--nav-bg-color) !important;
color: var(--text-color);
}
:root.light .tabulator {
border-top: 1px solid #222;
border-bottom: 2px solid #222;
}
@@ -1,384 +0,0 @@
// keeps track of blenders connected in form of
// shown:bool, workSchedule: {}, ganttTasks: {},
const connectedClients = {};
let socket;
// print options
const pageSizes = [
{ value: "210,297", text: "A4 Portrait" },
{ value: "297,210", text: "A4 Landscape" },
{ value: "297,420", text: "A3 Portrait" },
{ value: "420,297", text: "A3 Landscape" },
{ value: "420,594", text: "A2 Portrait" },
{ value: "594,420", text: "A2 Landscape" },
{ value: "594,841", text: "A1 Portrait" },
{ value: "841,594", text: "A1 Landscape" },
{ value: "841,1189", text: "A0 Portrait" },
{ value: "1189,841", text: "A0 Landscape" },
];
// Document ready function
$(document).ready(function () {
var systemTheme = window.matchMedia("(prefers-color-scheme: light)").matches
? "light"
: "dark";
var theme = localStorage.getItem("theme") || systemTheme;
setTheme(theme);
connectSocket();
});
// Function to connect to Socket.IO server
function connectSocket() {
const url = "ws://localhost:" + SOCKET_PORT + "/web";
socket = io(url);
console.log("socket: ", socket);
// Register socket event handlers
socket.on("blender_connect", handleBlenderConnect);
socket.on("blender_disconnect", handleBlenderDisconnect);
socket.on("gantt_data", handleGanttData);
socket.on("default_data", handleDefaultData);
}
// Function to handle 'blender_connect' event
function handleBlenderConnect(blenderId) {
console.log("blender_connect: ", blenderId);
if (!connectedClients.hasOwnProperty(blenderId)) {
connectedClients[blenderId] = {
shown: false,
workSchedule: {},
ganttTasks: {},
};
}
}
// Function to handle 'blender_disconnect' event
function handleBlenderDisconnect(blenderId) {
console.log("blender_disconnect: ", blenderId);
if (connectedClients.hasOwnProperty(blenderId)) {
delete connectedClients[blenderId];
removeGanttElement(blenderId);
}
}
// Function to handle 'gantt_data' event
function handleGanttData(data) {
const blenderId = data["blenderId"];
console.log(data);
const filename = data["data"]["ifc_file"];
const ganttTasks = data["data"]["gantt_data"]["tasks"];
const ganttWorkSched = data["data"]["gantt_data"]["work_schedule"];
// const ganttWorkSched = {};
if (connectedClients.hasOwnProperty(blenderId)) {
if (!connectedClients[blenderId].shown) {
connectedClients[blenderId] = {
shown: true,
ganttTasks: ganttTasks,
workSchedule: ganttWorkSched,
};
addGanttElement(blenderId, ganttTasks, ganttWorkSched, filename);
} else {
updateGanttElement(blenderId, ganttTasks, ganttWorkSched, filename);
connectedClients[blenderId].workSchedule = ganttWorkSched;
connectedClients[blenderId].ganttTasks = ganttTasks;
}
} else {
connectedClients[blenderId] = {
shown: true,
ganttTasks: ganttTasks,
workSchedule: ganttWorkSched,
};
addGanttElement(blenderId, ganttTasks, ganttWorkSched, filename);
}
}
function handleDefaultData(data) {
const blenderId = data["blenderId"];
const isDirty = data["data"]["is_dirty"];
showWarning(blenderId, isDirty);
console.log(data);
}
// Function to add a new gantt with data and filename
function addGanttElement(blenderId, tasks, workSched, filename) {
const ganttContainer = $("<div></div>")
.addClass("gantt-container")
.attr("id", "container-" + blenderId);
const ganttTitle = $("<h3></h3>")
.attr("id", "title-" + blenderId)
.text(filename)
.addClass("no-print")
.css("margin-bottom", "10px");
const warning = $("<div></div>")
.attr("id", "warning-" + blenderId)
.html(
"&#9888; Warning: This Gantt Chart may contain outdated data due to recent changes in Blender."
)
.addClass("warning no-print");
const workSchedDiv = $("<div></div>").attr("id", "workSched" + blenderId);
const scheduleTable = $("<table></table>")
.addClass("no-print table-description")
.attr("id", "workSchedTable-" + blenderId)
.hide();
$.each(workSched, (key, value) => {
value = value ? value : "null";
$("<tr></tr>")
.append($("<td></td>").text(key))
.append($("<td></td>").text(value))
.appendTo(scheduleTable);
});
const toggleButton = $("<button></button>")
.text("Show Schedule Info")
.addClass("btn no-print")
.on("click", function () {
scheduleTable.toggle();
const buttonText = scheduleTable.is(":visible")
? "Hide Schedule Info"
: "Show Schedule Info";
toggleButton.text(buttonText);
});
var ganttInfoDiv = $("<div></div>")
.addClass("gantt-info")
.attr("id", "gantt-info-" + blenderId);
const scheduleName = $("<span></span>").text("Schedule: " + workSched.Name);
const createdOn = $("<span></span>")
.text("Created: " + new Date(workSched.CreationDate).toLocaleDateString())
.css("float", "right");
const ganttDiv = $("<div></div>")
.addClass("gantt-chart")
.attr("id", "gantt-" + blenderId);
ganttInfoDiv.append(scheduleName);
ganttInfoDiv.append(createdOn);
workSchedDiv.append(toggleButton);
workSchedDiv.append(scheduleTable);
ganttContainer.append(ganttTitle);
ganttContainer.append(warning);
ganttContainer.append(workSchedDiv);
ganttContainer.append(ganttInfoDiv);
ganttContainer.append(ganttDiv);
$("#container").append(ganttContainer);
let g = new JSGantt.GanttChart($("#gantt-" + blenderId)[0], "week");
g.setOptions({
vCaptionType: "Caption", // Set to Show Caption : None,Caption,Resource,Duration,Complete,
vQuarterColWidth: 36,
vDateTaskDisplayFormat: "day dd month yyyy", // Shown in tool tip box
vDayMajorDateDisplayFormat: "mon yyyy - Week ww", // Set format to dates in the "Major" header of the "Day" view
vWeekMinorDateDisplayFormat: "dd mon", // Set format to display dates in the "Minor" header of the "Week" view
vLang: "en",
vShowTaskInfoLink: 1, // Show link in tool tip (0/1)
vShowEndWeekDate: 0, // Show/Hide the date for the last day of the week in header for daily
vUseSingleCell: 10000, // Set the threshold cell per table row (Helps performance for large data.
vFormatArr: ["Day", "Week", "Month", "Quarter"], // Even with setUseSingleCell using Hour format on such a large chart can cause issues in some browsers,
vShowRes: true, // Disable the resource column.
vShowComp: false, // Disable the completion column.
vShowDur: false, // Disable the duration column, because jsgantt doesn't calculate durations the way we want.
vAdditionalHeaders: {
ifcduration: { title: "Duration" },
resourceUsage: { title: "Resource Usage" },
},
vUseToolTip: true, // Disable tooltips.
vTooltipTemplate: generateTooltip,
vTotalHeight: 900,
vEventsChange: {
taskname: editValue, // if you need to use the this scope, do: editValue.bind(this)
res: editValue,
dur: editValue,
comp: editValue,
start: editValue,
end: editValue,
planstart: editValue,
planend: editValue,
cost: editValue,
additional_category: editValue,
},
});
JSGantt.addJSONTask(g, tasks);
g.setEditable(true);
g.Draw();
connectedClients[blenderId]["gantt"] = g;
let printButton = $("<button>", {
id: "print-btn-" + blenderId,
html: "Print",
class: "btn no-print",
});
let printOptions = $("<select>", {
id: "print-options-" + blenderId,
class: "no-print",
});
$.each(pageSizes, function (index, size) {
printOptions.append(
$("<option>", {
value: size.value,
text: size.text,
})
);
});
printButton.on("click", function () {
// make it only the corresponding gantt chart is printed
$(".gantt-chart").removeClass("no-print");
$(".gantt-chart")
.not("#gantt-" + blenderId)
.addClass("your-css-class");
var values = $("#print-options-" + blenderId)
.val()
.split(",");
g.setEditable(false);
g.setTotalHeight("");
g.Draw();
addEventListener("afterprint", (event) => {
g.setEditable(true);
});
let css =
"@media print {\n" +
" @page {\n" +
" size: " +
values[0] +
"mm " +
values[1] +
"mm;\n" +
" }\n" +
" /* Make all text black */\n" +
" body, p, span, h1, h2, h3, h4, h5, h6, div, a, li, td, th, * {\n" +
" color: black !important;\n" +
" }\n" +
"}";
g.printChart(values[0], values[1], css);
g.setTotalHeight(900);
g.Draw();
});
ganttContainer.append(printOptions);
ganttContainer.append(printButton);
}
// Function to update gantt and filename
function updateGanttElement(blenderId, tasks, workSched, filename) {
// update work schedule table
const table = $("#workSchedTable-" + blenderId);
table.empty();
$.each(workSched, (key, value) => {
value = value ? value : "null";
$("<tr></tr>")
.append($("<td></td>").text(key))
.append($("<td></td>").text(value))
.appendTo(table);
});
// update gantt chart with new data
let g = connectedClients[blenderId]["gantt"];
g.ClearTasks();
g.Draw();
JSGantt.addJSONTask(g, tasks);
g.Draw();
$("#title-" + blenderId).text(filename);
$("#warning-" + blenderId).css("display", "none");
}
// Function to remove gantt element
function removeGanttElement(blenderId) {
$("#container-" + blenderId).remove();
}
function showWarning(blenderId, isDirty) {
$("#warning-" + blenderId).css("display", "block");
}
// Utility function to create a tooltip for the gantt chars
function generateTooltip(task) {
var dataObject = task.getDataObject();
var numberResources = dataObject.resourceUsage
? dataObject.resourceUsage
: "NULL";
return `
<dl>
<dt>Name:</dt><dd>{{pName}}</dd>
<dt>Start:</dt><dd>{{pStart}}</dd>
<dt>End:</dt><dd>{{pEnd}}</dd>
<dt>Duration:</dt><dd>${dataObject.ifcduration}</dd>
<dt>Number of Resources:</dt><dd>${numberResources}</dd>
<dt>Resources:</dt><dd>{{pRes}}</dd>
</dl>
`;
}
// Event handlers for editing gantt table data
function editValue(list, task, event, cell, column) {
console.log("editValue function called with the following parameters:");
console.log("list:", list);
console.log("task:", task);
console.log("event:", event);
console.log("cell:", cell);
console.log("column:", column);
const ganttId = task.getGantt()["vDiv"].id;
const index = ganttId.indexOf("-") + 1;
const blenderId = ganttId.substring(index);
const workSchedId = connectedClients[blenderId].workSchedule.id;
// update data object reprsenting the task
const dataObj = task.getDataObject();
dataObj[column] = event.target.value;
task.setDataObject(dataObj);
const msg = {
sourcePage: "gantt",
blenderId: blenderId,
operator: {
type: "editTask",
workScheduleId: workSchedId,
taskId: task.getOriginalID(),
column: column,
value: event.target.value,
},
};
socket.emit("web_operator", msg);
}
function setTheme(theme) {
if (theme === "light") {
$("html").removeClass("dark").addClass("light");
$("#toggle-theme").html('<i class="fas fa-sun"></i>');
} else {
$("html").removeClass("light").addClass("dark");
$("#toggle-theme").html('<i class="fas fa-moon"></i>');
}
localStorage.setItem("theme", theme);
}
function toggleTheme() {
if ($("html").hasClass("dark")) {
setTheme("light");
} else {
setTheme("dark");
}
}
@@ -1,276 +0,0 @@
// keeps track of blenders connected in form of
// {shown:bool, filename:string, headers:array}
const connectedClients = {};
let socket;
// Document ready function
$(document).ready(function () {
var systemTheme = window.matchMedia("(prefers-color-scheme: light)").matches
? "light"
: "dark";
var theme = localStorage.getItem("theme") || systemTheme;
setTheme(theme);
connectSocket();
});
// Function to connect to Socket.IO server
function connectSocket() {
const url = "ws://localhost:" + SOCKET_PORT + "/web";
socket = io(url);
console.log("socket: ", socket);
// Register socket event handlers
socket.on("blender_connect", handleBlenderConnect);
socket.on("blender_disconnect", handleBlenderDisconnect);
socket.on("csv_data", handleCsvData);
socket.on("default_data", handleDefaultData);
}
// Function to handle 'blender_connect' event
function handleBlenderConnect(blenderId) {
console.log("blender_connect: ", blenderId);
if (!connectedClients.hasOwnProperty(blenderId)) {
connectedClients[blenderId] = { shown: false, ifc_file: "" };
}
}
// Function to handle 'blender_disconnect' event
function handleBlenderDisconnect(blenderId) {
console.log("blender_disconnect: ", blenderId);
if (connectedClients.hasOwnProperty(blenderId)) {
delete connectedClients[blenderId];
removeTableElement(blenderId);
}
}
// Function to handle 'csv_data' event
function handleCsvData(data) {
const blenderId = data["blenderId"];
const csvData = data["data"]["csv_data"];
const filename = data["data"]["ifc_file"];
console.log(data);
if (connectedClients.hasOwnProperty(blenderId)) {
if (!connectedClients[blenderId].shown) {
connectedClients[blenderId] = {
shown: true,
ifc_file: filename,
headers: [],
};
addTableElement(blenderId, csvData, filename);
} else {
updateTableElement(blenderId, csvData, filename);
}
} else {
connectedClients[blenderId] = {
shown: true,
ifc_file: filename,
headers: [],
};
addTableElement(blenderId, csvData, filename);
}
}
function handleDefaultData(data) {
const blenderId = data["blenderId"];
const isDirty = data["data"]["is_dirty"];
showWarning(blenderId, isDirty);
console.log(data);
}
// Function to add a new table with data and filename
function addTableElement(blenderId, csvData, filename) {
// store headers of the csv data
const firstLine = csvData.indexOf("\n");
const csvHeaders = csvData.substring(0, firstLine).split(",");
connectedClients[blenderId].headers = csvHeaders;
console.log(connectedClients[blenderId]);
const tableContainer = $("<div></div>")
.addClass("table-container")
.attr("id", "container-" + blenderId);
const tableTitle = $("<h3></h3>")
.attr("id", "title-" + blenderId)
.text(filename)
.css("margin-bottom", "10px");
const warning = $("<div></div>")
.attr("id", "warning-" + blenderId)
.html(
"&#9888; Warning: This table may contain outdated data due to recent changes in Blender."
)
.addClass("warning");
const tableDiv = $("<div></div>")
.addClass("csv-table")
.attr("id", "table-" + blenderId);
tableContainer.append(tableTitle);
tableContainer.append(warning);
tableContainer.append(tableDiv);
$("#container").append(tableContainer);
function createHeaderMenu(definitions) {
var menu = [];
for (let column of definitions) {
// Create text element for checkbox
if (!column.hasOwnProperty("key")) {
column.visible = true;
}
let checkbox = document.createElement("span");
checkbox.textContent = column.visible ? "\u2611" : "\u2610"; // ☑ or ☐
// Build label
let label = document.createElement("span");
let title = document.createElement("span");
title.textContent = " " + column.title;
label.appendChild(checkbox);
label.appendChild(title);
// Create menu item
menu.push({
label: label,
action: function (e) {
// Prevent menu closing
e.stopPropagation();
// Toggle current column visibility
column.visible = !column.visible;
console.log(column.title, column.visible);
// Change menu item checkbox
if (column.visible) {
table.showColumn(column.title);
checkbox.textContent = "\u2611"; // ☑
} else {
table.hideColumn(column.title);
checkbox.textContent = "\u2610"; // ☐
}
},
});
}
return menu;
}
var table = new Tabulator("#table-" + blenderId, {
height: "400px",
resizableColumnGuide: true,
index: "GlobalId",
data: csvData,
importFormat: "csv",
autoColumns: true,
selectableRows: 1,
layout: "fitColumns",
autoColumnsDefinitions: function (definitions) {
menu = createHeaderMenu(definitions, table);
definitions.forEach((column) => {
column.visible = true;
column.headerMenu = menu;
});
return definitions;
},
});
table.on("rowSelected", function (row) {
var index = row.getIndex(); // the guid of the object
if (!index) {
console.log("No Global ID found");
return;
}
// table id is usually "table-BlenderId" so blender id is always
// after the first 6 characters
var tableId = row.getTable().element.id.substr(6);
const msg = {
sourcePage: "csv",
blenderId: tableId,
operator: {
type: "selection",
globalId: index,
},
};
socket.emit("web_operator", msg);
});
}
// Function to update table and filename
function updateTableElement(blenderId, csvData, filename) {
// check if the headers are the same
// if yes, just replace the data
// else, replace the whole data and column definations
const firstLine = csvData.indexOf("\n");
const newHeaders = csvData.substring(0, firstLine).split(",");
const sameHeaders = compareHeaders(
connectedClients[blenderId].headers,
newHeaders
);
const table = Tabulator.findTable("#table-" + blenderId)[0];
if (table) {
if (sameHeaders) {
table.replaceData(csvData, { importFormat: "csv" });
} else {
table.setData(csvData);
connectedClients[blenderId].headers = newHeaders;
}
$("#title-" + blenderId).text(filename);
$("#warning-" + blenderId).css("display", "none");
}
}
// Function to remove table element
function removeTableElement(blenderId) {
$("#container-" + blenderId).remove();
}
function showWarning(blenderId, isDirty) {
$("#warning-" + blenderId).css("display", "block");
}
// Utility function to compare two csv header
function compareHeaders(headers1, headers2) {
if (headers1.length !== headers2.length) {
return false;
}
for (let i = 0; i < headers1.length; i++) {
if (headers1[i] !== headers2[i]) {
return false;
}
}
return true;
}
function setTheme(theme) {
var stylesheet = $("#tabulator-stylesheet");
if (theme === "light") {
stylesheet.attr(
"href",
"https://unpkg.com/tabulator-tables/dist/css/tabulator_site.min.css"
);
$("html").removeClass("dark").addClass("light");
$("#toggle-theme").html('<i class="fas fa-sun"></i>');
} else {
stylesheet.attr(
"href",
"https://unpkg.com/tabulator-tables/dist/css/tabulator_site_dark.min.css"
);
$("html").removeClass("light").addClass("dark");
$("#toggle-theme").html('<i class="fas fa-moon"></i>');
}
localStorage.setItem("theme", theme);
}
function toggleTheme() {
if ($("html").hasClass("dark")) {
setTheme("light");
} else {
setTheme("dark");
}
}
@@ -1,44 +0,0 @@
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Web Client</title>
<link rel="stylesheet" type="text/css" href="/jsgantt/jsgantt.css" />
<link rel="stylesheet" href="/static/css/gantt.css" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css"
/>
<script
type="text/javascript"
src="https://code.jquery.com/jquery-3.6.0.min.js"
></script>
<script
type="text/javascript"
src="https://cdn.socket.io/4.0.0/socket.io.min.js"
></script>
<script type="text/javascript" src="./jsgantt/jsgantt.js"></script>
<script>
var SOCKET_PORT = {{port}};
</script>
<script defer src="./static/js/gantt.js"></script>
</head>
<body>
<nav class="no-print">
<img
src="https://blenderbim.org/assets/images/blender/blender-logo.png"
alt="Logo"
class="logo"
/>
<ul>
<li><a href="/">IFC Data</a></li>
<li><a href="/gantt" class="active">Gantt Chart</a></li>
</ul>
<button id="toggle-theme" onclick="toggleTheme()">
<i class="fas fa-moon"></i>
</button>
</nav>
<div id="container"></div>
</body>
</html>
@@ -1,51 +0,0 @@
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Web Client</title>
<link rel="stylesheet" href="/static/css/index.css" />
<link
rel="stylesheet"
id="tabulator-stylesheet"
href="https://unpkg.com/tabulator-tables/dist/css/tabulator_site_dark.min.css"
/>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css"
/>
<script
type="text/javascript"
src="https://code.jquery.com/jquery-3.6.0.min.js"
></script>
<script
type="text/javascript"
src="https://unpkg.com/tabulator-tables/dist/js/tabulator.min.js"
></script>
<script
type="text/javascript"
src="https://cdn.socket.io/4.0.0/socket.io.min.js"
></script>
<script>
var SOCKET_PORT = {{port}};
</script>
<script defer src="./static/js/index.js"></script>
</head>
<body>
<nav>
<img
src="https://blenderbim.org/assets/images/blender/blender-logo.png"
alt="Logo"
class="logo"
/>
<ul>
<li><a href="/" class="active">IFC Data</a></li>
<li><a href="/gantt">Gantt Chart</a></li>
</ul>
<button id="toggle-theme" onclick="toggleTheme()">
<i class="fas fa-moon"></i>
</button>
</nav>
<div id="container"></div>
</body>
</html>
@@ -1,293 +0,0 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import gpu
import bmesh
import blenderbim.tool as tool
from math import sin, cos, radians
from bpy.types import SpaceView3D
from mathutils import Vector, Matrix
from gpu_extras.batch import batch_for_shader
from typing import Union
def transparent_color(color, alpha=0.1):
color = [i for i in color]
color[3] = alpha
return color
class ProfileDecorator:
installed = None
@classmethod
def install(cls, context, get_custom_bmesh=None, draw_faces=False, exit_edit_mode_callback=None):
"""Note that operators that change mesh in `exit_edit_mode_callback` can freeze blender.
The workaround is to move their code to function and use it for callback.
Example: https://devtalk.blender.org/t/calling-operator-that-saves-bmesh-freezes-blender-forever/28595"""
if cls.installed:
cls.uninstall()
handler = cls()
cls.installed = SpaceView3D.draw_handler_add(
handler, (context, get_custom_bmesh, draw_faces, exit_edit_mode_callback), "WINDOW", "POST_VIEW"
)
@classmethod
def uninstall(cls):
try:
SpaceView3D.draw_handler_remove(cls.installed, "WINDOW")
except ValueError:
pass
cls.installed = None
def draw_batch(self, shader_type, content_pos, color, indices=None):
shader = self.line_shader if shader_type == "LINES" else self.shader
batch = batch_for_shader(shader, shader_type, {"pos": content_pos}, indices=indices)
shader.uniform_float("color", color)
batch.draw(shader)
def draw_faces(self, bm, vertices_coords):
"""mutates original bm (triangulates it)
so the triangulation edges will be shown too
"""
traingulated_bm = bm
bmesh.ops.triangulate(traingulated_bm, faces=traingulated_bm.faces)
face_indices = [[v.index for v in f.verts] for f in traingulated_bm.faces]
faces_color = transparent_color(self.addon_prefs.decorator_color_special)
self.draw_batch("TRIS", vertices_coords, faces_color, face_indices)
def __call__(self, context, get_custom_bmesh=None, draw_faces=False, exit_edit_mode_callback=None):
self.addon_prefs = tool.Blender.get_addon_preferences()
selected_elements_color = self.addon_prefs.decorator_color_selected
unselected_elements_color = self.addon_prefs.decorator_color_unselected
special_elements_color = self.addon_prefs.decorator_color_special
error_elements_color = self.addon_prefs.decorator_color_error
background_elements_color = self.addon_prefs.decorator_color_background
obj = context.active_object
if obj.mode != "EDIT":
if exit_edit_mode_callback:
ProfileDecorator.uninstall()
exit_edit_mode_callback()
return
if get_custom_bmesh:
bm = get_custom_bmesh()
else:
bm = bmesh.from_edit_mesh(obj.data)
gpu.state.point_size_set(6)
gpu.state.blend_set("ALPHA")
### Actually drawing
all_vertices = []
error_vertices = []
selected_vertices = []
unselected_vertices = []
# special = associated with arcs/circles
special_vertices = []
special_vertex_indices = {}
selected_edges = []
unselected_edges = []
arc_edges = []
roof_angle_edges = []
preview_edges = []
arc_groups = []
circle_groups = []
for i, group in enumerate(obj.vertex_groups):
if "IFCARCINDEX" in group.name:
arc_groups.append(i)
elif "IFCCIRCLE" in group.name:
circle_groups.append(i)
arcs = {}
circles = {}
# https://docs.blender.org/api/blender_python_api_2_63_8/bmesh.html#CustomDataAccess
# This is how we access vertex groups via bmesh, apparently, it's not very intuitive
deform_layer = bm.verts.layers.deform.active
angle_layer = bm.edges.layers.float.get("BBIM_gable_roof_angles")
preview_layer = bm.edges.layers.int.get("BBIM_preview")
for vertex in bm.verts:
co = tuple(obj.matrix_world @ vertex.co)
all_vertices.append(co)
if vertex.hide:
continue
is_arc, is_circle = False, False
# deform_layer is None if there are no verts assigned to vertex groups
# even if there are vertex groups in the obj.vertex_groups
if deform_layer:
is_arc, group_index = tool.Blender.bmesh_check_vertex_in_groups(vertex, deform_layer, arc_groups)
if is_arc:
arcs.setdefault(group_index, []).append(vertex)
special_vertex_indices[vertex.index] = group_index
is_circle, group_index = tool.Blender.bmesh_check_vertex_in_groups(vertex, deform_layer, circle_groups)
if is_circle:
circles.setdefault(group_index, []).append(vertex)
special_vertex_indices[vertex.index] = group_index
if vertex.select:
selected_vertices.append(co)
else:
if len(vertex.link_edges) > 1 and is_circle:
error_vertices.append(co)
elif is_circle:
special_vertices.append(co)
elif len(vertex.link_edges) != 2:
error_vertices.append(co)
elif is_arc:
special_vertices.append(co)
else:
unselected_vertices.append(co)
for edge in bm.edges:
edge_indices = [v.index for v in edge.verts]
if edge.hide:
continue
if edge.select:
selected_edges.append(edge_indices)
else:
i1, i2 = edge.verts[0].index, edge.verts[1].index
# making sure that both vertices are in the same group
if i1 in special_vertex_indices and special_vertex_indices[i1] == special_vertex_indices.get(i2, None):
arc_edges.append(edge_indices)
elif angle_layer and edge[angle_layer] > 0:
roof_angle_edges.append(edge_indices)
elif preview_layer and edge[preview_layer] == 1:
preview_edges.append(edge_indices)
else:
unselected_edges.append(edge_indices)
### Actually drawing
# POLYLINE_UNIFORM_COLOR is good for smoothed lines since `bgl.enable(GL_LINE_SMOOTH)` is deprecated
self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
self.line_shader.bind()
# POLYLINE_UNIFORM_COLOR specific uniforms
self.line_shader.uniform_float("viewportSize", (context.region.width, context.region.height))
self.line_shader.uniform_float("lineWidth", 2.0)
# general shader
self.shader = gpu.shader.from_builtin("UNIFORM_COLOR")
self.shader.bind()
# Draw faces
if draw_faces:
self.draw_faces(bm, all_vertices)
self.draw_batch("LINES", all_vertices, transparent_color(unselected_elements_color), unselected_edges)
self.draw_batch("LINES", all_vertices, selected_elements_color, selected_edges)
self.draw_batch("LINES", all_vertices, background_elements_color, arc_edges)
self.draw_batch("LINES", all_vertices, special_elements_color, preview_edges)
self.draw_batch("LINES", all_vertices, special_elements_color, roof_angle_edges)
self.draw_batch("POINTS", unselected_vertices, transparent_color(unselected_elements_color, 0.5))
self.draw_batch("POINTS", error_vertices, error_elements_color)
self.draw_batch("POINTS", special_vertices, special_elements_color)
self.draw_batch("POINTS", selected_vertices, selected_elements_color)
# Draw arcs
arc_centroids = []
arc_segments = []
for arc in arcs.values():
if len(arc) != 3:
continue
sorted_arc = [None, None, None]
for v1 in arc:
connections = 0
for link_edge in v1.link_edges:
v2 = link_edge.other_vert(v1)
if v2 in arc:
connections += 1
if connections == 2: # Midpoint
sorted_arc[1] = v1
else:
sorted_arc[2 if sorted_arc[2] is None else 0] = v1
points = [tuple(obj.matrix_world @ v.co) for v in sorted_arc]
centroid = tool.Cad.get_center_of_arc(points)
if centroid:
arc_centroids.append(tuple(centroid))
arc_segments.append(tool.Cad.create_arc_segments(pts=points, num_verts=17, make_edges=True))
self.draw_batch("POINTS", arc_centroids, background_elements_color)
for verts, edges in arc_segments:
self.draw_batch("LINES", verts, special_elements_color, edges)
# Draw circles
circle_centroids = []
circle_segments = []
for circle in circles.values():
if len(circle) != 2:
continue
p1 = obj.matrix_world @ circle[0].co
p2 = obj.matrix_world @ circle[1].co
radius = (p2 - p1).length / 2
centroid = p1.lerp(p2, 0.5)
circle_centroids.append(tuple(centroid))
segments = self.create_circle_segments(360, 20, radius)
matrix = obj.matrix_world.copy()
matrix.translation = centroid
segments = [[list(matrix @ Vector(v)) for v in segments[0]], segments[1]]
circle_segments.append(segments)
self.draw_batch("POINTS", circle_centroids, background_elements_color)
for verts, edges in circle_segments:
self.draw_batch("LINES", verts, special_elements_color, edges)
def create_matrix(self, p, x, y, z):
return Matrix([x, y, z, p]).to_4x4().transposed()
# https://github.com/nortikin/sverchok/blob/master/nodes/generator/basic_3pt_arc.py
# This function is taken from Sverchok, licensed under GPL v2-or-later.
# This is a combination of the make_verts and make_edges function.
def create_circle_segments(self, Angle, Vertices, Radius):
if Angle < 360:
theta = Angle / (Vertices - 1)
else:
theta = Angle / Vertices
listVertX = []
listVertY = []
for i in range(Vertices):
listVertX.append(Radius * cos(radians(theta * i)))
listVertY.append(Radius * sin(radians(theta * i)))
if Angle < 360 and self.mode_ == 0:
sigma = radians(Angle)
listVertX[-1] = Radius * cos(sigma)
listVertY[-1] = Radius * sin(sigma)
elif Angle < 360 and self.mode_ == 1:
listVertX.append(0.0)
listVertY.append(0.0)
points = list((x, y, 0) for x, y in zip(listVertX, listVertY))
listEdg = [(i, i + 1) for i in range(Vertices - 1)]
if Angle < 360 and self.mode_ == 1:
listEdg.append((0, Vertices))
listEdg.append((Vertices - 1, Vertices))
else:
listEdg.append((Vertices - 1, 0))
return points, listEdg
@@ -1,113 +0,0 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
import blenderbim.tool as tool
import blenderbim.core.spatial
import blenderbim.core.aggregate
from blenderbim.bim.ifc import IfcStore
class OpenPieClass(bpy.types.Operator):
bl_idname = "bim.open_pie_class"
bl_label = "Open Pie Class"
bl_description = "Assign the IFC Class to the selected objects"
@classmethod
def poll(cls, context):
if not context.active_object and not context.selected_objects:
cls.poll_message_set("No object selected.")
return False
return True
def execute(self, context):
bpy.ops.wm.call_menu_pie(name="VIEW3D_MT_PIE_bim_class")
return {"FINISHED"}
class PieAddOpening(bpy.types.Operator):
bl_idname = "bim.pie_add_opening"
bl_label = "Add Opening"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
if len(context.selected_objects) == 2:
opening_name = None
obj_name = None
for obj in context.selected_objects:
if "IfcOpeningElement" in obj.name or not obj.BIMObjectProperties.ifc_definition_id:
opening_name = obj.name
elif len(obj.children) == 1 and not obj.children[0].BIMObjectProperties.ifc_definition_id:
opening_name = obj.children[0].name
else:
obj_name = obj.name
bpy.ops.bim.add_opening(obj=obj_name, opening=opening_name)
return {"FINISHED"}
class PieUpdateContainer(bpy.types.Operator):
bl_idname = "bim.pie_update_container"
bl_label = "Update Spatial Container"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
for obj in context.selected_objects:
if not obj.BIMObjectProperties.ifc_definition_id:
continue
for collection in obj.users_collection:
spatial_obj = collection.BIMCollectionProperties.obj
if spatial_obj and spatial_obj.BIMObjectProperties.ifc_definition_id:
blenderbim.core.spatial.assign_container(
tool.Ifc, tool.Collector, tool.Spatial, structure_obj=spatial_obj, element_obj=obj
)
break
return {"FINISHED"}
class VIEW3D_MT_PIE_bim(bpy.types.Menu):
bl_label = "Geometry"
def draw(self, context):
pie = self.layout.menu_pie()
pie.operator("bim.edit_object_placement")
pie.operator("bim.update_representation").ifc_representation_class = ""
pie.operator("bim.pie_add_opening")
pie.operator("bim.pie_update_container")
pie.operator("bim.open_pie_class", text="Assign IFC Class")
pie.operator("bim.aggregate_assign_object", text="Assign Aggregation")
pie.operator("bim.aggregate_unassign_object", text="Unassign Aggregation")
class VIEW3D_MT_PIE_bim_class(bpy.types.Menu):
bl_label = "Class"
def draw(self, context):
pie = self.layout.menu_pie()
pie.operator("bim.assign_class", text="IfcWall").ifc_class = "IfcWall"
pie.operator("bim.assign_class", text="IfcSlab").ifc_class = "IfcSlab"
pie.operator("bim.assign_class", text="IfcStair").ifc_class = "IfcStair"
pie.operator("bim.assign_class", text="IfcDoor").ifc_class = "IfcDoor"
pie.operator("bim.assign_class", text="IfcWindow").ifc_class = "IfcWindow"
pie.operator("bim.assign_class", text="IfcColumn").ifc_class = "IfcColumn"
pie.operator("bim.assign_class", text="IfcBeam").ifc_class = "IfcBeam"
@@ -1,104 +0,0 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
def add_georeferencing(georeference):
georeference.add_georeferencing()
def enable_editing_georeferencing(georeference):
georeference.import_projected_crs()
georeference.import_coordinate_operation()
georeference.enable_editing()
def remove_georeferencing(ifc):
ifc.run("georeference.remove_georeferencing")
def disable_editing_georeferencing(georeference):
georeference.disable_editing()
def edit_georeferencing(ifc, georeference):
ifc.run(
"georeference.edit_georeferencing",
projected_crs=georeference.get_projected_crs_attributes(),
coordinate_operation=georeference.get_coordinate_operation_attributes(),
)
georeference.disable_editing()
georeference.set_model_origin()
def get_cursor_location(georeference):
georeference.set_coordinates("local", georeference.get_cursor_location())
def convert_local_to_global(georeference):
coordinates = georeference.xyz2enh(georeference.get_coordinates("local"))
georeference.set_coordinates("map", coordinates)
georeference.set_cursor_location()
def convert_global_to_local(georeference):
coordinates = georeference.enh2xyz(georeference.get_coordinates("map"))
georeference.set_coordinates("local", coordinates)
georeference.set_cursor_location()
def convert_angle_to_coord(georeference, type):
vector_coordinates = georeference.angle2coords(georeference.get_angle(type), type)
georeference.set_vector_coordinates(vector_coordinates, type)
def import_plot(georeference, filepath):
georeference.import_plot(filepath)
def enable_editing_wcs(georeference):
georeference.import_wcs()
georeference.enable_editing_wcs()
def disable_editing_wcs(georeference):
georeference.disable_editing_wcs()
def edit_wcs(ifc, georeference):
wcs = georeference.export_wcs()
georeference.set_wcs(wcs)
georeference.disable_editing_wcs()
georeference.set_model_origin()
def enable_editing_true_north(georeference):
georeference.import_true_north()
georeference.enable_editing_true_north()
def disable_editing_true_north(georeference):
georeference.disable_editing_true_north()
def edit_true_north(ifc, georeference):
ifc.run("georeference.edit_true_north", true_north=georeference.get_true_north_attributes())
georeference.disable_editing_true_north()
def remove_true_north(ifc):
ifc.run("georeference.edit_true_north", true_north=None)
@@ -1,64 +0,0 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
from blenderbim.tool.aggregate import Aggregate
from blenderbim.tool.blender import Blender
from blenderbim.tool.boundary import Boundary
from blenderbim.tool.brick import Brick
from blenderbim.tool.bsdd import Bsdd
from blenderbim.tool.cad import Cad
from blenderbim.tool.clash import Clash
from blenderbim.tool.classification import Classification
from blenderbim.tool.collector import Collector
from blenderbim.tool.context import Context
from blenderbim.tool.debug import Debug
from blenderbim.tool.demo import Demo
from blenderbim.tool.document import Document
from blenderbim.tool.drawing import Drawing
from blenderbim.tool.geometry import Geometry
from blenderbim.tool.georeference import Georeference
from blenderbim.tool.ifc import Ifc
from blenderbim.tool.ifcgit import IfcGit
from blenderbim.tool.ifcgit import IfcGitRepo
from blenderbim.tool.library import Library
from blenderbim.tool.loader import Loader
from blenderbim.tool.material import Material
from blenderbim.tool.misc import Misc
from blenderbim.tool.model import Model
from blenderbim.tool.nest import Nest
from blenderbim.tool.owner import Owner
from blenderbim.tool.patch import Patch
from blenderbim.tool.project import Project
from blenderbim.tool.profile import Profile
from blenderbim.tool.pset import Pset
from blenderbim.tool.qto import Qto
from blenderbim.tool.resource import Resource
from blenderbim.tool.root import Root
from blenderbim.tool.sequence import Sequence
from blenderbim.tool.spatial import Spatial
from blenderbim.tool.covering import Covering
from blenderbim.tool.structural import Structural
from blenderbim.tool.style import Style
from blenderbim.tool.surveyor import Surveyor
from blenderbim.tool.system import System
from blenderbim.tool.tester import Tester
from blenderbim.tool.type import Type
from blenderbim.tool.unit import Unit
from blenderbim.tool.search import Search
from blenderbim.tool.cost import Cost
from blenderbim.tool.web import Web
@@ -1,55 +0,0 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
import bmesh
import shapely
import ifcopenshell
import blenderbim.core.tool
import blenderbim.core.root
import blenderbim.core.spatial
import blenderbim.core.geometry
import blenderbim.tool as tool
import json
from math import pi
from mathutils import Vector, Matrix
from shapely import Polygon, MultiPolygon
class Covering(blenderbim.core.tool.Covering):
@classmethod
def get_z_from_ceiling_height(cls):
props = bpy.context.scene.BIMCoveringProperties
return props.ceiling_height
# def toggle_spaces_visibility_wired_and_textured(cls, spaces):
# first_obj = tool.Ifc.get_object(spaces[0])
# if bpy.data.objects[first_obj.name].display_type == "TEXTURED":
# for space in spaces:
# obj = tool.Ifc.get_object(space)
# bpy.data.objects[obj.name].show_wire = True
# bpy.data.objects[obj.name].display_type = "WIRE"
# return
#
# elif bpy.data.objects[first_obj.name].display_type == "WIRE":
# for space in spaces:
# obj = tool.Ifc.get_object(space)
# bpy.data.objects[obj.name].show_wire = False
# bpy.data.objects[obj.name].display_type = "TEXTURED"
# return
-401
View File
@@ -1,401 +0,0 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>, 2022 Yassine Oualid <yassine@sigmadimensions.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
from blenderbim.bim.module.web.data import WebData
import blenderbim.core.tool
import blenderbim.tool as tool
import ifcopenshell.api.sequence
from typing import Any, Dict, Optional
import socket
import sys
import os
import errno
import subprocess
import webbrowser
import asyncio
import socketio
import threading
import queue
import json
from time import sleep
from pathlib import Path
sio = None
ws_process = None
ws_thread = None
web_operator_queue = queue.Queue()
RECONNECTION_ATTEMPTS = 3
RECONNECTION_DELAY = 2
IFC_TASK_ATTRIBUTE_MAP = {
"pStart": "ScheduleStart",
"pEnd": "ScheduleFinish",
"pName": "Name",
}
class Web(blenderbim.core.tool.Web):
@classmethod
def generate_port_number(cls) -> int:
"""
Generate a free port number.
This method creates a temporary socket to bind to a free port.
It then retrieves the port number, and returns it.
Returns:
int: The port number that was generated.
"""
print("Generating port number")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(("localhost", 0)) # Bind to a free port
port = s.getsockname()[1] # get the bound port
print(f"Port number: {port}")
return port
@classmethod
def is_port_available(cls, port: int) -> bool:
"""
Attempts to connect to the specified port on localhost.
If the connection is refused, the port is available for use; otherwise, it is in use.
Args:
- port (int): The port number to check.
Returns:
bool: True if the port is available, False if it is in use.
"""
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
# connect_ex returns errno.SUCCESS (0) if the connection succeeds
# otherwise returns errno.ECONNREFUSED (111 or 10061) if no server is listening
return s.connect_ex(("localhost", port)) == errno.ECONNREFUSED
@classmethod
def start_websocket_server(cls, port: int) -> None:
"""
Starts a WebSocket server on the specified port.
This method sets up the environment, locates paths, and starts
the WebSocket server process. It also handles the creation and updating of a PID file to keep track
of running server instances.
Args:
- port (int): The port number on which to start the WebSocket server.
"""
import addon_utils
global ws_process
webui_path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "webui")
ws_path = os.path.join(webui_path, "sioserver.py")
py_version = sys.version_info
if bpy.app.version >= (4, 2, 0):
blenderbim_lib_path = (
Path(bpy.utils.user_resource("EXTENSIONS"))
/ ".local"
/ "lib"
/ f"python{py_version.major}.{py_version.minor}"
/ "site-packages"
)
else:
addon = [a for a in addon_utils.modules() if a.bl_info["name"] == "BlenderBIM"][0]
blenderbim_path = os.path.dirname(addon.__file__)
blenderbim_lib_path = os.path.join(blenderbim_path, "libs", "site", "packages")
env = os.environ.copy()
env["blenderbim_lib_path"] = str(blenderbim_lib_path)
ws_process = subprocess.Popen(
[sys.executable, ws_path, "--p", str(port), "--host", "127.0.0.1"],
cwd=webui_path,
env=env,
)
pid_file = os.path.join(webui_path, "running_pid.json")
if os.path.exists(pid_file):
with open(pid_file, "r") as f:
pids = json.load(f)
else:
pids = {}
pids[str(ws_process.pid)] = port
with open(pid_file, "w") as f:
json.dump(pids, f, indent=4)
cls.set_is_running(True)
@classmethod
def connect_websocket_server(cls, port: int) -> None:
"""
Connect to a WebSocket server on the specified port.
This method sets up an asynchronous Socket.IO client with
reconnection attempts, starts an asyncio thread, connects to the WebSocket server, and sets the connection status.
Args:
- port (int): The port number to connect to the WebSocket server.
"""
global ws_thread, sio
if bpy.context.scene.WebProperties.is_connected:
print(f"Already connected to websocket server on port: {port}")
return
sio = socketio.AsyncClient(
reconnection=True,
reconnection_attempts=RECONNECTION_ATTEMPTS,
reconnection_delay=RECONNECTION_DELAY,
logger=True,
)
ws_thread = AsyncioThread()
ws_thread.daemon = True
ws_thread.start()
ws_url = f"ws://localhost:{port}/blender"
ws_thread.run_coro(cls.sio_connect(ws_url))
cls.set_is_connected(True)
bpy.app.timers.register(cls.check_operator_queue)
@classmethod
def disconnect_websocket_server(cls) -> None:
"""
Disconnects the WebSocket server and stops the associated thread.
This method is responsible for disconnecting the WebSocket server, stopping the asyncio thread,
and resetting the global variables related to the WebSocket connection.
"""
global ws_thread, sio
ws_thread.run_coro(cls.sio_disconnect())
ws_thread.stop()
ws_thread = None
sio = None
cls.set_is_connected(False)
@classmethod
def kill_websocket_server(cls) -> None:
"""
Terminate the currently running WebSocket server.
This method checks if there is an active WebSocket server process. If so, it disconnects it (if connected),
removes its PID from the PID file, terminates the process, and updates the server's running status.
"""
global ws_process
if ws_process is None:
print("No Websocket server running")
return
if bpy.context.scene.WebProperties.is_connected:
cls.disconnect_websocket_server()
# sleep(0.5)
webui_path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "webui")
pid_file = os.path.join(webui_path, "running_pid.json")
with open(pid_file, "r") as f:
pids = json.load(f)
if str(ws_process.pid) in pids:
del pids[str(ws_process.pid)]
# Write the updated PIDs back to the file
with open(pid_file, "w") as f:
json.dump(pids, f, indent=4)
ws_process.terminate()
ws_process.wait()
ws_process = None
cls.set_is_running(False)
print("Websocket server terminated successfully")
@classmethod
def send_webui_data(
cls,
data: Optional[Any] = None,
data_key: str = "data",
event: str = "data",
namespace: str = "/blender",
use_web_data: bool = True,
) -> None:
"""
Sends data to the Web UI via Websocket connection.
Args:
- data (Optional[Any]): The data to send. If None, just sends data from WebData.
- data_key (str): The key under which to store the data in the payload. Defaults to "data".
- event (str): The WebSocket event to emit. Defaults to "data".
- namespace (str): The namespace for the WebSocket event. Defaults to "/blender".
- use_web_data (bool): Whether to use data from WebData. Defaults to True.
"""
global ws_thread
payload = {}
if use_web_data:
if not WebData.is_loaded:
WebData.load()
payload = WebData.data
if data is not None:
payload[data_key] = data
if ws_thread is not None and bpy.context.scene.WebProperties.is_connected:
ws_thread.run_coro(cls.sio_send(payload, event, namespace))
@classmethod
def check_operator_queue(cls) -> None | float:
if not bpy.context.scene.WebProperties.is_connected:
with web_operator_queue.mutex:
web_operator_queue.queue.clear()
return None # unregister timer if not connected
while not web_operator_queue.empty():
operator = web_operator_queue.get_nowait()
if not operator:
continue
if operator["sourcePage"] == "csv":
cls.handle_csv_operator(operator["operator"])
elif operator["sourcePage"] == "gantt":
cls.handle_gantt_operator(operator["operator"])
return 1.0
@classmethod
def handle_csv_operator(cls, operator_data: dict) -> None:
if operator_data["type"] == "selection":
bpy.ops.object.select_all(action="DESELECT")
guid = operator_data["globalId"]
ele = tool.Ifc.get().by_guid(guid)
obj = tool.Ifc.get_object(ele)
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
@classmethod
def handle_gantt_operator(cls, operator_data: dict) -> None:
ifc_file = tool.Ifc.get()
if operator_data["type"] == "editTask":
task_id = int(operator_data["taskId"])
task = ifc_file.by_id(task_id)
task_time = task.TaskTime
column = operator_data["column"]
new_value = operator_data["value"]
try:
ifcopenshell.api.sequence.edit_task(
ifc_file, task, attributes={IFC_TASK_ATTRIBUTE_MAP[column]: str(new_value)}
)
except AttributeError:
if task_time is None:
ifcopenshell.api.sequence.add_task_time(ifc_file, task)
task_time = task.TaskTime
ifcopenshell.api.sequence.edit_task_time(
ifc_file, task_time=task_time, attributes={IFC_TASK_ATTRIBUTE_MAP[column]: str(new_value)}
)
bpy.ops.bim.load_task_properties()
# after updating, send new gantt data to handle the case where
# changing a task cascades and changes other tasks. as this wouldn't
# be reflected in the web ui
work_schedule = ifc_file.by_id(operator_data["workScheduleId"])
task_json = tool.Sequence.create_tasks_json(work_schedule)
gantt_data = {"tasks": task_json, "work_schedule": work_schedule.get_info(recursive=True)}
cls.send_webui_data(data=gantt_data, data_key="gantt_data", event="gantt_data")
@classmethod
def open_web_browser(cls, port: int) -> None:
webbrowser.open(f"http://127.0.0.1:{port}/")
@classmethod
async def sio_connect(cls, url: str) -> None:
await sio.connect(url, transports=["websocket"], namespaces="/blender")
sio.on("web_operator", cls.sio_listen_web_operator, namespace="/blender")
@classmethod
async def sio_disconnect(cls) -> None:
await sio.disconnect()
@classmethod
async def sio_send(cls, data: Any, event: str = "data", namespace: str = "/blender") -> None:
await sio.emit(event, data, namespace=namespace)
@classmethod
async def sio_listen_web_operator(cls, data: dict) -> None:
try:
web_operator_queue.put_nowait(data)
except queue.Full:
pass
@classmethod
def set_is_running(cls, is_running: bool) -> None:
bpy.context.scene.WebProperties.is_running = is_running
@classmethod
def set_is_connected(cls, is_connected: bool) -> None:
bpy.context.scene.WebProperties.is_connected = is_connected
class AsyncioThread(threading.Thread):
def __init__(self, *args, loop=None, **kwargs):
"""
Initialize an instance of AsyncioThread.
This class represents a thread that runs an asyncio event loop. It is used to handle asynchronous tasks
in a separate thread from the main thread.
Args:
- *args: Variable length argument list. These arguments are passed to the superclass constructor.
- loop: An existing asyncio event loop. If None, a new event loop is created.
- **kwargs: Arbitrary keyword arguments. These arguments are passed to the superclass constructor.
"""
super().__init__(*args, **kwargs)
self.loop = loop or asyncio.new_event_loop()
self.running = False
def run(self):
"""
Start the asyncio event loop and mark the thread as running.
"""
self.running = True
self.loop.run_forever()
def run_coro(self, coro) -> Any:
"""
Run a coroutine in the asyncio event loop from a separate thread.
Args:
- coro: The coroutine to be run.
Returns:
The result of the coroutine.
"""
return asyncio.run_coroutine_threadsafe(coro, loop=self.loop).result()
def stop(self) -> None:
"""
Stop the asyncio event loop and join the thread.
"""
self.loop.call_soon_threadsafe(self.loop.stop)
self.join()
self.running = False
-20
View File
@@ -1,20 +0,0 @@
Code style
============
Black code formatter
-------------------------------
For Python code formatting, we use `Black code formatter <https://pypi.org/project/black/>`__ with ``--line-length 120``.
``black`` can be installed using ``pip install black`` and files can be formatted with the following example command:
.. code-block:: bash
black --line-length 120 src/blenderbim/blenderbim/bim/module/qto/operator.py
Using PowerShell, you can run the Black formatter on the last commit in the repository.
You can change ``~1`` to ``~n`` to affect ``n`` commits.
.. code-block:: powershell
git diff HEAD HEAD~1 --name-only | where {$_ -like "*.py"} | foreach-object { start $_ && black --line-length 120 $_ }
@@ -1,29 +0,0 @@
Getting Started
===============
BlenderBIM is an open-source project, and its development is driven by the contributions of a dedicated community of developers,
architects, engineers, and enthusiasts. If you're interested in contributing to the project, whether by submitting bug reports,
suggesting new features, or contributing code, your involvement is highly encouraged and appreciated.
This part of the documentation covers various aspects of the BlenderBIM development process, including:
- :doc:`Writing User Documentation </contribute/writing_docs>`
- :doc:`Translations and Internationalisation </contribute/translations>`
- Contributing Code
- :doc:`Installation and Setting up a Development Environment </devs/installation>`
- Understanding the Project Structure and Codebase
- :doc:`Hello, World! </devs/hello_world>`
- :doc:`Undo System </devs/undo_system>`
- :doc:`Code Style Guidelines and Best Practices </devs/code_style>`
..
- :doc:`Submitting Pull Requests and Contributing Code </devs/contributing_code>`
- :doc:`Testing and Quality Assurance </devs/running_tests>`
- :doc:`Running Tests </devs/running_tests>`
- :doc:`System Support and Multiplatform Compatibility </devs/system_support>`
- :doc:`User Experience and User Interface Guidelines </devs/ux_guidelines>`
The BlenderBIM Developer Documentation is a living resource maintained by the core development team and the open-source community. It serves as a central hub for developers who want to get involved in the project, ensuring a consistent and efficient development process.
By contributing to BlenderBIM, you'll not only be helping to improve and expand the capabilities of this powerful open-source BIM authoring platform but also be part of a vibrant community driving innovation in the AEC industry.
-194
View File
@@ -1,194 +0,0 @@
Installation
============
There are different methods of installation, depending on your situation.
1. **Unstable installation** is recommended for power users helping with testing.
2. **Bundling for Blender** is recommended for distributing the add-on.
3. **Live development environment** is recommended for developers who are actively coding.
4. **Packaged installation** is recommended for those who use a package manager.
Unstable installation
---------------------
**Unstable installation** is almost the same as **Stable installation**, except
that they are typically updated every day. Simply download a daily build from
the `GitHub releases page
<https://github.com/IfcOpenShell/IfcOpenShell/releases>`__, then follow the
usual :doc:`installation instructions</users/quickstart/installation>`.
You will need to choose which build to download.
- If you are on Blender >=4.1, choose py311
- If you are on Blender >=3.1 and <=4.0, choose py310
- If you are on Blender >=2.93 and <3.1, choose py39
- Choose ``linux-x64``, ``macos-x64`` (Apple Intel), ``macos-arm64`` (Apple Silicon), or
``windows-x64`` depending on your operating system
For users who don't follow the `VFX Platform <https://vfxplatform.com/>`_
standard, we also provide py312 builds.
Sometimes, a build may be delayed, or contain broken code. We try to avoid this,
but it happens.
Bundling for Blender
--------------------
Instead of waiting for an official release on the BlenderBIM Add-on website, it
is possible to make your own Blender add-on from the bleeding edge source code
of BlenderBIM. BlenderBIM is coded in Python and doesn't require any
compilation, so this is a relatively easy process.
Note that the BlenderBIM Add-on does depend on IfcOpenShell, and IfcOpenShell
does require compilation. The following instructions will use a pre-built
IfcOpenShell (using an IfcOpenBot build) for convenience. Instructions on how to
compile IfcOpenShell is out of scope of this document.
You can create your own package by using the Makefile as shown below. You can
choose between a ``PLATFORM`` of ``linux``, ``macos``, ``macosm1``, and ``win``.
You can choose between a ``PYVERSION`` of ``py311``, ``py310``, or ``py39``.
.. code-block:: bash
cd src/blenderbim
make dist PLATFORM=linux PYVERSION=py311
ls dist/
This will give you a fully packaged Blender add-on zip that you can distribute
and install.
Live development environment
----------------------------
One option for developers who want to actively develop from source is to follow
the instructions from **Bundling for Blender**. However, creating a build,
uninstalling the old add-on, and installing a new build is a slow process.
Although it works, it is very slow, so we do not recommend it.
A more rapid approach is to follow the **Unstable installation** method, as this
provides all dependencies for you out of the box.
Once you've done this, you can replace certain Python files that tend to be
updated frequently with those from the Git repository. We're going to use
symlinks (Windows users can use ``mklink``), so we can code in our Git
repository, and see the changes in our Blender installation (you will need to
restart Blender to see changes).
For Linux or Mac:
.. literalinclude:: ../../scripts/installation/dev_environment.sh
:language: bash
:caption: dev_environment.sh
Or, if you're on Windows, you can use the batch script below. You need to run
it as an administrator. Before running it follow the instructions descibed
in the `rem` tags.
.. literalinclude:: ../../scripts/installation/dev_environment.bat
:language: bat
:caption: dev_environment.bat
After you modify your code in the Git repository, you will need to restart
Blender for the changes to take effect.
The downside with this approach is that if a new dependency is added, or a
compiled dependency version requirement has changed, or the build system
changes, you'll need to fix your setup manually. But this is relatively rare.
Reviewing the Makefile history, `here <https://github.com/IfcOpenShell/IfcOpenShell/commits/v0.8.0/src/blenderbim/Makefile>`__, is one quick way to see if a dependency has changed.
.. seealso::
There is a `useful Blender Addon
<https://blenderartists.org/uploads/short-url/yto1sjw7pqDRVNQzpVLmn51PEDN.zip>`__
(see `forum thread
<https://blenderartists.org/t/reboot-blender-addon/640465/13>`__) that adds
a Reboot button in File menu. In this way, it's possible to directly
restart Blender and test the modified source code. There is also a VS Code
add-on called `Blender Development
<https://marketplace.visualstudio.com/items?itemName=JacquesLucke.blender-development>`__
that has a similar functionality.
Packaged installation
---------------------
- **Arch Linux**: `Direct from Git <https://aur.archlinux.org/packages/ifcopenshell-git/>`__.
- **Chocolatey on Windows**: `Unstable <https://community.chocolatey.org/packages/blenderbim-nightly/>`__.
Tips for package managers
-------------------------
If you are interested in packaging the BlenderBIM Add-on for a packaging
manager, read on.
The BlenderBIM Add-on is fully contained in the ``blenderbim/`` subfolder of the
Blender add-ons directory. This is typically distributed as a zipfile as per
Blender add-on conventions. Within this folder, you'll find the following file
structure:
::
core/ (Blender agnostic core code)
tool/ (Blender specific logic)
bim/ (Blender specific UI)
libs/ (dependencies)
__init__.py
This corresponds to the structure found in the source code `here
<https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.8.0/src/blenderbim/blenderbim>`__.
The BlenderBIM Add-on is complex, and requires many dependencies, including
Python modules, binaries, and static assets. When packaged for users, these
dependencies are bundled with the add-on for convenience.
If you choose to install the BlenderBIM Add-on and use your own system
dependencies, the source of truth for how dependencies are bundled are found in
the `Makefile
<https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.8.0/src/blenderbim/Makefile>`__.
Required Python modules to be stored in ``libs/site/packages/`` are:
::
ifcopenshell
bcf
ifcclash
bimtester
ifccobie
ifccsv
ifcdiff
ifc4d
ifc5d
ifcpatch
ifctester
pystache
svgwrite
dateutil
isodate
networkx
https://github.com/Andrej730/aud/archive/refs/heads/master-reduced-size.zip
deepdiff
jsonpickle
ordered_set
pyparsing
xmlschema
elementpath
six
lark-parser
behave
parse
parse_type
xlsxwriter
odfpy
defusedxml
jmespath
ifcjson
Notes:
1. ``ifcopenshell`` almost always requires the latest version due to the fast paced nature of the add-on development.
2. ``behave`` requires `patches <https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.8.0/src/ifcbimtester/patch>`__.
3. ``ifcjson`` can be found `here <https://github.com/IFCJSON-Team/IFC2JSON_python/tree/master/file_converters>`__.
Required static assets are:
::
bim/data/gantt/jsgantt.js (from jsgantt-improved)
bim/data/gantt/jsgantt.css (from jsgantt-improved)
@@ -1,45 +0,0 @@
System support
==============
The BlenderBIM Add-on officially supports all major 64-bit platforms, as well as
the Python version shipped by the Blender Foundation for the most recent three
major Blender versions:
- 64-bit Linux on Python 3.10
- 64-bit Linux on Python 3.11
- 64-bit MacOS Intel on Python 3.10
- 64-bit MacOS Intel on Python 3.11
- 64-bit MacOS Silicon on Python 3.10
- 64-bit MacOS Silicon on Python 3.11
- 64-bit Windows on Python 3.10
- 64-bit Windows on Python 3.11
Note that developer builds may exist for older versions of Python but there will
be no guarantee of the uptime or stability of these builds.
Other system specifications match the `Blender Requirements
<https://www.blender.org/download/requirements/>`_.
Add-on compatibility
--------------------
The BlenderBIM Add-on is a non-trivial add-on. By turning Blender into a
graphical front-end to a native IFC authoring platform, some fundamental Blender
features (such as hotkeys for basic functionality like object deletion or
duplication) have been patched and many dependencies have been introduced.
Other add-ons may no longer work as intended when the BlenderBIM Add-on is
enabled, or vice versa, the BlenderBIM Add-on may no longer work as intended
when other add-ons are enabled.
Known scenarios which will lead to add-on incompatibility include:
- The add-on also overrides the same hotkeys. For example, if an add-on
overrides the "X" key to delete an object, you will need to manually trigger
(either via menu or custom hotkey) the BlenderBIM Add-on equivalent operator
(e.g. IFC Delete).
- The add-on uses object deletion or duplication macros with dictionary
override. Note that this is also deprecated in Blender, so the other add-on
should be updated to fix this.
- The add-on requires a conflicting dependency, or a conflicting version of the
same dependency. Neither add-on may work simultaneously.
-178
View File
@@ -1,178 +0,0 @@
User Experience and User Interface guidelines
=============================================
This is intended as a reference document for developers working on the BlenderBim addon.
Operators
^^^^^^^^^
BIM will by definition contain a (big) number of submodules or subschemas. Granting access to the features of these submodules to the users needs to be considered with several things in minds :
1. Ease of use : How do I achieve my goal with the minimal number of clicks ? How many different menu items do I have to go through to get to my goal ? How long do I have to scroll a menu to get to the specific thing I have in mind ?
2. Clarity : How long do I have to visually parse the interface to find the item or button I'm looking for ? Are the buttons correctly labeled and are the icons descriptive enough ? If something is forbidden, can I easily know why ? Can I know what a button does before clicking on it ?
3. Completeness : I need to have access to all the items that are related to the topic I'm interested in. If it is tied to another submodule, I need to have access to it.
* **Blender**
These considerations must be adapted to the Python API, to the general paradigm we have chosen to access, modify or create IFC data, and to the general philosophy of Blender. There are many ways and places where an add-on creator can choose to present information to the user. BlenderBim currently works that way :
- Information about the current context is displayed inside the properties editor. We leverage the fact that it is already built around displaying different types of information whether we are in the Scene, Material, Mesh, Object, Curve, Texture, etc. subpanels. It fits really well with the way things are already organized in the IFC classification.
- Tools to create, modify or delete items are in the dedicated Toolbar (The left one) in the 3D viewport
- Some Misc tools and information are displayed in the N panel of the 3D viewport . They're shortcuts to things that are already present elsewhere in the UI, but are handy to have when modifying objects or geometry in the Viewport.
- Adding specific Import / Export IFC operators (arguably a bit misleading since BlenderBim does more than import / export in these operations)
* **Interface panels**
- The good : Every submodule is visually separated from each other. The user can customize its interface to only show what's relevant to them at any one point by folding in or out panels. Development / Debugging is facilitated because each submodule's interface is separated from the others.
- The bad : Having many interface panels clutters the interface, leading to an overwhelming experience for newcomers especially.
- Proposal : The addon should in the long run provide the user with dynamic UI depending on what's their usecase. Preferably accessed in the Addon Preferences interface, with pre-made options that dynamically enable or disable specific parts of the UI. It should also provide the option to selectively add or remove specific parts of the UI on top of that. Additionally, when it does not make sense to display a specific panel, it should be hidden from the UI. (eg if an object has no IFC Class, it can't be spatially contained, so the IFC Spatial Container panel should be hidden until the user sets the IFC class)
In the long term it could also be interesting to think about some kind of tutorial mode where more information is conveyed through the interface for new users.
* **Item Lists**
An item list should provide right off the bat a few features :
- Add a new item.
- Modify an item, whether by adding a button to each item in the list, or adding a button on the list header to modify the selected item.
- Delete an item, whether by adding a button to each item in the list, or adding a button on the list header to delete the selected item.
- Modify an item's name by double-clicking on the field if applicable
- The currently selected item should be highlighted
- There should be a search field to filter through specific items in the list, with buttons to invert selection, sort alphabetically and revert display. (Features that are provided by the `UIList` class)
* **Operators**
- Some buttons should be dynamically disabled (grayed out and impossible to click on) when the context to execute them does not make sense. It is important to note there should not be any heavy computation to determine this since this is executed several times per second for each button where it is implemented. It should only test for simple things and not rely on retrieving information from other modules too much. eg : `Is an item selected ?` `Is the z position of the selected object > 0 ?` or `Is the selected object an IfcOpeningElement ?` and **not** `Is there an IfcOpeningElement in the current file ?` or `How many different classes of IfcBeam are implemented in the file ?`
In Blender this is done in two ways :
- Directly in the operator `poll` method which is executed when the button is displayed in the interface. The drawback is that some operators rely on custom attributes which are provided only when the user clicks on the button, and cannot be test in the `poll` method. Note in V3.0 we can implement custom messages when the `poll` method fails, depending on the step where the context was not right.
- In the UI drawing code, where specific layout parts can be disabled.
- Some buttons or entire interface layout rows or columns may be disabled or hidden at once. It may be desirable when it relies on specific things or combinations of things not being met in the project. In order to avoid UI flicker or the user wondering where the button went, dynamically hiding UI elements should have a minimal interference with the rest of the UI by :
(1) Hiding the last row(s) of a panel
(2) Dynamically resizing the rest of the UI when it's not possible to (1)
The user should be advised why they are prevented to do things via either :
- A custom message using Blender's report system
- A label in the UI replacing the missing UI elements
- A helpful tooltip on an operator
Generally the context itself should be used to the best of its ability to convey why it's possible to do some things or not. The separation of concerns in multiple different dynamically hidden-or-shown sub-panels should help limit confusion.
- The user should be forbidden to click on buttons when its execution returns early and does nothing. If a button is clickable and the user clicks on it, there should always be some kind of feedback.
Icons
^^^^^
* .. image:: https://user-images.githubusercontent.com/25156105/137270452-bf6c03ea-2d3e-4ae3-8121-6799e8beb335.png
**Icon name** : `"CANCEL"`
**Use** : To disable the edition state of a particular item.
**Expected result** : A part of the interface showing the item attributes is either shrunk down or hidden. The button is usually replaced by a button to delete this item.
* .. image:: https://user-images.githubusercontent.com/25156105/137271575-dcae9e56-3c64-4d8b-89b0-6cf103b999f2.png
**Icon name** : `"X"`
**Use** : To delete a particular item, for instance an element of a list.
**Expected result** : The interface element referencing the deleted item is hidden from the interface. If the item was in a list, and the deleted element was selected, the next element becomes selected, or if there is no next element, no element is selected.
* .. image:: https://user-images.githubusercontent.com/25156105/137271601-e79012e5-fc61-402e-830c-b34b4ca757a0.png
**Icon name** : `"GREASEPENCIL"`
**Use** : To Enable the edition of a particular item.
**Behaviour** : Usually only one element of a particular context can be edited at a time.
**Expected result** : The interface should either expand or spawn new elements to display the chosen item's editable attributes. If the editem item is part of a list and its interface elements contained an operator to delete it, it is swapped for an operator to disable the edition of that item.
**Proposal** : Currently all the edition buttons are hidden from the interface when editing a particular item. This results on buttons jumping to the right slightly. My proposal is to instead show but disable the other buttons to prevent interface flicker.
**Current** : https://user-images.githubusercontent.com/25156105/137273603-f9ac39e5-7616-4fb9-89e2-4dae453e650a.gif
**Proposal** : https://user-images.githubusercontent.com/25156105/137273329-532d6d59-e39d-483e-980b-b8405062eaa8.gif
.. image:: https://user-images.githubusercontent.com/25156105/137273981-26fa664a-a29e-402e-9d7e-67b8b71c2d5d.png
* **Icon name** : `"ADD"`
**Use** : To add an item to a particular context, either initializing it (eg. adding a coordinate system) or adding an element to a list.
**Expected result** : The interface should either expand to display the new item or a new line should be shown if the item is added in a list.
**Proposal** : In some instances adding an element in a list automatically enables the edition of this item's attributes. (eg IFC Groups) but in other instances it does not (eg IFC strucural load cases). It is arguable but I do not think the user should expect a new item to be in editable state right off the bat when they add it to a list.
* .. image:: https://user-images.githubusercontent.com/25156105/137274869-0d0b876a-545c-4a58-a386-90f85764b7cc.png
**Icon name** : `"RESTRICT_SELECT_OFF"`
**Use** : To select all the instances related to a particular item.
**Expected result** : All the objects relating to a particular item should be selected in the 3D viewport and/or in the outline.
**Proposal** : Whether or not previously selected objects should be deselected beforehand is up for debate I think, because both behaviours can be desirable. It also raises the question of which object should be set to active. (Random ? First one ? Biggest one ?...)
* .. image:: https://user-images.githubusercontent.com/25156105/137275582-98c1dfcc-fc96-41d6-80dd-fdb82796e66e.png
**Icon name** : `"IMPORT"`
**Use** : to import a particular file from the user's computer's directory to the current context
**Expected result** : A new file browser window should open, with sufficient information provided to the user to know which file type should be loaded in (eg adding a file extension, adding information in the filebrowser UI). When the file is loaded, the interface should expand to show the attributes or information or new context-sensitive operations provided by the imported file.
**Proposal** : Currently there are some instances where I don't know if the elements are supposed to require an external file, eg
.. image:: https://user-images.githubusercontent.com/25156105/137275887-e0f0b694-842b-422f-bc09-cdcefef64107.png
* .. image:: https://user-images.githubusercontent.com/25156105/137276333-4d083f6a-36b9-494f-b0de-ec1d321cbd3d.png
**Icon name** : `"EXPORT"`
**Use** : To export a particular file to the user's computer's directory
**Expected result** : A new file browser window should open, with sufficient information provided to the user to know which file type is going to be saved (eg adding a file extension, adding information in the filebrowser UI).
**Proposal** : When there is no actual file to be saved in the user's directory or the filepath is already set in another place in the UI :
.. image:: https://user-images.githubusercontent.com/25156105/137276840-3ceda0cd-87bd-45f5-8488-bfce86bf3d84.png
It may be better to use a save icon of some sort instead, eg
.. image:: https://user-images.githubusercontent.com/25156105/137276758-5d60f0ca-5a93-4af3-9c4f-30c5794e0657.png
* .. image:: https://user-images.githubusercontent.com/25156105/137277047-bd45df5b-3b47-4b2c-aa29-a340b0710345.png
**Icon name** : `"FILEBROWSER"`
**Use** : To Provide the current context with the path to a particular file or folder
**Expected result** : A new file browser window should open, with sufficient information provided to the user to know which file type is required (eg adding a file extension, adding information in the filebrowser UI). Upon file or folder selection, this should populate a field in the current interface context with the path to the selected file or folder, or at least let the user know that the required information is now correctly filled in.
* .. image:: https://user-images.githubusercontent.com/25156105/137277374-fa7ff310-0b41-49a9-98bd-7c4686da05fd.png
**Icon name** : `"EYEDROPPER"`
**Use** : To select a particular object in the interface to fill the field it is attached to
**Expected result** : The cursor should change to an eyedropper until the user clicks on the required item. The user should be made aware after selection if it was successful (associated field being filled) or unsuccessful (message ? or field staying empty)
-220
View File
@@ -1,220 +0,0 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
BlenderBIM Reference Manual
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Welcome to the manual for `BlenderBIM <https://blenderbim.org>`__,
the free and open source BIM add-on for Blender.
Quickstart
==========
.. only:: builder_html and (not singlehtml)
.. container:: toc-cards
.. container:: card
:doc:`/users/quickstart/introduction_to_bim` (2-minute read)
Brief overview of BIM concepts and BlenderBIM's role.
.. container:: card
:doc:`/users/quickstart/installation` (5 to 10-minute process)
Installation guide and system requirements.
.. container:: card
:doc:`/users/quickstart/explore_model` (15-minute guide)
Load and navigate an IFC model.
.. container:: card
:doc:`/users/quickstart/create_model` (20-minute guide)
Create a simple BIM project.
.. container:: global-index-toc
.. toctree::
:hidden:
:caption: Quickstart
:maxdepth: 1
users/quickstart/introduction_to_bim
users/quickstart/installation
users/quickstart/explore_model
users/quickstart/create_model
users/quickstart/next_steps
Sections
========
.. only:: builder_html and (not singlehtml)
.. container:: toc-cards
.. container:: card
:doc:`/users/modeling/interface`
Guide to the BlenderBIM interface.
.. container:: card
:doc:`/users/modeling/ifc_modeling`
IFC modeling techniques and concepts.
.. container:: card
:doc:`/users/git_support`
Collaborate on projects using Git
.. container:: card
:doc:`/users/drawing/index`
2D drawing generation and annotation.
.. container:: card
:doc:`/users/structural_analysis/index`
Structural analysis capabilities in BlenderBIM.
.. container:: card
:doc:`/users/costing_and_scheduling/index`
Cost estimation and project scheduling features.
.. container:: card
:doc:`/users/advanced/index`
Advanced topics and large-scale modeling.
.. container:: card
:doc:`/users/tutorials/index`
Real-world BIM project tutorials.
.. container:: card
:doc:`/users/user_interface`
Detailed UI reference.
.. container:: card
:doc:`/users/other_addons`
Other complementary add-ons
.. container:: card
:doc:`/users/troubleshooting`
Troubleshooting when things go wrong
.. container:: global-index-toc
.. toctree::
:hidden:
:caption: Sections
:maxdepth: 2
users/modeling/interface
users/modeling/ifc_modeling
users/git_support
users/drawing/index
users/structural_analysis/index
users/costing_and_scheduling/index
users/advanced/index
users/tutorials/index
users/user_interface
users/other_addons
users/troubleshooting
Get Involved
============
This manual is maintained largely by volunteers.
Please consider joining the effort and :doc:`/contribute/writing_docs`.
You can also can help with :doc:`Translations and Internationalisation </contribute/translations>`
For users who want to contribute to the BlenderBIM codebase,
please refer to the :doc:`Documentation for Developers </devs/getting_started>`.
This part of the documentation covers various aspects of the BlenderBIM development process.
You can get in touch by `joining the chat <https://osarch.org/chat/>`__.
.. toctree::
:hidden:
:caption: Get Involved
:maxdepth: 1
contribute/writing_docs
contribute/translations
Developer Documentation
=======================
BlenderBIM is an open-source project, and its development is driven by the contributions of a dedicated community of developers,
architects, engineers, and enthusiasts. If you're interested in contributing to the project, whether by submitting bug reports,
suggesting new features, or contributing code, your involvement is highly encouraged and appreciated.
.. only:: builder_html and (not singlehtml)
.. container:: toc-cards
.. container:: card
:doc:`/devs/getting_started`
Introduction to contributing to BlenderBIM.
.. container:: card
:doc:`/devs/installation`
Setting up a development environment.
.. container:: card
:doc:`/devs/hello_world`
Understanding the project structure.
.. container:: card
:doc:`/devs/undo_system`
Working with BlenderBIM's undo system.
.. container:: card
:doc:`/devs/code_style`
Code style guidelines and best practices.
.. container:: card
:doc:`/devs/running_tests`
Testing and quality assurance.
.. container:: card
:doc:`/devs/system_support`
Multiplatform compatibility.
.. container:: card
:doc:`/devs/ux_guidelines`
User experience and interface guidelines.
.. container:: global-index-toc
.. toctree::
:hidden:
:caption: Developer Documentation
:maxdepth: 1
devs/getting_started
devs/installation
devs/hello_world
devs/undo_system
devs/code_style
devs/running_tests
devs/system_support
devs/ux_guidelines
@@ -1,10 +0,0 @@
Advanced Use Cases
==================
Advanced topics and large-scale modeling.
.. toctree::
:maxdepth: 1
georeferencing
dealing_with_large_models
@@ -1,51 +0,0 @@
============================
Advanded Modeling Techniques
============================
Complex modeling techniques for advanced users.
.. note::
This page is a stub. More detailed content will be added in future updates.
Custom Parametric Wall Types
----------------------------
[Content about creating custom parametric wall types]
Material assignment
-------------------
:doc:`material_assignment`
Modeling Furniture and Fixtures
-------------------------------
[Content about modeling furniture and fixtures]
Structural Elements
-------------------
.. seealso::
:doc:`/users/structural_analysis/index`
[Content about modeling structural elements]
Multi-Story Buildings
---------------------
[Content about modeling multi-story buildings]
Complex Structures
------------------
[Content about modeling complex structures]
.. toctree::
:hidden:
:caption: Sections
:maxdepth: 2
material_assignment
parametric_geometry
@@ -1,44 +0,0 @@
=========================
Basic Modeling Techniques
=========================
Fundamental techniques for IFC modeling.
.. only:: builder_html and (not singlehtml)
.. container:: toc-cards
.. container:: card
:doc:`creating_walls`
Learn how to create and modify walls in your IFC model.
.. container:: card
:doc:`openings/index`
Techniques for adding and customizing doors, windows and other openings.
.. container:: card
:doc:`modeling_slabs_roofs`
Guide to modeling slabs and different types of roofs.
.. container:: card
:doc:`defining_rooms_spaces`
Methods for defining and managing rooms and spaces in your model.
.. container:: global-index-toc
.. toctree::
:hidden:
:caption: Basic Modeling Techniques
:maxdepth: 1
creating_walls
openings/index
modeling_slabs_roofs
defining_rooms_spaces
@@ -1,66 +0,0 @@
Openings
========
This section covers the creation and management of openings in BlenderBIM.
Openings are crucial elements in building design, serving various purposes such as passage, ventilation, and lighting.
.. only:: builder_html and (not singlehtml)
.. container:: toc-cards
.. container:: card
:doc:`door`
Learn how to add and customize doors in your BIM model.
.. container:: card
:doc:`window`
Discover the process of creating and modifying windows.
.. container:: card
:doc:`opening`
Create openings without fillings for special architectural features.
Overview
--------
In the context of Building Information Modeling (BIM) and the Industry Foundation Classes (IFC)
standard, openings are represented through a combination of elements:
1. Voids: Represented by IfcOpeningElement, these are the actual cut-outs in the wall.
2. Fillings: These are the elements that occupy the voids, such as doors (IfcDoor) or windows (IfcWindow).
3. Relationships: These are abstract objects that connect fillings to voids and voids to elements in which they're created.
BlenderBIM provides tools to create and manage these elements:
- Door Creation Tool: For adding doors to walls.
- Window Creation Tool: For adding windows to walls.
- Wall Creation Tool > Void Application: For creating openings without fillings
(currently achieved by creating a door or window and removing it
or by using "Add Void" feature of the Create Wall tool or any element).
These tools allow you to:
- Create openings with precise dimensions and positions.
- Modify opening properties and geometries.
- Manage the relationships between walls, voids, and fillings.
The following pages provide detailed guides on working with each type of wall opening in BlenderBIM.
.. container:: global-index-toc
.. toctree::
:hidden:
:caption: Wall Openings
:maxdepth: 1
door
window
opening
See Also
--------
- :doc:`../creating_walls`
@@ -1,4 +0,0 @@
Importing and Viewing IFC Models
================================
[Content about importing and viewing IFC models]
@@ -1,92 +0,0 @@
============================
BlenderBIM Interface Guide
============================
Introduction
============
The BlenderBIM interface extends Blender's powerful 3D environment with specialized tools for Building Information Modeling (BIM). This guide will help you navigate the BlenderBIM interface and understand its key components.
BlenderBIM Workspace
====================
When you start Blender with BlenderBIM installed, you can switch to the BlenderBIM workspace
by clicking on the BIM workspace tab at the top of the Blender window.
This workspace is preconfigured with the most commonly used panels and tools for BIM workflows.
Key Interface Elements
======================
Properties Extended
-------------------
The Properties Editor is extended to provide IFC-specific properties and settings.
- Scene
- Project Information
- Tool
- Object
BIM Toolbar
-----------
The BIM toolbar, typically located at the left of the 3D Viewport, contains shortcuts to frequently used BIM tools:
- Explore tool
- Create various building elements
- Create annotations, measure distance and angles, calculate volumes, etc
IFC Tree View
-------------
Found in the Outliner, the IFC Tree View displays the hierarchical structure of your BIM model:
- Spatial Structure (Site, Building, Storey)
- Building Elements
- Types
Customizing the Interface
=========================
BlenderBIM respects Blender's highly customizable interface. You can:
- Rearrange editors and panels
- Save custom workspace layouts
- Create custom shortcuts for BIM operations
Tips for Efficient Use
======================
1. Familiarize yourself with IFC classes and their properties.
2. Utilize Blender's search function (F3) to quickly access BlenderBIM tools.
Next Steps
==========
Now that you're familiar with the BlenderBIM interface, you have two main paths to continue your learning:
1. Proceed with IFC Modeling:
If you're ready to start creating and working with BIM models, you can move on to:
- :doc:`IFC Modeling Basics </users/modeling/ifc_modeling>`
2. Dive deeper into the User Interface:
If you want to explore more details about the BlenderBIM interface, you can refer to:
- :doc:`User Interface Reference </users/user_interface>`
Choose the path that best suits your current needs and learning style. You can always come back to explore the other option later.
Remember, as you become more comfortable with the interface and basic modeling, you can explore more advanced topics such as:
- :doc:`Generating Documentation </users/drawing/index>`
- :doc:`Advanced BIM Techniques </users/advanced/index>`
The BlenderBIM interface is designed to integrate seamlessly with Blender while providing powerful BIM-specific functionality.
As you progress, you'll find your BIM workflow becoming increasingly efficient and productive.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 332 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

@@ -1,143 +0,0 @@
Installation
============
.. raw:: html
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/videoseries?list=PLMDcOjMJYxUPHHvEHqAsOuBdSPsp6or32" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
1. **Download and install Blender**
Blender is a free and open-source program for 3D authoring. It works on
Linux, Mac, and Windows. It is developed by the Blender community.
.. container:: blockbutton
`Download Blender <https://www.blender.org/download/>`__
.. tip::
No administrator rights on Windows? Choose the "Portable .zip" option when
downloading from the Blender website.
2. **Download the BlenderBIM Add-on**
The BlenderBIM Add-on extends Blender with OpenBIM related capabilities.
.. container:: blockbutton
`Download BlenderBIM Add-on <https://blenderbim.org/download.html>`__
.. warning::
If you are not using Blender version >=4.1, please follow the **Unstable installation** instructions. :doc:`Read more </devs/installation>`
3. **Install the BlenderBIM Add-on**
Open up Blender, and click on ``Edit > Preferences``.
.. image:: images/install-blenderbim-1.png
Select the **Add-ons** tab, and press **Install...** on the top right. Navigate
to the .zip you downloaded in Step 2, and press **Install Add-on**.
.. image:: images/install-blenderbim-2.png
.. warning::
You do not need to unzip the add-on file. You should install it as a zipped file.
You should now see **System: BlenderBIM** available in your add-ons list. Enable the add-on by pressing the checkbox.
.. image:: images/install-blenderbim-3.png
All done! Your interface will now look similar to below. If you check the ``File`` menu you should also see an option to ``Open IFC Project``.
.. image:: images/install-blenderbim-4.png
You can enable add-ons permanently by using ``Save User Settings`` from the Addons menu.
.. seealso::
If you are a poweruser, you may be interested in the **Unstable installation** to help with testing. :doc:`Read more </devs/installation>`
.. _where is the add-on installed:
Updating
--------
First follow the `Uninstalling`_ section below, then install the latest version.
Uninstalling
------------
Navigate to ``Edit > Preferences > Add-ons``. Due to a limitation in Blender,
you have to **first disable the BlenderBIM Add-on in your Blender preferences**
by pressing the checkbox next to the add-on, then **restart Blender**. It is
critical to follow this sequence of disabling first, and then restarting.
After restarting, you can uninstall the BlenderBIM Add-on by pressing the
``Remove`` button in the Blender preferences window.
Alternatively, you may uninstall manually by deleting the ``blenderbim``
directory in :ref:`your Blender add-ons directory<where is the add-on
installed>`.
.. warning::
It is important to follow the sequence of disabling, restarting, then removing.
If you do not restart Blender, the add-on will fail to remove correctly, and you
will need to uninstall manually.
.. _installation_location:
Where is the add-on installed?
------------------------------
Upon installation, the BlenderBIM Add-on is stored in the
``scripts/addons/blenderbim/`` directory, within your Blender configuration
folder. However, the location of your Blender configuration folder depends on
how you have installed Blender.
If you downloaded Blender as a ``.zip`` file without running an installer, the
BlenderBIM Add-on will be installed in the following directory, where ``X.XX``
is the Blender version:
::
/path/to/blender/X.XX/scripts/addons/blenderbim/
Otherwise, if you installed Blender using an installation package, the Blender
configuration folder depends on which operating system you use.
On Linux, if you are installing the add-on as a user:
::
~/.config/blender/X.XX/scripts/addons/blenderbim/
On Linux, if you are deploying the add-on system-wide (this may also depend on
your Linux distribution):
::
/usr/share/blender/X.XX/scripts/addons/blenderbim/
On Mac, if you are installing the add-on as a user:
::
/Users/{YOUR_USER}/Library/Application Support/Blender/X.XX/scripts/addons/blenderbim/
On Mac, if you are deploying the add-on system-wide:
::
/Library/Application Support/Blender/X.XX/scripts/addons/blenderbim/
On Windows:
::
C:\Users\{YOUR_USER}\AppData\Roaming\Blender Foundation\X.XX\scripts\addons\blenderbim\
@@ -1,98 +0,0 @@
Introduction to BIM
===================
**Building Information Modeling**, or **BIM**, is a way of digitally describing
our built environment to computers. Aspects of our built environment that can be
described are:
- **Products**, like walls, doors, and windows
- **Processes**, like construction or maintenance tasks, and procedures
- **Resources**, like labour, materials, and equipment
- **Controls**, like permits, orders, costs, or calendar availability
- **Actors**, like occupants, clients, architects, and liable parties
- **Groups**, like systems, inventories, or zones
These objects may have lots of data and relationships. Examples of data might be
classification systems, physical materials, associated documents, simulation
results, and construction types. The data may be relevant to multiple
disciplines, such as architecture, engineering, and construction.
.. note::
BIM data is very different from a regular 3D model. In fact, geometry is
optional, and most data is non-geometric. This means that it is not simply a
3D format that you can import or export from and expect meaningful results.
**Industry Foundation Classes**, or **IFC**, is an international standard for
**BIM**. **IFC** is the most well-established open digital language for our
built environment. Most software will be able to describe their **BIM** data
using **IFC**. Most commonly, **IFC** models will be shared as a ``.ifc`` file.
For example, **IFC** will define a wall as an object that can have a name,
construction type, and quantities. **IFC** will also describe that a wall that
be associated with a location, like a building storey, or have an associated
cost item in a schedule.
When you use the BlenderBIM Add-on, you will be able to view and create **BIM**
objects and relationships using the **IFC** standard.
Things you can do
-----------------
The BlenderBIM Add-on is designed to be a comprehensive and truly native
BIM authoring platform. Its capabilities include a wide range of tasks
and workflows typically found across various BIM and CAD software, costing
programs, scheduling tools, and simulation applications. While not
an exhaustive list, some of the key things you can do with BlenderBIM include:
- View and explore IFC models, including spaces, properties, and relationships
- Edit and extract attributes, properties, and metadata directly from IFC data
- Move, rotate, and modify the geometry of objects while preserving IFC semantics
- Create new objects using predefined library elements or custom parametric types
- Manage classification systems, document references, and link to external libraries
- Generate 2D drawing views like plans, sections, and elevations with customizable annotations
- Investigate and edit structural analysis models with support for various steel profiles
- Model and manage complex distribution systems like HVAC, plumbing, and electrical (MEP)
- Create construction schedules, perform critical path analysis, and generate sequence animations
- Derive quantities from model elements and create cost schedules with formulas
- Perform clash detection and coordinate models, managing issues across disciplines
- Integrate non-geometric data like costing, scheduling, and asset management
Roadmap and Upcoming Features
-----------------------------
While BlenderBIM already offers a comprehensive set of BIM authoring capabilities,
the development team and community are continuously working to expand its functionality and improve existing workflows.
Some of the most ambitious features and enhancements on the roadmap include:
Usability and Workflow Enhancements
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Improve user-friendliness to equip average "Joe" with capabilities to model simple projects like single family homes, making BlenderBIM a viable alternative to SketchUp.
- Make BlenderBIM more approachable for users across different skill levels, from advanced BIM experts to architects working on smaller residential projects.
Improved Drawing and Documentation Workflows
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Continued enhancements to the drawing generation capabilities, including better dimensioning tools and support for associative dimensions linked to model geometry.
- Advanced annotation tools with customizable tags, callouts, and the ability to define reusable annotation styles and templates.
- Streamlined sheet layout management and improved integration with external tools like Inkscape for creating title blocks and sheet compositions.
- Continued improvement of BlenderBIM's ability to generate comprehensive documentation sets, including drawing annotations, door schedules, wall schedules, and material tagging.
Expanded Parametric Modeling Capabilities
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Native modeling tools for complex building elements like curtain wall systems and facade panels.
- Expanded libraries with support for country-specific and manufacturer-provided object types.
- Enhanced support for multi-story modeling, enabling efficient duplication and coordination of building elements across various levels.
- Expanded parametric relationships and automating more common BIM tasks to reduce manual effort and enhance productivity.
Enhanced Coordination and Collaboration Features
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Robust model merge and coordination workflows, with detailed clash detection capabilities across different disciplines and data sources.
- Built-in support for version control and model sharing using Git repositories, enabling better team collaboration and change tracking.
The development roadmap is continuously updated based on user feedback, industry requirements,
and contributions from the open-source community. By embracing an open and collaborative approach,
BlenderBIM aims to push the boundaries of what's possible in BIM authoring,
ensuring that it remains at the forefront of innovation in the AEC industry.
@@ -1,93 +0,0 @@
Troubleshooting
===============
The BlenderBIM Add-on is alpha software. There are many bugs! When something
goes wrong, you may see some computer code flash up on your screen. You may
also see an error message:
.. image:: images/error-message.png
**Don't panic!** Click on the button that says **Copy Error Message To
Clipboard**. You will need to paste this text in a bug report.
If you do not have a GitHub account, you will need to sign up to report a bug.
In addition to pasting the error message text, please also describe what you
were doing, and attach your IFC file or screenshots if relevant.
.. container:: blockbutton
`Report a bug <https://github.com/IfcOpenShell/IfcOpenShell/issues/new>`__
If your issue is particularly complex, you can also chat live with developers
or other powerusers.
.. container:: blockbutton
`Chat live with a developer <https://osarch.org/chat>`_
Installation issues
-------------------
If you are unable to install the BlenderBIM Add-on, make sure you are using
**Blender 4.1** installed from https://blender.org/ and are installing the
latest version from https://blenderbim.org.
Other common solutions are listed below. If none of these fix the problem, you
can `report a bug <https://github.com/ifcopenshell/ifcopenshell/issues>`_ or
`live chat with a developer <https://osarch.org/chat/>`_.
1. **Some other error prevents me from installing or doing basic functions with
the add-on. Is it specific to my environment?**
Try installing and using the BlenderBIM Add-on on a "clean environment". A
clean environment is a fresh Blender installation with no other add-ons
enabled with factory settings.
To quickly test in a clean environment, first :ref:`find your Blender
configuration folder<installation_location>`.
Rename the folder from ``X.XX`` to something else like ``X.XX_backup``, then
restart Blender and try follow the :doc:`installation
instructions</users/quickstart/installation>` again.
If this fixes your issue, consider disabling other add-ons one by one until
you find a conflict as a next step to isolating the issue.
2. **I get an error similar to "ImportError: IfcOpenShell not built for 'linux/64bit/python3.10'"**
If you are using a Mac, be sure to use the Mac Silicon version if you have a
newer Mac. The only exception is if you have installed Blender using Steam
on a Mac, in which case you need to use the Mac Intel download.
For all other scenarios, check the BlenderBIM Add-on zip file which you
downloaded. The zip will have either ``py39``, ``py310``, or ``py311`` in
the name. See the instructions in the :ref:`devs/installation:unstable
installation` section to check that you have installed the correct version.
3. **I am on Ubuntu and get an error similar to "ImportError:
/lib/x86_64-linux-gnu/libm.so.6: version GLIBC_2.29 not found"**
Our latest package which uses IfcOpenShell v0.8.0 is built using Ubuntu 20 LTS.
If you have an older Ubuntu version, you can either upgrade to 19.10 or above,
or you'll need to compile IfcOpenShell yourself.
4. **I get an error saying "ModuleNotFoundError: No module named 'numpy'"**"
If you have installed Blender from another source instead of from
`Blender.org <https://www.blender.org/download/>`__, such as from your
distro's package repositories, then you may be missing some modules like
``numpy``. Try installing it manually like ``apt install python-numpy``.
Common issues
-------------
1. **I get an error similar to RuntimeError: Instance #1234 not found**
Blender saves and loads projects to a ``.blend`` file. However. the
BlenderBIM Add-on works with native IFC, and this means instead of saving
and loading ``.blend`` files, you should instead save and load the ``.ifc``
project.
If you have opened a ``.blend`` file, there is a risk that the contents of
the ``.blend`` session do not correlate to the contents of the ``.ifc``,
which can cause this error. Unless you are an advanced user, only save and
load ``.ifc`` files.
@@ -1,98 +0,0 @@
=======================
Tutorials
=======================
Project Series
==============
Step-by-step guides for real-world BIM projects.
.. toctree::
:maxdepth: 2
:hidden:
project0
project1
project2
project3
project4
project5
.. only:: builder_html and (not singlehtml)
.. container:: toc-cards
.. container:: card
:doc:`Project 0: Designing a Room <project0>`
* Basic walls and openings
* Slabs
* MEP
* Basic furniture
* Basic floor plan drawings
.. container:: card
:doc:`Project 1: Designing a Flat <project1>`
* Advanced walls and openings
* Profiles
* Rooms and spaces
* Furniture/fixture libraries
* Elevation/section drawings
.. container:: card
:doc:`Project 2: Building a Bungalow <project2>`
* Roof
* Advanced foundation
* Structural elements
* Roof openings
* Underground services
* Running services in subfloor space
* Drawing details
* Basic costing and scheduling
.. container:: card
:doc:`Project 3: Multi-Storey Single-Family Home <project3>`
* Templating
* Types
* Complex roofs
* Complex fixtures (e.g. solar panels)
* Complex HVAC, plumbing, electrical
* Basic site landscaping
.. container:: card
:doc:`Project 4: Terraced/Town Houses/Duplexes <project4>`
* Shared walls
* Shared roofs
* Complex landscaping
* Duplicating units
* Basic parametric floor plans
* Generating drawings parametrically
* Clash detection
* Coordination with other stakeholders
.. container:: card
:doc:`Project 5: Apartment Block <project5>`
* Multiple levels
* Typical floor
* Shared amenities and common areas
* Elevators
* Parametric services
* Complex structural elements
* Advanced exporting
* Merging
* Coordination
* Analysis
* Advanced costing and scheduling
* External tools
Quickstart Video Tutorial
=========================
Learn how to model a small building and create simple architectural plans, sections, 2D details, and sheet layouts in this short tutorial series.
`View all tutorial videos <https://www.youtube.com/playlist?list=PLMDcOjMJYxUPHHvEHqAsOuBdSPsp6or32>`__
@@ -1,23 +0,0 @@
User Interface Reference
========================
This section covers the general user interface of BlenderBIM. User interface documentation does not cover any specific use case but provides a general reference of BlenderBIM UI.
The documentation doesn't cover Blender UI, but makes references to `Blender documentation <https://docs.blender.org/manual/en/latest/interface/index.html>`__ where appropriate.
.. * Navigating the Project Browser and Outliner
.. * Using the Property Panels
.. * Toolbars and Menus
.. * Customizing the Interface
.. * Keyboard Shortcuts and Preferences
.. toctree::
:hidden:
:maxdepth: 1
:caption: Contents:
user_interface/topbar
user_interface/workspace
user_interface/toolbar/index
user_interface/property-editor
Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 KiB

@@ -1,60 +0,0 @@
Property Editor Scene Properties
================================
.. container:: location-scene
|location| Scene Properties
.. |location| image:: /images/location-scene.svg
BlenderBIM adds new functionality to the `Property Editor` -> `Scene` tab.
.. figure:: images/interface_property-editor_project-overview_start-up.png
:alt: Property editor on Blender start-up
The property editor on Blender startup.
Most of these sub-tabs become available with a created or loaded IFC file.
Don't worry, the default Blender scene properties are still reachable under their own dedicated sub-tab.
.. figure:: images/interface_property-editor_icons.png
:alt: Overview over the added property sub-tabs by BlenderBIM
Overview over the added property sub-tabs by BlenderBIM.
1. Project Overview
2. Object Information
3. Geometry and Materials
4. Drawings and Documents
5. Services and Systems
6. Structural Analyses
7. Costing and Scheduling
8. Facility Management
9. Quality and Coordination
10. Blender Properties
11. Switch Tab
You can also select the needed panel via the drop-down menue.
.. figure:: images/interface_property-editor_panel-dropdown.png
:alt: BlenderBIM property editor sub-tabs drop-down menue
Switching between BlenderBIM property editor sub-tabs via the drop-down menue.
.. toctree::
:hidden:
:maxdepth: 1
:caption: Contents:
property_editor/scene_editor/project_overview/index
property_editor/scene_editor/object_information/index
property_editor/scene_editor/geometry_and_materials/index
property_editor/scene_editor/drawings_and_documents/index
property_editor/scene_editor/services_and_systems/index
property_editor/scene_editor/structural_analysis/index
property_editor/scene_editor/costing_and_scheduling/index
property_editor/scene_editor/facility_management/index
property_editor/scene_editor/quality_and_coordination/index
property_editor/scene_editor/blender
property_editor/scene_editor/switch_tab
@@ -1,44 +0,0 @@
Topbar
======
For general informations about the Blender Topbar see the respective
`Workspaces <https://docs.blender.org/manual/en/latest/interface/window_system/topbar.html>`__ section in Blender documentation.
Menus
-----
The `File` menu in the Topbar adds menu entries to Create/Open and Save an IFC project directly.
.. figure:: images/interface_window_file-menue.png
:alt: Additional file menu options related to IFC projects
Additional file menu options related to IFC projects.
New IFC Project
^^^^^^^^^^^^^^^
The New IFC Project submenu offers several options for creating a new IFC project:
.. figure:: images/file_new-ifc-project-submenu.png
:alt: New IFC Project submenu options
New IFC Project submenu options
- New Metric (m) Project: Creates a new IFC project using meters as the base unit.
- New Metric (mm) Project: Creates a new IFC project using millimeters as the base unit.
- New Imperial (ft) Project: Creates a new IFC project using feet as the base unit.
- New Demo Project: Creates a new IFC project with pre-populated demo content.
- New Project Wizard: Creates a default Blender project (including the default cube)
and opens the Scene Properties > Project Overview > Project Info tab.
This allows users to customize their project settings before creation.
Clicking the "Create Project" button in this panel will delete the default cube and set up the new IFC project with the specified settings.
These options provide flexibility in setting up new IFC projects,
allowing users to choose between quick starts with predefined units
or a more customizable approach through the Project Wizard.
BIM Workspace
-------------
BlenderBIM adds the **BIM** Workspace to the Topbar Workspaces tabs.
@@ -1,26 +0,0 @@
BIM Workspace
=============
For general informations about the Blender Workspaces see the respective
`Workspaces <https://docs.blender.org/manual/en/latest/interface/window_system/workspaces.html>`__ section in Blender documentation.
After installation of BlenderBIM the default Blender start-up screen looks different from the standard Blender interface.
BlenderBIM adds the **BIM** Workspace to the interface and by default activates this workspace on start-up.
It also modifies the layout of views and sidebars and adds custom functionality to the toolbar.
The left **Outliner** panel shows a tree of geometric objects. The centre main **Viewport** panel shows 3D geometry.
The right **Properties** panel shows data and relationships.
.. figure:: images/interface_window_start-up.png
:alt: Blender start-up window with installed BlenderBIM add-on
Blender start-up window with installed BlenderBIM add-on.
1. **BIM** Workspace tab
2. Outliner with the document tree
3. Main 3D viewport
4. Property editor
5. Toolbar with added BIM functionality
6. Sidebar with BlenderBIM & 4D/5D Toolkit panels
7. Status bar with information about the currently used Blender and BlenderBIM version
@@ -1,70 +0,0 @@
@echo off
echo SETUP BLENDERBIM ADD-ON LIVE DEVELOPMENT ENVIRONMENT
echo Update BLENDER, BLENDER_VERSION, PYTHON_VERSION, BBIM_REPO, BLENDER_USER_NAME in the script bellow.
echo Put the script at the root of your IfcOpenShell git repository
echo This script needs to be run as administrator (to create symbolic links)
echo Make sure you have followed these steps before proceeding :)
pause
SET BLENDER_VERSION=4.2
SET PYTHON_VERSION=3.11
SET BBIM_REPO=user_default
rem Can be useful e.g. if you're running script from administrator account
rem and need to setup dev environment for some other user.
SET BLENDER_USER_NAME=%USERNAME%
SET BLENDER=%HOMEDRIVE%\Users\%BLENDER_USER_NAME%\AppData\Roaming\Blender Foundation\Blender\%BLENDER_VERSION%
SET BLENDER_LOCAL=%BLENDER%\extensions\.local\lib\python%PYTHON_VERSION%\site-packages
SET BLENDERBIM=%BLENDER_LOCAL%\blenderbim
SET BLENDER_EXT=%BLENDER%\extensions\%BBIM_REPO%\blenderbim
echo Removing the Blender add-on Python code...
del "%BLENDER_EXT%\__init__.py"
rd /S /Q "%BLENDERBIM%"
echo Replacing them with links to the Git repository...
mklink "%BLENDER_EXT%\__init__.py" "%CD%\src\blenderbim\blenderbim\__init__.py"
mklink /D "%BLENDERBIM%" "%CD%\src\blenderbim\blenderbim"
echo Copy over compiled IfcOpenShell files...
copy "%BLENDER_LOCAL%\ifcopenshell\*_wrapper*" "%CD%\src\ifcopenshell-python\ifcopenshell\"
echo Remove the IfcOpenShell dependency...
rd /S /Q "%BLENDER_LOCAL%\ifcopenshell"
echo Replace them with links to the Git repository...
mklink /D "%BLENDER_LOCAL%\ifcopenshell" "%CD%\src\ifcopenshell-python\ifcopenshell"
echo Remove and link other IfcOpenShell utilities...
del "%BLENDER_LOCAL%\ifccsv.py"
del "%BLENDER_LOCAL%\ifcdiff.py"
del "%BLENDER_LOCAL%\bsdd.py"
rd /S /Q "%BLENDER_LOCAL%\bcf"
rd /S /Q "%BLENDER_LOCAL%\ifc4d"
rd /S /Q "%BLENDER_LOCAL%\ifc5d"
rd /S /Q "%BLENDER_LOCAL%\ifccityjson"
rd /S /Q "%BLENDER_LOCAL%\ifcclash"
rd /S /Q "%BLENDER_LOCAL%\ifcpatch"
rd /S /Q "%BLENDER_LOCAL%\ifctester"
rd /S /Q "%BLENDER_LOCAL%\ifcfm"
mklink "%BLENDER_LOCAL%\ifccsv.py" "%CD%\src\ifccsv\ifccsv.py"
mklink "%BLENDER_LOCAL%\ifcdiff.py" "%CD%\src\ifcdiff\ifcdiff.py"
mklink "%BLENDER_LOCAL%\bsdd.py" "%CD%\src\bsdd\bsdd.py"
mklink /D "%BLENDER_LOCAL%\bcf" "%CD%\src\bcf\bcf"
mklink /D "%BLENDER_LOCAL%\ifc4d" "%CD%\src\ifc4d\ifc4d"
mklink /D "%BLENDER_LOCAL%\ifc5d" "%CD%\src\ifc5d\ifc5d"
mklink /D "%BLENDER_LOCAL%\ifccityjson" "%CD%\src\ifccityjson\ifccityjson"
mklink /D "%BLENDER_LOCAL%\ifcclash" "%CD%\src\ifcclash\ifcclash"
mklink /D "%BLENDER_LOCAL%\ifcpatch" "%CD%\src\ifcpatch\ifcpatch"
mklink /D "%BLENDER_LOCAL%\ifctester" "%CD%\src\ifctester\ifctester"
mklink /D "%BLENDER_LOCAL%\ifcfm" "%CD%\src\ifcfm\ifcfm"
echo Manually downloading some third party dependencies...
curl https://raw.githubusercontent.com/jsGanttImproved/jsgantt-improved/master/dist/jsgantt.js -o "%BLENDERBIM%\bim\data\gantt\jsgantt.js"
curl https://raw.githubusercontent.com/jsGanttImproved/jsgantt-improved/master/dist/jsgantt.css -o "%BLENDERBIM%\bim\data\gantt\jsgantt.css"
curl -L https://github.com/BrickSchema/Brick/releases/download/nightly/Brick.ttl -o "%BLENDERBIM%\bim\schema\Brick.ttl"
pause
@@ -1,60 +0,0 @@
git clone https://github.com/IfcOpenShell/IfcOpenShell.git
cd IfcOpenShell
# path to BlenderBIM addon
# default path on Mac: "/Users/$USER/Library/Application Support/Blender/X.X/scripts/addons/blenderbim"
# default path on Linux: "$HOME/.config/blender/X.X/"
BLENDER_ADDON_PATH="/path/to/blender/X.XX/scripts/addons/blenderbim"
# Remove the Blender add-on Python code
rm -r $BLENDER_ADDON_PATH/core/
rm -r $BLENDER_ADDON_PATH/tool/
rm -r $BLENDER_ADDON_PATH/bim/
# Replace them with links to the Git repository
ln -s $PWD/src/blenderbim/blenderbim/core $BLENDER_ADDON_PATH/core
ln -s $PWD/src/blenderbim/blenderbim/tool $BLENDER_ADDON_PATH/tool
ln -s $PWD/src/blenderbim/blenderbim/bim $BLENDER_ADDON_PATH/bim
# Copy over compiled IfcOpenShell files
cp $BLENDER_ADDON_PATH/libs/site/packages/ifcopenshell/*_wrapper* $PWD/src/ifcopenshell-python/ifcopenshell/
# Remove the IfcOpenShell dependency
rm -r $BLENDER_ADDON_PATH/libs/site/packages/ifcopenshell
# Replace them with links to the Git repository
ln -s $PWD/src/ifcopenshell-python/ifcopenshell $BLENDER_ADDON_PATH/libs/site/packages/ifcopenshell
# Remove and link other IfcOpenShell utilities
rm -r $BLENDER_ADDON_PATH/libs/site/packages/ifccsv.py
rm -r $BLENDER_ADDON_PATH/libs/site/packages/ifcdiff.py
rm -r $BLENDER_ADDON_PATH/libs/site/packages/bsdd.py
rm -r $BLENDER_ADDON_PATH/libs/site/packages/bcf
rm -r $BLENDER_ADDON_PATH/libs/site/packages/ifc4d
rm -r $BLENDER_ADDON_PATH/libs/site/packages/ifc5d
rm -r $BLENDER_ADDON_PATH/libs/site/packages/ifccityjson
rm -r $BLENDER_ADDON_PATH/libs/site/packages/ifcclash
rm -r $BLENDER_ADDON_PATH/libs/site/packages/ifcpatch
rm -r $BLENDER_ADDON_PATH/libs/site/packages/ifctester
rm -r $BLENDER_ADDON_PATH/libs/site/packages/ifcfm
rm -r $BLENDER_ADDON_PATH/libs/Desktop
ln -s $PWD/src/ifccsv/ifccsv.py $BLENDER_ADDON_PATH/libs/site/packages/ifccsv.py
ln -s $PWD/src/ifcdiff/ifcdiff.py $BLENDER_ADDON_PATH/libs/site/packages/ifcdiff.py
ln -s $PWD/src/bsdd/bsdd.py $BLENDER_ADDON_PATH/libs/site/packages/bsdd.py
ln -s $PWD/src/bcf/bcf $BLENDER_ADDON_PATH/libs/site/packages/bcf
ln -s $PWD/src/ifc4d/ifc4d $BLENDER_ADDON_PATH/libs/site/packages/ifc4d
ln -s $PWD/src/ifc5d/ifc5d $BLENDER_ADDON_PATH/libs/site/packages/ifc5d
ln -s $PWD/src/ifccityjson/ifccityjson $BLENDER_ADDON_PATH/libs/site/packages/ifccityjson
ln -s $PWD/src/ifcclash/ifcclash $BLENDER_ADDON_PATH/libs/site/packages/ifcclash
ln -s $PWD/src/ifcpatch/ifcpatch $BLENDER_ADDON_PATH/libs/site/packages/ifcpatch
ln -s $PWD/src/ifctester/ifctester $BLENDER_ADDON_PATH/libs/site/packages/ifctester
ln -s $PWD/src/ifcfm/ifcfm $BLENDER_ADDON_PATH/libs/site/packages/ifcfm
ln -s $PWD/src/blenderbim/blenderbim/libs/desktop $BLENDER_ADDON_PATH/libs/Desktop
# Manually download some third party dependencies
cd $BLENDER_ADDON_PATH/bim/data/gantt
wget https://raw.githubusercontent.com/jsGanttImproved/jsgantt-improved/master/dist/jsgantt.js
wget https://raw.githubusercontent.com/jsGanttImproved/jsgantt-improved/master/dist/jsgantt.css
cd $BLENDER_ADDON_PATH/bim/schema
wget https://github.com/BrickSchema/Brick/releases/download/nightly/Brick.ttl
@@ -1,122 +0,0 @@
@aggregate
Feature: Aggregate
Covers element and spatial aggregation
Scenario: Enable editing aggregate
Given an empty IFC project
And the object "IfcSite/My Site" is selected
When I press "bim.enable_editing_aggregate"
Then nothing happens
Scenario: Disable editing aggregate
Given an empty IFC project
And the object "IfcSite/My Site" is selected
And I press "bim.enable_editing_aggregate"
When I press "bim.disable_editing_aggregate"
Then nothing happens
Scenario: Assign object
Given an empty IFC project
And the object "IfcSite/My Site" is selected
And the object "IfcBuildingStorey/My Storey" is selected
And I press "bim.enable_editing_aggregate"
And the variable "relating_object" is "tool.Ifc.get().by_type('IfcSite')[0].id()"
When I press "bim.aggregate_assign_object(relating_object={relating_object})"
Then the object "IfcSite/My Site" is in the collection "IfcSite/My Site"
And the object "IfcBuildingStorey/My Storey" is in the collection "IfcBuildingStorey/My Storey"
And the collection "IfcBuildingStorey/My Storey" is in the collection "IfcSite/My Site"
Scenario: Unassign object
Given an empty IFC project
And the object "IfcBuildingStorey/My Storey" is selected
And I press "bim.enable_editing_aggregate"
And the variable "relating_object" is "tool.Ifc.get().by_type('IfcSite')[0].id()"
And I press "bim.aggregate_assign_object(relating_object={relating_object})"
And the object "IfcBuildingStorey/My Storey" is selected
When I press "bim.aggregate_unassign_object"
Then the object "IfcSite/My Site" is in the collection "IfcSite/My Site"
And the object "IfcBuildingStorey/My Storey" is in the collection "IfcBuildingStorey/My Storey"
And the collection "IfcBuildingStorey/My Storey" is in the collection "IfcProject/My Project"
Scenario: Unassign object - multiple objects are contained again to their indirect container
Given an empty IFC project
And I add a cube
And the object "Cube" is selected
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
And I set "scene.BIMRootProperties.ifc_class" to "IfcMember"
And I press "bim.assign_class"
And I add a cube
And the object "Cube" is selected
And I set "scene.BIMRootProperties.ifc_class" to "IfcCovering"
And I press "bim.assign_class"
And the object "IfcMember/Cube" is selected
And additionally the object "IfcCovering/Cube" is selected
And I press "bim.add_aggregate(ifc_class='IfcWall')"
And the object "IfcMember/Cube" is selected
And additionally the object "IfcCovering/Cube" is selected
When I press "bim.aggregate_unassign_object"
Then the object "IfcMember/Cube" is in the collection "IfcBuildingStorey/My Storey"
And the object "IfcCovering/Cube" is in the collection "IfcBuildingStorey/My Storey"
Scenario: Add aggregate
Given an empty IFC project
And I add a cube
And the object "Cube" is selected
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
And I press "bim.assign_class"
And the object "IfcWall/Cube" is selected
When I press "bim.add_aggregate"
Then the object "IfcWall/Cube" is in the collection "IfcElementAssembly/Assembly"
And the object "IfcElementAssembly/Assembly" is in the collection "IfcElementAssembly/Assembly"
And the collection "IfcElementAssembly/Assembly" is in the collection "IfcBuildingStorey/My Storey"
Scenario: Add aggregate - with the aggregate inheriting the existing spatial collection
Given an empty IFC project
And I add a cube
And the object "Cube" is selected
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
And I press "bim.assign_class"
And the object "IfcWall/Cube" is placed in the collection "IfcBuildingStorey/My Storey"
And the object "IfcWall/Cube" is selected
When I press "bim.add_aggregate"
Then the object "IfcWall/Cube" is in the collection "IfcElementAssembly/Assembly"
And the object "IfcElementAssembly/Assembly" is in the collection "IfcElementAssembly/Assembly"
And the collection "IfcElementAssembly/Assembly" is in the collection "IfcBuildingStorey/My Storey"
Scenario: Add aggregate - add a nested aggregate
Given an empty IFC project
And I add a cube
And the object "Cube" is selected
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
And I press "bim.assign_class"
And the object "IfcWall/Cube" is placed in the collection "IfcBuildingStorey/My Storey"
And the object "IfcWall/Cube" is selected
When I press "bim.add_aggregate"
And the object "IfcWall/Cube" is selected
And I press "bim.add_aggregate"
Then the object "IfcWall/Cube" is in the collection "IfcElementAssembly/Assembly.001"
And the object "IfcElementAssembly/Assembly.001" is in the collection "IfcElementAssembly/Assembly.001"
And the collection "IfcElementAssembly/Assembly.001" is in the collection "IfcElementAssembly/Assembly"
And the collection "IfcElementAssembly/Assembly" is in the collection "IfcBuildingStorey/My Storey"
Scenario: Add aggregate - add multiple elements to a custom aggregate class
Given an empty IFC project
And I add a cube
And the object "Cube" is selected
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
And I set "scene.BIMRootProperties.ifc_class" to "IfcMember"
And I press "bim.assign_class"
And I add a cube
And the object "Cube" is selected
And I set "scene.BIMRootProperties.ifc_class" to "IfcCovering"
And I press "bim.assign_class"
And the object "IfcMember/Cube" is selected
And additionally the object "IfcCovering/Cube" is selected
When I press "bim.add_aggregate(ifc_class='IfcWall')"
Then the object "IfcMember/Cube" is in the collection "IfcWall/Assembly"
And the object "IfcCovering/Cube" is in the collection "IfcWall/Assembly"
And the object "IfcWall/Assembly" is in the collection "IfcWall/Assembly"
And the collection "IfcWall/Assembly" is in the collection "IfcBuildingStorey/My Storey"
@@ -1,9 +0,0 @@
@bimtester
Feature: Bimtester
Scenario: Execute Bimtester
Given an empty IFC project
When I set "scene.BimTesterProperties.should_load_from_memory" to "True"
And I set "scene.BimTesterProperties.feature" to "{cwd}/test/files/sample.feature"
And I press "bim.execute_bim_tester"
Then nothing happens
@@ -1,15 +0,0 @@
@covering
Feature: Covering
Covers covering tool.
Scenario: Execute generate flooring coverings from walls
Given an empty IFC project
And I load the demo construction library
And I set "scene.BIMModelProperties.ifc_class" to "IfcWallType"
And the variable "element_type" is "[e for e in {ifc}.by_type('IfcWallType') if e.Name == 'WAL100'][0].id()"
And I set "scene.BIMModelProperties.relating_type_id" to "{element_type}"
And I press "bim.add_constr_type_instance"
And the object "IfcWall/Wall" is selected
When I press "bim.add_instance_flooring_coverings_from_walls"
Then nothing happens
@@ -1,76 +0,0 @@
@georeference
Feature: Georeference
Scenario: Add georeferencing
Given an empty IFC project
When I press "bim.add_georeferencing"
Then nothing happens
Scenario: Enable editing georeferencing
Given an empty IFC project
And I press "bim.add_georeferencing"
When I press "bim.enable_editing_georeferencing"
Then nothing happens
Scenario: Remove georeferencing
Given an empty IFC project
And I press "bim.add_georeferencing"
When I press "bim.remove_georeferencing"
Then nothing happens
Scenario: Edit georeferencing
Given an empty IFC project
And I press "bim.add_georeferencing"
And I press "bim.enable_editing_georeferencing"
When I press "bim.edit_georeferencing"
Then nothing happens
Scenario: Disable editing georeferencing
Given an empty IFC project
And I press "bim.add_georeferencing"
And I press "bim.enable_editing_georeferencing"
When I press "bim.disable_editing_georeferencing"
Then nothing happens
Scenario: Set IFC grid north
Given an empty IFC project
And I press "bim.add_georeferencing"
And I press "bim.enable_editing_georeferencing"
When I press "bim.set_ifc_grid_north"
Then nothing happens
Scenario: Set Blender grid north
Given an empty IFC project
And I press "bim.add_georeferencing"
And I press "bim.enable_editing_georeferencing"
And I press "bim.set_ifc_grid_north"
When I press "bim.set_blender_grid_north"
Then nothing happens
Scenario: Get cursor location
Given an empty IFC project
When I press "bim.get_cursor_location"
Then nothing happens
Scenario: Set IFC true north
Given an empty IFC project
When I press "bim.set_ifc_true_north"
Then nothing happens
Scenario: Set Blender true north
Given an empty IFC project
And I press "bim.set_ifc_true_north"
When I press "bim.set_blender_true_north"
Then nothing happens
Scenario: Convert local to global
Given an empty IFC project
When I set "scene.BIMGeoreferenceProperties.local_coordinates" to "0,0,0"
And I press "bim.convert_local_to_global"
Then "scene.BIMGeoreferenceProperties.map_coordinates" is "0.0,0.0,0.0"
Scenario: Convert global to local
Given an empty IFC project
When I set "scene.BIMGeoreferenceProperties.map_coordinates" to "0,0,0"
And I press "bim.convert_global_to_local"
Then "scene.BIMGeoreferenceProperties.local_coordinates" is "0.0,0.0,0.0"
@@ -1,25 +0,0 @@
@patch
Feature: Patch
Scenario: Execute IFC Patch - file in memory
Given an empty IFC project
And I set "scene.BIMPatchProperties.ifc_patch_recipes" to "OffsetObjectPlacements"
And I set "scene.BIMPatchProperties.should_load_from_memory" to "True"
And I set "scene.BIMPatchProperties.ifc_patch_output" to "{cwd}/test/files/temp/basic-patched.ifc"
And I set "scene.BIMPatchProperties.ifc_patch_args" to "[123454321,0,0,0]"
When I press "bim.execute_ifc_patch(use_json_for_args=True)"
Then the file "{cwd}/test/files/temp/basic-patched.ifc" should contain "123454321"
Scenario: Execute IFC Patch - file from disk
Given an empty IFC project
And I set "scene.BIMPatchProperties.ifc_patch_recipes" to "OffsetObjectPlacements"
And I set "scene.BIMPatchProperties.ifc_patch_input" to "{cwd}/test/files/basic.ifc"
And I set "scene.BIMPatchProperties.ifc_patch_output" to "{cwd}/test/files/temp/basic-patched.ifc"
And I set "scene.BIMPatchProperties.ifc_patch_args" to "[123454321,0,0,0]"
When I press "bim.execute_ifc_patch(use_json_for_args=True)"
Then the file "{cwd}/test/files/temp/basic-patched.ifc" should contain "123454321"
Scenario: Run migrate patch
Given an empty Blender session
When I press "bim.run_migrate_patch(infile='{cwd}/test/files/ifc2x3.ifc', outfile='{cwd}/test/files/temp/ifc2x3-migrated.ifc', schema='IFC4')"
Then the file "{cwd}/test/files/temp/ifc2x3-migrated.ifc" should contain "IFC4"
@@ -1,68 +0,0 @@
@qto
Feature: Qto
Scenario: Calculate circle radius
Given an empty Blender session
And I add a cube
And the object "Cube" is selected
When I press "bim.calculate_circle_radius"
Then "scene.BIMQtoProperties.qto_result" is "1.732"
Scenario: Calculate edge lengths
Given an empty Blender session
And I add a cube
And the object "Cube" is selected
When I press "bim.calculate_edge_lengths"
Then "scene.BIMQtoProperties.qto_result" is "24.0"
Scenario: Calculate face areas
Given an empty Blender session
And I add a cube
And the object "Cube" is selected
When I press "bim.calculate_face_areas"
Then "scene.BIMQtoProperties.qto_result" is "24.0"
Scenario: Calculate object volumes
Given an empty Blender session
And I add a cube
And the object "Cube" is selected
When I press "bim.calculate_object_volumes"
Then "scene.BIMQtoProperties.qto_result" is "8.0"
Scenario: Execute qto method - formwork areas
Given an empty Blender session
And I add a cube
And I add a cube of size "1" at "1,0,0"
And the object "Cube" is selected
And additionally the object "Cube.001" is selected
When I set "scene.BIMQtoProperties.qto_methods" to "FORMWORK"
And I press "bim.execute_qto_method"
Then "scene.BIMQtoProperties.qto_result" is "21.5"
Scenario: Execute qto method - side formwork areas
Given an empty Blender session
And I add a cube
And the object "Cube" is selected
When I set "scene.BIMQtoProperties.qto_methods" to "SIDE_FORMWORK"
And I press "bim.execute_qto_method"
Then "scene.BIMQtoProperties.qto_result" is "16.0"
Scenario: Assign objects base qto
Given an empty IFC project
And I add a cube
And the object "Cube" is selected
And I press "bim.assign_class(ifc_class='IfcWall', predefined_type='SOLIDWALL')"
When I press "bim.assign_objects_base_qto"
Then "active_object.PsetProperties.qto_name" is "Qto_WallBaseQuantities"
Scenario: Calculate all quantities
Given an empty IFC project
And I add a cube
And the object "Cube" is selected
And I press "bim.assign_class(ifc_class='IfcWall', predefined_type='SOLIDWALL')"
When I press "bim.calculate_all_quantities"
And the variable "qset_id" is "{ifc}.by_type('IfcElementQuantity')[0].id()"
And I press "bim.enable_pset_editing(pset_id={qset_id}, obj='IfcWall/Cube', obj_type='Object')"
And I press "bim.disable_pset_editing(obj='IfcWall/Cube', obj_type='Object')"
Then "active_object.PsetProperties.qto_name" is "Qto_WallBaseQuantities"
Then "active_object.PsetProperties.properties['Length'].metadata.float_value" is "2000.0"
@@ -1,16 +0,0 @@
@search
Feature: Search
Scenario: Select all walls
Given an empty IFC project
And I add a cube
And the object "Cube" is selected
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
And I press "bim.assign_class"
And I press "bim.add_filter_group(module='search')"
And I set "scene.BIMSearchProperties.facet" to "entity"
And I press "bim.add_filter(index=0, type='entity', module='search')"
And I set "scene.BIMSearchProperties.filter_groups[0].filters[0].value" to "IfcWall"
When I press "bim.search"
Then the object "IfcWall/Cube" is selected
@@ -1,94 +0,0 @@
@style
Feature: Style
Scenario: Update style colours
Given an empty IFC project
And I add a cube
And I add a material
And I press "bim.add_style"
When I press "bim.update_style_colours"
Then nothing happens
Scenario: Remove style
Given an empty IFC project
And I add a cube
And I add a material
And I press "bim.add_style"
And the variable "style" is "{ifc}.by_type('IfcSurfaceStyle')[0].id()"
When I press "bim.remove_style(style={style})"
Then nothing happens
Scenario: Add style to current blender material
Given an empty IFC project
And I add a cube
And I add a material
When I press "bim.add_style"
Then nothing happens
Scenario: Unlink style
Given an empty IFC project
And I add a cube
And I add a material
And I press "bim.add_style"
When I press "bim.unlink_style"
Then the material "Material" is not an IFC style
Scenario: Add a new style
Given an empty IFC project
And I press "bim.load_styles(style_type='IfcSurfaceStyle')"
And I press "bim.enable_adding_presentation_style"
When I press "bim.add_presentation_style"
Then nothing happens
Scenario: Disable adding a new style
Given an empty IFC project
And I press "bim.load_styles(style_type='IfcSurfaceStyle')"
When I press "bim.disable_adding_presentation_style"
Then nothing happens
Scenario: Edit style
Given an empty IFC project
And I press "bim.load_styles(style_type='IfcSurfaceStyle')"
And I press "bim.enable_adding_presentation_style"
And I press "bim.add_presentation_style"
And the variable "style" is "{ifc}.by_type('IfcSurfaceStyle')[0].id()"
And I press "bim.enable_editing_style(style={style})"
When I press "bim.edit_style"
Then nothing happens
Scenario: Disable editing style
Given an empty IFC project
And I press "bim.load_styles(style_type='IfcSurfaceStyle')"
And I press "bim.enable_adding_presentation_style"
And I press "bim.add_presentation_style"
And the variable "style" is "{ifc}.by_type('IfcSurfaceStyle')[0].id()"
And I press "bim.enable_editing_style(style={style})"
When I press "bim.disable_editing_style"
Then nothing happens
Scenario: Load styles
Given an empty IFC project
And I add a cube
And I add a material
And I press "bim.add_style"
When I press "bim.load_styles(style_type='IfcSurfaceStyle')"
Then nothing happens
Scenario: Disable editing styles
Given an empty IFC project
And I add a cube
And I add a material
And I press "bim.add_style"
And I press "bim.load_styles(style_type='IfcSurfaceStyle')"
When I press "bim.disable_editing_styles"
Then nothing happens
Scenario: Select by style
Given an empty IFC project
And I add a cube
And I add a material
And I press "bim.add_style"
And I press "bim.load_styles(style_type='IfcSurfaceStyle')"
And the variable "style" is "{ifc}.by_type('IfcSurfaceStyle')[0].id()"
When I press "bim.select_by_style(style={style})"
Then nothing happens
@@ -1,17 +0,0 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
-17
View File
@@ -1,17 +0,0 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
@@ -1,112 +0,0 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import blenderbim.core.georeference as subject
from test.core.bootstrap import ifc, georeference
class TestAddGeoreferencing:
def test_run(self, ifc):
ifc.run("georeference.add_georeferencing").should_be_called()
subject.add_georeferencing(ifc)
class TestEnableGeoreferencing:
def test_run(self, georeference):
georeference.import_projected_crs().should_be_called()
georeference.import_map_conversion().should_be_called()
georeference.import_true_north().should_be_called()
georeference.enable_editing().should_be_called()
subject.enable_editing_georeferencing(georeference)
class TestRemoveGeoreferencing:
def test_run(self, ifc):
ifc.run("georeference.remove_georeferencing").should_be_called()
subject.remove_georeferencing(ifc)
class TestEditGeoreferencing:
def test_run(self, ifc, georeference):
georeference.get_projected_crs_attributes().should_be_called().will_return("projected_crs_attributes")
georeference.get_map_conversion_attributes().should_be_called().will_return("map_conversion_attributes")
georeference.get_true_north_attributes().should_be_called().will_return("true_north_attributes")
ifc.run(
"georeference.edit_georeferencing",
projected_crs="projected_crs_attributes",
map_conversion="map_conversion_attributes",
true_north="true_north_attributes",
).should_be_called()
georeference.disable_editing().should_be_called()
subject.edit_georeferencing(ifc, georeference)
class TestSetIfcGridNorth:
def test_run(self, georeference):
georeference.set_ifc_grid_north().should_be_called()
subject.set_ifc_grid_north(georeference)
class TestSetBlenderGridNorth:
def test_run(self, georeference):
georeference.set_blender_grid_north().should_be_called()
subject.set_blender_grid_north(georeference)
class TestSetIfcTrueNorth:
def test_run(self, georeference):
georeference.set_ifc_true_north().should_be_called()
subject.set_ifc_true_north(georeference)
class TestSetBlenderTrueNorth:
def test_run(self, georeference):
georeference.set_blender_true_north().should_be_called()
subject.set_blender_true_north(georeference)
class TestGetCursorLocation:
def test_run(self, georeference):
georeference.get_cursor_location().should_be_called().will_return("coordinates")
georeference.set_coordinates("input", "coordinates").should_be_called()
subject.get_cursor_location(georeference)
class TestSetCursorLocation:
def test_run(self, georeference):
georeference.get_coordinates("output").should_be_called().will_return("coordinates")
georeference.set_cursor_location("coordinates").should_be_called()
subject.set_cursor_location(georeference)
class TestConvertLocalToGlobal:
def test_run(self, georeference):
georeference.get_coordinates("input").should_be_called().will_return("coordinates")
georeference.xyz2enh("coordinates").should_be_called().will_return("enh")
georeference.set_coordinates("output", "enh").should_be_called()
georeference.set_cursor_location("enh").should_be_called()
subject.convert_local_to_global(georeference)
class TestConvertGlobalToLocal:
def test_run(self, georeference):
georeference.get_coordinates("input").should_be_called().will_return("coordinates")
georeference.enh2xyz("coordinates").should_be_called().will_return("xyz")
georeference.set_coordinates("output", "xyz").should_be_called()
georeference.set_cursor_location("xyz").should_be_called()
subject.convert_global_to_local(georeference)
-17
View File
@@ -1,17 +0,0 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.

Some files were not shown because too many files have changed in this diff Show More