Compare commits

..

1286 Commits

Author SHA1 Message Date
Ryan Schultz cc90340b3b tweaked active operator 2024-10-26 14:22:18 -05:00
Ryan Schultz db075c7160 display the sum of all selected objects 2024-10-26 13:26:11 -05:00
Thomas Krijnen ea48996f0d Double check for relationship subtype when processing openings on aggregate parent #5639 2024-10-26 14:53:36 +02:00
Andrej730 6b55e5e6ee Fix find_openings for ifc2x3 #5639 2024-10-25 17:43:41 +05:00
Richard Brice e270583451 Fixes unit conversion on clothoid constant 2024-10-24 08:43:47 -07:00
Andrej730 99dc4795c7 Reset not applied objects scales during project save
We try to apply scales using bim.update_representation and if didn't worked (presumably because object has openings) we reset the scales.
It was confusing for users that they scaled an object, saved IFC and they would know that scaling didn't worked only after they reopen the IFC project.
2024-10-24 18:38:17 +05:00
Andrej730 1642f231fb typing 2024-10-24 18:38:17 +05:00
Andrej730 9998442eb4 Use common method for checking if object is scaled 2024-10-24 18:38:16 +05:00
Andrej730 4040c31583 Lock scale for objects with openings
Currently there is an UX problem that it's not clear for users when it's possible to use scale or not. We definitely won't be able to safely apply scales for objects with openings, so will try to lock them from the start.
2024-10-24 18:38:16 +05:00
Andrej730 6614245fc1 Fix unnamed button for editing openings 2024-10-24 18:38:16 +05:00
Andrej730 c7a41b46fd More complete fix for breaking styles ui e85043ae3
Now it also doesn't break if user will undo style rename.
2024-10-24 18:38:16 +05:00
Andrej730 dfd11fb723 black . 2024-10-24 18:38:16 +05:00
Manu Varkey 8d3aa98b58 Implement rounding of elevation (#5532)
* Implement rounding of elevation

Implement rounding of elevation based on precision stored in IfcGeometricRepresentationContext

* Move formating function to tool
2024-10-24 15:17:47 +05:00
Andrej730 b08acd1625 Fix incorrect error message for bim.link_ifc when linking using 'files' argument
self.filepath is empty if bim.link_ifc was executed using 'files' argument
2024-10-24 14:25:26 +05:00
Andrej730 181b0cefc3 Fix linking ifc from shared folder on Windows #5386
The problem was that shared folders names are starting with `\\`, e.g. `\\SERVERNAME\shared_folder`. When we pass path strings we usually sanitize them and save them as posix, so it's saved as `//SERVERNAME/shared_folder` and Blender has a convention that paths starting with `//` it interprets as filepaths relative to the current .blend file, therefore it was giving some weird error that `C:\Users\xxxx\SERVERNAME\shared_folder\test.blend` is missing instead of `\\SERVERNAME\shared_folder`.

So need to be careful passing strings to Blender operators and use str instead of as_posix for those operators, so  \\` wouldn't be misinterpreted.
2024-10-24 14:25:25 +05:00
Andrej730 e85043ae31 Fix styles UI breaking on undo
Turn out storing bpy.types.PropetyGroups was not very reliable idea as they get invalidated, just as Objects.
It's still breaking if you'd try to rename the style and then undo.
2024-10-23 18:34:03 +05:00
Andrej730 ca0e4f9cd6 Fix error duplicating type when current tool doesn't match the type #5591 2024-10-23 18:34:03 +05:00
Andrej730 3ff0ff66a4 Try to ensure undo will still work in case of an error
Previously transaction was never finished and therefore is_top_level_operator would never be triggered (without restarting project) making any IFC undo useless.
Previously it wsan't finishing transaction therefore:
- it was possible to undo ifc changes in the last step that had an error

- since transaction was never finished, IfcStore.current_transaction was never cleared and therefore is_top_level_operator will be never be triggered for the next operators, so new transactions are never created breaking undo for any further ifc changes.

Now user can try to undo the last action to save the file.
2024-10-23 18:34:02 +05:00
Andrej730 0ea71b0795 Ifc.Operator - remove second refresh_ui_data
Seems to be already covered by refresh_ui_data in IfcStore.execute_ifc_operator.
2024-10-23 18:34:02 +05:00
Andrej730 932a718d2d limit active_material_index handler callback 2024-10-23 18:34:02 +05:00
Andrej730 106b6f74e1 Handle listeners on unlink commit/rollback 2024-10-23 18:34:02 +05:00
Andrej730 88de650660 Simplify IfcStore.relink_object 2024-10-23 18:34:02 +05:00
Andrej730 72ea93bc0f Prevent adding None to guid_map
OperationData was always including guid key, so guid_map[None] was pointing to some object (typically a style). Also covered by rebuild_element_maps in the most cases.
2024-10-23 18:34:02 +05:00
Andrej730 6f347bcb81 Undo to clear listeners for linked objects
Typically it's already covered by rebuild_element_maps after undo but just to be consistent with commit_link_element.
2024-10-23 18:34:01 +05:00
Andrej730 fa29c42887 common method for setting up Blender listeners for objects 2024-10-23 18:34:01 +05:00
Andrej730 86edd52894 Unlinking elements to clear Blender listeners
to prevent unnecessary callbacks
2024-10-23 18:34:01 +05:00
Andrej730 db0a72c794 Add min/max values for roof angle/percentage
That way those props should be easier to edit, previously dragging "percentage" would go to infinity very quickly.
2024-10-23 18:34:01 +05:00
Andrej730 d68dee148b Fix infinite recursion with angle/percentage roof properties in 2597827
Probably was harmless, it was just flooding the console with errors such as:

object address  : 000002485A776380
object refcount : 2
object type     : 00007FFBD1249050
object type name: RecursionError
object repr     :
lost sys.stderr
File "\bonsai\bim\module\model\prop.py", line 707, in <lambda>
object address  : 000002485A774520
object refcount : 2
object type     : 00007FFBD1249050
object type name: RecursionError
object repr     :
lost sys.stderr
File "\bonsai\bim\module\model\prop.py", line 713, in <lambda>
2024-10-23 18:34:01 +05:00
Andrej730 a1134e83a4 Fix test after 8372e12f8 2024-10-23 18:34:00 +05:00
Andrej730 b61927b460 deprecate Style.get_style
In favor of Ifc.get_entity
2024-10-23 18:34:00 +05:00
Andrej730 863633f2dc Prevent adding name callback to non-ifc blender materials
Also removing one more artifact from #4843
2024-10-23 18:34:00 +05:00
Andrej730 b7dfeaee37 typing 2024-10-23 18:34:00 +05:00
Andrej730 2771465996 black . 2024-10-23 18:34:00 +05:00
Ryan Schultz f62b1ed326 Have svg tags with IfcColumn/IfcBeam classes always on top.
discussion: https://community.osarch.org/discussion/2572/a-clever-way-to-get-a-column-buried-in-a-wall-to-still-read-when-you-print-a-drawing
2024-10-22 18:45:19 -05:00
Bruno Perdigão 0c0225543b Add polyline tool for slabs.
No preview yet.
2024-10-22 17:39:19 -03:00
Bruno Perdigão ffe8d4fad2 Make wall preview decorator work only with IfcWallType. 2024-10-22 17:32:48 -03:00
Andrej730 c18d2e8c17 ifcopenshell.file - store default history_size in class instead of instance 2024-10-22 18:20:29 +05:00
Andrej730 70521b1020 IfcStore.edited_objs - document issues 2024-10-22 18:20:29 +05:00
Andrej730 a777d67252 bim.generate_space - add a test 2024-10-22 18:20:29 +05:00
Andrej730 7544053f0b bim.generate_space not to fail silently 2024-10-22 18:20:29 +05:00
Andrej730 7bebd2f7ce bim.generate_space - fix missing undo step 2024-10-22 18:20:29 +05:00
Andrej730 64fe2240e6 bim.generate_space - not to produce orphaned ifc mesh
Orphaned mesh was also linked to IFC which could have lead to some hard to debug issues.
2024-10-22 18:20:28 +05:00
Andrej730 54b104b822 fix not working bim.generate_space because of the units mismatch
Not sure when this occurred but get_bmesh_from_polygon was expecting Polygon in project units but it was SI. Since it's probably better to move everything to SI, added an option to specify whether polygon is in SI or not.
2024-10-22 18:20:28 +05:00
Andrej730 abd7c93c35 bim.generate_space - document 2024-10-22 18:20:28 +05:00
Andrej730 5c56ea6343 spatial tool ui - sync shift-a hotkey UI with hotkey_S_A
Previously it was always showing two S_A operators
2024-10-22 18:20:28 +05:00
Andrej730 e8a2f3aed2 remove recalculate_dumb_wall_origin and don't mark aligned walls as edited
Since 5677768 recalculate_dumb_wall_origin is never used and bim.align_wall is either just changing the location (align_centerline) or might change object's representation but it's already saved to ifc (exterior/interior).
2024-10-22 18:20:27 +05:00
Andrej730 931e945044 Fix broken centerline alignment hotkey after e8f66ab
Ping @trhyder just in case
2024-10-22 18:20:27 +05:00
Andrej730 5eeea23774 bim.align_product - document 2024-10-22 18:20:27 +05:00
Andrej730 2a44af57d2 bim.align_product.align_type to use enum
to make it less error prone
2024-10-22 18:20:27 +05:00
Andrej730 035b6d00c5 bim.align_wall.align_type - use enum 2024-10-22 18:20:27 +05:00
Andrej730 8372e12f88 deprecate geometry.is_edited
in favor of ifc.is_edited
2024-10-22 18:20:26 +05:00
Andrej730 76869b0b02 deprecate misc.mark_object_as_edited
in favor of ifc.edit
2024-10-22 18:20:26 +05:00
Andrej730 5c08b8f22d bim.resize_to_storey - document 2024-10-22 18:20:26 +05:00
Andrej730 bcf54b643d Hide scale warning for non ifc objects 2024-10-22 18:20:26 +05:00
Andrej730 71c5e83fa0 typing 2024-10-22 18:20:25 +05:00
Andrej730 9eaecdb0a4 black . 2024-10-22 18:20:25 +05:00
Bruno Perdigão 3077687c59 Move product preview logic to its own decorator. 2024-10-22 10:01:50 -03:00
Bruno Perdigão 71997d37c0 Add support for cardinal point in beam and column preview. 2024-10-21 21:51:27 -03:00
Bruno Perdigão acc9e7f706 Adds beam and columns to insertion point product preview. 2024-10-21 16:29:23 -03:00
Bruno Perdigão 5fa5b28484 Allow AddOccurence to use default container elevation value. 2024-10-21 11:10:10 -03:00
Bruno Perdigão 745c8e173a Small fix after 14917d2c3 2024-10-21 10:46:26 -03:00
Bruno Perdigão 14917d2c31 Windows and Doors preview now get the wall rotation. 2024-10-21 10:34:42 -03:00
Bruno Perdigão 340916a5a4 Refactor snapping point selection to add the object name. 2024-10-21 10:34:42 -03:00
Bruno Perdigão 734ac2ba70 Fix issue with using shift + mousewheel while polyline is active. 2024-10-21 10:34:42 -03:00
Andrej730 dbfe3ea3c4 bim.update_representation - error message for objects with openings 2024-10-21 18:05:27 +05:00
Andrej730 c581946fa8 railing, roof - save representation to ifc instead of marking it as edited #5610 2024-10-21 18:05:27 +05:00
Andrej730 492df2310d parametric stair - don't mark object as edited
As representation already saved to IFC and edited_objs seems to be getting less reliable because of the openings.
2024-10-21 18:05:27 +05:00
Andrej730 e8eb3972a1 Support styles without shading styles after 189bcd5
Noticed that after 189bcd5 some representations were missing styles - the ones that are using IfcSurfaceStyle with just IfcExternallyDefinedSurfaceStyle.

Ping @aothms just in case
2024-10-21 16:45:50 +05:00
Andrej730 45b3008b99 bim.edit_style to update representations if Side was edited
Mentioned in #5604. Since IfcSurfaceStyle.Side is used during representation generation, we need to regenerate them if the value was changed. Previously it would require manual update / project reload.
2024-10-21 16:45:50 +05:00
Andrej730 ce6c56cab4 model.workspace - cache is_representation_item
To avoid accessing IFC on every draw call
2024-10-21 14:40:39 +05:00
Andrej730 1d90665c3a split_by_loose_parts to preserve the objects selection
Noticed that bim.assign_class started to loose the objects selection after 29d6d2b
2024-10-21 14:40:39 +05:00
Andrej730 6bfbcb8f92 typing 2024-10-21 14:40:38 +05:00
Andrej730 4acdd7c960 Fix assigning cost item to resource after 97393eb #5601
fyi @myoualid
2024-10-21 11:26:09 +05:00
Richard Brice 647e379c69 Fixes problem with evaluating point on vertical alignment
Fixes evaluation of IfcLine parent curve for IfcGradientCurve. See https://github.com/IfcOpenShell/IfcOpenShell/discussions/5587
2024-10-20 08:19:49 -07:00
Thomas Krijnen 18d5957424 Defensiveness against invalid syntax #5608 2024-10-20 14:17:13 +02:00
Chris Mayo 65ecb92c03 python: Fix ifcopenshell.guid.new()
pyException:

<class 'AttributeError'>: module 'ifcopenshell' has no attribute 'guid'
2024-10-20 14:01:34 +02:00
Bruno Perdigão b8d98b7512 Black format 2024-10-19 11:15:30 -03:00
Bruno Perdigão 97ed3bb0d5 Add product preview for mesh type objects when insertion point is active.
Currently works with doors, windows and furnitures.
2024-10-19 10:57:06 -03:00
Bruno Perdigão 217ada0993 Refactor wall preview for polyline tool. 2024-10-19 10:25:03 -03:00
Chris Mayo dcd6acb1f4 Install cityjson_converter lib and exe
Fixes:

$ IfcConvert
IfcConvert: error while loading shared libraries: libcityjson_converter.so: cannot open shared object file: No such file or directory
2024-10-19 13:48:17 +02:00
Andrej730 122ec6fb0a Use clever Blender length props for editing representation item extrusion depth
Example - https://imgchest.com/p/ljyqzpmwoy2
2024-10-18 18:12:00 +05:00
Andrej730 60837b9512 Operator to save pset as a template
Mentioned in #5596

Example - https://imgchest.com/p/5xy235xvj4l

Adds 2 things:
1) UI indicator whether pset is based on template or not
2) When pset is not based on a template, indicator becomes clickable and works as a shortcut for creating pset template based on the current pset.
2024-10-18 18:11:59 +05:00
Andrej730 ada4a8884b tool.PsetTemplate 2024-10-18 18:11:59 +05:00
Andrej730 a27bdc4e3e Add description to pset template props
As name doesn't seem to be displayed in the enum tooltip
2024-10-18 18:11:59 +05:00
Andrej730 43cecf6c5e Hide 'remove pset template/file' operator when there are no templates/files 2024-10-18 18:11:59 +05:00
Andrej730 4666589fcd bim.add_pset_template to add psets with unique names for convenience 2024-10-18 18:11:59 +05:00
Andrej730 e3ef64d0b3 Fix UI error switching between pset template files 2024-10-18 18:11:59 +05:00
Andrej730 828160c1b1 Fix UI errors if there are no pset template files 2024-10-18 18:11:59 +05:00
Andrej730 832ccff139 fix broken enum after removing pset template/file 2024-10-18 18:11:59 +05:00
Andrej730 17e67fbdaa bim.remove_pset_template_file - note 2024-10-18 18:11:58 +05:00
Andrej730 01b28fde6f remove BIMPsetTemplateProperties.new_template_filename
- as it was only used inside bim.add_pset_template_file operator
- also remove second unnecessary ":" in the prop label (":" is automatically added by Blender)
2024-10-18 18:11:58 +05:00
Andrej730 9130659f71 ifcopenshell.open - readable error if file doesn't exist
Previously it would show obscure error like:

RuntimeError: Type held at index 0 is class Blank and not class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >
2024-10-18 18:11:58 +05:00
Andrej730 e073f11e25 typing 2024-10-18 18:11:58 +05:00
Andrej730 dbd64ebb0e black . 2024-10-18 18:11:58 +05:00
Thomas Krijnen ecba1c3e7b Fix for UVs in python binding #5592 2024-10-18 10:37:53 +02:00
Andrej730 5837a143da bump IOS #5583 2024-10-18 11:55:38 +05:00
Bruno Perdigão 01c67eea48 Fix issue with joining walls with negative direction sense. 2024-10-18 07:49:46 +11:00
Andrej730 0e5008d21e Bonsai daily build tag to include hours and minutes
The problem is index.json is using urls pointing to zip files from the releases and it's possible that installation from unstable repo will be broken (user will get error message like '"Archive size mismatch "bonsai", expected 87417726, was 87418259"') in 2 cases:

1) during 5 minutes after commit while builds are still uploaded to the releases but index.json is not yet updated
2) if some builds were uploaded and some builds failed to upload, then for platforms that were uploaded successfully unstable installation will be broken until we fix the builds

When we add hours and minutes to the tag, that should be enough to make urls unique for each build avoiding this problem. If needed we can came up with some mechanism to clean up all builds besides the last one.
2024-10-17 18:25:08 +05:00
Andrej730 b17eacfa6a typing 2024-10-17 18:25:08 +05:00
Thomas Krijnen a04912e174 Assure edges are emitted in some topological order 2024-10-17 14:35:17 +02:00
Andrej730 ee7fd0cadf Fix issues with unsanitized cache names #5589
Underlay filename wasn't sanitized when saved to 'cache' and when added to .svg but later when it's moved from 'cache' to 'drawings' folder the filename was regenerated using sanitized main .svg filename leading to issues.
2024-10-17 15:10:29 +05:00
Andrej730 5ae75d32bd fix bug in a0e660583 #5585 2024-10-16 21:23:56 +05:00
Andrej730 a0e6605834 support adding parametric roof to object without representations 2024-10-16 18:00:43 +05:00
Andrej730 903e673984 Fix adding parametric geometry operators missing undo step
This also seems to by accident resolve #5565 🤨🤨🤨
2024-10-16 18:00:43 +05:00
Andrej730 a7efdb0bff support adding parametric stair to object without representations 2024-10-16 18:00:43 +05:00
Andrej730 695ab0bfab bump ifc sverchok #5546 #5178 2024-10-16 18:00:43 +05:00
Andrej730 e9e89c1280 remove unnecessary second style reload when disabling style editing 2024-10-16 18:00:43 +05:00
Andrej730 e29f8ce18a clear collections properties for styles when not editing 2024-10-16 18:00:43 +05:00
Andrej730 ee892f63bf Fix bug loading wrong external style #5576
By mistake it was always using currently edited external style, even if external style was not edited anymore and even if it was different style currently edited.
2024-10-16 18:00:43 +05:00
Andrej730 bb8e1866b0 Subscribe to viewport shading changes for appended BIM workspace too 2024-10-16 18:00:42 +05:00
Andrej730 3a5856511d bim.update_current_style - optimization for updating styles for multiple objects 2024-10-16 18:00:42 +05:00
Andrej730 725df97ac0 bim.save_project to preserve relative ifc path #5407 2024-10-16 18:00:42 +05:00
Andrej730 98888d5096 bim.load_project - use_relative_path to override should_start_fresh_session 2024-10-16 18:00:42 +05:00
Andrej730 14d44dcd3e remove ExportIFCBase as it's unused 2024-10-16 18:00:42 +05:00
Andrej730 7f1f249759 typing 2024-10-16 18:00:42 +05:00
Andrej730 3113d62c85 black . 2024-10-16 18:00:35 +05:00
Gorgious56 58b46da04d Fix SHIFT+D shortcut for duplication not working for vanilla non-meshlike objects (eg lights) 2024-10-16 11:56:04 +02:00
Bruno Perdigão db77d06a8a Fix error introduced by b9c6508aa 2024-10-15 23:21:38 -03:00
Dion Moult 4684aa4a55 Fix bug where you couldn't add conditional material psets 2024-10-16 12:26:33 +11:00
Bruno Perdigão b9c6508aa7 Polyline wall ability to switch axis while drawing.
While drawing the polyline the user can press:
- F to flip the wall. Changes the direction sense.
- O to change the offset type between Exterior, Center and Interior. This will change the offset from reference line.

Those attributes can be verified in the Object Materials panels of each wall after they are created.
2024-10-15 21:58:34 -03:00
Bruno Perdigão d7bf8eba02 Fix small issue with the area decorator for the measure tool. 2024-10-15 21:47:42 -03:00
Bruno Perdigão e7a725dca3 Fix #5562 2024-10-15 21:25:16 -03:00
Bruno Perdigão f763e4b0a7 Remove increment snap from the measure tool. 2024-10-15 10:01:25 -03:00
Andrej730 12742bd08c bim.load_project to support relative paths #5407 2024-10-15 17:57:00 +05:00
Andrej730 8940ec7b80 hide non-ifc objects from relating product dropdown 2024-10-15 17:57:00 +05:00
Andrej730 cb2895cc41 util.shape for materials and material_ids 2024-10-15 17:57:00 +05:00
Andrej730 1facba797d aggregate data - small optimization
check for first BBIM_Linked_Aggregate instead of iterating over all rels
2024-10-15 14:30:49 +05:00
Andrej730 a76e802ab4 aggregate module - remove unnecessary ifc operators 2024-10-15 14:30:49 +05:00
Andrej730 afeec29261 Document bim.aggregate_assign_object 2024-10-15 12:34:07 +05:00
Andrej730 6c573445dd More clever object selection for assigning aggregates #5560
Basically those two properties (Relating Whole and Related Part) are now showing only objects that are valid for the assigning an aggregate - https://i.imgur.com/bqQsXhG.png
2024-10-15 12:34:07 +05:00
Andrej730 f17c2eb80e bim.query_linked_element - close db connection manually
otherwise it seems it was never closed (even if you open some other ifc project in current blender session) and .sqlite file is locked from being deleted (at least on Windows)
2024-10-15 11:28:37 +05:00
Andrej730 0888cbb675 small fix 2aeb87b5f 2024-10-14 17:53:12 +05:00
Andrej730 2aeb87b5fe reuse ifcopenshell.util.shape 2024-10-14 17:37:34 +05:00
Andrej730 79c09ae225 Error appending inspected linked element for detailed meshes #5415
Was resulting in error below for meshes with > 1000 face indices (>~333 tris)

last_error: Traceback (most recent call last):
  File "C:\Users\Ryan Schultz\AppData\Roaming\Blender Foundation\Blender\4.2\extensions\.local\lib\python3.11\site-packages\bonsai\bim\ifc.py", line 408, in execute_ifc_operator
    result = getattr(operator, "_execute")(context)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ryan Schultz\AppData\Roaming\Blender Foundation\Blender\4.2\extensions\.local\lib\python3.11\site-packages\bonsai\bim\module\project\operator.py", line 1858, in _execute
    ifc_file = ifcopenshell.open(queried_obj["ifc_filepath"])
                                 ~~~~~~~~~~~^^^^^^^^^^^^^^^^
KeyError: 'bpy_struct[key]: key "ifc_filepath" not found'
2024-10-14 17:37:29 +05:00
Andrej730 686514b88a fix toggling link visibility after be68a8f #5524 2024-10-14 17:37:29 +05:00
Andrej730 a014cd58e3 fix toggling link selectibility after be68a8f #5524 2024-10-14 17:37:29 +05:00
Andrej730 090c670f04 avoid reimport representation meshes having .001 suffixes 2024-10-14 17:37:29 +05:00
Andrej730 d1b9d9697e document.operator - remove unnecessary ifc operators 2024-10-14 17:37:28 +05:00
Andrej730 fe316e2741 documents ui - hide Name attribute from editing for document references #5542
To avoid invalid ifc.
2024-10-14 17:37:28 +05:00
Andrej730 16553417c1 document.import_references - note about not using Name #5542 2024-10-14 17:37:28 +05:00
Andrej730 fac9444cfd ifc5d - use utf-8 encoding for reading csv files #5561
Same encoding as we use in Ifc5DCsvWriter.
2024-10-14 17:37:28 +05:00
Andrej730 cd8f6e2c78 typing 2024-10-14 17:37:28 +05:00
Andrej730 9e2189fea4 prop_with_search for external styles enum #5569
Ping @Gorgious56 as perhaps you might be interested in this weird case - it seems passing Operator with context_pointer_set makes it OperatorProperties which doesn't have original __annotations__.
2024-10-14 12:23:31 +05:00
Andrej730 5ffef568f7 black . 2024-10-14 12:23:31 +05:00
tim 9ccbd332cf Type Manager fixes
- Corrected the alignment of the Type Manager preview in tool header
- Improved click-ability of the thumbnail icon in the Type Manger preview in the side bar
2024-10-14 11:47:23 +11:00
Ryan Schultz a1fb4d6b81 fix #4051: filter to only show IfcProfileDefs that are attached to IfcMaterialProfiles 2024-10-13 11:24:41 -05:00
Ryan Schultz 2f0500a14b have dimensions like 0 7/8" read like 7/8" 2024-10-13 08:48:21 -05:00
Bruno Perdigão 6f6700db06 Fix bug with mixed snap. 2024-10-11 10:38:15 -03:00
Bruno Perdigão 0235d84f25 Fix small issue with area and length measurement text in polyline tool. 2024-10-11 09:43:23 -03:00
Bruno Perdigão 1225073bef Remove debug print statement 2024-10-11 08:47:39 -03:00
Dion Moult fb714e8fd8 Fix #5482. Reimplement handling of arc detection to allow consecutive arcs. 2024-10-11 21:33:10 +11:00
Dion Moult a0aa5396c9 Purge option for native meshes 2024-10-11 20:18:47 +11:00
Bruno Perdigão 017de3bd59 Fix measurement area text showing in wall polyline 2024-10-10 22:08:19 -03:00
Bruno Perdigão fe5dada256 Fix measurement area text position. 2024-10-10 21:48:11 -03:00
Bruno Perdigão fe0aa4b5b7 Change angle increment for axis snap. 2024-10-10 20:59:57 -03:00
Bruno Perdigão 3a2f29aefc Fix bug in measurement area decorator.
Make input validation accept "m²" and "mm²"
2024-10-10 20:59:57 -03:00
Bruno Perdigão cdaa782c18 Poyline tool - Adds more layers to increment snap base on viewport zoom. 2024-10-10 20:59:57 -03:00
Bruno Perdigão b4d652d12e Fix small issue with snap axis when using measure tool with different planes 2024-10-10 20:59:57 -03:00
Bruno Perdigão 014edcdadc Fix X, Y and Z axis snapping after e673226ea1249a2432ff7b00a7581d750825b544 2024-10-10 20:59:57 -03:00
Bruno Perdigão 3f2efcc846 Fix small issue with increment snap 2024-10-10 20:59:57 -03:00
Bruno Perdigão 095c854d41 Improves angle snapping 2024-10-10 20:59:57 -03:00
Bruno Perdigão dd646d2763 Increment snap now works only for plane and axis snapping. 2024-10-10 20:59:57 -03:00
Dion Moult a32c4ae694 CGAL-Hybrid is now the default. Let's see what happens! 2024-10-11 08:49:42 +11:00
Dion Moult 2e21ec749b Fix #5538. Purge native mesh handling in Blender. This is now obsolete with CGAL-Hybrid. 2024-10-11 08:40:22 +11:00
Thomas Krijnen 189bcd5ad6 Maintain identity and cache styles based on surface-style-shading not styled-item #5486 2024-10-10 16:48:30 +02:00
Dion Moult dc1842dbe8 Fix #5520. Incorrect double calculation of daylight savings and UTC zone. 2024-10-10 22:02:50 +11:00
Dion Moult c75e2e3fc0 Fix failing core tests 2024-10-10 21:36:48 +11:00
Dion Moult 10e76a09de Fix failing MacOS builds 2024-10-10 21:12:35 +11:00
Thomas Krijnen 766f8adce7 nix/build-all propagate BUILD_SHARED_LIBS for -shared build 2024-10-10 09:16:28 +00:00
Dion Moult 47f013fc18 Add support for adding curvelike items 2024-10-10 18:34:20 +11:00
Dion Moult bd42fc9cef Add support for editing curves 2024-10-10 14:45:05 +11:00
Bruno Perdigão 0eb713a7ff Fix #5545 2024-10-09 14:37:04 -03:00
Bruno Perdigão 50c6cbcb2d Polyline tool now shows dimensions for meters and centimeters. 2024-10-09 12:04:45 -03:00
Bruno Perdigão 304db50692 Improved snap hierarchy to allow better face snapping. 2024-10-09 10:41:53 -03:00
Bruno Perdigão 1a55212099 Revert snap stickiness value after changes in increment snap. 2024-10-09 10:28:40 -03:00
Bruno Perdigão ddd17d519e Fix error that was preventing 3d panning while polyline tool is active.
This error was introduced by 48784ba
2024-10-09 10:19:51 -03:00
Bruno Perdigão 481e6b8a8d New implementation for increment snap.
The first implementation was based directly on Blender increment snap.
The new one works just by rounding distance and angle to a better number.
The rounding is still contextual to the window zoom.
2024-10-09 10:14:07 -03:00
Thomas Krijnen d01438e7f1 Retain transform when doing unification in kernel 2024-10-09 13:16:58 +02:00
Thomas Krijnen da0d383666 Distinction between general exception / not supported / not implemented #5484 2024-10-09 13:14:49 +02:00
Thomas Krijnen a38a3ad2fb Fix funky mep geometry #5255 2024-10-09 09:34:52 +02:00
Dion Moult bba862e3ae Fix #5544. Assign / add of objects with styles are now supported. 2024-10-09 18:27:36 +11:00
Dion Moult 11eb1c26f0 Fix #3120. You can now assign styles to individual items. 2024-10-09 18:17:12 +11:00
Dion Moult d09ab54869 Allow reloading of camera geometric representations 2024-10-09 12:26:03 +11:00
Dion Moult aeb00e518b Run black 2024-10-09 12:25:34 +11:00
Dion Moult 844be6bd1c Fix #5231. Remove workaround for missing model-offset in v0.8. 2024-10-09 12:24:25 +11:00
Dion Moult 4f6ca68195 Bump IOS 2024-10-09 11:24:30 +11:00
Bruno Perdigão c33c0b7780 Fix snap to exclude objects that are in a hidden collection. 2024-10-08 18:37:36 -03:00
Bruno Perdigão 7137d95c63 Fix - Mixed snap now gives two snapping points options.
The function was only passing the closest option, but this is not always
the best option. It still defaults to the shortest, but now the user can
select the other option by cycling through snapping points with the "M"
key.
2024-10-08 18:13:24 -03:00
Bruno Perdigão 48784ba834 Polyline tool - user can now change the angle of the snap axis.
- Press "L" while the tool is active to lock axis to the current angle.
- Press "Shift" + "Mouse Wheel" up or down to adjust the angle.

If using with the measure tool it will only work if you have a plane method selected.
2024-10-08 18:13:24 -03:00
Bruno Perdigão fa642e6203 Lower snap axis stickiness. 2024-10-08 18:13:24 -03:00
Bruno Perdigão ee54b3a6f4 Increment snap now works with x, y, z axis snap. 2024-10-08 18:13:24 -03:00
Thomas Krijnen e3223db059 More includes to make gcc happy 2024-10-08 21:04:11 +02:00
Thomas Krijnen b34157e257 Allow returning nativeelement in create_shape() 2024-10-08 20:58:02 +02:00
Thomas Krijnen bfe3601fd1 wkt-use-section option for svg-like occt section cuts instead of polyhedral topology 2024-10-08 20:57:27 +02:00
Kristoffer Andersen cc6249d6cc Add bcf conda-forge badge 2024-10-08 18:26:28 +02:00
Thomas Krijnen 4c2fc55cfe Bring back some v0.7 logic for sweeps over continuous wires #5473 2024-10-08 15:44:51 +02:00
Thomas Krijnen 36a0a0f2dd Work-around for tiny radii sweeps #5474 2024-10-08 14:53:56 +02:00
Dion Moult 89b1f9c2d7 Fix #5527. Unlinking an object should never share its mesh data with IFC elements. 2024-10-08 22:47:22 +11:00
Dion Moult 3c51c6325c Fix #5515. Spaces are now special and have their own collection. Elements in a space don't go inside a space collection anymore.
There can be hundreds of spaces in a building, and generally we use collections for bulk selections (i.e. at the floor level) not for spaces.
2024-10-08 22:35:21 +11:00
Thomas Krijnen fdf4749dd7 Missing include for OSX build 2024-10-08 09:19:29 +02:00
krande 742b3ca120 add ifdef for cgal 6 2024-10-08 09:12:04 +02:00
Dion Moult c85eb79c50 Remove deprecated copy class operator 2024-10-08 17:48:53 +11:00
Dion Moult 1d6b0f781b Fix #5533. Duplicating objects now updates item ids for new item editing workflow. 2024-10-08 17:48:42 +11:00
Dion Moult 32899ebffb Fix #5543. Updating a representation reloads the representation. 2024-10-08 15:45:03 +11:00
Dion Moult 1b321f0747 Fix #5512. Minor fix of console errors in workspace. 2024-10-08 14:32:48 +11:00
Bruno Perdigão 774791cf97 Polyline tool - increment snap now works for imperial units. 2024-10-07 22:28:03 -03:00
Bruno Perdigão c5f27e908a Polyline tool - increment snap implementation. 2024-10-07 22:28:03 -03:00
tim 0f4e4730e2 Progress on Selected Type Preview (#5535)
* Remove length from wall tool

No longer relevant with the new draw method

* Selected Type Preview and Launch Type Manager

Redesign of thumbnail preview

* Update to Type Manager

Moved Create new type to end of paginated loop
Added Predefined type label under thumbnail

* No Types Found

Modified to match Types Manager tiles
Quick Default icon added

* No Types Found

Modified to match Types Manager tiles
Quick Default icon added

* Description in thumbnail linked to value

---------

Co-authored-by: tim <tjrhyder@gmail.com>
2024-10-08 12:24:56 +11:00
Dion Moult 6fb4ce202e Loading shapes now uses the selected geometry library 2024-10-08 12:16:56 +11:00
Dion Moult f66d1bed73 Conveniently preselect object representation template if an object is selected 2024-10-08 12:16:32 +11:00
Dion Moult af3fb78e1b Fix #5526. Fix bug where reloading a representation used by filtered / unloaded elements would fail. 2024-10-08 11:59:04 +11:00
Dion Moult 29d6d2ba97 Fix #5541. Creating an object from a mesh now separates by loose parts to prevent unwanted vertex fusing. 2024-10-08 11:30:40 +11:00
Thomas Krijnen a4226369bd Update type literal 2024-10-07 20:48:58 +02:00
Thomas Krijnen 250fad696e --unify-shapes setting 2024-10-07 20:47:01 +02:00
Thomas Krijnen 461e3d478a Store lowest_z in WKT footprint generation 2024-10-07 20:45:52 +02:00
Thomas Krijnen f3df7b8475 Rerun codegen 2024-10-07 20:43:19 +02:00
Thomas Krijnen aa9b2d7428 populate_derived() upon instance creation, don't only rely on serialization 'hack' #5364 2024-10-07 20:41:34 +02:00
Bruno Perdigão 8e8136ffb6 Fix issue when using "C" to close polyline. 2024-10-07 14:15:42 -03:00
Bruno Perdigão b595eb043e Reverting a change in insert_polyline_point. 2024-10-07 14:07:34 -03:00
Bruno Perdigão 2e6ea4fffb Small fix in polyline input ui decorator. 2024-10-07 14:07:34 -03:00
Bruno Perdigão eef0eb5d43 Bug fix on polyline model decorator when there is no polyline yet. 2024-10-07 14:07:34 -03:00
Bruno Perdigão 9cad7269fd Measure tool - allow for pan, orbit and zoom while tool is active. 2024-10-07 14:07:34 -03:00
Bruno Perdigão 0979c37ba8 Measure tool - center area text horizontally 2024-10-07 14:07:34 -03:00
Bruno Perdigão f9fc563de9 Bug fixes for measure tool in area type with imperial units. 2024-10-07 14:07:34 -03:00
Bruno Perdigão ad74d02165 Measure tool - Removed "Area" from the input UI.
Area is now shows as text decorator since be3354ece063c2c2abcb6f6904df7cd6865dee47
2024-10-07 14:07:34 -03:00
Bruno Perdigão 93457051da Measure tool - show text decorator for polyline area and length. 2024-10-07 14:07:34 -03:00
Bruno Perdigão ce1f1bc394 Bug fix in polyline wall after 95202364a86c8c56f54dde2873b703ac0cc548b4 2024-10-07 14:07:34 -03:00
Bruno Perdigão 0068023c6f Refactor - moved tool/Snap functions that should be in tool/Polyline 2024-10-07 14:07:34 -03:00
Bruno Perdigão 2ea4fc6491 Polyline tool - properties refactor.
Better separation of insertion polyline and measurement polyline
2024-10-07 14:07:34 -03:00
Bruno Perdigão b057f89459 Measure tool - single and area measurement now persist on screen.
Also, the measure polyline properties now stores the area and the total length that will be used by the decorator in later development.
2024-10-07 14:07:33 -03:00
Bruno Perdigão 1a8c11c715 Measure tool - added measurement type to each measurement properties. 2024-10-07 14:07:33 -03:00
Bruno Perdigão cf2a156872 Small refactor. Variable renaming. 2024-10-07 14:07:33 -03:00
Bruno Perdigão 79a8fb1f7f Single measure tool now show x,y and z formatted values. 2024-10-07 14:07:33 -03:00
Bruno Perdigão d4848f26f6 Small refactor 2024-10-07 14:07:33 -03:00
Bruno Perdigão 9b5f20e1dc Initial implementation of measure tool modes: single, polyline and area.
- Single: draws a single measurement that shows the lines and dimensions for x, y and z.
- Polyline: it's how it was already working
- Area: show the area value in the input panel and creates the polygon shape that represents the area. Only works for coplanar points.

The mode can be chosen by clicking the option icon in the workspace menu.
2024-10-07 14:07:33 -03:00
Dion Moult 864cc10b24 Fix #5529. Escape now switches back from item mode to object mode. 2024-10-06 17:34:59 +11:00
Dion Moult 2e7e2d24e4 Fix #5536. Trigger advanced mode by default on large models. Default to unlimited loading, but show warning.
This is a very common complaint: missing elements on large models. It seems as better default is to warn the user that the model is large, but give them the option to filter prior to loading the model.
2024-10-06 17:16:23 +11:00
Dion Moult c10056611b Bump IOS. 2024-10-06 16:13:26 +11:00
Thomas Krijnen 89a078bc50 Test case #5485 2024-10-04 19:12:18 +02:00
Thomas Krijnen 07fda60794 Return edges as planar-component boundaries in CGAL #5485 2024-10-04 19:11:02 +02:00
Andrej730 0935159c42 Restore IFC element menu removed in 23db38d
Example - https://i.imgur.com/1FRgYiQ.png
Restored it until we find some other place for it.
2024-10-04 18:45:40 +05:00
Andrej730 ca9681568c Fix error editing curves based representations #5499
KeyError: 'bpy_struct[key]: key "ios_edges_item_ids" not found'

It's still not possible to edit curve representations, just fixing an error trying to import representation items.
2024-10-04 18:45:40 +05:00
Andrej730 13a6d5b64a Materials UI - suggest MODEL_VIEW context for assigning material style by default
Probably makes more sense than just "Model".
2024-10-04 18:45:39 +05:00
Andrej730 8aa1b68d3e Bonsai - fix issues with default ifcpatch recipe is not loading properly #5540 2024-10-04 18:45:39 +05:00
Andrej730 dc63e989d6 remove try except for ifcpatch import as it's not optional 2024-10-04 18:45:39 +05:00
Andrej730 0cef788a09 Fix console errors after c96c661 (failed to register selection_mode)
Apparently Blender is strict that items should be tuples, not lists. Interestingly enough, though it did failed to register, operator still was working fine.

Example error:
TypeError: EnumProperty(...): expected a tuple containing (identifier, name, description) and optionally an icon name and unique number
ValueError: bpy_struct "BIM_OT_select_container" registration error: 'selection_mode' EnumProperty could not register (see previous error)
2024-10-04 18:45:39 +05:00
Andrej730 38d450e111 Show templates based on selected IFC schema #5530 2024-10-04 18:45:39 +05:00
Andrej730 e5c83b1538 same as 3b71d0050 #5537 2024-10-04 18:45:39 +05:00
Andrej730 9177e19efa Reset proposed property fields after adding custom property #5539 2024-10-04 18:45:38 +05:00
Andrej730 bf9d84e738 typing 2024-10-04 18:45:38 +05:00
Andrej730 2994f5c170 Add a warning if not all project elements were loaded #5536
Example - https://i.imgur.com/Tu3OOIm.png
2024-10-04 18:45:38 +05:00
Andrej730 3107fd91ee Fix issues adding roof and railing representation #5534
Apparently after recent changes with how types are added, it's now required to add a representation for them explicitly instead of just marking them as edited
2024-10-04 18:45:38 +05:00
Andrej730 69781daa6b Materials UI - update material styles data on expanding categories
otherwise style data was missing for materials that were previously hidden
2024-10-04 18:45:38 +05:00
Andrej730 e810dc76e0 Materials UI - support showing styles assigned with IfcPresentationStyleAssignment 2024-10-04 18:45:37 +05:00
Andrej730 cab3fd266d Materials UI - display other styles assigned to material besides IfcSurfaceStyle 2024-10-04 18:45:37 +05:00
Andrej730 62aef09bc7 Fix UI issue when material styles were not reflecting active material #5447
It was reflecting active material but it was only updated when ifc UI data was refreshed (usually after some IFC operators), now it should be always up to date.
2024-10-04 18:45:37 +05:00
Andrej730 2626968a05 materials ui - reuse Material.get_active_material_item 2024-10-04 18:45:37 +05:00
Andrej730 0e6479b090 Show all available styles editing material styles #5525
Previously it would fail e.g. if IfcFillAreaStyle was already assigned to the material but UI was showing errors because enum items contained only surface styles.
2024-10-04 18:45:37 +05:00
Andrej730 7b0a792ff7 bim.merge_identical_objects to support merging IfcMaterials 2024-10-04 18:45:36 +05:00
Andrej730 944e9c45ac black . 2024-10-04 18:45:36 +05:00
tim 99b1f5ec45 Tool header and side panel improvements (#5500)
* Conditions added to show Edit vs Create for each Tool

* Void conditions revised

Apply Voids now only show when number of selected objects ==2, and one of them is a void

* Conditions added to show create vs edit for each tool

example: to edit a wall -> the wall tool must be the active tool and a wall must be selected, to add a wall -> the wall tool must be the active tool and a wall must not be selected

* Extend wall to slab icons added

dark and light mode versions added

* Reset vertex icons added

dark and light mode version added

* Type Manager Preview added

---------

Co-authored-by: tim <tjrhyder@gmail.com>
Co-authored-by: Dion Moult <dion@thinkmoult.com>
2024-10-04 11:02:39 +10:00
Andrej730 3b71d00508 merge_identical_objects - temporarily replace get_info_2 with get_info 2024-10-03 18:37:56 +05:00
Andrej730 c3e4ebd996 bim.merge_identical_objects for merging identical styles
Button location - https://i.imgur.com/3O8gHUn.png

Could also be used as a temporary workaround for #5446
2024-10-03 17:15:34 +05:00
Andrej730 be9c9b2caa fix missing assert statements 2024-10-03 17:15:34 +05:00
Andrej730 306a269061 bim.unlink_style - make it more safe
Even if user decide not to delete style during unlinking, we will create a material copy and relink style to it, so it will be safe to assume that each surface style is always linked to blender material.
2024-10-03 17:15:34 +05:00
Andrej730 392b458563 ifcopenshell.util.element.replace_element 2024-10-03 17:15:34 +05:00
Andrej730 8ae951d27a get_info_2 to support excluding identifier 2024-10-03 17:15:33 +05:00
Andrej730 770e25dbc2 typing 2024-10-03 17:15:33 +05:00
Thomas Krijnen 2c08cff67b Make sure $ chars in TTL are only enclosed in <IRI> not shortened postfixes" 2024-10-03 10:30:53 +02:00
Thomas Krijnen 83c40c7fb4 Don't try to install directories as files (some change in recent cmake?) 2024-10-03 10:30:53 +02:00
Thomas Krijnen 3b9c1d88c8 Handle missing placement location gracefully #5528 2024-10-03 10:30:53 +02:00
Tyler Kvochick 040aec3e52 Derive docker tags from git refs 2024-10-02 17:28:12 +02:00
Thomas Krijnen 8f443a79f3 Merge pull request #5184 from csritter/v0.8.0
Adding --surface-colour in conversion settings to force the use of surface color instead of diffuse color. Issue #5075
2024-10-02 17:24:34 +02:00
Andrej730 3a9598a9d9 bonsai - bim.append_library_element option to skip reusing materials by name
Example - https://imgur.com/PsAPugJ
2024-10-02 18:33:31 +05:00
Andrej730 104b6f5564 append_asset option to avoid assuming unique names for assets #5391 2024-10-02 18:33:31 +05:00
smr02 d5fddd5f1b https://github.com/IfcOpenShell/IfcOpenShell/issues/5511#issuecomment-2388073735 2024-10-02 15:28:58 +02:00
Thomas Krijnen 99ae69f1e4 Don't estimate normal from collinear edges in TTL serializer 2024-10-02 11:12:23 +02:00
Thomas Krijnen b700c5e448 Don't escape $ in TTL output 2024-10-02 11:12:23 +02:00
Andrej730 2a9301ead2 project.append_asset - slight optimization for existing elements search 2024-10-01 18:08:03 +05:00
Andrej730 315d3c6437 ifcopenshell.file.to_string 2024-10-01 18:08:03 +05:00
Andrej730 35f53232b6 typing 2024-10-01 18:08:03 +05:00
Gorgious56 3978226b65 #5514 : Add information as to where to unlock elements in the error tooltip when trying to edit, delelete or move a locked object. Also fix active object / selection discrepancies 2024-10-01 14:14:48 +02:00
Andrej730 c3a6d28927 avoid writing to ifc loading ui elements 2024-10-01 16:50:17 +05:00
Andrej730 0ca3837fc2 update object name changing name from spatial manager #5449 2024-10-01 16:50:13 +05:00
Gorgious56 c96c661394 By default the "Select container" button in the spatial decomposition panel clears current selection before selecting the container. Shift + Click adds the container to selection, ALT + Click removes the container from selection. Added tooltip to the button for keypresses. 2024-10-01 13:38:20 +02:00
Andrej730 a4ac71f9f7 Replace freestyle extension warning with poll message #5472 2024-10-01 16:23:13 +05:00
Andrej730 f63a7d420e style.remove_style to handle IfcFillAreaStyles 2024-10-01 15:38:46 +05:00
Andrej730 19f1c87437 style.remove_style to handle IfcFillAreaStyleHatching 2024-10-01 15:38:46 +05:00
Andrej730 4b39631b98 get_element_by_style to support IfcFillAreaStyleTiles 2024-10-01 15:38:46 +05:00
Andrej730 e040dc4562 get_elements_by_style to support curve styles used in IfcFillAreaStyleHatching 2024-10-01 15:38:45 +05:00
Andrej730 55726b3d50 bonsai - fix breaking ui after style is removed
not sure when this one occurred but ui was breaking since ui blender items were still referring to the deleted ids
2024-10-01 15:38:45 +05:00
Andrej730 f4165d4149 bonsai - fix error removing non-linked styles
including non-ifcsurfacestyle ifcpresentationstyles
2024-10-01 15:38:45 +05:00
Andrej730 b7c390585b ios - fix error removing other IfcPresentationStyles
besides IfcSurfaceStyle
2024-10-01 15:38:45 +05:00
Andrej730 7133b01b76 Count styles based on the current stype type #5462
Previously it was showing number of all IfcPresentationStyles
2024-10-01 15:38:45 +05:00
Andrej730 616a8882d9 bim.load_style - avoid writing to ifc every time 2024-10-01 15:38:45 +05:00
Andrej730 e6e6bd841c project.operator - use pathlib 2024-10-01 15:38:45 +05:00
Andrej730 45ae7634a8 select linked model object when it's loaded 2024-10-01 15:38:45 +05:00
Andrej730 b67be01590 Operator to select link handle
Example - https://imgchest.com/p/md7oxbze97p
2024-10-01 15:38:44 +05:00
Andrej730 06a2c5bf0b Fix linked model decorator not moving for moved linked models (be68a8fdde) 2024-10-01 15:38:44 +05:00
Dion Moult 79b1388e44 Remove Shift-P hotkey 2024-10-01 19:11:40 +10:00
Dion Moult 53765222d6 See #4915. Experimental code for polyhedron without holes 2024-10-01 19:11:08 +10:00
Bruno Perdigão 665afc0375 Wall preview decorator now show tris. 2024-09-30 18:25:09 -03:00
Bruno Perdigão 5129d2016e Fix rebase conflicts 2024-09-30 13:15:19 -03:00
Andrej730 5d83c49fe0 fix saving clash results to bcf #5377 2024-09-30 16:02:52 +05:00
Andrej730 3ad58aba7a ifcclash typing 2024-09-30 16:02:52 +05:00
Andrej730 9131804e4e black . 2024-09-30 16:02:52 +05:00
Thomas Krijnen 6e2e01b460 Fix incomplete swept surface mapping #5484 2024-09-30 12:30:34 +02:00
Thomas Krijnen 5d1dee4480 Apply transformation to swept surfaces in occt advanced brep impl #5484 2024-09-30 12:29:14 +02:00
Thomas Krijnen 62f696da51 Don't handle bspline-edges on planar faces in cgal-kernel #5484 2024-09-30 12:28:28 +02:00
Dion Moult af7bdf6b9f Deprecate type_class in favour of new simpler type manager workflow 2024-09-30 14:04:03 +10:00
Thomas Krijnen 2c22421889 Don't consume token on invalid entity typename #5504 2024-09-29 19:15:29 +02:00
Dion Moult 8a0e87b8f8 Start cleaning up type manager to serve its new purpose as a fancy dropdown 2024-09-29 22:39:21 +10:00
Dion Moult 1bcc7199f6 Redesign BIM tool to have mutually exclusive add/edit modes. 2024-09-29 21:20:17 +10:00
Dion Moult 275d615d42 Shift-A now triggers the wall polyline tool for all LAYER2 elements 2024-09-29 18:11:08 +10:00
Dion Moult 905044f0d7 Shift-A in BIM tools now lets you pick a point interactively. No more 3D cursor requirement.
Still incomplete, but the goal is to not require a "huh?" moment for new users who have no idea what a 3D cursor is.
2024-09-29 17:11:32 +10:00
Thomas Krijnen e2ae2a4a89 Fix negative modelo #5509 2024-09-28 19:44:19 +02:00
Richard Brice abe3d7e5db Fixes problem normalizing IfcDirection direction ratios 2024-09-28 06:19:41 -07:00
Thomas Krijnen dd01cb0e51 BaseUri setting for TTL+WKT 2024-09-28 14:47:08 +02:00
Daniel Bo Olesen 2eecda17e4 Minor updates
Added a debug and run script to the documentation section.  Added a tip and clarifies how to roll back to a previous version, when running unstable release.
2024-09-28 21:48:56 +10:00
Daniel Bo Olesen c45b4372a8 Update writing_docs.rst
Some additions on how to get the local server up and running
2024-09-28 21:48:56 +10:00
Dion Moult 5bb40111c1 Pop up add menu in item mode 2024-09-28 21:22:57 +10:00
Dion Moult faa94eb636 Fix #5466. Support duplicating representation items 2024-09-28 19:39:29 +10:00
Dion Moult 2a6616707c Remove random debug print statements 2024-09-28 17:45:32 +10:00
Dion Moult d1c430cd4d Show clipping plane in front to make it easy to select 2024-09-28 17:35:06 +10:00
Dion Moult a5e6539ddf Support joining representation items 2024-09-28 17:35:06 +10:00
Dion Moult 7bc4b5100b Support separating representation items 2024-09-28 17:35:06 +10:00
Bruno Perdigão 8d08d358af Measure tool persists on screen and can be snapped.
The user has an option to clean previous measurements polylines by pressing "E" while using the measure tool.
2024-09-27 16:48:28 -03:00
Thomas Krijnen 314534436d Add .ttl + Well Known Text geometry serializer 2024-09-27 16:32:47 +02:00
Andrej730 be68a8fdde Support for moving/rotating/scaling for linked models
Example - https://imgchest.com/p/lqye6da2z4d
2024-09-27 19:06:31 +05:00
Andrej730 400ebf2efb bim.append_inspected_linked_element to ensure linked file schema is compatible 2024-09-27 19:06:31 +05:00
Andrej730 0dff19ba6a Project library dropdown - show only libraries compatible with the current schema
To prevent errors trying to append elements from the wrong schema library
2024-09-27 19:06:31 +05:00
Andrej730 24a6ed0e5c Show an error if library file schema is not compatible with the current file
Example - https://i.imgur.com/t1gxBJ4.png ("Schema of library file (IFC4X3_ADD2) is not compatible with the current IFC file (IFC4).")
2024-09-27 19:06:31 +05:00
Andrej730 63ffa1aadb Add upgrade to ifc4/ifc4x3 button to libraries file browser
Example - https://i.imgur.com/cTdwCvt.png
2024-09-27 19:06:31 +05:00
Andrej730 f7bf440848 AbstractKernel::dispatch_curve_creation - use static cast
Similar to 93c4749
2024-09-27 19:06:31 +05:00
Dion Moult 82fd49e4c4 Fix bug when tabbing into empties 2024-09-27 23:14:22 +10:00
Dion Moult 4261fdbed6 Rewrite coordinate offset to use np.array not Vector() for precision 2024-09-27 23:09:00 +10:00
Andrej730 9f02737a2e Fix segfault trying to create IfcSweptDiskSolid with invalid curve #5474
In my case it was IfcIndexedPolyCurve with just 1 vertex. Though kernel->convert does return a boolean value to indicate if conversion was successful, we never used it - so it failed silently leading to segfault later on.
Now we also stop processing those polycurves during mapping stage but checking kernel->convert result still might be useful in some other cases.
2024-09-27 17:00:33 +05:00
Andrej730 fe3b66c044 Stop processing IfcIndexedPolyCurve with < 2 verts at mapping stage #5474
as they're invalid and would't be able to create a curve
2024-09-27 17:00:33 +05:00
Andrej730 14cea7453b Skip failed to load IfcSweptDiskSolid shapes
Noticed in the file attached in #5474 (note that it's not the issue that's causing the segfault), it was failing due IFCSWEPTDISKSOLID's IFCINDEXEDPOLYCURVE having just 1 point, resulting in something like '[Error] [ 14:07:00]  No segment successfully converted: 80=IfcIndexedPolyCurve(79,$)'.

Not sure if this kind of polyline is considered valid in IFC but it doesn't trigger any validation errors, so I guess it shouldn't stop IFC project from loading in BBIM.
2024-09-27 17:00:33 +05:00
Andrej730 cfa2dc5d97 Contexts UI - import Precision as string due problems with Blender UI
Btw this is where you can edit model geometry precision - https://i.imgur.com/CLln0oK.png
Related Blender issue - https://projects.blender.org/blender/blender/issues/128238
2024-09-27 17:00:33 +05:00
Andrej730 123d023bb3 context.operator - remove unnecessary ifc operators 2024-09-27 17:00:33 +05:00
Andrej730 8ff94d3f61 context.data - skip passing unnecessary attributes 2024-09-27 17:00:33 +05:00
Andrej730 3b64350a3f bim.create_shape_from_step_id to include ifc class and id to object name 2024-09-27 17:00:33 +05:00
Andrej730 78302d1583 typing 2024-09-27 17:00:33 +05:00
Dion Moult d93ffb1fe6 See #5491. Clean up orphaned meshes when editing. 2024-09-27 21:59:42 +10:00
Bruno Postle ceeba53c18 Fix linux Associate Bonsai with *.ifc files #5494
The package configuration only included files with extensions, so the
`bonsai` wrapper script was not packaged in the wheel
2024-09-26 22:23:38 +01:00
Andrej730 ecd147675e Ooops, revert wip commit c80c52c248 commited by accident 2024-09-26 22:02:42 +05:00
Andrej730 1cf7f65902 Hide non-simple property types to avoid breaking UI #5496
Property types that are now skipped (at least in IFC4):
<type IfcArcIndex: <list [3:3] of <type IfcPositiveInteger: <type IfcInteger: <integer>>>>> ('list', 'integer')
<type IfcBinary: <binary>> binary
<type IfcComplexNumber: <array [1:2] of <real>>> ('array', 'float')
<type IfcCompoundPlaneAngleMeasure: <list [3:4] of <integer>>> ('list', 'integer')
<type IfcLineIndex: <list [2:?] of <type IfcPositiveInteger: <type IfcInteger: <integer>>>>> ('list', 'integer')
<type IfcPropertySetDefinitionSet: <set [1:?] of <entity IfcPropertySetDefinition>>> ('set', 'entity')
2024-09-26 18:40:52 +05:00
Andrej730 7d8ef3ffd0 Fix invalid IfcRevolvedAreaSolid representations with angle <360 deg
It was always assuming angle is 360 deg
2024-09-26 18:40:52 +05:00
Andrej730 ca5f083481 Fix error trying to tab into IfcRevolvedAreaSolid
by temporary not recognizing reprs with IfcRevolvedAreaSolid as a profile usage
2024-09-26 18:40:52 +05:00
Andrej730 a35304f1d5 lock_object to also lock scales and additional rotations
to indicate that they won't have an effect (or might break things)
2024-09-26 18:40:52 +05:00
Andrej730 c80c52c248 Allow editing poly curve representation items 2024-09-26 18:40:52 +05:00
Andrej730 dd516fb873 Support moving IfcConic representation items
Example - https://imgur.com/a/UDWxXWX
2024-09-26 18:40:52 +05:00
Andrej730 f8680503ef Add default values for IfcEllipseProfileDef 2024-09-26 18:40:51 +05:00
Andrej730 23389dcac0 Update ellipse profile just for consistency with 11deb95 2024-09-26 18:40:51 +05:00
Andrej730 8814d3a22b Lock all representation items that are not movable
Otherwise it was confusing that user can move item but when they exit item mode position was lost
2024-09-26 18:40:51 +05:00
Andrej730 340e8515f5 Fix error switching mode for multiple objects 2024-09-26 18:40:51 +05:00
Andrej730 22b9a8804d notes for loading indexed maps 2024-09-26 18:40:51 +05:00
Andrej730 341b97bce2 typing 2024-09-26 18:40:51 +05:00
Andrej730 24f66bbcb4 black . 2024-09-26 18:40:51 +05:00
Dion Moult a273c87e41 Fix #5416. Optimise item decorator and make decoration more subtle to make it easier to see the mesh. 2024-09-26 23:30:12 +10:00
Dion Moult b01471aa55 See #5491. Don't show items in front. 2024-09-26 23:28:47 +10:00
Dion Moult ebb7f0c8a9 Less in-your-face grid decorations that are easily selectable due to show in front 2024-09-26 23:21:44 +10:00
Ryan Schultz d581174513 Fix #5493: Bonsai, error when using , in drawing names and clicking on the drawing in the sheet part of UI. 2024-09-25 18:36:39 -05:00
Bruno Perdigão 41d5c391e1 Polyline wall - added top and bottom division lines to product preview. 2024-09-25 16:38:33 -03:00
csritter a8157e7dd6 Merge branch 'v0.8.0' into v0.8.0 2024-09-25 11:20:47 -03:00
Andrej730 4e33569851 ifc join to support joining 3d polyline curves 2024-09-25 19:09:15 +05:00
Andrej730 761795ccbf ifc join to show error message if joining is not supported
Example - https://i.imgur.com/5vsmJN8.png
2024-09-25 19:09:15 +05:00
Andrej730 95e9b8aeef Import representation items for curve representations too
https://i.imgur.com/TeITxa0.png
2024-09-25 19:09:14 +05:00
Andrej730 dd9de98290 Store edges representation item ids in Triangulation 2024-09-25 19:09:14 +05:00
Andrej730 aad66f94a3 rename addEdge overload to registerEdgeCount
So it won't be confused with addEdge that actually does add an edge to edges_.
2024-09-25 19:09:14 +05:00
Andrej730 6ac40b4ab3 typing 2024-09-25 19:09:14 +05:00
Dion Moult fce7b4416e Forgot to handle cases where no object is selected when adding a new element 2024-09-25 23:56:18 +10:00
Dion Moult 42f32e3418 Fix #5460. Assigning a class now uses the new add element mode internally. 2024-09-25 23:48:44 +10:00
Dion Moult 47581f2316 Hooray! New add element means we no longer do this silly "add cube" and delete when adding occurrences. 2024-09-25 23:47:18 +10:00
Dion Moult c68c621400 Loading and saving extrusion items now take into account georef cartesian point offsets 2024-09-25 23:03:06 +10:00
Andrej730 61151442cf Merge branch 'bonsai-bump-macos' into v0.8.0 2024-09-25 14:00:17 +05:00
Andrej730 7b36f93973 remove debug logging 2024-09-25 13:59:55 +05:00
Andrej730 5952ce8ed3 disable_item_mode - to set previously edited object as active
It seems very natural that after exiting item mode the edited item should become active (similar to how it works in edit mode).
2024-09-25 13:59:55 +05:00
Andrej730 3c309bbac8 load_indexed_colour_map - to support loading colors for rep items
Enter item mode for simple faceset cube was failing because this wasn't supported.
2024-09-25 13:59:55 +05:00
Andrej730 3e3b133c7b black . 2024-09-25 13:59:55 +05:00
Andrej730 0af2ab53a0 bonsai makefile update regex to keep track of x86_64 version automatically 2024-09-25 13:45:37 +05:00
Andrej730 700a453501 fix breaking bonsai builds - bump macos to 10.13 for python 3.12
Recently released Python 3.12.6 dropped support for Mac OS 10.9-10.12 - https://www.python.org/downloads/release/python-3126/

And Python 3.12.6 is the one that's used by compiled builds from now - in our case it was fonttools (used by ezdxf) that compiled binaries and it's using cibuildwheel which is also started using Python 3.12.6 as it's released.
2024-09-25 13:45:32 +05:00
Jason Hilton e45b41c04b fix: compile errors qt app
I was able to hardcode load an ifc file, by uncommenting the hard
coded parse ifcfile, but I was unable to open and load files with the
qt menu.
2024-09-25 10:22:14 +02:00
Dion Moult 86367e9c1f Loading and saving meshlike items now take into account georef cartesian point offsets 2024-09-25 17:46:59 +10:00
Dion Moult 9af9120dff Fix bug where switching representations didn't take into account georef cartesian point offsets 2024-09-25 17:46:15 +10:00
Dion Moult dc5e3d86b4 Lazy optimisation to prioritise styledbyitem instead of indexed maps. Allow blank data_index in case we have multiple rep items. 2024-09-25 13:00:14 +10:00
Daniel Bo Olesen 4472578915 Changed tools tips for commands. 2024-09-25 11:59:01 +10:00
Dion Moult 9ede6a693d See #5475. Fix quoting in dev script and default to Github repo. 2024-09-25 11:26:43 +10:00
Dion Moult 7584a40219 Fix #5483. Units is optional when loading. 2024-09-25 11:13:09 +10:00
Dion Moult 1d4f5de4a0 Fix #5475. Quote paths to accommodate spaces in dev setup. 2024-09-25 10:39:12 +10:00
dylcos fa92d3bd59 Update code_examples.rst
Replaced "product=wall" with "products=[wall]" in:
# Place our wall in the ground floor
ifcopenshell.api.spatial.assign_container(model, relating_structure=storey, products=[wall])
As code example fails otherwise
2024-09-25 09:36:25 +10:00
Bruno Perdigão d868eeb77d Updates on polyline decorator to match standard colors. 2024-09-24 17:30:34 -03:00
Bruno Perdigão 083a1e4074 Small fix in polyline decorator. 2024-09-24 13:55:14 -03:00
Bruno Perdigão ef5dc58b91 Fix some cases where wall joining were not working after they were created by polyline tool. 2024-09-24 13:47:21 -03:00
Bruno Perdigão c4232e7407 small fix on 36b4225b1 2024-09-24 11:40:47 -03:00
Andrej730 209c0fef57 restore lost code after a1d99b5 2024-09-24 19:30:17 +05:00
Andrej730 d4bc34dea7 ifc2sql - remove debug print statements 2024-09-24 19:30:08 +05:00
Andrej730 0ce92587bf ifc2sql - add test 2024-09-24 19:30:08 +05:00
Andrej730 56de208470 ifcopenshell.sql - add simple test 2024-09-24 19:30:08 +05:00
Andrej730 266416226b ifcopenshell.sql - repr for entities 2024-09-24 19:30:08 +05:00
Andrej730 810f42ea24 ifc2sql - clarify how output works in docs, add a suffix to temp file 2024-09-24 19:30:08 +05:00
Andrej730 21dd5054e6 ifcopenshell.sql - fix error in by_id method
it was fetching some random row from id_map instead of using ifc_id filter
2024-09-24 19:30:07 +05:00
Andrej730 08e221fe93 ifcopenshell.sql - garbage collection errors (same as fe1dff0191) 2024-09-24 19:30:07 +05:00
Andrej730 c7e97d06bd ifcopenshell.sql - fix error opening files similar to #5457 2024-09-24 19:30:07 +05:00
Andrej730 46cc3a449a ifcopenshell.sql - handle non existing files
previously it would create an empty database and give a confusing error "AssertionError: SQLite schema not supported."
2024-09-24 19:30:07 +05:00
Andrej730 9e86d83616 ifcopenshell.sql - typing 2024-09-24 19:30:07 +05:00
Andrej730 2829b7daf6 ifcopenshell.stream - remove unrelated code from ifcopenshell.sql 2024-09-24 19:30:07 +05:00
Andrej730 86ec618327 ifcopenshell.stream - add simple test 2024-09-24 19:30:07 +05:00
Andrej730 9a23daf7b3 stream - add support of crlf files 2024-09-24 19:30:07 +05:00
Andrej730 4e3d6f1773 typing 2024-09-24 19:30:07 +05:00
Andrej730 7045fba9c0 black . 2024-09-24 19:30:00 +05:00
Bruno Perdigão 36b4225b18 Warning messages for prohibit cases when inserting polyline points 2024-09-24 10:55:59 -03:00
Bruno Perdigão b05e6cf71a Small fix 2024-09-24 10:55:54 -03:00
myoualid 7692b910f4 loading multiple cost schedules in the web ui is now more responsive, clean up and organise css code #5369 2024-09-24 12:13:18 +01:00
Thomas Krijnen 0c70d4c828 Manually detect facet boundary intersections before triangulation #5470 2024-09-24 13:09:30 +02:00
Thomas Krijnen 11deb955f8 Fix ellipse major < minor workaround #5470 2024-09-24 13:09:30 +02:00
Dion Moult 036754ea20 Bump IOS to OCC 7.8.1 2024-09-24 18:50:07 +10:00
Thomas Krijnen 2557fcf628 Do let cgal handle planar adv brep #4915 2024-09-24 08:54:52 +02:00
Dion Moult 4bee80edc5 Optimise array setup during load 2024-09-24 15:31:55 +10:00
Dion Moult d1c4a0a415 Check walls first for false origin guessing for speed, checking one object seems to be enough 2024-09-24 15:31:37 +10:00
Dion Moult f92a02cfcb Fix regression in speed in collection assignment
As hinted in the TODO note for linking collections safely, try-catch is actually much faster. This brings it to 10% faster than 0.7 speeds. Previously the regression made it 10x slower.
2024-09-24 14:54:25 +10:00
Dion Moult ff5c402750 Optimisation for not iterating through things with no representations
Iterator initialise can take a few seconds on large models even though you're just doing a few elements which have no representations.
2024-09-24 14:54:25 +10:00
Bruno Perdigão 2151035afd Small fix in Raycast function ray_cast_by_proximity. 2024-09-23 22:46:36 -03:00
Bruno Perdigão cc11c43240 Fix raycast to detect objects with partial visibility in the scene. 2024-09-23 22:37:37 -03:00
Bruno Perdigão 7339325cc9 Fix #5464 2024-09-23 22:25:28 -03:00
Bruno Perdigão 3c2a0c9bf3 Fixed issue with polyline inserting point at world origin (0, 0, 0). 2024-09-23 17:13:57 -03:00
Bruno Perdigão 98d767988e Added support to snap on empty objects. 2024-09-23 17:04:42 -03:00
myoualid 7b2a30e5b7 web-ui: fix classifications file navigation 2024-09-23 20:41:26 +01:00
myoualid 455012de4c cost web ui:
- add "Linked rate" column,
- assign a cost rate to multiple cost items by selecting linked rate cells & clicking the "assign" button on the chosen cost rate
#5369
2024-09-23 20:19:06 +01:00
Andrej730 ab8a6b80e4 debug module - remove unnecessary ifc operators 2024-09-23 19:33:36 +05:00
Andrej730 acd1b165f8 bim.create_shape_from_step_id to support different geometric libraries 2024-09-23 19:33:29 +05:00
Andrej730 fe1dff0191 ifcopenshell.stream - fix garbage collection errors
Mentioined in #5457

Errors such as:
Exception ignored in: <function file.__del__ at 0x7f4cfcc9f920>
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/ifcopenshell/file.py", line 284, in __del__
    del file_dict[self.file_pointer()]
                  ^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/ifcopenshell/file.py", line 444, in __getattr__
    return getattr(self.wrapped_data, attr)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'file_pointer'
2024-09-23 19:33:28 +05:00
Andrej730 08bba92b2e fix opening ifc files with streaming #5457 2024-09-23 19:33:28 +05:00
Andrej730 7e6be53237 Improve error messages for shapes failed to process
Example error messages now:

RuntimeError: Failed to process shape. Product: #3855=IfcSite('3ZGD7y6S5209$mGLi_sPll',#20,'Surface:411452',$,$,#3854,#3850,$,.ELEMENT.,(42,12,46,799999),(-71,-2,0,-599999),0.,$,$), representation: #3849=IfcShapeRepresentation(#93,'FootPrint','Curve2D',(#3841,#31427,#31471,#45600,#45628))

RuntimeError: Failed to process shape. Instance: #3841=IfcPolyline((#3800,#3801,#3802,#3803,#3804,#3805,#3806,#3807,#3808,#3809,#3810,#3811,#3812,#3813,#3814,#3815,#3816,#3817,#3818,#3819,#3820,#3821,#3822,#3823,#3824,#3825,#3826,#3827,#3828,#3829,#3830,#3831,#3832,#3833,#3834,#3835,#3836,#3837,#3838,#3839,#3840,#3800))
2024-09-23 19:33:28 +05:00
Andrej730 c6c9f400d3 BBIM Parametric psets - show warning when user edits them manually
as they are not intended to be edited manually but through the special ui

example - https://i.imgur.com/nsuy0I0.png
2024-09-23 19:33:28 +05:00
Andrej730 2b35e5fb91 Make parametric doors/windows available for ifc2x3 2024-09-23 19:33:28 +05:00
Andrej730 e7dd186349 Fix roof tooltip in templates 2024-09-23 19:33:27 +05:00
Andrej730 0091f5c09b Simplify spatial elements sorting 2024-09-23 19:33:27 +05:00
Andrej730 c33e2fc689 Fix #5320 2024-09-23 19:33:27 +05:00
Andrej730 df055cefd4 typing 2024-09-23 19:33:27 +05:00
Andrej730 65f9a745a3 black . 2024-09-23 19:33:27 +05:00
Thomas Krijnen a51ed6e6b3 Fixes for using hybrid kernel on non-products #5443 2024-09-23 16:18:00 +02:00
Gorgious56 aaf5fde92e Fix error when the "Add Parametric Window" button is drawn 2024-09-23 16:03:34 +02:00
Thomas Krijnen 0389f1e984 Make cgal implementation a little bit less confident #5453 2024-09-23 16:03:10 +02:00
Dion Moult 84ceb11584 Minor fix 2024-09-23 23:55:15 +10:00
Dion Moult 0426c8e115 Adding an occurrence of a non-geometric type now lets you choose the type of geometry to add 2024-09-23 23:49:34 +10:00
Thomas Krijnen a9ca4e7366 Mark status when parsing is terminated 2024-09-23 15:24:28 +02:00
Thomas Krijnen e4d1118124 Manually write out if-statements instead of visit with if-constexpr #5444 2024-09-23 15:10:37 +02:00
Gorgious56 f2efa53fdf Fix #5456 : Unbound variable error when no snap decorator is drawn 2024-09-23 11:34:35 +02:00
Dion Moult 23db38d0e9 Finally, a way to actually add an IFC element directly
Previously, the way to add an IFC element would be to 1) create a blender element then assign or 2) activate bim tool, launch type manager, click create type, fill out field, or 3) using various menus for parametric stuff like stairs. This is now the new proposed way to do things and everything will consolidate to here - and it allows you to directly create non-mesh geometry immediately too!
2024-09-23 18:21:44 +10:00
Dion Moult 194acb078c See #3707. See #5445. Type now launches type manager, and type manager icons are clickable.
Previously you could either use the dropdown, or launch the type manager, but now they are one and the same, and more inuitive to click icons.
2024-09-23 18:18:44 +10:00
Dion Moult c30ac2d061 Slightly more accurate loading time to include initialisation time 2024-09-23 18:14:52 +10:00
tim 621393e67a Toggle openings typo 2024-09-23 18:13:24 +10:00
tim 2386b935aa Toggle openings icons
renamed png files to match operator name
2024-09-23 18:13:24 +10:00
tim 0071fa515a Apply void icons
This is a temporary fix
2024-09-23 18:13:24 +10:00
Thomas Krijnen 154059126c Update build-all.py - reset --hard before checkout 2024-09-23 09:16:24 +02:00
Thomas Krijnen 4c048e4695 Update face.cpp - snail artefact on 7.8 as well #4924 2024-09-23 09:12:10 +02:00
Thomas Krijnen 4ce3413cdf Update build-all.py - fetch before checkout 2024-09-23 06:52:49 +02:00
myoualid 33d8ecdc8b smart copy paste option for cost schedules in web ui - #5369 2024-09-23 03:21:15 +01:00
myoualid 193daff617 web-ui: enable assigning parametric quantities from queries #5369 2024-09-23 02:21:15 +01:00
myoualid 9f542c30b3 cost module web ui:
- add setting options to hide/show columns
- Cost classification column
- New Cost Classification Form to display active classification library, add/delete classification references
2024-09-22 20:00:09 +01:00
Manu Varkey a053472558 Fixes #5320 2024-09-22 22:19:49 +10:00
Dion Moult 14fe3e6150 Rewrite mode switching from object to item to edit modes 2024-09-22 22:17:07 +10:00
mrfcoelho df494a3def Update create_model.rst
Fix minor typo
2024-09-22 08:32:20 +10:00
mrfcoelho ff7c7932e1 Update installation.rst
Fix broken link
2024-09-22 08:32:06 +10:00
Dion Moult 9ea44f0a89 You can now add new swept area solid items 2024-09-21 21:27:17 +10:00
Dion Moult ce010f1e56 You can now add new mesh representation items 2024-09-21 16:34:41 +10:00
Dion Moult 2a8d43c42c Basic editing of item attributes implemented 2024-09-21 14:27:17 +10:00
tim ef412c36c6 Cancel and Apply buttons (#5435)
* Cancel button added back in, Green apply replaced with CHECKMARK

* 2-point arc icon added

---------

Co-authored-by: tim <tjrhyder@gmail.com>
2024-09-21 13:48:33 +10:00
myoualid 8c4ab5bf03 enable displaying schedule of rates - web ui ref #5369 2024-09-21 00:16:11 +01:00
Thomas Krijnen e0095cd446 occt 7.8.1 #4924 2024-09-20 20:49:22 +02:00
Gorgious56 ea3f5cea1f Fix parametric stairs not appearing in the type manager templates 2024-09-20 20:26:03 +02:00
Andrej730 a3c0523fbd Fix #5432 2024-09-20 22:56:59 +05:00
Andrej730 c819368445 code_style.rst - some notes on black formatting 2024-09-20 22:11:15 +05:00
Andrej730 287f08dc7b bim.print_unused_elements_stats to ignore IfcIndexedTextureMap 2024-09-20 22:03:20 +05:00
Andrej730 5ce9d21dff Purging styles to also purge associated blender materials #3914 2024-09-20 22:03:19 +05:00
Andrej730 d4df21c4be ifcopenshell.util.shape.get_normals 2024-09-20 22:03:19 +05:00
Andrej730 95e76c3ab9 bsdd classes - typing for not required attributes 2024-09-20 22:03:19 +05:00
Andrej730 18476ec7f3 bsdd - update classes according to the latest API
Also added yml_to_classes.py script that can extract the classes automatically
2024-09-20 22:03:19 +05:00
Andrej730 aeeae7365f load bsdd classes recursively if query fetches more than 100 items
previously it would just hit the limit 100 and stop
2024-09-20 22:03:19 +05:00
Andrej730 9953ce1b39 typing 2024-09-20 22:03:19 +05:00
Andrej730 d7adec3d54 black . 2024-09-20 22:03:19 +05:00
myoualid e0e9892ff0 cost module web-ui:
- remove Blender operators in favor of ifc.api functions
- replace BonsaiBIM Data class dependency with new ifc5D2json script
- enable viewing multiple cost schedules
- add Identifaction column
ref #5369
2024-09-20 16:26:40 +01:00
tim e8f66abf17 New and updated icons for CAD and BIM workspace
* Updates to some icons, new icons added for CAD tools, and new layout for CAD tools

* updates to icons

* WIP changes to BIM Tool UI

* Separated BimToolUI,  added Draw wall icon

Separated BimToolUI into AddElementUI and ModifySelectedUI classes, added Draw wall icon

* Voids back in UI

* WIP UI tools and icons

partial support for draw wall tool added

* 40d95c294 WIP UI tools and icons

Minor tweaks

* WIP on profile-axis-ui

* WIP on profile-axis-ui

* Added Merge, Split, Rotate, and Flip back into wall edit tools

* Separators added

* Restore commented out code in CAD workspace.py

---------

Co-authored-by: tim <tjrhyder@gmail.com>
Co-authored-by: Dion Moult <dion@thinkmoult.com>
2024-09-20 22:16:40 +10:00
mrfcoelho 560983c6b8 Update interface.rst
Add minor tip to be able to see all the workspaces when the screen size is small.
2024-09-20 21:55:06 +10:00
Gorgious56 07291022b4 Fix purging types in the type manager not working. The purge button is now in a menu for a cleaner interface and avoiding accidentally clicking on it when opening the type manager. 2024-09-20 12:09:55 +02:00
Andrej730 6d94871683 Attribute.data_type -> EnumProperty (+typing) 2024-09-20 13:17:41 +05:00
Andrej730 774db8e997 sort wheel files list in manifest 2024-09-20 13:17:27 +05:00
Manu Varkey 31d49a7bbc Update drawing shadow settings for consistentency 2024-09-20 18:10:26 +10:00
Dion Moult 542ae6b44a Basic support for editing swept profiles and positions 2024-09-20 18:08:16 +10:00
Gorgious56 c1a92bf1f3 Fix #5398 : Only show relevant parametric templates in the type manager. Also fix forgotten line in previous commit. 2024-09-20 09:58:26 +02:00
Gorgious56 a8abc8e379 Fix #5333 : Searching for the class name using the looking glass button doesn't close the type manager anymore. 2024-09-20 09:53:00 +02:00
Andrej730 4f64d044ac Option to assign non-ifc bsdd properties #5404
Example - https://imgur.com/a/cPtEkX2

Also Attribute now has additional field "metadata" for storing some case specific data
2024-09-20 12:34:27 +05:00
Andrej730 1f4d973a79 black . 2024-09-20 12:34:26 +05:00
Dion Moult bfd5b3c1c7 Increase websocket server limit from 1MB to 10MB to allow for larger datasets like large work schedules. 2024-09-20 17:03:46 +10:00
Dion Moult 8866a34f22 Fix #5408. Use an angular tolerance of 0.1 degrees to determine if something has moved and need resyncing. 2024-09-20 17:03:00 +10:00
Andrej730 669d88fbb1 sequence - fix all import operators missing Ifc operator #5423 2024-09-20 11:14:34 +05:00
Andrej730 7470fb0786 sequence - remove unnecessary Ifc operators 2024-09-20 11:14:34 +05:00
Andrej730 b6fca3916e assigning process to control - add an error message 2024-09-20 11:14:34 +05:00
Andrej730 5373c7ee9e sequence import/export - add info message when operator finished 2024-09-20 11:14:34 +05:00
Manu Varkey f708d9cb4d Support natural sorting of types closes #5050 2024-09-20 09:20:03 +10:00
Andrej730 f1f055d19d Restore missing dev docs after 53d7624 2024-09-19 18:56:45 +05:00
Andrej730 e175de5365 Fix misleading docs urls after 53d7624 2024-09-19 18:56:45 +05:00
Andrej730 31befd424b Fix documentation missing dev env scripts
Mentioned in #5398
2024-09-19 18:56:45 +05:00
Andrej730 394b24ddfe More realistic test for ca8577a8dd 2024-09-19 18:24:37 +05:00
Andrej730 f184ce5386 Support de08d3726e for ifc2x3 #5420 2024-09-19 18:13:14 +05:00
Andrej730 b7d725254d Temporarily revert 51211dc527 to fix broken bonsai builds #4924
Need to not to forget to revert a revert later...
2024-09-19 17:30:10 +05:00
Andrej730 c9f9cf89e8 file -> import/export - add poll messages in case ifc is not loaded 2024-09-19 17:21:51 +05:00
Andrej730 fb6d2b8de2 pp2ifc - preserve original ids
Now we're going to use bar ids instead their detalization ids (e.g. expanded task ids, task ids, milestone ids) because it is the way how it works in the software pp file originates from.
2024-09-19 17:21:51 +05:00
Andrej730 ddca950f65 pp2ifc - save calendar identification for pp file to ifc 2024-09-19 17:21:51 +05:00
Andrej730 96756d63d4 pp2ifc refactor and add support for more languages #5417 2024-09-19 17:21:50 +05:00
Andrej730 a5b3c9beb4 black . 2024-09-19 17:21:50 +05:00
Gorgious56 1974974071 Fix #5410 : bim.enable_adding_presentation_style no longer throws an error in a file with no ifc project when launching the search operator (F3) 2024-09-19 14:03:56 +02:00
Manu Varkey 4225643bc0 Disable blf shadow setting after use. Fixes #5387 2024-09-19 21:49:58 +10:00
Dion Moult 4b7bb1533e Fix #5394. Fix bug when switching fillings where the current representation was not the body representation. 2024-09-19 16:25:33 +10:00
Dion Moult d3fdbf4dae (Un)Bump IOS - downgrade due to critical bugs with OCC 7.7 2024-09-19 11:12:11 +10:00
Dion Moult 5d0fb18ea1 Fix #5395. Apparently wheels exclude directories with no files in them, so the cache folder wasn't shipped. 2024-09-19 10:59:32 +10:00
myoualid 45708ee287 Cost module web UI:
- quick button to add a SUM cost value
- style improvements
2024-09-18 20:34:31 +01:00
Thomas Krijnen 116a0f1a02 Add test 2024-09-18 19:28:55 +02:00
Thomas Krijnen 2554280e50 triangulation-type setting for non-triangulated polyhedral from iterator 2024-09-18 19:28:07 +02:00
Andrej730 748fcce3f5 Adding classification reference tests 2024-09-18 18:44:34 +05:00
Andrej730 5b2733bb3c add classification reference from bsdd - support ObjectType
it seems in bsdd some ObjectType is also provided using "undefined_set" pset
example - https://identifier.buildingsmart.org/uri/ifcairport/ifcairport/1.0/class/ifcairport0000000004
2024-09-18 18:44:34 +05:00
Andrej730 115a48fc1a bsdd - fix bug when loading pset would set properties in incorrect way
It was using name instead of propertyCode which was leading to assigning incorrect properties...
2024-09-18 18:44:34 +05:00
Andrej730 06d927f8bb bsdd operators descriptions and naming 2024-09-18 18:44:34 +05:00
Andrej730 de08d3726e Bonsai - set active bsdd when loading project
When loading an ifc project it will search it for bsdd ifcclassifications and will set one as active if finds it, so now it will be a bit more convenient working with bsdd classification assignment as it active bsdd previously was always getting reset when you reload ifc file.

Example - https://imgur.com/a/stlJqwm
2024-09-18 18:44:34 +05:00
Andrej730 4dbfeefe53 Fix UI errors getting elements using qset in IFC2X3
In IFC2X3 IfcQuantitySet didn't existed yet
Mentioned in #5404
2024-09-18 18:44:33 +05:00
Andrej730 eb823a5ecd bsdd search to check whether query is long enough
It's an API requirement and using shorter queries was giving confusing results.
https://github.com/buildingSMART/bSDD/blob/master/Documentation/bSDD%20OpenAPI.yaml
2024-09-18 18:44:33 +05:00
Andrej730 8f7949808a Move id to IfcGeom::Representation::Representation and document it
as it's a common attribute for all 3 Representation subclasses we have
2024-09-18 18:44:33 +05:00
Andrej730 5860c3fe50 black . 2024-09-18 18:44:33 +05:00
Dion Moult dbfa4ecf65 Fix minor regression in fe0be0c 2024-09-18 22:58:22 +10:00
Dion Moult 1320eac800 Switch representation now cleans up orphaned meshes itself so callers don't need that responsibility 2024-09-18 22:58:22 +10:00
ArturTomczak 81e4ad2ce2 handle numeric simpleValue (#5376)
The input value can be a string or number, but 1.0 schema only accepts strings. The processing of int and float was missing. The casting to string might no longer be needed in IDS 1.1. https://github.com/buildingSMART/IDS/issues/342
2024-09-18 21:42:31 +10:00
Dion Moult 736d91f38e Shape builder now supportes meshy things and faceted breps 2024-09-18 21:35:40 +10:00
Dion Moult a1d99b544a Basic support for deleting items, and editing meshlike items 2024-09-18 21:35:40 +10:00
Dion Moult ed530f737c Remove deprecated code for fixed bug #2002. 2024-09-18 21:35:40 +10:00
Dion Moult 0899a2a87b Fix bug where switching geometry may not correctly share representations 2024-09-18 21:35:40 +10:00
Thomas Krijnen 3bdbb3d513 Don't import cwd ifcopenshell folder when running tests 2024-09-18 11:35:24 +02:00
Andrej730 e22ec57e16 Fix #5409 2024-09-18 13:56:06 +05:00
Dion Moult 9b06797efa Fix crash when removing representation item with removed inverses 2024-09-18 17:35:51 +10:00
Dion Moult 96ba8e8e29 Fix bug where dissolving edges created corrupted geometry for advanced breps with curved surfaces 2024-09-18 17:34:41 +10:00
Bruno Postle 6e9e270683 IfcGit don't switch colouring so much closes #5402
Viewing changes necessarily sets object colours and switches the
viewport to object colouring.  Previously most other operations switched
the viewport 'back' to material colouring. This was an annoyance for
users whose workflow makes use of manual object colouring.

Now only operators that reload the model (revert, switch and merge), the
refresh button, and attempting to view changes with the current revision
switch to material colouring.
2024-09-17 23:34:04 +01:00
Andrej730 53a6192858 Skip loading mappings if representation has openings #5405
To avoid errors
2024-09-17 18:25:59 +05:00
Andrej730 2a2efefac3 IfcSchema declaration_by_name to be safe
Couldn't find if we actually use it anywhere in the code but better to keep it safe, especially because it's exposed to Python and by accident user might provide some too bit integer instead of a string.
2024-09-17 16:28:02 +05:00
Andrej730 a7cac5c77b IfcWrap cmake - regenerate .py and .cxx on changes in ifcopenshell libs
Previously they wouldn't be regenerated unless you edit .i files or manually remove .py/.cxx.
2024-09-17 16:28:01 +05:00
Andrej730 1575696a8b ifcwrap cmake - use default CMP0078 policy
Something weird happened during merge in 7d90c31 and changes from 0055a5d were not applied
2024-09-17 16:28:01 +05:00
Thomas Krijnen 555eb44f00 Add IfcAlignmentSegments to XML output 2024-09-17 13:07:33 +02:00
Thomas Krijnen 0b555b30d2 Add IfcAlignmentSegments to XML output 2024-09-17 13:03:25 +02:00
Andrej730 06f14774f7 Avoid more unnecessary calls to docs api
Noticed that prop_value could be other types besides str (e.g. int when using context menu on UIList item) and we can skip them to avoid redundant api calls.
2024-09-16 18:54:13 +05:00
Andrej730 11ddcb0256 IfcSchema declaration_by_name to use size_t instead of int
By accident noticed that `declaration_by_name(-1)` crashes python. If we use size_t it will just throw an error like below

NotImplementedError: Wrong number or type of arguments for overloaded function 'schema_definition_declaration_by_name'.
  Possible C/C++ prototypes are:
    IfcParse::schema_definition::declaration_by_name(std::string const &) const
    IfcParse::schema_definition::declaration_by_name(size_t) const
2024-09-16 18:54:13 +05:00
Andrej730 0d77ff5270 remove debug code 2024-09-16 18:54:13 +05:00
Andrej730 c75fa70d23 Support for loading face colors from ifc (IfcIndexedColourMap)
example - https://imgur.com/a/l8Yn4Rr
2024-09-16 18:54:13 +05:00
Andrej730 6d8ffc27cc ifcopenshell.util.shape.get_material_colors 2024-09-16 18:54:13 +05:00
Andrej730 531327578f bim.print_unused_elements_stats - to skip colour map 2024-09-16 18:54:12 +05:00
Andrej730 6a47e68b78 fix typo 2024-09-16 18:54:12 +05:00
Andrej730 5ec10018d9 bim.purge_unused_elements_by_class - skip IfcRepresentationContext 2024-09-16 18:54:12 +05:00
Andrej730 ec0094ef33 bim.purge_unused_elements_by_class - keep list sorted 2024-09-16 18:54:12 +05:00
Andrej730 a2c2cf65a1 bim.purge_unused_elements_by_class - make filepath argument optional 2024-09-16 18:54:12 +05:00
Andrej730 cfd63392e7 Add to recent projects when project is saved 2024-09-16 18:54:12 +05:00
Andrej730 0891df5d6c typing 2024-09-16 18:54:12 +05:00
Bruno Postle cf95c9151c black formatting after 71de39e 2024-09-15 17:34:44 +01:00
Bruno Postle 71de39ea7c Recover external git repo changes, fixes #5311
IfcGit didn't cope gracefully when commits and/or repositories vanished
unexpectedly
2024-09-15 17:24:36 +01:00
Andrej730 c487643d76 ifcgit - fix errors if paths are mixing up slashes and backslashes
`repo.path` is always setup using current platform type of slashes since it's normalized by get_path_dir but when we pass a path to index.add it's not normalized leading to errors
2024-09-14 11:41:58 +05:00
Andrej730 6dbfb3afb3 black format 2024-09-14 11:41:58 +05:00
Bruno Perdigão aa3a362391 Fixed issue in polyline tools where orbit and pan where not updating the ray cast. 2024-09-13 17:35:08 -03:00
Bruno Perdigão a2cf95038a Custom snap symbols #5325. 2024-09-13 17:34:08 -03:00
Bruno Perdigão 96f3ee2f3a Added text background to polyline measurements. 2024-09-13 15:38:05 -03:00
Bruno Perdigão 1659498c88 Fix 'C' to trigger wall preview 2024-09-13 14:08:18 -03:00
Bruno Perdigão a992844e93 Fix enter to trigger wall preview 2024-09-13 13:50:27 -03:00
Bruno Perdigão 59b665758d Colors update in polyline decorators. 2024-09-13 12:38:35 -03:00
Bruno Perdigão 4dc8a27e82 Fix on polyline wall preview when dealing with closed loops. 2024-09-13 12:38:35 -03:00
Bruno Perdigão e83bdcc820 Polyline tool - Wall preview is now working for angled walls. 2024-09-13 12:38:35 -03:00
Bruno Perdigão 7ea3d63aa0 Small fix to clear wall preview when deleting all polyline points. 2024-09-13 12:38:35 -03:00
Bruno Perdigão bd51363532 Small fix related to trying to use polyline wall without wall type. 2024-09-13 12:38:35 -03:00
Bruno Perdigão d4ccc0dff9 More fixes related to d5b20397a 2024-09-13 12:38:35 -03:00
Bruno Perdigão 66fe2331ef fix rebase conflict 2024-09-13 12:38:31 -03:00
Bruno Perdigão b7c4f1a1f0 Minor fix in polyline decorator variables initialization. 2024-09-13 12:37:45 -03:00
Bruno Perdigão c2cf8cd7dd Fix bug in polyline tool when "=" were pressed before "TAB". 2024-09-13 12:37:45 -03:00
Bruno Perdigão efcaf14fbb fix rebase conflict 2024-09-13 12:37:39 -03:00
Bruno Perdigão bc884c9dc4 fix rebase conflict 2024-09-13 12:35:50 -03:00
Andrej730 c340f496f2 swizzle material and style purging operators
purging material should come first as it may unlock purging more styles
2024-09-13 18:50:54 +05:00
Andrej730 b8aefe7df0 geometry.unassign_representation - fix missing ifc2x3 tests 2024-09-13 18:50:54 +05:00
Andrej730 8061e22480 geometry.unassign_representation to remove shape aspects
previously it was leaving unused shape aspects unconnected to any other elements, now it will purge them
2024-09-13 18:50:54 +05:00
Andrej730 aa289fd796 purge unused materials to consider IfcMaterialLists #3914
and IFC2X3 material sets and layers
2024-09-13 18:50:54 +05:00
Andrej730 b911b68aec typing 2024-09-13 18:50:54 +05:00
Andrej730 80af847f99 purge unused material to try to purge materials recursively #3914
As on first iteration it may remove only unused material sets and on the next iteration it will be able to remove IfcMaterials that were not used anywhere else besides those material sets.
2024-09-13 15:15:51 +05:00
Andrej730 4d149e8a78 Purge unused materials to consider materials with styles and psets #3914
If material has a style or a pset it creates an inverse that shouldn't prevent material from being purged.
2024-09-13 15:15:51 +05:00
Andrej730 c41a4607d1 Fix missing return values in e5a59d0bea 2024-09-13 15:15:50 +05:00
Andrej730 148f8361be make bump - show an error for incorrect use 2024-09-13 15:15:50 +05:00
Thomas Krijnen d879bf9f89 Reintroduce --model-offset/-rotation MODEL_OFFSET/_ROTATION setting #5231 2024-09-13 11:38:24 +02:00
Andrej730 81399ffd19 Support loading project without clearing Blender session
It wasn't working anymore after 27a2c94. Importing IFC file as just geometry should be a separate option from 'should_start_fresh_session' and I've added it as 'import_without_ifc_data' property during project load (now both options are also available for users in project load dialog - https://i.imgur.com/Fvbv4Dy.png)
2024-09-13 11:47:49 +05:00
Thomas Krijnen 21cfd03301 Merge pull request #5362 from IfcOpenShell/fix-ifccircle-ifcellipse-processing
Fix error processing IfcCircle/IfcEllipse #5352
2024-09-12 20:19:17 +02:00
Thomas Krijnen 1697e49e65 Merge branch 'v0.8.0' into fix-ifccircle-ifcellipse-processing 2024-09-12 20:18:57 +02:00
Andrej730 51211dc527 ifcopenshell makefile - use VERSION 2024-09-12 19:19:11 +05:00
Andrej730 806975c4b9 bump ifcopenshell build for bonsai 2024-09-12 19:07:20 +05:00
Andrej730 e3c23072a5 Hide edit mode for locked elements #5371 2024-09-12 18:40:22 +05:00
Andrej730 d34d3312ba Add messages for operations with locked elements
Otherwise they just silently failing leaving user confused
2024-09-12 18:40:21 +05:00
Andrej730 845402ea9c Replace grids/space elements visibility two toggles with one
See - https://i.imgur.com/5GssIDp.png (same for grids)
2024-09-12 18:40:21 +05:00
Andrej730 e5a59d0bea remove unnecessary ifc operators 2024-09-12 18:40:21 +05:00
Andrej730 3bb4243850 Purge unused styles and materials #3914
Example - https://imgur.com/a/JXEofa1
2024-09-12 18:40:21 +05:00
Andrej730 094bbe6913 bim.override_origin_set to reuse descriptions from blender operator 2024-09-12 18:40:20 +05:00
Andrej730 0f6cc7326c bim.add_proposed_prop - document possible property types 2024-09-12 18:40:20 +05:00
Andrej730 cc90c92dec bim.add_proposed_prop to show error message if property already exists 2024-09-12 18:40:20 +05:00
Andrej730 e81fe60218 CMakeLists - fix issue on msvc >= 14.40 #5158 2024-09-12 18:40:20 +05:00
Andrej730 aa97ff7f16 typing 2024-09-12 18:40:20 +05:00
Andrej730 2168b3b7bd black format 2024-09-12 18:40:20 +05:00
Andrej730 cb21f9bc07 taxonomy::cast - order upgrades in the same order as in taxonomy::dcast for consistency 2024-09-12 16:30:06 +05:00
Andrej730 f930897240 taxonomy::dcast - add missing curve_to_loop_upgrade 2024-09-12 16:30:05 +05:00
Andrej730 93c47498ef AbstractKernel::dispatch_conversion - use static cast
Previously it was using taxonomy::cast that was also trying to upgrade current item - due to the strictness of dispatch_conversion (it works only if type matches exactly because of `N == item_kind`) upgrades will never succeed so we may just skip them.
2024-09-12 16:30:05 +05:00
Thomas Krijnen 2545769f67 Add support for IfcSectionedSurface 2024-09-12 11:20:48 +02:00
Ryan Schultz 35a4d87a65 give schedules a css style called 'schedule' to help with styling 2024-09-11 23:06:43 -05:00
Thomas Krijnen c7183a58ea aggregate of int/real compatibility in parsing #5302 2024-09-11 20:15:14 +02:00
Thomas Krijnen 5a44a8e325 Defensiveness against invalid data 2024-09-11 20:13:50 +02:00
myoualid f5e02d1413 Merge branch 'v0.8.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.8.0 2024-09-11 19:00:27 +01:00
myoualid 1964def3ca web ui cost module features:
- improve UI for editing cost quantites
- add, edit, delete manual quantities
2024-09-11 19:00:15 +01:00
Thomas Krijnen cc2017518b Update build-all.py : _ifcopenshell_wrapper now called ifcopenshell_wrapper? 2024-09-11 19:58:52 +02:00
myoualid 97393eb173 prevent spatial elements selection from being assigned to cost control 2024-09-11 18:48:59 +01:00
Andrej730 4c04bc7cb5 fix test_create_IfcBSplineCurve 2024-09-11 19:42:47 +05:00
Andrej730 005c17084b dispatch_with_upgrade to use only upgrade types for optimization 2024-09-11 19:42:47 +05:00
Andrej730 858e57351e AbstractKernel::convert - more generic approach 2024-09-11 19:42:47 +05:00
Andrej730 9be392e2f1 test TesselateElements #5199 2024-09-11 16:02:48 +05:00
Andrej730 f4c3ceb693 black format 2024-09-11 16:02:48 +05:00
Andrej730 32c6ea9363 shapebuilder.profile - fix bug in ifc2x3 assigning non existing Position attr
confused arbitrary profiles with parametric profiles in 640320f
2024-09-11 16:02:48 +05:00
Andrej730 ad8131114d IfcLine, IfcBSplineCurve geometry tests 2024-09-11 15:53:04 +05:00
Andrej730 fe0be0cdae shape_builder.create_axis2_placement_2d 2024-09-11 15:53:04 +05:00
Andrej730 35221ed772 AbstractKernel::convert to use upgrade to edge as a fallback 2024-09-11 15:53:04 +05:00
Andrej730 37315e941a taxonomy.h - move upgrades code to cpp 2024-09-11 15:53:04 +05:00
Andrej730 11f017e715 revert manual upgrade to edges for ellipses and circles 2024-09-11 15:53:04 +05:00
Thomas Krijnen c63f1cfa88 Iterator: Don't crash on calling get() before initialize() 2024-09-11 11:18:09 +02:00
Dion Moult 5fe85e71bb Work in progress example to import multiple representation items as an object-based breakdown 2024-09-11 18:04:03 +10:00
Dion Moult f8f3519a68 Minor bugfix to allow unaggregation of hidden elements 2024-09-11 13:45:11 +10:00
Dion Moult bad6931a84 Fix bug in tessellate elements 2024-09-11 12:26:39 +10:00
myoualid 158f11d58c Cost web ui improvements:
- hovering cost item row displays quick actions
- clicking the quantity cells and cost cells prompts form to edit values
- further style improvements & refactoring
2024-09-10 22:48:22 +01:00
Bruno Perdigão 794154f6f5 Instructions in polyline tools were moved to the status bar.
Previously the instructions were shown on screen with decorators. Now it is handled by the modal function of the polyline tools.
2024-09-10 15:41:02 -03:00
Bruno Perdigão c06929e1c7 Major refactor in polyline tool to use a base class for other operators.
Polyline Wall and Measure tool now share most of the logic by inheriting from a base class PolylineOperator.
This should facilitate the implementation of other tools that use polyline.
2024-09-10 15:37:57 -03:00
Bruno Perdigão 1a587dea7d Minor refactor of tool/polyline 2024-09-10 15:37:57 -03:00
Bruno Perdigão 55df9a42e6 WIP - More refactor 2024-09-10 15:37:57 -03:00
Bruno Perdigão be8b325a83 WIP - Polyline tool refactor 2024-09-10 15:37:57 -03:00
Bruno Perdigão 2e192034f8 Small tweak in 8032e4851 2024-09-10 15:37:57 -03:00
Bruno Perdigão ce8e104b0b Change snap axis to 15 angles increments. 2024-09-10 15:37:57 -03:00
Bruno Perdigão e48050af4b Fix #5336 2024-09-10 15:37:57 -03:00
Bruno Perdigão d63961d840 Small fix on previous commit 2024-09-10 15:37:57 -03:00
Bruno Perdigão edf0804b0e Small fix on how the input UI rounds numbers 2024-09-10 15:37:57 -03:00
Bruno Perdigão aaa3d5c443 Small fix on previos commit 2024-09-10 15:37:57 -03:00
Bruno Perdigão 2008081d9a Implementation of #5317.
The number in the input UI will be replaced if the user presses a number.
This behavior will be different if the user press "=" or backspace.
2024-09-10 15:37:57 -03:00
Bruno Perdigão e546971ada Changed input validation to tool/polyline.py 2024-09-10 15:37:57 -03:00
Bruno Perdigão 8dc77735a5 fix rebase conflict 2024-09-10 15:37:57 -03:00
Richard Brice cc7171060f Decouples evaluation of a piecewise_function from the function itself (#5344) 2024-09-10 10:11:17 -07:00
myoualid 67a7e713b2 fix util.get_elements_by_pset to account for quantity sets 2024-09-10 17:17:42 +01:00
myoualid 3abe5edd21 Fix generating 3D view drawing when IFC elements don't exist in the Blender scene ( such as IfcDistributionPort) 2024-09-10 17:16:09 +01:00
Andrej730 34aed93b7b Fix 2 segfaults creating IfcEllipseProfileDef
1) taxonomy::ellipse was missing matrix so create_shape was segfaulting either was if Position was set or was not (segfaulting on line - https://github.com/IfcOpenShell/IfcOpenShell/blob/5616367a03ea397885e93523e55788da82238742/src/ifcgeom/kernels/opencascade/loop.cpp#L92)
2) was segfaulting when there was no default matrix

Removed fc->matrix assignment as matrix is already assigned to the curve.
2024-09-10 18:28:18 +05:00
Andrej730 6fd4d8b1ba Fix sequence.get_related_products bug after 845d772 2024-09-10 18:28:18 +05:00
Andrej730 2d0b262351 get_nested_tasks to discard non-ifctask elements #4911 2024-09-10 18:28:18 +05:00
Andrej730 a4f669e549 ifc5d.qto - some clarifications for arguments 2024-09-10 18:28:18 +05:00
Andrej730 dc92a8fd27 Bonsai - setup default values for new patametric profiles
So there will be less invalid IFC and user will get a preview right away after creating a new profile.
Example - https://imgur.com/a/GjkCql4
2024-09-10 18:28:18 +05:00
Andrej730 3bb0901e3e Profiles UI - better handling for invalid profiles
Previously it would be just console errors possibly breaking UI, now there will be UI error message - https://imgur.com/1o9teJ0
2024-09-10 18:28:17 +05:00
Andrej730 2d68d344bd Profiles UI - update displayed psets when user is changing active profile
previously it would get stuck until some other operator would refresh ui
2024-09-10 18:28:17 +05:00
Andrej730 ddf92ab8fb typing 2024-09-10 18:28:02 +05:00
Andrej730 9a6fc58949 Fix typo 2024-09-10 18:28:02 +05:00
Andrej730 765b5c2f5c black format 2024-09-10 18:28:01 +05:00
Andrej730 5616367a03 don't deep copy psets for optimization
Related to #5291

pset.edit_pset should cover it since it does support unsharing shared properties
2024-09-10 14:21:14 +05:00
Andrej730 6cf9875472 Fix error processing IfcCircle/IfcEllipse #5352 2024-09-10 12:54:44 +05:00
Dion Moult 5f8fdf233f Fix #5358. Easy way to toggle visibility of spatial elements and grids. 2024-09-10 14:29:55 +10:00
Manu Varkey be090a3a81 Fixes #5353 (#5354)
* Fixes #5353

* Change logic to use natsorted
2024-09-10 14:14:27 +10:00
Takayuki Kato 1da47d9271 Add support for editing IfcPhysicalComplexQuantity in edit_qto (#5335) (#5356)
* Add support for editing IfcPhysicalComplexQuantity in edit_qto (#5335)

* Fix lint-formatting issues
2024-09-10 14:13:57 +10:00
Ryan Schultz 4917cd19a2 addresses https://github.com/IfcOpenShell/IfcOpenShell/commit/3ceeaa739fb20125b7195dbd69e5e8606a3d5ed8#r146061329 2024-09-09 20:01:32 -05:00
Andrej730 e7ad71b51d black format 2024-09-09 18:01:23 +05:00
Andrej730 e87faa167c typing
also small optimization in MaterialCreator.create to address ifc a couple times less
2024-09-09 17:28:24 +05:00
Andrej730 13ed4d3a6c ifcopenshell to support styles assigned to IfcFaces #4038 2024-09-09 17:28:23 +05:00
Andrej730 27b9709b78 style.assign_representation_styles to support topology reprensentations #4038 2024-09-09 17:28:23 +05:00
Andrej730 2d988ac445 Representation UI - show IfcTopologyRepresentation #4038
Now it will show representation items count and will load representation items for IfcTopologyRepresentations.
2024-09-09 17:28:23 +05:00
Andrej730 6da7e18f50 Fix error adding typed text annotations #5300
Apparently it's part of #4832, previously creating a shape for IfcTypeProduct with literals would error, we ignored the error and type product end up being an empty. After 0.8.0 create_shape for literals creates an empty shape (0 verts) and we need to skip it, otherwise there would be an empty mesh representaiton.
2024-09-09 17:28:23 +05:00
Andrej730 a3c5c334f1 Show info message using annotation tool hotkeys without drawing loaded 2024-09-09 17:28:23 +05:00
Manu Varkey 09b8c4482f Update tooltips for UI elements (#5348)
* Update documentation

* Add further documentation

* Update tooltip after discussion

1. Change void to opening
2. Add blank bl_label fields

* Make missed out correction
2024-09-09 19:38:10 +10:00
Thomas Krijnen 680c73f15b Less noisy faceset helper messages 2024-09-09 09:58:02 +02:00
Thomas Krijnen 89e3650d77 No need to check for manifoldness when processing boolean ops in 2d 2024-09-09 09:57:43 +02:00
Thomas Krijnen bcc3b43dc1 --element-hierarchy matrix transpose #5191 2024-09-09 09:57:09 +02:00
Dion Moult 5cfcba5272 Fix #3333. Fix #5290. Fix bugs where Shift-Click or Alt-Click drawing activation modes didn't quite do what was advertised. 2024-09-09 17:43:40 +10:00
Andrej730 2416d91748 black format 2024-09-09 10:37:44 +05:00
Andrej730 7d90c319f0 Merge branch 'test-cmake-policy-fix' into v0.8.0 2024-09-09 10:34:15 +05:00
Dion Moult b71034765c Black 2024-09-09 12:43:22 +10:00
Dion Moult f82b97e97b Fix #5329. Fix #5267. Add support for composite profile definitions and nested closed profiles. 2024-09-09 12:43:13 +10:00
Dion Moult ba5b27d03c Support getting 2D coordinates in util.shape.get_vertices 2024-09-09 12:41:40 +10:00
myoualid 98ab5399f2 web ui cost module:
- double click cost cell to enable editing cost values.
- fix tables' height / scrollbar behaviour
2024-09-09 01:08:29 +01:00
myoualid 2d7614622f fix table styles for cost schedule module 2024-09-08 20:37:46 +01:00
Bruno Perdigão 1c7b36f233 Polyline tool - changed decorator order to show Input UI in front. 2024-09-08 12:04:38 -03:00
Bruno Perdigão d42890f214 Fix bug when trying to calculate the angle from vectors too close to each other. 2024-09-08 12:01:04 -03:00
myoualid c607cbc9d7 cost module web ui improvements:
-add ribbon bar,
- improve settings menu with ability to change font size for tables.
- Improve cost schedule spreadsheet layout
2024-09-08 15:29:46 +01:00
myoualid 83be26e196 fix loading cost schedule webui from blender operator 2024-09-08 15:25:56 +01:00
Dion Moult 2f026218ff Purge deprecated dumb wall / slab qto listener in favour of Ifc5D 2024-09-08 17:31:33 +10:00
Dion Moult 7615173924 Minor fix to sync IFC mode and Blender mode when editing profiles 2024-09-08 17:31:33 +10:00
myoualid 171c3083da Cost module web-ui can now:
- assign cost item products from Blender selection
- display list of selected products ( with available quantities, subtotals, and highlighting already assigned products)
- display and refresh assigned products
- highlight loaded cost schedule
2024-09-08 01:16:48 +01:00
Ryan Schultz fe317f9231 fix #3959 - drawing boundary changes are reflected on bim.create_sheets as well.
and only updates drawings that have been changed
2024-09-07 15:35:05 -05:00
Ryan Schultz 5363c33888 fix #5290: to fix error after shift and click bim.activate_drawing 2024-09-07 13:01:09 -05:00
Dion Moult 795d2c371e Fix #5340. Fix cosmetic console bug when adding a spatial subelement and selecting it. 2024-09-07 22:12:54 +10:00
Manu Varkey 1dfa3f8d79 Implement sorting of spacial containers by elevation and name 2024-09-07 21:46:35 +10:00
Dion Moult 2626165629 Fix #5334. Bug where the wrong type would be added if you added a new type then switched tool. 2024-09-07 21:13:56 +10:00
Dion Moult 0a17588db8 Fix #5346. 2024-09-07 17:05:19 +10:00
Andrej730 33001e6c6d profile.copy_profile
Fixes issue duplicated profile missing it's psets.
2024-09-07 11:22:43 +05:00
Andrej730 e224bfd19f Fix error showing material/profile psets in bbim after 691815fd41 2024-09-07 11:22:43 +05:00
Andrej730 c1d5c18724 fix black format 2024-09-07 11:22:43 +05:00
Dion Moult 557a120178 Fix #5341. Editing elevations in spatial decomposition panel is now a string and has an immediate effect. 2024-09-07 15:37:01 +10:00
Dion Moult cea4c0c01d Fix #5345. Bug when adding a new representation using "full representation". No temp data is used, so deletion not required. 2024-09-07 14:50:09 +10:00
Dion Moult 8b1d3a0c5d Fix #4769. Bug where editing grids didn't work with non-SI units.
I really don't know how this mistake lasted this long.
2024-09-07 13:48:42 +10:00
Dion Moult c5fc86d148 Fix #5337. You can now delete grids, which recursively delete all axes. Edit mode now also respects locking. 2024-09-07 13:18:36 +10:00
Ryan Schultz 8cec717315 fix #5304: Have demo project have Plan/Annotation/REFLECTED_PLAN_VIEW context 2024-09-06 19:49:38 -05:00
Dion Moult 7905cd8bd3 See #5337. Grid decorators now turn off when editing an axis. 2024-09-07 10:01:57 +10:00
Dion Moult 0337034d28 Fix #4881. Fix bug where editing grid axes didn't work. 2024-09-07 10:01:57 +10:00
myoualid 88a40e0052 improve cost table responsiveness and highlight currently loaded cost schedule 2024-09-06 20:51:46 +01:00
Richard Brice c9d2390d9a Implements cant geometry 2024-09-06 10:02:08 -07:00
Andrej730 0055a5dd82 ifcwrap cmake - use default CMP0078 policy 2024-09-06 19:58:52 +05:00
Andrej730 4ff0893a8b ifcwrap cmake - fix CMP0078 warning 2024-09-06 18:28:50 +05:00
Andrej730 791d098800 ifcwrap cmake - fix CMP0078 warning 2024-09-06 18:12:00 +05:00
Andrej730 8e87d0e303 typing 2024-09-06 18:11:25 +05:00
Andrej730 eaaa18468a Reuse tool.Ifc.Operator 2024-09-06 18:11:25 +05:00
Andrej730 871cd45f53 selector.set_element_value to support 'predefined_type' keyword
See more details in https://community.osarch.org/discussion/comment/22134/#Comment_22134
2024-09-06 18:11:24 +05:00
Andrej730 39fd9ce462 attribute.edit_attributes - small optimizations
remove settings dictionary and remove some ifc calls
2024-09-06 18:11:24 +05:00
Dion Moult 4c68ec6f82 Fix bug where editing AxisTag didn't change the grid axis name 2024-09-06 23:10:43 +10:00
myoualid be71eb274b display cost schedule predefined type in web ui 2024-09-06 12:08:45 +01:00
Andrej730 008e2c01c3 selector.set_element_value - temporarily skip 'predefined_type'
to avoid issues importing csvs that used it to extract correct predefined type

Example warning:
WARNING. Assigning 'predefined_type' is not yet supported. Skipping value 'ELECTRICACTUATOR' for element: '#89=IfcActuator('1RjCen6XL6WAdhz7HumLFU',$,'Actuator.002',$,$,#179,$,$,.ELECTRICACTUATOR.)'.
2024-09-06 15:18:15 +05:00
Andrej730 a1e51757b1 attribute.edit_attributes - document behaviour for PredefinedType 2024-09-06 15:18:15 +05:00
Andrej730 d5169e85fa bim.import_ifccsv to support undo (missing Ifc Operator)
Previously it wasn't possible to undo changes in the currently loaded IFC model after bim.import_ifccsv
2024-09-06 15:18:15 +05:00
Andrej730 cfc243949d Fix error unassigning type from element without representation
Traceback
Traceback (most recent call last):
  File "\bonsai\bim\module\type\operator.py", line 63, in execute
    return IfcStore.execute_ifc_operator(self, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "\bonsai\bim\ifc.py", line 408, in execute_ifc_operator
    result = getattr(operator, "_execute")(context)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "\bonsai\bim\module\type\operator.py", line 78, in _execute
    active_context = active_representation.ContextOfItems
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'ContextOfItems'
Error: Python: Traceback (most recent call last):
  File "\bonsai\bim\ifc.py", line 408, in execute_ifc_operator
    result = getattr(operator, "_execute")(context)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "\bonsai\bim\module\type\operator.py", line 78, in _execute
    active_context = active_representation.ContextOfItems
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'ContextOfItems'
2024-09-06 15:18:15 +05:00
Andrej730 a3ff0a61a6 ifccsv to web - fix Tabulator dropping columns with non-unique names 2024-09-06 15:18:15 +05:00
`myoualid` 456ad2af8e remove annoying console logs 2024-09-06 10:14:21 +01:00
Dion Moult 7b8e234683 Remove add grid in add menu, and run black 2024-09-06 18:18:32 +10:00
Dion Moult 95b7a79c64 Locked elements are now blocked from being duplicated too 2024-09-06 18:07:09 +10:00
Dion Moult 4a5e180479 You can now lock and unlock spatial / grid elements, which affects your ability to delete or move them 2024-09-06 17:58:52 +10:00
`myoualid` d6098a0b6d - web ui features to add a new cost schedules, and root cost items
- improved ui for cost schedules
- sharing more css across files
- refactor get_predefined_types(cost_schedule)
2024-09-06 08:55:10 +01:00
Dion Moult 541a6e18e6 Fix broken ifcconvert table in docs 2024-09-06 16:55:56 +10:00
Dion Moult 11497f9b37 Add decorator for grids outside drawing view 2024-09-06 16:40:56 +10:00
Dion Moult 6b14111b24 More grid panel to spatial subpanel 2024-09-06 16:40:56 +10:00
Andrej730 f27bb6effe black format 2024-09-06 11:13:09 +05:00
Andrej730 6ebec7e0e5 pset.unshare_pset - fix bug where it would leaving an orphaned pset
It was leaving an orphaned pset if 'products' was a list of all elements pset is assigned to. Then it would create a new pset for each element leaving original pset orphaned.
2024-09-06 11:04:05 +05:00
Andrej730 ffb2ea2be3 bim.unshare_pset - move implementation to core 2024-09-06 11:04:04 +05:00
Andrej730 89bb7c76de bim.unshare_pset - to work for all selected objects #5291 2024-09-06 11:04:04 +05:00
Andrej730 a867e72fd3 rename get_elements_using_pset -> get_elements_by_pset for consistency
To be consistent with other get_elements_by_xxx methods.
2024-09-06 11:04:04 +05:00
Andrej730 a03c55d15f fix poll breaking with no active object 2024-09-06 11:04:04 +05:00
Richard Brice 1a75d95d47 Updates dependencies for boost 1.86.0 2024-09-05 20:34:49 -07:00
Dion Moult fe5f48c655 Positional elements, project, and spatial elements are now locked. Remove user option to change behaviour. 2024-09-06 12:09:06 +10:00
Dion Moult a4396ee766 See #5318. Prevent deletion of project or spatial structures. 2024-09-06 11:44:30 +10:00
Dion Moult 977f3c7dcc Fix #5243. Remove usage of types_with_super which is no longer available. 2024-09-06 10:38:19 +10:00
Bruno Perdigão 8ba52a2b1c Scale the text for polyline tool decorators. 2024-09-05 14:18:12 -03:00
Bruno Perdigão 214c278fc5 Added a function to scale the font size according to preferences.
The scale will be calculated in relation to the system dpi and Blender's interface resolution scale.
2024-09-05 14:18:12 -03:00
Ryan Schultz f521945766 Have bim.select_assigned_product make selected object active, so it's easier to change its Object Information 2024-09-05 10:09:35 -05:00
Thomas Krijnen 12318fbfc2 Handle storage of nullptr as a proper Blank type in variant #5308 2024-09-05 14:38:57 +02:00
Andrej730 56428eb605 Ooops, fix black formatter ignoring bonsai folder #5178 2024-09-05 17:19:15 +05:00
Andrej730 88319bfa57 Fix missing ifc2x3 tests for pset.edit_pset 2024-09-05 17:13:41 +05:00
Andrej730 cce4e426c3 util.get_pset to support ifc2x3 material props 2024-09-05 17:13:41 +05:00
Andrej730 7782ab5479 should_load_from_memory related poll messages 2024-09-05 15:38:32 +05:00
Andrej730 7e5bd0ca83 ifcwrap cmake - rebuild if .i files changed 2024-09-05 15:08:36 +05:00
Andrej730 051d5479fb Strip redundant newline in repr() for taxonomy items
E.g.
print([m.diffuse for m in shape.geometry.materials])

would print
[colour 0.7 0.7 0.7
]

Instead of:
[colour 0.7 0.7 0.7]
2024-09-05 15:08:36 +05:00
Andrej730 deb41d2158 Geometry settings documentation fixes #5312 2024-09-05 15:08:35 +05:00
Andrej730 ea6df7f617 Use latest syntax for setting geometry settings #5299
Also fixed:
- old include_curves use
- missing use of 'include_curves' in ifcopenshell.draw
2024-09-05 15:08:35 +05:00
Andrej730 fcf41bf00c fix typing issue
Overloads were breaking because type checker is confused what default value should it use for the argument.
Made it keyword-only to resolve the issue.
2024-09-05 15:04:17 +05:00
tim 7c3fbda01e Updated icons
- new master svg file for storing icons bonsai_icons.svg
script for exporting png files and generating light mode versions
support for light mode
2024-09-05 09:21:15 +10:00
`myoualid` d0712c7186 1/ WEB UI Cost Schedule features to :
- delete cost items
- duplicate cost items
- delete individual cost values
- update cost values on the fly
- Shitf + LMB to recursively hide or show nested rows

2/ Improved UI for cost schedules
3/ Reuse css styles across pages with import statements
4/ Remove console/print statements
2024-09-04 23:39:46 +01:00
Andrej730 e1a5e73106 black format 2024-09-04 18:52:09 +05:00
Andrej730 1282f5c308 geom.Iterate - fix incorrect typing, document some arguments #5299 2024-09-04 18:51:07 +05:00
Andrej730 b0eaf23d2c Fix missing serializer_settings argument #5299 2024-09-04 18:51:07 +05:00
Andrej730 0ab70827e5 pset.assign_pset, pset.unassign_pset 2024-09-04 18:51:07 +05:00
Andrej730 691815fd41 Tools for handling shared psets #5291
In IFC it's possible for a property set to be assigned to multiple elements and which may lead to confusing behaviour when you edit a pset on one element and other element seems to get edited too.

Which makes it worse is that that it is possible that some software is might be doing this unintentionally when exporting IFC (as some sort of optimization as storing 1 is more optimal than n copies of it).

So now there are some tools in Bonsai and in IfcOpenShell to handle the shared psest:

1) Indication that property is shared - https://imgur.com/a/9dd3jST (similar to how Blender indicates ID data-block users). You can click on it to "unshare" the pset - a new copy for the pset will be created and it's going to be linked only to the active object.

2) api pset.unshare_pset method that does the same. And util.element.get_elements_using_pset method that encapsulates schema differences and different approaches for occurrences/types.

3) ifcpatch recipe 'UnsharePsets' that's making all property sets in the IFC file to have just 1 element that's using them. You can limit the affected elements by providing query.

ifcpatch recipe is also available in Bonsai - https://i.imgur.com/aOCx7HI.png
2024-09-04 18:51:06 +05:00
dependabot[bot] 3c3b56d1ae Bump actions/download-artifact from 2 to 4.1.7 in /.github/workflows
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 2 to 4.1.7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v2...v4.1.7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-04 10:43:04 +10:00
htlcnn 116192befd fix last point coincides with first point 2024-09-03 16:36:45 -03:00
Bruno Perdigão b6a96828ec Fix #5277 2024-09-03 16:23:32 -03:00
Ryan Schultz c4c611d778 whoops 2024-09-03 13:21:48 -05:00
Ryan Schultz 290c08d6d5 updated links in docs 2024-09-03 13:18:55 -05:00
Thomas Krijnen eb7411b310 ifcopenshell.file.assign_header_from() to copy header 2024-09-03 18:49:05 +02:00
Andrej730 bea837299e root.reassign_class to handle switching occurrence class <-> type class #5260
Kind of experimental. The idea is that it will reassign class e.g. from IfcWindow to IfcWindowType (or vice versa) and will keep the IFC representations and property sets.

Example - https://imgur.com/a/X7MHR0s
2024-09-03 18:53:25 +05:00
Andrej730 acbdc0ed4c typing 2024-09-03 18:53:25 +05:00
Andrej730 bec1d913c5 util.representation.get_representations_iter 2024-09-03 18:38:22 +05:00
Andrej730 b957505bfc bim.add_xxxx descriptions 2024-09-03 18:38:22 +05:00
Andrej730 3c69fffb19 ifcopenshell.validate fix missing space in indentation 😅 2024-09-03 18:38:22 +05:00
Andrej730 1c7e7c5269 prohibit user from removing a profile that still has inverses #5101
To avoid creating invalid material profile sets, representation items. Currently the only inverse that is allowed before removal is profile properties.

Example - https://i.imgur.com/UobI4pL.png
2024-09-03 18:38:21 +05:00
Andrej730 92525db14f profile.remove_profile - tests 2024-09-03 18:38:21 +05:00
Andrej730 01d965fe25 profile.remove_profile - clean up removing profile psets 2024-09-03 18:38:21 +05:00
Andrej730 d2bc6f9509 pset.add_pset - support ifc2x3 material/profile psets
1) For psets there was an issue - it was instantiating abstract IfcProfileProperties
2) For materials it was only able to instantiate IfcExtendedMaterialProperties though there are other pset types too in ifc2x3.
2024-09-03 18:38:21 +05:00
krande 88b861737c if boost >= 1.86 append newline to json logger 2024-09-03 11:56:15 +02:00
Kristoffer Andersen 0f87bd8206 use a macro to change for boost > 1.86 2024-09-03 11:09:22 +02:00
Kristoffer Andersen 1fe168d331 Update IfcGlobalId.cpp to support boost 1.86
It looks like mt19937 is no longer a member of boost in boost 1.86. I propose we use to std::mt19937 (which is already how it is used by svgfill.cpp)

see failure log from conda forge libboost 1.86 test here:
https://dev.azure.com/conda-forge/feedstock-builds/_build/results?buildId=1008654&view=logs&j=4f922444-fdfe-5dcf-b824-02f86439ef14&t=b2a8456a-fb11-5506-ca32-5ccd32538dc0&l=880
2024-09-03 11:09:22 +02:00
Thomas Krijnen a7925622ed Handle nix patches for V7_7_2 #5285 2024-09-03 08:52:39 +00:00
Dion Moult 3675429385 Fix #2437. You can now see the spatial hierarchy decomposed by classification. 2024-09-03 18:42:52 +10:00
Thomas Krijnen 44ab38cb24 Add V7_7_2.patch #5285 2024-09-03 10:01:44 +02:00
Thomas Krijnen 1a146ada48 Add V7_7_2.patch #5285 2024-09-03 09:57:02 +02:00
Dion Moult 2ed2b4fe71 Fix #5230. Reimplement spatial decomposition hierarchy. 2024-09-03 14:36:01 +10:00
Dion Moult 4ce30b3153 See #5269. Minor tweak to show warning if object scaling detected. 2024-09-03 12:52:57 +10:00
Dion Moult 4ce2251717 See #5269. Minor tweak to show warning if manual mode changes detected. 2024-09-03 10:19:35 +10:00
Andrej730 c6e8d2a585 bim.add_material_set to ensure adding valid material sets 2024-09-02 18:41:15 +05:00
Andrej730 90e9c21320 material.add_profile note 2024-09-02 18:40:12 +05:00
Andrej730 236fbc7864 remove unused add_empty_type_button ui function 2024-09-02 17:25:04 +05:00
Andrej730 ae75acb0b9 Fix test after 521b0ab58d 2024-09-02 17:24:59 +05:00
Andrej730 11068fe338 bim.add_drawing_to_sheet - poll message 2024-09-02 17:24:59 +05:00
Andrej730 3c333c6b59 typing 2024-09-02 17:24:58 +05:00
Andrej730 ccbb253d2c Fix new sheets having non-unique identification
It was checking for the wrong scope "DOCUMENTATION".
Scope "DOCUMENTATION" was left from the old times, now we use scope "SHEET".
2024-09-02 17:04:55 +05:00
Andrej730 7c542418e6 fix create sheet test failing if bonsai and tests are on different disks
It was failing on Windows with something like "ValueError: path is on mount 'L:', start on mount 'C:'".
I guess it doesn't really occur in bonsai as sheets are typically stored next to the titleblocks (we used to use absolute paths awhile ago and now everything is relative to the ifc project)
2024-09-02 17:04:55 +05:00
Andrej730 d77f57c68e ifc.resolve_uri - remove redundant second check
os.path.isabs(uri) is already checked at the beginning of the function
2024-09-02 17:04:55 +05:00
Andrej730 151244ae79 ifcopenshell.file() to create valid ifc header by default #5246
Valid type for author and organization is 'LIST [ 1 : ? ] OF STRING (256)'
2024-09-02 17:04:55 +05:00
Andrej730 e50a90cc9f ifcopenshell.validate return code 1 in case of some file is invalid 2024-09-02 17:04:54 +05:00
Andrej730 5f5ab10b35 ifcopenshell.validate to validate ifc header #4119 2024-09-02 17:04:54 +05:00
Andrej730 0e791c7dfd Fix ifcopenshell.validate missing output in some cases after 07a0b4f
Apparently adding LogDetectionHandler disabled default handler that prints the output.
2024-09-02 17:04:54 +05:00
Dion Moult 07be50b365 See #5261. Fix bug when editing parametric stairs (not stair flights) which sets an inapplicable predefined type 2024-09-02 21:23:06 +10:00
Dion Moult fb422692c8 You can now make the selected element in the spatial decomposition panel active 2024-09-02 20:37:04 +10:00
Dion Moult 1a8be005cf Fix bug where toggled openings didn't properly appear in the dedicated opening collection 2024-09-02 20:14:43 +10:00
Dion Moult 9dcb5b103c Fix #5237. Fix bug where flipping or splitting walls didn't take into account project units and voids were misplaced. 2024-09-02 20:14:30 +10:00
Dion Moult 091824910b Increase debug log limit to 20 2024-09-02 19:42:26 +10:00
Dion Moult ea6d5918ba Fix bug where openings were invalidly contained in a container 2024-09-02 19:42:26 +10:00
Manu Varkey a452d29bab Fix bug: Add type instance button duplicated (#5281) 2024-09-02 19:37:08 +10:00
Dion Moult fb803ac35d Fix #5256. Use layer collection visibility, not collection visibility to hide types. 2024-09-02 18:48:09 +10:00
Dion Moult eec4b37827 See #5256. Fix bug where old "Types" collection was still being created and unused. 2024-09-02 18:47:09 +10:00
Dion Moult d1565ec1e6 Fix #5273. Bug where Shift-E allowed you to edit non-roof/railing elements if you also had them selected. 2024-09-02 17:46:44 +10:00
Dion Moult 521b0ab58d Fix #5271. Prevent duplicate entries when getting a decomposition. 2024-09-02 17:35:49 +10:00
Thomas Krijnen 04bbfc04ad Try 7.7.2 for HLR poly/edge behaviour 2024-09-02 09:20:38 +02:00
Thomas Krijnen f0167b812a Try 7.7.2 for HLR poly/edge behaviour 2024-09-02 09:19:46 +02:00
Dion Moult 0b8a701423 Fix #5275. Fix bug where orthographic sections would appear over freestyle linework in perspective views. 2024-09-02 16:51:25 +10:00
Dion Moult aa7e80fc8c Fix #5276. Fix inaccurate tooltip for assign container operator. 2024-09-02 16:40:51 +10:00
Bruno Perdigão f48c7d6af5 Fix polytool issue with distance input while snapping above the xy plane. 2024-09-01 11:20:14 -03:00
Bruno Perdigão 977014b86a Fix #5274 2024-09-01 10:48:16 -03:00
Bruno Perdigão 43e13ef8f3 Fix polytool issue when backspacing the whole input. 2024-09-01 10:38:03 -03:00
Thomas Krijnen daba504981 Update draw.py - test for --drawing-guid existance 2024-09-01 15:33:52 +02:00
Thomas Krijnen f8a2cce202 Use polygon_from_points() and handle Position for CSG Pyramid #5241 2024-09-01 15:14:22 +02:00
Thomas Krijnen b786e129bd Fix faceset helper stats 2024-09-01 15:12:43 +02:00
sukanka b82073dd57 fix-py-syntax-warning 2024-09-01 14:02:24 +02:00
Thomas Krijnen d4d9fdff1a Fix and augment v0.8 taxonomy wrapper 2024-09-01 10:40:23 +02:00
Dion Moult b3b14e87ec Next release cycle! 2024-09-01 18:00:31 +10:00
Andrej730 6bc31105bf Mention common error in troubleshooting docs 2024-09-01 11:10:13 +05:00
Dion Moult 73e3ebd1f0 Update README.md with new doc links 2024-09-01 16:08:45 +10:00
Dion Moult 32f216a594 Minor fix to bonsai-stable build 2024-09-01 14:23:29 +10:00
Dion Moult 296ebf5253 Fix failing tests in Bonsai 2024-09-01 14:08:52 +10:00
Dion Moult e072870fd3 Fix bcf pypi build 2024-09-01 13:35:57 +10:00
Dion Moult af4475fe46 Run black 2024-09-01 13:26:58 +10:00
Dion Moult eb3104367a Bump version to v0.8.0 2024-09-01 13:23:54 +10:00
Dion Moult 90f9ebd25e Add dev install instructins to official docs 2024-09-01 13:23:31 +10:00
Yassine Oualid f2554bc968 - Add button to generate cost schedule
- Feature to view, edit and add cost item values. ( Right Click - Edit ).
2024-09-01 01:40:53 +01:00
Dion Moult 53a78f38e5 You can now assign objects to the selected container in the spatial decomposition panel 2024-09-01 08:13:29 +10:00
Dion Moult b476cb825c Fix #5265. Accommodate invalid material sets. 2024-09-01 07:53:49 +10:00
Bruno Perdigão ec21574be5 Fix measure tool to now show the angle for the first point. 2024-08-31 14:39:58 -03:00
Bruno Perdigão b552665dd9 Round angle in polytool input numbers calculations. 2024-08-31 14:39:58 -03:00
Bruno Perdigão 48b630696f Fix 3ceeaa7 2024-08-31 14:39:58 -03:00
Bruno Perdigão 8c94ef6e54 A better fix for dabb85c. 2024-08-31 14:39:58 -03:00
Bruno Perdigão bdcadfd100 Refactor tool.Cad.angle_3_vectors
This functions was built to work with the input calculations for the polytool.
Part of its code was being duplicated in another part of the code. The refactor
keeps most of the calculation in the same place.
2024-08-31 14:39:58 -03:00
Bruno Perdigão 90e83d77a7 more improvement on distance and angle calculations 2024-08-31 14:39:58 -03:00
Bruno Perdigão 2e80363bac improved general input calculations 2024-08-31 14:39:58 -03:00
Bruno Perdigão b6f80eabb4 Fix input calculation and conversion for measure tool 2024-08-31 14:39:58 -03:00
Bruno Perdigão c93e52089b Fix input calculation and conversion for wall polytool 2024-08-31 14:39:58 -03:00
Andrej730 76ba3947f5 Expose header properties with invalid values #5246 2024-08-31 14:31:41 +02:00
Dion Moult 50cb09aac2 See #3880. Freestyle support for perspective vector linework. 2024-08-31 20:56:10 +10:00
Andrej730 dac1aaa7f3 Errors adding roof, stair, railing types #5261
It wasn't considering that type object can be hidden and can't be active.
Removed obj property since it can be covered with just temp_override.
2024-08-31 13:30:12 +05:00
Dion Moult eed603bbcd Bump IOS 2024-08-31 18:09:54 +10:00
Dion Moult 1d62f6f736 Support experimental freestyle linework generation 2024-08-31 18:09:14 +10:00
Andrej730 799cf47316 Fix error removing a cost schedule (after 7a44f9e) #5264
It wasn't really leaving orphaned data and interrupting the process of the ifc object deletion but it was leading to confusing errors
2024-08-31 13:00:11 +05:00
Dion Moult 03935a91da Fix bug where linework merging may create polygons where there should be interior holes instead. 2024-08-30 23:53:02 +10:00
Dion Moult 37baa9235a Fix bug where a voided element by OCC will be considered non-manifold. Remove doubles with a very small distance fixes it. 2024-08-30 23:51:47 +10:00
Dion Moult b4b2b60935 New bisect-based drawing cut mode. This replaces OCC's cut (but keeps the projection HLR) with a blender bisect based cut 2024-08-30 20:33:09 +10:00
Dion Moult a11c7535d8 Turn fill modes (shapely / svgfill) into a dropdown to prevent selecting both and crashing 2024-08-30 20:33:09 +10:00
Andrej730 e8d6dd333c Fix failing import if 'sun position' extension (9633d92)
ping @chiragsingh1711
2024-08-30 12:15:00 +05:00
Chirag Singh 9633d92c17 Light/radiance (#5252)
* Cam fix, Sun Fix, import-export as json

* Ran black formatting
2024-08-30 08:32:45 +10:00
Andrej730 afd5a5b23e Fix get_info_2 #5248 after d80bcd1 2024-08-29 18:57:47 +05:00
Dion Moult 15481c0a59 Bump docs to use spatial panel. Format menuselection. 2024-08-29 23:30:53 +10:00
Dion Moult 32b37b8823 Implement recursive toggling for elements in spatial panel 2024-08-29 23:30:53 +10:00
Andrej730 f3ab214752 Use first layer/profile from the set to pick up the material #5238
As currently we do not support multilayer/profile geometry and therefore we can't correctly represent them when they have multiple styles. As a workaround we'll use the material/style from the first layer and apply it to the entire object.
2024-08-29 17:21:21 +05:00
Dion Moult 4a59b30f1b Fix #5244. Prioritise collection of drawing groups over containment groups 2024-08-29 18:42:42 +10:00
Andrej730 87d6960356 Fix #5249 after acf135a 2024-08-29 13:42:08 +05:00
Andrej730 aff893e690 bim.create_drawing - poll message 2024-08-29 13:42:08 +05:00
Dion Moult 486eb259ea Fix #5245. Consider situation where object may not be loaded due to partial loading. 2024-08-29 18:09:31 +10:00
Ziad-I 8164b496f8 fix #5219 underlay links are now base64 encoded in the svg before sending it to web UI
this is not really the best solution and might need to look for better ones
2024-08-29 10:50:50 +03:00
Dion Moult fda23f350a Fix #5247. Fix typo when opening drawing web UI. 2024-08-29 17:19:28 +10:00
Dion Moult 711c597065 See #5231. Workaround for missing offset. 2024-08-29 16:22:42 +10:00
Dion Moult 80a396dc12 You can now select geometry library in advanced settings 2024-08-29 16:22:42 +10:00
Dion Moult 2b70f12d44 More bonsai name fixes 2024-08-29 15:17:52 +10:00
Dion Moult c3bcc2d90c See #5243. types_with_super() is no longer available. Also maybe overkill in this scenario. 2024-08-29 10:11:01 +10:00
Dion Moult 88e5a51f01 Merge pull request #5236 from IfcOpenShell/webui_updates
Add RMB context menu to web UI spreadsheets and small updates
2024-08-29 09:55:55 +10:00
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
Cristian Ritter a450c24739 Merge branch 'v0.8.0' of https://github.com/csritter/IfcOpenShell into v0.8.0 2024-08-26 15:34:55 -03:00
Cristian Ritter 56d19039e3 always apply in diffuse color, if doens't have surface color
Signed-off-by: Cristian Ritter <cristian_ritter@hotmail.com>
2024-08-26 15:34:50 -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
csritter 2b8124071a Merge branch 'v0.8.0' into v0.8.0 2024-08-26 10:26:10 -03:00
Cristian Ritter 9fceec35cc add diffuse on surface, if has no surface color
Signed-off-by: Cristian Ritter <cristian_ritter@hotmail.com>
2024-08-26 10:17:50 -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
csritter ae2933eea5 prevent a copy
Co-authored-by: Thomas Krijnen <t.krijnen@gmail.com>
2024-08-26 01:08:06 -03: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
Cristian Ritter 7d50491a99 checking if diffuse has value, if not, use surface
Signed-off-by: Cristian Ritter <cristian_ritter@hotmail.com>
2024-08-20 12:16:19 -03:00
Cristian Ritter 371b4b6079 removing unnecessary use_surface_color on calc_hash 2024-08-20 11:45:29 -03:00
Cristian Ritter d714eca4ee replacing diffuse to get_color method 2024-08-20 11:44:20 -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
Cristian Ritter cd3df94a4b add surface and use_surface_color on style class 2024-08-19 18:44:43 -03:00
Cristian Ritter 0efafada1d fixed missing SurfaceColour on SettingsContainer 2024-08-19 18:41:45 -03: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
Cristian Ritter 876f059459 remove surface white if doesn't have surface colour
Signed-off-by: Cristian Ritter <cristian_ritter@hotmail.com>
2024-08-15 14:18:13 -03:00
Cristian Ritter b5a61753a5 Adding --surface-color in conversion settings to force the use of surface color instead of diffuse color. Issue #5075 2024-08-15 13:56:31 -03: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
1491 changed files with 163639 additions and 160818 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@v2 # https://github.com/actions/checkout
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
with:
python-version: '3.10' # Version range or exact version of a Python version to use, using SemVer's version range syntax
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
- run: echo ${{ env.DATE }}
- name: Get current date
-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: [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
+158
View File
@@ -0,0 +1,158 @@
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
# Include hours and minutes to release tag
# to avoid possibility of unstable repo's index.json
# pointing to the new file when index.json itself wasn't yet updated.
run: echo "date=$(date +'%y%m%d%H%M')" >> $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: [py310, py311, py312]
pyver: [py311, py312]
config:
- {
name: "Windows Build",
@@ -32,15 +32,15 @@ jobs:
}
- {
name: "Linux Build",
short_name: linux
short_name: linux,
}
- {
name: "MacOS Build",
short_name: macos
short_name: macos,
}
- {
name: "MacOS ARM Build",
short_name: macosm1
short_name: macosm1,
}
steps:
- uses: actions/checkout@v2
@@ -53,12 +53,11 @@ jobs:
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
- name: Compile
run: |
cd src/blenderbim &&
make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }} IS_STABLE=TRUE
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 +66,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
+4 -2
View File
@@ -93,7 +93,7 @@ jobs:
lfs: true
- name: Download
uses: actions/download-artifact@v2
uses: actions/download-artifact@v4.1.7
with:
# Artifact name
name: ifcos-artifacts
@@ -116,6 +116,8 @@ jobs:
with:
context: artifacts
repository: aecgeeks/ifcopenshell
tags: aecgeeks/ifcopenshell:latest
# Since the dispatch is set to `tag`, `github.ref_name` should evaluate to the pushed tag
# On a workflow dispatch, `ref_name` will take on the value from the dispatch payload
tags: aecgeeks/ifcopenshell:${{ github.ref_name }}${{ github.ref_name == github.event.repository.default_branch && ',aecgeeks/ifcopenshell:latest' }}
file: ./Dockerfile
push: true
+3 -1
View File
@@ -107,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; \
@@ -130,5 +130,7 @@ jobs:
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 \
+7 -7
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), Bonsai (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/quickstart/installation.html)
* [Exploring an IFC model](https://docs.bonsaibim.org/quickstart/explore_model.html)
Development is sponsored through your generous donations!
@@ -36,8 +36,8 @@ 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/) |
| 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/) [![Anaconda-Server Badge](https://anaconda.org/conda-forge/bcf-client/badges/version.svg)](https://anaconda.org/conda-forge/bcf-client) |
| 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=bonsai-*&label=GitHub-Unstable&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=bonsai&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/) |
+1 -1
View File
@@ -1 +1 @@
0.7.11
0.8.1
@@ -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
+17 -2
View File
@@ -27,9 +27,11 @@ if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
endif()
add_definitions(-D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR)
cmake_policy(SET CMP0048 NEW)
cmake_policy(SET CMP0074 NEW)
cmake_policy(SET CMP0078 OLD)
cmake_policy(SET CMP0078 NEW)
cmake_policy(SET CMP0086 NEW)
if (POLICY CMP0144)
cmake_policy(SET CMP0144 NEW) # find_package() uses upper-case <PACKAGENAME>_ROOT variables.
@@ -221,7 +223,7 @@ endif()
if(GLTF_SUPPORT OR CITYJSON_SUPPORT)
UNIFY_ENVVARS_AND_CACHE(JSON_INCLUDE_DIR)
find_path(json_header_path "json.hpp" ${JSON_INCLUDE_DIR} PATH_SUFFIXES "nlohmann")
find_path(json_header_path "nlohmann/json.hpp" HINTS ${JSON_INCLUDE_DIR})
set(JSON_INCLUDE_DIR ${json_header_path})
if(json_header_path)
@@ -730,6 +732,10 @@ if(MSVC)
# endif()
add_definitions(-D_ENABLE_EXTENDED_ALIGNED_STORAGE)
# See #5158.
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.40)
add_definitions(-D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR)
endif()
else()
add_definitions(-Wall -Wextra)
@@ -1045,10 +1051,19 @@ if(BUILD_CONVERT)
target_include_directories(cityjson_converter PRIVATE ../src)
set(IFCOPENSHELL_LIBRARIES ${IFCOPENSHELL_LIBRARIES} cityjson_converter)
install(TARGETS cityjson_converter
ARCHIVE DESTINATION ${LIBDIR}
LIBRARY DESTINATION ${LIBDIR}
)
add_executable(cityjson_converter_exe ${CITYJSON_CONVERT_FILES})
set_target_properties(cityjson_converter_exe PROPERTIES COMPILE_FLAGS "-DCITYJSON_EXECUTABLE")
target_include_directories(cityjson_converter_exe PRIVATE ../src)
target_link_libraries(cityjson_converter_exe ${IFCOPENSHELL_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${HDF5_LIBRARIES} ${USD_LIBRARIES})
install(TARGETS cityjson_converter_exe
RUNTIME DESTINATION ${BINDIR}
)
endif()
# IfcConvert
+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>
+12 -4
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.8.1"
BOOST_VERSION = "1.80.0"
PCRE_VERSION = "8.41"
LIBXML2_VERSION = "2.9.11"
@@ -220,6 +220,7 @@ if "v" in flags:
else:
logger.setLevel(logging.INFO)
OFF_ON = ["OFF", "ON"]
BUILD_STATIC = "shared" not in flags
ENABLE_FLAG = "--enable-static" if BUILD_STATIC else "--enable-shared"
DISABLE_FLAG = "--disable-shared" if BUILD_STATIC else "--disable-static"
@@ -331,7 +332,7 @@ def run_cmake(arg1, cmake_args, cmake_dir=None, cwd=None):
if "wasm" in flags:
wasm.append("emcmake")
run([*wasm, "cmake", P, *cmake_args, f"-DCMAKE_BUILD_TYPE={BUILD_CFG}"], cwd=cwd)
run([*wasm, "cmake", P, *cmake_args, f"-DCMAKE_BUILD_TYPE={BUILD_CFG}", f"-DBUILD_SHARED_LIBS={OFF_ON[not BUILD_STATIC]}"], cwd=cwd)
def git_clone_or_pull_repository(clone_url, target_dir, revision=None):
@@ -351,6 +352,8 @@ def git_clone_or_pull_repository(clone_url, target_dir, revision=None):
run([git, "pull", clone_url], cwd=target_dir)
if revision != None:
run([git, "reset", "--hard"], cwd=target_dir)
run([git, "fetch", "--all"], cwd=target_dir)
run([git, "checkout", revision], cwd=target_dir)
@@ -588,6 +591,12 @@ if USE_OCCT and "occ" in targets:
if OCCT_VERSION == "7.7.1":
patches.append("./patches/occt/no_ExpToCasExe.patch")
if OCCT_VERSION == "7.7.2":
patches.append("./patches/occt/no_ExpToCasExe_7_7_2.patch")
if OCCT_VERSION == "7.8.1":
patches.append("./patches/occt/no_ExpToCasExe_7_8_1.patch")
if "wasm" in flags:
patches.append("./patches/occt/no_em_js.patch")
@@ -821,7 +830,6 @@ os.makedirs(IFCOS_DIR, exist_ok=True)
executables_dir = os.path.join(IFCOS_DIR, "executables")
os.makedirs(executables_dir, exist_ok=True)
OFF_ON = ["OFF", "ON"]
cmake_args = [
"-DUSE_MMAP=" "OFF",
@@ -963,7 +971,7 @@ if "IfcOpenShell-Python" in targets:
logger.info(f"\rBuilding python {python_version} wrapper... ")
run([make, f"-j{IFCOS_NUM_BUILD_PROCS}", "_ifcopenshell_wrapper"], cwd=python_dir)
run([make, f"-j{IFCOS_NUM_BUILD_PROCS}", "ifcopenshell_wrapper"], cwd=python_dir)
run([make, "install/local"], cwd=os.path.join(python_dir, "ifcwrap"))
if python_executable:
@@ -0,0 +1,13 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1bacca1a48..11f931ad39 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -820,6 +820,8 @@ else()
OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE")
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
@@ -0,0 +1,13 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 86905287dc..9d0bce984c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -828,6 +828,8 @@ else()
OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE")
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
+1 -1
View File
@@ -4,7 +4,7 @@ include = '''
src/(
bcf
|bcfserver
|blenderbim
|bonsai
|bsdd
|foundationserver
|ifc2ca
+2 -2
View File
@@ -30,8 +30,8 @@ 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:
+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.
+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.float64], *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 (
+111 -6
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)
@@ -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.
@@ -228,7 +333,7 @@ def build_viewpoint_from_position_and_guids(position: NDArray[np.float64], *guid
"""
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.
+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.float64], *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 (
+119 -8
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)
@@ -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()),
@@ -222,7 +333,7 @@ def build_viewpoint_from_position_and_guids(position: NDArray[np.float64], *guid
"""
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.
+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,181 +0,0 @@
import sys
import os
import webbrowser
blenderbim_lib_path = os.environ.get("BLENDERBIM_LIB_PATH")
blenderbim_version = os.environ.get("BLENDERBIM_VERSION")
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.get("blenderId", None),
)
async def on_get_svg(self, sid, data):
print("hello world!")
file_path = data["path"]
with open(file_path, "r") as file:
svg_data = file.read()
await sio.emit("svg_data", svg_data, room=sid, namespace="/web")
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")
async def on_drawings_data(self, sid, data):
print(f"Drawings directory from Blender client {sid}")
print(data)
blender_messages[sid]["drwings_data"] = data
await sio.emit("drawings_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, "version": blenderbim_version})
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, "version": blenderbim_version})
return web.Response(text=html_content, content_type="text/html")
async def drawings(request):
with open("templates/drawings.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 on_startup(app):
pid_file = "running_pid.json"
if os.path.exists(pid_file):
with open(pid_file, "r") as f:
pids = json.load(f)
else:
pids = {}
pids[str(os.getpid())] = sio_port
with open(pid_file, "w") as f:
json.dump(pids, f, indent=4)
app.router.add_get("/", index)
app.router.add_get("/drawings", drawings)
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(on_startup)
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,410 +0,0 @@
:root {
--font-family: Arial, sans-serif;
--base-font-size: 16px;
--margin-tiny: 0.125rem;
--margin-small: 0.625rem;
--margin-medium: 1.25rem;
--margin-large: 2.5rem;
--padding-tiny: 0.125rem;
--padding-small: 0.625rem;
--padding-medium: 1rem;
--font-size-small: 1rem;
--font-size-large: 1.2rem;
--logo-height: 2.5rem;
--nav-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;
--details-border-color: #464444;
}
: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;
--details-border-color: #222;
}
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);
display: flex;
flex-direction: column;
min-height: 100vh;
}
#container {
flex: 1;
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-tiny);
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;
}
#client-list {
position: absolute;
top: calc(0 + var(--nav-height));
overflow-y: auto;
overflow: hidden;
transition: opacity 0.3s ease-out, visibility 0.3s ease-out;
border: 1px solid var(--table-border-color);
background-color: var(--nav-bg-color);
z-index: 1;
opacity: 0;
visibility: hidden;
width: auto;
}
#client-list.show {
opacity: 1;
visibility: visible;
}
#connected-list-div {
display: inline-block;
}
.client {
padding: var(--margin-small);
border-bottom: 1px solid var(--table-border-color);
cursor: pointer;
}
.client-details {
max-height: 0;
overflow: hidden;
padding-left: var(--padding-small);
transition: max-height 0.2s ease-out, padding 0.2s ease-out, opacity 0.1s ease-out;
background-color: var(--nav-bg-color);
margin-top: var(--margin-tiny);
opacity: 0;
}
.client-details.show {
max-height: none;
opacity: 1;
}
.client-detail {
border-bottom: 1px solid var(--table-border-color);
padding: var(--padding-small);
}
#show-connected-button {
width: auto;
background-color: var(--bg-color);
border: none;
font-size: var(--base-font-size);
}
#show-connected-button:hover,
.scroll-button:hover {
cursor: pointer;
}
.scroll-button {
font-size: var(--base-font-size);
margin-left: var(--margin-tiny);
margin-top: var(--margin-small);
}
footer {
background-color: var(--nav-bg-color);
text-align: right;
padding: var(--padding-tiny);
border-top: 1px solid var(--nav-border-color);
}
footer p {
margin: 0;
color: var(--text-color);
margin-right: var(--margin-small);
font-size: 0.8rem;
}
.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,224 +0,0 @@
:root {
--font-family: Arial, sans-serif;
--base-font-size: 16px;
--margin-tiny: 0.125rem;
--margin-small: 0.625rem;
--margin-medium: 1.25rem;
--margin-large: 2.5rem;
--padding-tiny: 0.125rem;
--padding-small: 0.625rem;
--padding-medium: 1rem;
--font-size-large: 1.2rem;
--logo-height: 2.5rem;
--nav-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;
--table-border-color: #464444;
}
: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;
--table-border-color: #222;
}
html {
font-size: var(--base-font-size);
}
body {
background-color: var(--bg-color);
color: var(--text-color);
margin: 0;
font-family: var(--font-family);
display: flex;
flex-direction: column;
min-height: 100vh;
}
#container {
flex: 1;
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);
height: var(--nav-height);
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-tiny);
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;
}
#client-list {
position: absolute;
top: calc(0 + var(--nav-height));
overflow-y: auto;
overflow: hidden;
transition: opacity 0.3s ease-out, visibility 0.3s ease-out;
border: 1px solid var(--table-border-color);
background-color: var(--nav-bg-color);
z-index: 1;
opacity: 0;
visibility: hidden;
width: auto;
}
#client-list.show {
opacity: 1;
visibility: visible;
}
#connected-list-div {
display: inline-block;
}
.client {
padding: var(--margin-small);
border-bottom: 1px solid var(--table-border-color);
cursor: pointer;
}
.client-details {
max-height: 0;
overflow: hidden;
padding-left: var(--padding-small);
transition: max-height 0.2s ease-out, padding 0.2s ease-out, opacity 0.1s ease-out;
background-color: var(--nav-bg-color);
margin-top: var(--margin-tiny);
opacity: 0;
}
.client-details.show {
max-height: none;
opacity: 1;
}
.client-detail {
border-bottom: 1px solid var(--table-border-color);
padding: var(--padding-small);
}
#show-connected-button {
width: auto;
background-color: var(--bg-color);
border: none;
font-size: var(--base-font-size);
}
#show-connected-button:hover,
.scroll-button:hover {
cursor: pointer;
}
.scroll-button {
font-size: var(--base-font-size);
margin-left: var(--margin-tiny);
margin-top: var(--margin-small);
}
footer {
background-color: var(--nav-bg-color);
text-align: right;
padding: var(--padding-tiny);
border-top: 1px solid var(--nav-border-color);
}
footer p {
margin: 0;
color: var(--text-color);
margin-right: var(--margin-small);
font-size: 0.8rem;
}
.table-container {
margin-bottom: var(--margin-large);
}
.csv-table {
margin-top: var(--margin-small);
}
/* ------------ 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 var(--table-border-color);
border-bottom: 2px solid var(--table-border-color);
}
@@ -1,466 +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);
}
$("#blender-count").text(function (i, text) {
return parseInt(text, 10) - 1;
});
}
// 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,
ifc_file: filename,
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,
ifc_file: filename,
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) {
$("#blender-count").text(function (i, text) {
return parseInt(text, 10) + 1;
});
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");
}
}
function toggleClientList() {
var clientList = $("#client-list");
if (clientList.hasClass("show")) {
clientList.removeClass("show");
return;
}
clientList.empty();
$.each(connectedClients, function (id, client) {
if (!client.shown) return;
const dropdownIcon = $("<i>")
.addClass("fas fa-chevron-down")
.css("margin-left", "0.5rem");
const clientDiv = $("<div>").addClass("client").text(client.ifc_file);
clientDiv.append(dropdownIcon);
const clientDetailsDiv = $("<div>").addClass("client-details");
if (id) {
const clientId = $("<div>")
.addClass("client-detail")
.text(`Blender ID: ${id}`);
clientDetailsDiv.append(clientId);
}
if (client.workSchedule && client.gantt) {
const clientScheduleName = $("<div>")
.addClass("client-detail")
.text(`Schedule Name: ${client.workSchedule.Name}`);
const clientScheduleDate = $("<div>")
.addClass("client-detail")
.text(
`Schedule Date: ${new Date(
client.workSchedule.CreationDate
).toLocaleDateString()}`
);
const scrollButton = $("<button>")
.addClass("scroll-button")
.text("Scroll to Gantt Chart")
.on("click", function () {
$("html, body").animate(
{
scrollTop: $("#gantt-" + id).offset().top,
},
600
);
clientList.removeClass("show");
});
clientDetailsDiv.append(clientScheduleName);
clientDetailsDiv.append(clientScheduleDate);
clientDetailsDiv.append(scrollButton);
}
clientDiv.append(clientDetailsDiv);
clientDiv.on("click", function () {
clientDetailsDiv.toggleClass("show");
});
clientList.append(clientDiv);
});
clientList.addClass("show");
}
@@ -1,56 +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>
<li><a href="/drawings">Drawings</a></li>
</ul>
<button id="toggle-theme" onclick="toggleTheme()">
<i class="fas fa-moon"></i>
</button>
</nav>
<div id="connected-list-div">
<button id="show-connected-button" onclick="toggleClientList()">
Connected Blenders:
<span id="blender-count">0</span>
<i class="fas fa-chevron-down"></i>
</button>
<div id="client-list"></div>
</div>
<div id="container"></div>
<footer>
<p>BlenderBIM Version: {{version}}</p>
</footer>
</body>
</html>
@@ -1,60 +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
from blenderbim.bim.prop import StrProperty, Attribute
from blenderbim.bim.module.spatial.data import SpatialData
from bpy.types import PropertyGroup
from bpy.props import (
PointerProperty,
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
CollectionProperty,
)
def update_relating_object(self, context):
def message(self, context):
self.layout.label(text="Please select a valid IFC Element")
if self.relating_object:
self.related_object = None
if not self.relating_object.BIMObjectProperties.ifc_definition_id:
context.window_manager.popup_menu(message, title="Invalid Element Selected", icon="INFO")
self.relating_object = None
def update_related_object(self, context):
def message(self, context):
self.layout.label(text="Please select a valid IFC Element")
if self.related_object:
self.relating_object = None
if not self.related_object.BIMObjectProperties.ifc_definition_id:
context.window_manager.popup_menu(message, title="Invalid Element Selected", icon="INFO")
self.related_object = None
class BIMObjectAggregateProperties(PropertyGroup):
is_editing: BoolProperty(name="Is Editing")
relating_object: PointerProperty(name="Relating Whole", type=bpy.types.Object, update=update_relating_object)
related_object: PointerProperty(name="Related Part", type=bpy.types.Object, update=update_related_object)
@@ -1,308 +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 os
import bpy
import blenderbim.tool as tool
import blenderbim.bim.module.type.prop as type_prop
import ifcopenshell.util.unit
from bpy.types import WorkSpaceTool
from blenderbim.bim.module.model.data import AuthoringData, RailingData, RoofData
class CadTool(WorkSpaceTool):
bl_space_type = "VIEW_3D"
bl_context_mode = "EDIT_MESH"
bl_idname = "bim.cad_tool"
bl_label = "CAD Tool"
bl_description = "Gives you CAD authoring related superpowers"
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.cad")
bl_widget = None
bl_keymap = tool.Blender.get_default_selection_keypmap() + (
("bim.cad_hotkey", {"type": "C", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_C")]}),
("bim.cad_hotkey", {"type": "E", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_E")]}),
("bim.cad_hotkey", {"type": "F", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_F")]}),
("bim.cad_hotkey", {"type": "O", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_O")]}),
("bim.cad_hotkey", {"type": "Q", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_Q")]}),
("bim.cad_hotkey", {"type": "R", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_R")]}),
("bim.cad_hotkey", {"type": "T", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_T")]}),
("bim.cad_hotkey", {"type": "V", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_V")]}),
("bim.cad_hotkey", {"type": "X", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_X")]}),
)
def draw_settings(context, layout, workspace_tool):
obj = context.active_object
if not obj or not obj.data:
return
if hasattr(obj.data, "BIMMeshProperties") and obj.data.BIMMeshProperties.subshape_type == "PROFILE":
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_Q")
element = tool.Ifc.get_entity(obj)
if element:
if element.is_a("IfcProfileDef"):
row.operator("bim.edit_arbitrary_profile", text="Save Profile")
row.operator("bim.align_view_to_profile", text="", icon="AXIS_FRONT")
row.operator("bim.disable_editing_arbitrary_profile", text="", icon="CANCEL")
elif element.is_a("IfcRelSpaceBoundary"):
row.operator("bim.edit_boundary_geometry", text="Save Profile")
row.operator("bim.disable_editing_boundary_geometry", text="", icon="CANCEL")
else:
row.operator("bim.edit_extrusion_profile", text="Save Profile")
row.operator("bim.align_view_to_profile", text="", icon="AXIS_FRONT")
row.operator("bim.disable_editing_extrusion_profile", text="", icon="CANCEL")
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_E")
row.operator("bim.cad_hotkey", text="Extend").hotkey = "S_E"
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_T")
row.operator("bim.cad_hotkey", text="Mitre").hotkey = "S_T"
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_F")
row.operator("bim.cad_hotkey", text="Fillet").hotkey = "S_F"
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_O")
row.operator("bim.cad_hotkey", text="Offset").hotkey = "S_O"
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_R")
row.operator("bim.add_rectangle", text="Rectangle")
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_C")
row.operator("bim.add_ifccircle", text="Circle")
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_V")
row.operator("bim.set_arc_index", text="3-Point Arc")
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_X")
row.operator("bim.reset_vertex", text="Reset Vertex")
elif hasattr(obj.data, "BIMMeshProperties") and obj.data.BIMMeshProperties.subshape_type == "AXIS":
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_Q")
row.operator("bim.edit_extrusion_axis", text="Save Axis")
row.operator("bim.disable_editing_extrusion_axis", text="", icon="CANCEL")
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_E")
row.operator("bim.cad_hotkey", text="Extend").hotkey = "S_E"
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_T")
row.operator("bim.cad_hotkey", text="Mitre").hotkey = "S_T"
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_F")
row.operator("bim.cad_hotkey", text="Fillet").hotkey = "S_F"
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_O")
row.operator("bim.cad_hotkey", text="Offset").hotkey = "S_O"
else:
if (
(RailingData.is_loaded or not RailingData.load())
and RailingData.data["pset_data"]
and context.active_object.BIMRailingProperties.is_editing_path
):
row = layout.row(align=True)
row.label(text="", icon=f"EVENT_TAB")
row.operator("bim.finish_editing_railing_path")
row.operator("bim.cancel_editing_railing_path", icon="CANCEL", text="")
elif (
(RoofData.is_loaded or not RoofData.load())
and RoofData.data["pset_data"]
and context.active_object.BIMRoofProperties.is_editing_path
):
row = layout.row(align=True)
row.label(text="", icon=f"EVENT_TAB")
row.operator("bim.finish_editing_roof_path")
row.operator("bim.cancel_editing_roof_path", icon="CANCEL", text="")
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_R")
row.operator("bim.cad_hotkey", text="Set Gable Roof Angle").hotkey = "S_R"
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_E")
row.operator("bim.cad_hotkey", text="Extend").hotkey = "S_E"
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_T")
row.operator("bim.cad_hotkey", text="Mitre").hotkey = "S_T"
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_F")
row.operator("bim.cad_hotkey", text="Fillet").hotkey = "S_F"
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_O")
row.operator("bim.cad_hotkey", text="Offset").hotkey = "S_O"
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="2-Point Arc", icon="EVENT_C")
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_V")
row.operator("bim.cad_hotkey", text="3-Point Arc").hotkey = "S_V"
class CadHotkey(bpy.types.Operator):
bl_idname = "bim.cad_hotkey"
bl_label = "CAD Hotkey"
bl_options = {"REGISTER", "UNDO"}
hotkey: bpy.props.StringProperty()
def execute(self, context):
self.props = context.scene.BIMCadProperties
getattr(self, f"hotkey_{self.hotkey}")()
return {"FINISHED"}
def draw(self, context):
props = context.scene.BIMCadProperties
if self.hotkey == "S_C":
if self.is_profile():
row = self.layout.row()
row.prop(props, "radius")
elif self.hotkey == "S_F":
if not self.is_profile():
row = self.layout.row()
row.prop(props, "resolution")
row = self.layout.row()
row.prop(props, "radius")
elif self.hotkey == "S_O":
row = self.layout.row()
row.prop(props, "distance")
elif self.hotkey == "S_R":
if self.is_profile():
row = self.layout.row()
row.prop(props, "x")
row = self.layout.row()
row.prop(props, "y")
elif (
(RoofData.is_loaded or not RoofData.load())
and RoofData.data["pset_data"]
and bpy.context.active_object.BIMRoofProperties.is_editing_path
):
self.layout.row().prop(props, "gable_roof_edge_angle")
self.layout.row().prop(props, "gable_roof_separate_verts")
elif self.hotkey == "S_V":
if not self.is_profile():
row = self.layout.row()
row.prop(props, "resolution")
def hotkey_S_C(self):
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
if self.is_profile():
bpy.ops.bim.add_ifccircle(radius=self.props.radius / si_conversion)
else:
bpy.ops.bim.cad_arc_from_2_points()
def hotkey_S_E(self):
bpy.ops.bim.cad_trim_extend()
def hotkey_S_F(self):
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
if self.is_profile():
bpy.ops.bim.add_ifcarcindex_fillet(radius=self.props.radius / si_conversion)
else:
bpy.ops.bim.cad_fillet(resolution=self.props.resolution, radius=self.props.radius / si_conversion)
def hotkey_S_O(self):
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
bpy.ops.bim.cad_offset(distance=self.props.distance / si_conversion)
def hotkey_S_Q(self):
element = tool.Ifc.get_entity(bpy.context.active_object)
if bpy.context.active_object.data.BIMMeshProperties.subshape_type == "PROFILE":
if element.is_a("IfcProfileDef"):
bpy.ops.bim.edit_arbitrary_profile()
elif element.is_a("IfcRelSpaceBoundary"):
bpy.ops.bim.edit_boundary_geometry()
else:
bpy.ops.bim.edit_extrusion_profile()
elif bpy.context.active_object.data.BIMMeshProperties.subshape_type == "AXIS":
bpy.ops.bim.edit_extrusion_axis()
def hotkey_S_R(self):
if self.is_profile():
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
bpy.ops.bim.add_rectangle(x=self.props.x / si_conversion, y=self.props.y / si_conversion)
elif (
(RoofData.is_loaded or not RoofData.load())
and RoofData.data["pset_data"]
and bpy.context.active_object.BIMRoofProperties.is_editing_path
):
bpy.ops.bim.set_gable_roof_edge_angle(
angle=self.props.gable_roof_edge_angle, separate_verts=self.props.gable_roof_separate_verts
)
def hotkey_S_T(self):
bpy.ops.bim.cad_mitre()
def hotkey_S_V(self):
if self.is_profile():
bpy.ops.bim.set_arc_index()
else:
bpy.ops.bim.cad_arc_from_3_points(resolution=self.props.resolution)
def hotkey_S_X(self):
if self.is_profile():
bpy.ops.bim.reset_vertex()
def is_profile(self):
obj = bpy.context.active_object
return (
obj
and obj.data
and hasattr(obj.data, "BIMMeshProperties")
and obj.data.BIMMeshProperties.subshape_type == "PROFILE"
)
@@ -1,27 +0,0 @@
[
{
"ceiling": {
"Black Ceiling 1": "void plastic black_ceiling\n0\n0\n5 0.0460 0.0456 0.0463 0.0052 0.2000",
"Black Ceiling 2": "void plastic black_ceiling\n0\n0\n5 0.1116 0.1085 0.0938 0.0000 0.0000",
"Plastic Ceiling Vent E14 526": "void plastic plastic_ceiling_vent_e14_526\n0\n0\n5 0.7384 0.7195 0.6540 0.0110 0.0500",
"Specular Reflective Ceiling Panels": "void plastic specular_reflective_ceiling_panels\n0\n0\n5 0.7708 0.7673 0.6819 0.0741 0.0500"
},
"Door": {
"Wooden Door": "void plastic wooden_door\n0\n0\n5 0.6164 0.4257 0.2156 0.0185 0.2000",
"Wooden Door 2": "void plastic wooden_door_2\n0\n0\n5 0.0403 0.0388 0.0406 0.0121 0.2000",
"White Wooden Door": "void plastic white_wooden_door\n0\n0\n5 0.7893 0.7502 0.6413 0.0080 0.2000",
"Off White Door": "void plastic off_white_door\n0\n0\n5 0.8607 0.8611 0.7852 0.0258 0.2000",
"Bedroom Door": "void plastic bedroom_door\n0\n0\n5 0.2508 0.0782 0.0111 0.0279 0.2000"
},
"Floor": {
"Light Blue Ceramic": "void plastic light_blue_ceramic\n0\n0\n5 0.7477 0.7776 0.7807 0.0323 0.1000",
"Light Grey Ceramic": "void plastic light_grey_ceramic\n0\n0\n5 0.6386 0.5941 0.4982 0.0106 0.2000",
"Purple Carpet": "void plastic purple_carpet\n0\n0\n5 0.0425 0.0179 0.0371 0.0001 0.3000"
},
"Wall": {
"Dirty Dark Pink Painted Wall": "void plastic dirty_dark_pink_painted_wall\n0\n0\n5 0.3533 0.1751 0.1690 0.0000 0.2000",
"Blue Green Painted Walls": "void plastic blue_green_painted_walls\n0\n0\n5 -0.0013 0.2092 0.2601 0.0140 0.2000",
"Red Painted Wall": "void plastic red_painted_wall\n0\n0\n5 0.4621 0.0156 0.0091 0.0396 0.2000"
}
}
]
@@ -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,81 +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 ifcopenshell
import ifcopenshell.api
from blenderbim.bim.module.model import root, product, wall, slab, profile, opening, task
from blenderbim.bim.ifc import IfcStore
from bpy.app.handlers import persistent
@persistent
def load_post(*args):
ifcopenshell.api.add_pre_listener("attribute.edit_attributes", "BlenderBIM.Root.SyncName", root.sync_name)
ifcopenshell.api.add_pre_listener("style.edit_presentation_style", "BlenderBIM.Root.SyncStyleName", root.sync_name)
ifcopenshell.api.add_post_listener(
"geometry.add_representation", "BlenderBIM.Product.GenerateBox", product.generate_box
)
ifcopenshell.api.add_post_listener(
"sequence.edit_task_time", "BlenderBIM.Task.CalculateQuantities", task.calculate_quantities
)
ifcopenshell.api.add_post_listener(
"material.edit_profile_usage",
"BlenderBIM.Product.RegenerateProfileUsage",
product.regenerate_profile_usage,
)
ifcopenshell.api.add_post_listener(
"geometry.add_representation", "BlenderBIM.DumbWall.CalculateQuantities", wall.calculate_quantities
)
ifcopenshell.api.add_post_listener(
"material.edit_layer", "BlenderBIM.DumbWall.RegenerateFromLayer", wall.DumbWallPlaner().regenerate_from_layer
)
ifcopenshell.api.add_post_listener(
"type.assign_type", "BlenderBIM.DumbWall.RegenerateFromType", wall.DumbWallPlaner().regenerate_from_type
)
ifcopenshell.api.add_post_listener(
"geometry.add_representation", "BlenderBIM.DumbSlab.CalculateQuantities", slab.calculate_quantities
)
ifcopenshell.api.add_post_listener(
"material.edit_layer", "BlenderBIM.DumbSlab.RegenerateFromLayer", slab.DumbSlabPlaner().regenerate_from_layer
)
ifcopenshell.api.add_post_listener(
"type.assign_type", "BlenderBIM.DumbSlab.RegenerateFromType", slab.DumbSlabPlaner().regenerate_from_type
)
ifcopenshell.api.add_post_listener(
"material.edit_profile",
"BlenderBIM.DumbProfile.RegenerateFromProfile",
profile.DumbProfileRegenerator().regenerate_from_profile,
)
ifcopenshell.api.add_post_listener(
"type.assign_type",
"BlenderBIM.DumbProfile.RegenerateFromType",
profile.DumbProfileRegenerator().regenerate_from_type,
)
ifcopenshell.api.add_post_listener(
"type.assign_type",
"BlenderBIM.Opening.RegenerateFromType",
opening.FilledOpeningGenerator().regenerate_from_type,
)
@@ -1,90 +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 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.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,870 +0,0 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2020, 2021, 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 os
import bpy
import blenderbim.tool as tool
import blenderbim.core.model as core
from blenderbim.bim.module.model.wall import DumbWallJoiner
from blenderbim.bim.helper import prop_with_search
from bpy.types import WorkSpaceTool
from blenderbim.bim.module.model.data import AuthoringData
from blenderbim.bim.module.system.data import PortData
from blenderbim.bim.module.model.prop import get_ifc_class
class BimTool(WorkSpaceTool):
bl_space_type = "VIEW_3D"
bl_context_mode = "OBJECT"
bl_idname = "bim.bim_tool"
bl_label = "Create Element"
bl_description = "Gives you BIM authoring related superpowers"
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.bim")
bl_widget = None
bl_keymap = tool.Blender.get_default_selection_keypmap() + (
# ("bim.wall_tool_op", {"type": 'MOUSEMOVE', "value": 'ANY'}, {"properties": []}),
# ("mesh.add_wall", {"type": 'LEFTMOUSE', "value": 'PRESS'}, {"properties": []}),
# ("bim.sync_modeling", {"type": 'MOUSEMOVE', "value": 'ANY'}, {"properties": []}),
("bim.hotkey", {"type": "A", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_A")]}),
("bim.hotkey", {"type": "B", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_B")]}),
("bim.hotkey", {"type": "C", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_C")]}),
("bim.hotkey", {"type": "E", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_E")]}),
("bim.hotkey", {"type": "F", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_F")]}),
("bim.hotkey", {"type": "G", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_G")]}),
("bim.hotkey", {"type": "K", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_K")]}),
("bim.hotkey", {"type": "M", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_M")]}),
("bim.hotkey", {"type": "O", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_O")]}),
("bim.hotkey", {"type": "L", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_L")]}),
("bim.hotkey", {"type": "Q", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_Q")]}),
("bim.hotkey", {"type": "R", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_R")]}),
("bim.hotkey", {"type": "T", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_T")]}),
("bim.hotkey", {"type": "V", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_V")]}),
("bim.hotkey", {"type": "X", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_X")]}),
("bim.hotkey", {"type": "Y", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_Y")]}),
("bim.hotkey", {"type": "D", "value": "PRESS", "alt": True}, {"properties": [("hotkey", "A_D")]}),
("bim.hotkey", {"type": "E", "value": "PRESS", "alt": True}, {"properties": [("hotkey", "A_E")]}),
("bim.hotkey", {"type": "O", "value": "PRESS", "alt": True}, {"properties": [("hotkey", "A_O")]}),
("bim.hotkey", {"type": "P", "value": "PRESS", "ctrl": True}, {"properties": [("hotkey", "C_P")]}),
("bim.hotkey", {"type": "P", "value": "PRESS", "alt": True}, {"properties": [("hotkey", "A_P")]}),
)
def draw_settings(context, layout, ws_tool):
# Unlike operators, Blender doesn't treat workspace tools as a class, so we'll create our own.
BimToolUI.draw(context, layout, ifc_element_type="all")
class WallTool(BimTool):
bl_space_type = "VIEW_3D"
bl_context_mode = "OBJECT"
bl_idname = "bim.wall_tool"
bl_label = "Create Wall"
bl_description = "Create and edit walls"
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.wall")
bl_widget = None
ifc_element_type = "IfcWallType"
@classmethod
def draw_settings(cls, context, layout, ws_tool):
BimToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
class SlabTool(BimTool):
bl_space_type = "VIEW_3D"
bl_context_mode = "OBJECT"
bl_idname = "bim.slab_tool"
bl_label = "Create Slab"
bl_description = "Create and edit slabs"
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.slab")
bl_widget = None
ifc_element_type = "IfcSlabType"
@classmethod
def draw_settings(cls, context, layout, ws_tool):
BimToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
class DoorTool(BimTool):
bl_space_type = "VIEW_3D"
bl_context_mode = "OBJECT"
bl_idname = "bim.door_tool"
bl_label = "Create Door"
bl_description = "Create and edit doors"
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.door")
bl_widget = None
ifc_element_type = "IfcDoorType"
@classmethod
def draw_settings(cls, context, layout, ws_tool):
BimToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
class WindowTool(BimTool):
bl_space_type = "VIEW_3D"
bl_context_mode = "OBJECT"
bl_idname = "bim.window_tool"
bl_label = "Create Window"
bl_description = "Create and edit windows"
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.window")
bl_widget = None
ifc_element_type = "IfcWindowType"
@classmethod
def draw_settings(cls, context, layout, ws_tool):
BimToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
class ColumnTool(BimTool):
bl_space_type = "VIEW_3D"
bl_context_mode = "OBJECT"
bl_idname = "bim.column_tool"
bl_label = "Create Column"
bl_description = "Create and edit columns"
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.column")
bl_widget = None
ifc_element_type = "IfcColumnType"
@classmethod
def draw_settings(cls, context, layout, ws_tool):
BimToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
class BeamTool(BimTool):
bl_space_type = "VIEW_3D"
bl_context_mode = "OBJECT"
bl_idname = "bim.beam_tool"
bl_label = "Create Beam"
bl_description = "Create and edit beams"
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.beam")
bl_widget = None
ifc_element_type = "IfcBeamType"
@classmethod
def draw_settings(cls, context, layout, ws_tool):
BimToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
class DuctTool(BimTool):
bl_space_type = "VIEW_3D"
bl_context_mode = "OBJECT"
bl_idname = "bim.duct_tool"
bl_label = "Create Duct"
bl_description = "Create and edit ducks" # No, not a typo.
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.duct")
bl_widget = None
ifc_element_type = "IfcDuctSegmentType"
@classmethod
def draw_settings(cls, context, layout, ws_tool):
BimToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
class CableCarrierTool(BimTool):
bl_space_type = "VIEW_3D"
bl_context_mode = "OBJECT"
bl_idname = "bim.cable_carrier_tool"
bl_label = "Create Cable Carrier"
bl_description = "Create and edit cable carriers"
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.cablecarrier")
bl_widget = None
ifc_element_type = "IfcCableCarrierSegmentType"
@classmethod
def draw_settings(cls, context, layout, ws_tool):
BimToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
class PipeTool(BimTool):
bl_space_type = "VIEW_3D"
bl_context_mode = "OBJECT"
bl_idname = "bim.pipe_tool"
bl_label = "Create Pipe"
bl_description = "Create and edit pipes"
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.pipe")
bl_widget = None
ifc_element_type = "IfcPipeSegmentType"
@classmethod
def draw_settings(cls, context, layout, ws_tool):
BimToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
class CableTool(BimTool):
bl_space_type = "VIEW_3D"
bl_context_mode = "OBJECT"
bl_idname = "bim.cable_tool"
bl_label = "Create Cable"
bl_description = "Create and edit cables"
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.cable")
bl_widget = None
ifc_element_type = "IfcCableSegmentType"
@classmethod
def draw_settings(cls, context, layout, ws_tool):
BimToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
def add_layout_hotkey_operator(layout, text, hotkey, description):
modifiers = {
"A": "EVENT_ALT",
"C": "EVENT_CTRL",
"S": "EVENT_SHIFT",
}
modifier, key = hotkey.split("_")
row = layout.row(align=True)
row.label(text="", icon=modifiers[modifier])
row.label(text="", icon=f"EVENT_{key}")
op = row.operator("bim.hotkey", text=text)
op.hotkey = hotkey
op.description = description
return op
class BimToolUI:
@classmethod
def draw(cls, context, layout, ifc_element_type=None):
cls.layout = layout
cls.props = context.scene.BIMModelProperties
row = cls.layout.row(align=True)
if not tool.Ifc.get():
row.label(text="No IFC Project", icon="ERROR")
return
if not PortData.is_loaded:
PortData.load()
if not AuthoringData.is_loaded:
AuthoringData.load(ifc_element_type)
elif ifc_element_type == "all" and AuthoringData.data["ifc_element_type"] is not None:
AuthoringData.load("all")
elif AuthoringData.data["ifc_element_type"] != ifc_element_type:
AuthoringData.load(ifc_element_type)
if context.region.type == "TOOL_HEADER":
cls.draw_header_interface()
elif context.region.type in ("UI", "WINDOW"):
# same interface for both n-panel sidebar and object properties
cls.draw_basic_bim_tool_interface()
if context.active_object and context.selected_objects:
cls.draw_edit_object_interface(context)
elif not context.selected_objects:
cls.draw_create_object_interface()
@classmethod
def draw_create_object_interface(cls):
if not AuthoringData.data["relating_type_id"]:
return
if cls.props.ifc_class == "IfcWallType":
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="rl1", text="RL")
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="extrusion_depth", text="Height")
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="length", text="Length")
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="x_angle", text="X Angle")
elif cls.props.ifc_class in ("IfcSlabType", "IfcRampType", "IfcRoofType"):
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="x_angle", text="X Angle")
elif cls.props.ifc_class in ("IfcColumnType", "IfcBeamType", "IfcMemberType"):
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="cardinal_point", text="Axis")
row = cls.layout.row(align=True)
label = "Height" if cls.props.ifc_class == "IfcColumn" else "Length"
row.prop(data=cls.props, property="extrusion_depth", text=label)
elif cls.props.ifc_class in ("IfcDoorType", "IfcDoorStyle"):
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="rl1", text="RL")
elif cls.props.ifc_class in (
"IfcWindowType",
"IfcWindowStyle",
"IfcDoorType",
"IfcDoorStyle",
"IfcDuctSegmentType",
"IfcPipeSegmentType",
"IfcCableCarrierSegmentType",
"IfcCableSegmentType",
):
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="rl2", text="RL")
elif cls.props.ifc_class in ("IfcSpaceType"):
add_layout_hotkey_operator(cls.layout, "Generate", "S_G", bpy.ops.bim.generate_space.__doc__)
else:
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="rl_mode", text="RL")
@classmethod
def draw_edit_object_interface(cls, context):
if AuthoringData.data["active_material_usage"] == "LAYER2":
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="extrusion_depth", text="Height")
op = row.operator("bim.change_extrusion_depth", icon="FILE_REFRESH", text="")
op.depth = cls.props.extrusion_depth
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="length", text="Length")
op = row.operator("bim.change_layer_length", icon="FILE_REFRESH", text="")
op.length = cls.props.length
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="x_angle", text="X Angle")
op = row.operator("bim.change_extrusion_x_angle", icon="FILE_REFRESH", text="")
op.x_angle = cls.props.x_angle
add_layout_hotkey_operator(cls.layout, "Extend", "S_E", "")
add_layout_hotkey_operator(cls.layout, "Butt", "S_T", "")
add_layout_hotkey_operator(
cls.layout,
"Mitre",
"S_Y",
"Join two intersecting walls using a mitre joint.\nOther selected wall is connected to the active",
)
add_layout_hotkey_operator(cls.layout, "Merge", "S_M", bpy.ops.bim.merge_wall.__doc__)
add_layout_hotkey_operator(cls.layout, "Flip", "S_F", bpy.ops.bim.flip_wall.__doc__)
add_layout_hotkey_operator(cls.layout, "Split", "S_K", bpy.ops.bim.split_wall.__doc__)
add_layout_hotkey_operator(cls.layout, "Rotate 90", "S_R", bpy.ops.bim.rotate_90.__doc__)
add_layout_hotkey_operator(cls.layout, "Regen", "S_G", bpy.ops.bim.recalculate_wall.__doc__)
row.operator("bim.unjoin_walls", icon="X", text="")
elif AuthoringData.data["active_material_usage"] == "LAYER3":
if len(context.selected_objects) == 1:
add_layout_hotkey_operator(cls.layout, "Edit Profile", "S_E", "")
elif "LAYER2" in AuthoringData.data["selected_material_usages"]:
add_layout_hotkey_operator(cls.layout, "Extend Wall To Slab", "S_E", "")
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="x_angle", text="X Angle")
op = row.operator("bim.change_extrusion_x_angle", icon="FILE_REFRESH", text="")
op.x_angle = cls.props.x_angle
elif AuthoringData.data["active_material_usage"] == "PROFILE":
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="cardinal_point", text="Axis")
op = row.operator("bim.change_cardinal_point", icon="FILE_REFRESH", text="")
op.cardinal_point = int(cls.props.cardinal_point)
row = cls.layout.row(align=True)
label = (
"Height" if AuthoringData.data["active_class"] in ("IfcColumn", "IfcColumnStandardCase") else "Length"
)
row.prop(data=cls.props, property="extrusion_depth", text=label)
op = row.operator("bim.change_profile_depth", icon="FILE_REFRESH", text="")
op.depth = cls.props.extrusion_depth
add_layout_hotkey_operator(cls.layout, "Extend", "S_E", "")
add_layout_hotkey_operator(cls.layout, "Flip", "S_F", bpy.ops.bim.flip_object.__doc__)
if AuthoringData.data["active_class"] in (
"IfcCableCarrierSegment",
"IfcCableSegment",
"IfcDuctSegment",
"IfcPipeSegment",
):
add_layout_hotkey_operator(cls.layout, "Add Fitting", "S_Y", "")
if context.region.type != "TOOL_HEADER":
cls.layout.operator("bim.mep_add_bend")
cls.layout.operator("bim.mep_add_transition")
cls.layout.operator("bim.mep_add_obstruction")
else:
add_layout_hotkey_operator(cls.layout, "Edit Axis", "A_E", "")
add_layout_hotkey_operator(cls.layout, "Butt", "S_T", "")
add_layout_hotkey_operator(cls.layout, "Mitre", "S_Y", "")
add_layout_hotkey_operator(cls.layout, "Rotate 90", "S_R", bpy.ops.bim.rotate_90.__doc__)
add_layout_hotkey_operator(cls.layout, "Regen", "S_G", bpy.ops.bim.recalculate_profile.__doc__)
row.operator("bim.extend_profile", icon="X", text="").join_type = ""
elif (
tool.Model.is_parametric_railing_active() and not context.active_object.BIMRailingProperties.is_editing_path
):
# NOTE: should be above "active_representation_type" = "SweptSolid" check
# because it could be a SweptSolid too
row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_TAB")
row.operator("bim.enable_editing_railing_path", text="Edit Railing Path")
elif AuthoringData.data["active_class"] in (
"IfcWindow",
"IfcWindowStandardCase",
"IfcDoor",
"IfcDoorStandardCase",
):
if AuthoringData.data["active_class"] in ("IfcWindow", "IfcWindowStandardCase"):
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="rl2", text="RL")
elif AuthoringData.data["active_class"] in ("IfcDoor", "IfcDoorStandardCase"):
row = cls.layout.row(align=True)
row.prop(data=cls.props, property="rl1", text="RL")
add_layout_hotkey_operator(cls.layout, "Regen", "S_G", bpy.ops.bim.recalculate_fill.__doc__)
add_layout_hotkey_operator(cls.layout, "Flip", "S_F", "")
elif AuthoringData.data["active_representation_type"] == "SweptSolid":
if not tool.Model.is_parametric_window_active() and not tool.Model.is_parametric_door_active():
add_layout_hotkey_operator(cls.layout, "Edit Profile", "S_E", "")
elif AuthoringData.data["active_class"] in ("IfcSpace",):
add_layout_hotkey_operator(cls.layout, "Regen", "S_G", bpy.ops.bim.generate_space.__doc__)
elif tool.Model.is_parametric_roof_active() and not context.active_object.BIMRoofProperties.is_editing_path:
row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_TAB")
row.operator("bim.enable_editing_roof_path", text="Edit Roof Path")
if context.region.type != "TOOL_HEADER" and PortData.data["total_ports"] > 0:
add_layout_hotkey_operator(
cls.layout, "Regen MEP", "S_G", bpy.ops.bim.regenerate_distribution_element.__doc__
)
cls.layout.operator("bim.mep_connect_elements")
row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_O")
if len(context.selected_objects) > 1:
row.operator("bim.add_opening", text="Apply Void")
else:
row.operator("bim.add_potential_opening", text="Add Void")
if AuthoringData.data["is_voidable_element"]:
if AuthoringData.data["has_visible_openings"]:
row.operator("bim.edit_openings", icon="CHECKMARK", text="")
row.operator("bim.hide_openings", icon="CANCEL", text="")
else:
row.operator("bim.show_openings", icon="HIDE_OFF", text="")
if AuthoringData.data["active_class"] in ("IfcOpeningElement",):
row.operator("bim.edit_openings", icon="CHECKMARK", text="")
row.operator("bim.hide_openings", icon="CANCEL", text="")
if len(context.selected_objects) == 2:
row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_L")
row.operator("bim.clone_opening", text="Clone Opening")
cls.layout.row(align=True).label(text="Align")
add_layout_hotkey_operator(cls.layout, "Align Exterior", "S_X", "")
add_layout_hotkey_operator(cls.layout, "Align Centerline", "S_C", "")
add_layout_hotkey_operator(cls.layout, "Align Interior", "S_V", "")
add_layout_hotkey_operator(cls.layout, "Mirror", "S_M", bpy.ops.bim.mirror_elements.__doc__)
cls.layout.row(align=True).label(text="Mode")
add_layout_hotkey_operator(cls.layout, "Void", "A_O", "Toggle openings")
add_layout_hotkey_operator(cls.layout, "Decomposition", "A_D", "Select decomposition")
cls.layout.row(align=True).label(text="Aggregation")
add_layout_hotkey_operator(cls.layout, "Assign", "C_P", bpy.ops.bim.aggregate_assign_object.__doc__)
add_layout_hotkey_operator(cls.layout, "Unassign", "A_P", bpy.ops.bim.aggregate_unassign_object.__doc__)
cls.layout.separator()
add_layout_hotkey_operator(
cls.layout, "Perform Quantity Take-off", "S_Q", bpy.ops.bim.perform_quantity_take_off.__doc__
)
@classmethod
def draw_header_interface(cls):
cls.draw_type_selection_interface()
if AuthoringData.data["ifc_classes"]:
row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_A")
op = row.operator("bim.add_constr_type_instance", text="Add")
op.from_invoke = True
if cls.props.relating_type_id.isnumeric():
op.relating_type_id = int(cls.props.relating_type_id)
@classmethod
def draw_type_selection_interface(cls):
# shared by both sidebar and header
row = cls.layout.row(align=True)
row.label(text=f"Container: {AuthoringData.data['default_container']}", icon="OUTLINER_COLLECTION")
if AuthoringData.data["ifc_classes"]:
if not AuthoringData.data["ifc_element_type"]:
row.label(text="", icon="FILE_VOLUME")
prop_with_search(row, cls.props, "ifc_class", text="")
row = cls.layout.row(align=True)
if AuthoringData.data["relating_type_id"]:
row.label(text="", icon="FILE_3D")
prop_with_search(row, cls.props, "relating_type_id", text="")
else:
row.label(text="No Construction Type", icon="FILE_3D")
row.operator("bim.launch_type_manager", icon=tool.Blender.TYPE_MANAGER_ICON, text="")
else:
if AuthoringData.data["ifc_element_type"]:
row.label(text=f"No {AuthoringData.data['ifc_element_type']} Found", icon="ERROR")
row = cls.layout.row()
row.prop(cls.props, "type_name")
row = cls.layout.row(align=True)
op = row.operator(
"bim.add_default_type", icon="ADD", text=f"Add {AuthoringData.data['ifc_element_type']}"
)
op.ifc_element_type = AuthoringData.data["ifc_element_type"]
row.operator("bim.launch_type_manager", icon=tool.Blender.TYPE_MANAGER_ICON, text="")
else:
row.label(text="No Element Types Found", icon="ERROR")
row.operator("bim.launch_type_manager", icon=tool.Blender.TYPE_MANAGER_ICON, text="Launch Type Manager")
@classmethod
def draw_basic_bim_tool_interface(cls):
cls.draw_type_selection_interface()
if AuthoringData.data["ifc_classes"]:
if cls.props.ifc_class:
box = cls.layout.box()
if AuthoringData.data["type_thumbnail"]:
box.template_icon(icon_value=AuthoringData.data["type_thumbnail"], scale=5)
else:
op = box.operator("bim.load_type_thumbnails", text="Load Thumbnails", icon="FILE_REFRESH")
op.ifc_class = cls.props.ifc_class
row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_A")
op = row.operator("bim.add_constr_type_instance", text="Add")
op.from_invoke = True
if cls.props.relating_type_id.isnumeric():
op.relating_type_id = int(cls.props.relating_type_id)
class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.hotkey"
bl_label = "Hotkey"
bl_options = {"REGISTER", "UNDO"}
hotkey: bpy.props.StringProperty()
description: bpy.props.StringProperty()
x: bpy.props.FloatProperty(name="X", default=0.5)
y: bpy.props.FloatProperty(name="Y", default=0.5)
z: bpy.props.FloatProperty(name="Z", default=0.5)
@classmethod
def poll(cls, context):
return tool.Ifc.get()
@classmethod
def description(cls, context, operator):
return operator.description or ""
def _execute(self, context):
self.props = context.scene.BIMModelProperties
self.has_ifc_class = True
self.active_class = None
self.active_material_usage = None
element = tool.Ifc.get_entity(context.active_object)
if element:
self.active_class = element.is_a()
self.active_material_usage = tool.Model.get_usage_type(element)
if get_ifc_class(None, None):
try:
self.has_ifc_class = bool(self.props.ifc_class)
except:
pass
getattr(self, f"hotkey_{self.hotkey}")()
def invoke(self, context, event):
# https://blender.stackexchange.com/questions/276035/how-do-i-make-operators-remember-their-property-values-when-called-from-a-hotkey
self.props = context.scene.BIMModelProperties
self.x = self.props.x
self.y = self.props.y
self.z = self.props.z
return self.execute(context)
def draw(self, context):
if self.hotkey == "S_O":
row = self.layout.row()
row.prop(self, "x")
row = self.layout.row()
row.prop(self, "y")
row = self.layout.row()
row.prop(self, "z")
def hotkey_S_A(self):
bpy.ops.bim.add_constr_type_instance()
def hotkey_S_Q(self):
if not bpy.context.selected_objects:
return
bpy.ops.bim.perform_quantity_take_off()
def hotkey_C_P(self):
if not bpy.context.selected_objects:
return
bpy.ops.bim.aggregate_assign_object()
def hotkey_A_P(self):
if not bpy.context.selected_objects:
return
bpy.ops.bim.aggregate_unassign_object()
def hotkey_S_C(self):
if not bpy.context.selected_objects:
return
if self.active_material_usage == "LAYER2":
if bpy.ops.bim.align_wall.poll():
bpy.ops.bim.align_wall(align_type="CENTERLINE")
else:
bpy.ops.bim.align_product(align_type="CENTERLINE")
def hotkey_S_E(self):
if not bpy.context.selected_objects:
return
# NOTE: placing it before the other operations because railing can also be SweptSolid
# and it might conflict with one of the conditions below
if (
tool.Model.is_parametric_railing_active()
and not bpy.context.active_object.BIMRailingProperties.is_editing_path
):
bpy.ops.bim.enable_editing_railing_path()
return
elif tool.Model.is_parametric_roof_active() and not bpy.context.active_object.BIMRoofProperties.is_editing_path:
# undo the unselection done above because roof has no usage type
bpy.ops.bim.enable_editing_roof_path()
return
elif tool.Model.is_parametric_window_active() or tool.Model.is_parametric_door_active():
return
selected_usages = {}
for obj in bpy.context.selected_objects:
element = tool.Ifc.get_entity(obj)
if not element:
obj.select_set(False)
continue
usage = tool.Model.get_usage_type(element)
if not usage:
representation = tool.Geometry.get_active_representation(obj)
representation = tool.Geometry.resolve_mapped_representation(representation)
if representation and representation.RepresentationType == "SweptSolid":
usage = "SWEPTSOLID"
else:
obj.select_set(False)
continue
selected_usages.setdefault(usage, []).append(obj)
if len(bpy.context.selected_objects) == 1:
if self.active_material_usage == "LAYER3":
# Edit LAYER3 profile
if bpy.context.active_object and bpy.context.active_object.mode == "OBJECT":
bpy.ops.bim.enable_editing_extrusion_profile()
elif self.active_material_usage == "LAYER2":
# Extend LAYER2 to cursor
core.extend_walls(
tool.Ifc,
tool.Blender,
tool.Geometry,
DumbWallJoiner(),
tool.Model,
bpy.context.scene.cursor.location,
)
elif self.active_material_usage == "PROFILE":
# Extend PROFILE to cursor
bpy.ops.bim.extend_profile(join_type="T")
else:
# Edit SWEPTSOLID profile (assuming single profile for now)
bpy.ops.bim.enable_editing_extrusion_profile()
elif self.active_material_usage == "LAYER2" and selected_usages.get("PROFILE", []):
# Extend PROFILEs to LAYER2
[o.select_set(False) for o in selected_usages.get("LAYER3", [])]
[o.select_set(False) for o in selected_usages.get("LAYER2", []) if o != bpy.context.active_object]
bpy.ops.bim.extend_profile(join_type="T")
elif self.active_material_usage == "LAYER3" and selected_usages.get("LAYER2", []):
# Extend LAYER2s to LAYER3
[o.select_set(False) for o in selected_usages.get("PROFILE", [])]
[o.select_set(False) for o in selected_usages.get("LAYER3", []) if o != bpy.context.active_object]
try:
core.join_walls_TZ(tool.Ifc, tool.Blender, tool.Geometry, DumbWallJoiner(), tool.Model)
except core.RequireAtLeastTwoLayeredElements as e:
self.report({"ERROR"}, str(e))
elif self.active_material_usage == "LAYER2":
# Extend LAYER2s to LAYER2
[o.select_set(False) for o in selected_usages.get("LAYER3", [])]
[o.select_set(False) for o in selected_usages.get("PROFILE", [])]
try:
core.join_walls_TZ(tool.Ifc, tool.Blender, tool.Geometry, DumbWallJoiner(), tool.Model)
except core.RequireAtLeastTwoLayeredElements as e:
self.report({"ERROR"}, str(e))
elif self.active_material_usage == "PROFILE":
# Extend PROFILEs to PROFILE
[o.select_set(False) for o in selected_usages.get("LAYER3", [])]
[o.select_set(False) for o in selected_usages.get("LAYER2", [])]
bpy.ops.bim.extend_profile(join_type="T")
def hotkey_S_F(self):
if not bpy.context.selected_objects:
return
if self.active_material_usage == "LAYER2":
bpy.ops.bim.flip_wall()
elif self.active_class in ("IfcWindow", "IfcWindowStandardCase", "IfcDoor", "IfcDoorStandardCase"):
bpy.ops.bim.flip_fill()
elif self.active_material_usage == "PROFILE":
bpy.ops.bim.flip_object(flip_local_axes="XZ")
def hotkey_S_G(self):
obj = bpy.context.active_object
element = tool.Ifc.get_entity(obj)
if not bpy.context.selected_objects:
if self.props.ifc_class == "IfcSpaceType":
bpy.ops.bim.generate_space()
return
if self.active_material_usage == "LAYER2":
bpy.ops.bim.recalculate_wall()
elif tool.System.get_ports(element):
bpy.ops.bim.regenerate_distribution_element()
elif self.active_material_usage == "PROFILE":
if self.active_class not in (
"IfcCableCarrierSegment",
"IfcCableSegment",
"IfcDuctSegment",
"IfcPipeSegment",
):
bpy.ops.bim.recalculate_profile()
elif self.active_class in ("IfcWindow", "IfcWindowStandardCase", "IfcDoor", "IfcDoorStandardCase"):
bpy.ops.bim.recalculate_fill()
elif self.active_class in ("IfcSpace"):
bpy.ops.bim.generate_space()
def hotkey_S_M(self):
if not bpy.context.selected_objects:
return
if self.active_material_usage == "LAYER2":
bpy.ops.bim.merge_wall()
else:
if len(bpy.context.selected_objects) == 1:
self.report(
{"ERROR"},
"At least two objects must be selected: an object to be mirrored, and a mirror axis as the active object.",
)
else:
bpy.ops.bim.mirror_elements()
def hotkey_S_R(self):
if not bpy.context.selected_objects:
return
if self.active_material_usage == "LAYER2":
bpy.ops.bim.rotate_90(axis="Z")
elif self.active_class in ("IfcColumn", "IfcColumnStandardCase"):
bpy.ops.bim.rotate_90(axis="Z")
elif self.active_class in ("IfcBeam", "IfcBeamStandardCase", "IfcMember", "IfcMemberStandardCase"):
bpy.ops.bim.rotate_90(axis="Y")
def hotkey_S_K(self):
if not bpy.context.selected_objects:
return
if self.active_material_usage == "LAYER2":
bpy.ops.bim.split_wall()
def hotkey_S_T(self):
if not bpy.context.selected_objects:
return
if self.active_material_usage == "LAYER2":
try:
core.join_walls_LV(tool.Ifc, tool.Blender, tool.Geometry, DumbWallJoiner(), tool.Model, join_type="L")
except core.RequireTwoWallsError as e:
self.report({"ERROR"}, str(e))
elif self.active_material_usage == "PROFILE":
bpy.ops.bim.extend_profile(join_type="L")
def hotkey_S_V(self):
if not bpy.context.selected_objects:
return
if self.active_material_usage == "LAYER2":
bpy.ops.bim.align_wall(align_type="INTERIOR")
else:
bpy.ops.bim.align_product(align_type="POSITIVE")
def hotkey_S_X(self):
if not bpy.context.selected_objects:
return
if self.active_material_usage == "LAYER2":
if bpy.ops.bim.align_wall.poll():
bpy.ops.bim.align_wall(align_type="EXTERIOR")
else:
bpy.ops.bim.align_product(align_type="NEGATIVE")
def hotkey_S_Y(self):
if not bpy.context.selected_objects:
return
if self.active_material_usage == "LAYER2":
try:
core.join_walls_LV(tool.Ifc, tool.Blender, tool.Geometry, DumbWallJoiner(), tool.Model, join_type="V")
except core.RequireTwoWallsError as e:
self.report({"ERROR"}, str(e))
elif self.active_class in ("IfcDuctSegment", "IfcPipeSegment", "IfcCableCarrierSegment", "IfcCableSegment"):
bpy.ops.bim.fit_flow_segments()
elif self.active_material_usage == "PROFILE":
bpy.ops.bim.extend_profile(join_type="V")
def hotkey_S_B(self):
bpy.ops.bim.add_boundary()
def hotkey_S_O(self):
if len(bpy.context.selected_objects) == 2:
bpy.ops.bim.add_opening()
else:
bpy.ops.bim.add_potential_opening(x=self.x, y=self.y, z=self.z)
self.props.x = self.x
self.props.y = self.y
self.props.z = self.z
def hotkey_S_L(self):
if AuthoringData.data["active_class"] in ("IfcOpeningElement",):
if len(bpy.context.selected_objects) == 2:
bpy.ops.bim.clone_opening()
def hotkey_A_D(self):
if not bpy.context.selected_objects:
return
bpy.ops.bim.select_decomposition()
def hotkey_A_E(self):
if not bpy.context.selected_objects:
return
if self.active_material_usage == "PROFILE":
bpy.ops.bim.enable_editing_extrusion_axis()
def hotkey_A_O(self):
if not bpy.context.selected_objects:
return
if AuthoringData.data["has_visible_openings"]:
bpy.ops.bim.edit_openings()
else:
bpy.ops.bim.show_openings()
LIST_OF_TOOLS = [cls.bl_idname for cls in (BimTool.__subclasses__() + [BimTool])]
TOOLS_TO_CLASSES_MAP = {cls.bl_idname: cls.ifc_element_type for cls in BimTool.__subclasses__()}
@@ -1,78 +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 os
import bpy
import blenderbim.tool as tool
from blenderbim.bim.ifc import IfcStore
def refresh():
ProjectData.is_loaded = False
LinksData.is_loaded = False
class ProjectData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = {
"export_schema": cls.get_export_schema(),
"library_file": cls.library_file(),
"template_file": cls.template_file(),
"last_saved": cls.last_saved(),
}
cls.is_loaded = True
@classmethod
def get_export_schema(cls):
return [(s, "IFC4X3" if s == "IFC4X3_ADD2" else s, "") for s in IfcStore.schema_identifiers]
@classmethod
def library_file(cls):
files = os.listdir(os.path.join(bpy.context.scene.BIMProperties.data_dir, "libraries"))
results = [("0", "Custom Library", "")]
results.extend([(f, os.path.splitext(f)[0], "") for f in files if ".ifc" in f])
return results
@classmethod
def template_file(cls):
files = os.listdir(os.path.join(bpy.context.scene.BIMProperties.data_dir, "templates", "projects"))
results = [("0", "Blank Project", "")]
results.extend([(f, os.path.splitext(f)[0], "") for f in files if ".ifc" in f])
return results
@classmethod
def last_saved(cls):
ifc = tool.Ifc.get()
if not ifc:
return ""
try:
save_datetime = ifc.wrapped_data.header.file_name.time_stamp
save_date, save_time = save_datetime.split("T")
return f"{save_date} {':'.join(save_time.split(':')[0:2])}"
except:
return ""
class LinksData:
linked_data = {}
enable_culling = False
is_loaded = False
@@ -1,203 +0,0 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2024 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 bpy
import bmesh
import blenderbim.tool as tool
from bpy.types import SpaceView3D
from mathutils import Vector
from gpu_extras.batch import batch_for_shader
from bpy.app.handlers import persistent
@persistent
def toggle_decorations_on_load(*args):
if bpy.context.scene.BIMProjectProperties.clipping_planes:
ClippingPlaneDecorator.install(bpy.context)
else:
ClippingPlaneDecorator.uninstall()
# NOTE: ProjectDecorator cannot be loaded at reopening .blend file
# since selected_vertices and other data is stored in queried object's
# custom attributes and they get purged after Blender session is closed
# as queried object is linked from separate .blend file.
class ProjectDecorator:
installed = None
@classmethod
def install(cls, context):
if cls.installed:
cls.uninstall()
handler = cls()
cls.installed = SpaceView3D.draw_handler_add(handler, (context,), "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 __call__(self, context):
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
def transparent_color(color, alpha=0.1):
color = [i for i in color]
color[3] = alpha
return color
gpu.state.point_size_set(6)
gpu.state.blend_set("ALPHA")
self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
self.line_shader.bind() # required to be able to change uniforms of the shader
# 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")
selected_vertices = []
selected_edges = []
selected_tris = []
try:
obj = context.scene.BIMProjectProperties.queried_obj
selected_vertices = obj["selected_vertices"]
selected_edges = obj["selected_edges"]
selected_tris = obj["selected_tris"]
except:
return
if selected_edges:
self.draw_batch("LINES", selected_vertices, selected_elements_color, selected_edges)
self.draw_batch("TRIS", selected_vertices, transparent_color(selected_elements_color), selected_tris)
class ClippingPlaneDecorator:
installed = None
@classmethod
def install(cls, context):
if cls.installed:
cls.uninstall()
handler = cls()
cls.installed = SpaceView3D.draw_handler_add(handler, (context,), "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 __call__(self, context):
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
def transparent_color(color, alpha=0.1):
color = [i for i in color]
color[3] = alpha
return color
gpu.state.point_size_set(6)
gpu.state.blend_set("ALPHA")
self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
self.line_shader.bind() # required to be able to change uniforms of the shader
# 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")
selected_vertices = []
selected_edges = []
selected_tris = []
unselected_vertices = []
unselected_edges = []
unselected_tris = []
for clipping_plane in context.scene.BIMProjectProperties.clipping_planes:
obj = clipping_plane.obj
if not obj or not obj.data:
continue
if obj.mode == "EDIT":
continue # A profile decorator or something else is used here.
bm = bmesh.new()
bm.from_mesh(obj.data)
obj.data.calc_loop_triangles()
if obj.select_get():
offset = len(selected_vertices)
selected_vertices.extend([tuple(obj.matrix_world @ v.co) for v in bm.verts])
selected_edges.extend([tuple([v.index + offset for v in e.verts]) for e in bm.edges])
selected_tris.extend([tuple([i + offset for i in t.vertices]) for t in obj.data.loop_triangles])
else:
offset = len(unselected_vertices)
unselected_vertices.extend([tuple(obj.matrix_world @ v.co) for v in bm.verts])
unselected_edges.extend([tuple([v.index + offset for v in e.verts]) for e in bm.edges])
unselected_tris.extend([tuple([i + offset for i in t.vertices]) for t in obj.data.loop_triangles])
verts = [
tuple(obj.matrix_world @ Vector((0, 0, 0))),
tuple(obj.matrix_world @ Vector((0, 0, -0.5))),
tuple(obj.matrix_world @ Vector((-0.05, 0, -0.45))),
tuple(obj.matrix_world @ Vector((0.05, 0, -0.45))),
tuple(obj.matrix_world @ Vector((0, -0.05, -0.45))),
tuple(obj.matrix_world @ Vector((0, 0.05, -0.45))),
]
edges = [(0, 1), (1, 2), (1, 3), (1, 4), (1, 5)]
color = selected_elements_color if obj in context.selected_objects else special_elements_color
self.draw_batch("LINES", verts, color, edges)
if obj.mode != "EDIT":
bm.free()
if unselected_edges:
self.draw_batch("LINES", unselected_vertices, special_elements_color, unselected_edges)
self.draw_batch("TRIS", unselected_vertices, transparent_color(special_elements_color), unselected_tris)
if selected_edges:
self.draw_batch("LINES", selected_vertices, selected_elements_color, selected_edges)
self.draw_batch("TRIS", selected_vertices, transparent_color(selected_elements_color), selected_tris)
@@ -1,308 +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 ifcopenshell
import ifcopenshell.api
import ifcopenshell.util.schema
import ifcopenshell.util.element
import ifcopenshell.util.type
import blenderbim.bim.handler
import blenderbim.core.geometry
import blenderbim.core.material
import blenderbim.core.spatial
import blenderbim.core.style
import blenderbim.core.type
import blenderbim.core.root as core
import blenderbim.tool as tool
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.helper import get_enum_items
class EnableReassignClass(bpy.types.Operator):
bl_idname = "bim.enable_reassign_class"
bl_label = "Enable Reassign IFC Class"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
obj = context.active_object
self.file = IfcStore.get_file()
ifc_class = obj.name.split("/")[0]
context.active_object.BIMObjectProperties.is_reassigning_class = True
ifc_products = [
"IfcElement",
"IfcElementType",
"IfcSpatialElement",
"IfcGroup",
"IfcStructural",
"IfcPositioningElement",
"IfcContext",
"IfcAnnotation",
"IfcRelSpaceBoundary",
]
for ifc_product in ifc_products:
if ifcopenshell.util.schema.is_a(IfcStore.get_schema().declaration_by_name(ifc_class), ifc_product):
context.scene.BIMRootProperties.ifc_product = ifc_product
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
context.scene.BIMRootProperties.ifc_class = element.is_a()
context.scene.BIMRootProperties.relating_class_object = None
if hasattr(element, "PredefinedType"):
if element.PredefinedType:
context.scene.BIMRootProperties.ifc_predefined_type = element.PredefinedType
userdefined_type = ifcopenshell.util.element.get_predefined_type(element)
context.scene.BIMRootProperties.ifc_userdefined_type = userdefined_type or ""
return {"FINISHED"}
class DisableReassignClass(bpy.types.Operator):
bl_idname = "bim.disable_reassign_class"
bl_label = "Disable Reassign IFC Class"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
context.active_object.BIMObjectProperties.is_reassigning_class = False
return {"FINISHED"}
class ReassignClass(bpy.types.Operator):
bl_idname = "bim.reassign_class"
bl_label = "Reassign IFC Class"
bl_options = {"REGISTER", "UNDO"}
obj: bpy.props.StringProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
if self.obj:
objects = [bpy.data.objects.get(self.obj)]
else:
objects = set(context.selected_objects + [context.active_object])
self.file = IfcStore.get_file()
predefined_type = context.scene.BIMRootProperties.ifc_predefined_type
if predefined_type == "USERDEFINED":
predefined_type = context.scene.BIMRootProperties.ifc_userdefined_type
# NOTE: root.reassign_class
# automatically will reassign class for other occurrences of the type
# so we need to run it only for the types or non-typed elements
elements_to_reassign = set()
# need to update blender object name
# for all elements that were changed in the process
elements_to_update = set()
for obj in objects:
obj.BIMObjectProperties.is_reassigning_class = False
element = tool.Ifc.get_entity(obj)
if element.is_a("IfcTypeObject"):
elements_to_reassign.add(element)
elements_to_update.update(ifcopenshell.util.element.get_types(element))
continue
# check if element is typed
element_type = ifcopenshell.util.element.get_type(element)
if element_type:
elements_to_reassign.add(element_type)
elements_to_update.update(ifcopenshell.util.element.get_types(element_type))
continue
# non-typed element
elements_to_reassign.add(element)
# store elements to objects to update later as elements will get invalid
# after class reassignment
elements_to_update = elements_to_update | elements_to_reassign
objects_to_update = set(o for e in elements_to_update if (o := tool.Ifc.get_object(e)))
base_class = context.scene.BIMRootProperties.ifc_class
if context.scene.BIMRootProperties.ifc_product == "IfcElementType":
type_class = base_class
occurrence_classes = ifcopenshell.util.type.get_applicable_entities(type_class)
occurrence_class = None if len(occurrence_classes) == 0 else occurrence_classes[0]
else:
occurrence_class = base_class
type_classes = ifcopenshell.util.type.get_applicable_types(occurrence_class)
type_class = None if len(type_classes) == 0 else type_classes[0]
reassigned_elements = set()
for element in elements_to_reassign:
ifc_class = type_class if element.is_a("IfcTypeObject") else occurrence_class
if ifc_class is None:
self.report(
{"ERROR"},
f"Couldn't find valid class for reassigning element of class {element.is_a()} based on class {base_class}",
)
return {"CANCELLED"}
element = ifcopenshell.api.run(
"root.reassign_class",
self.file,
product=element,
ifc_class=ifc_class,
predefined_type=predefined_type,
)
reassigned_elements.add(element)
for obj in objects_to_update:
obj.name = tool.Loader.get_name(tool.Ifc.get_entity(obj))
return {"FINISHED"}
class AssignClass(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.assign_class"
bl_label = "Assign IFC Class"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Assign the IFC Class to the selected objects"
obj: bpy.props.StringProperty()
ifc_class: bpy.props.StringProperty()
predefined_type: bpy.props.StringProperty()
userdefined_type: bpy.props.StringProperty()
context_id: bpy.props.IntProperty()
should_add_representation: bpy.props.BoolProperty(default=True)
ifc_representation_class: bpy.props.StringProperty()
def _execute(self, context):
props = context.scene.BIMRootProperties
objects = [bpy.data.objects.get(self.obj)] if self.obj else context.selected_objects or [context.active_object]
if not objects:
self.report({"INFO"}, "No objects selected.")
return
ifc_class = self.ifc_class or props.ifc_class
predefined_type = self.userdefined_type if self.predefined_type == "USERDEFINED" else self.predefined_type
ifc_context = self.context_id
if not ifc_context and get_enum_items(props, "contexts", context):
ifc_context = int(props.contexts or "0") or None
if ifc_context:
ifc_context = tool.Ifc.get().by_id(ifc_context)
active_object = context.active_object
for obj in objects:
if obj.mode != "OBJECT":
self.report({"ERROR"}, "Object must be in OBJECT mode to assign class")
continue
core.assign_class(
tool.Ifc,
tool.Collector,
tool.Root,
obj=obj,
ifc_class=ifc_class,
predefined_type=predefined_type,
should_add_representation=self.should_add_representation,
context=ifc_context,
ifc_representation_class=self.ifc_representation_class,
)
context.view_layer.objects.active = active_object
class UnlinkObject(bpy.types.Operator):
bl_idname = "bim.unlink_object"
bl_label = "Unlink Object"
bl_description = (
"Unlink Blender object from it's linked IFC element.\n\n"
"You can either remove element the blender object is linked to from IFC or keep it. "
"Note that keeping the unlinked element in IFC might lead to unpredictable issues "
"and should be used only by advanced users"
)
bl_options = {"REGISTER", "UNDO"}
obj: bpy.props.StringProperty(name="Object Name")
should_delete: bpy.props.BoolProperty(name="Delete IFC Element", default=True)
skip_invoke: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
if self.obj:
objects = [bpy.data.objects.get(self.obj)]
else:
objects = context.selected_objects
objects: list[bpy.types.Object]
for obj in objects:
was_active_object = obj == context.active_object
tool.Ifc.finish_edit(obj)
element = tool.Ifc.get_entity(obj)
if element and self.should_delete:
object_name = obj.name
# Copy object, so it won't be removed by `delete_ifc_object`
obj_copy = obj.copy()
if obj.data:
obj_copy.data = obj.data.copy()
# prevent unlinking materials that might be used elsewhere
replacements: dict[bpy.types.Material, bpy.types.Material] = dict()
for material_slot in obj_copy.material_slots:
material = material_slot.material
if material is None:
continue
if material in replacements:
material_replacement = replacements[material]
# no need to copy non-ifc materials as unlinking won't do anything to them
elif tool.Ifc.get_entity(material) is None and tool.Style.get_style(material) is None:
replacements[material] = material
continue
else:
material_replacement = material.copy()
replacements[material] = material_replacement
material_slot.material = material_replacement
tool.Geometry.delete_ifc_object(obj)
obj = obj_copy
obj.name = object_name
elif element:
tool.Ifc.unlink(element)
tool.Root.unlink_object(obj)
for collection in obj.users_collection:
# Reset collection because its original collection may be removed too.
collection.objects.unlink(obj)
bpy.context.scene.collection.objects.link(obj)
if was_active_object:
tool.Blender.set_active_object(obj)
return {"FINISHED"}
def draw(self, context):
row = self.layout.row()
row.prop(self, "should_delete")
def invoke(self, context, event):
if self.skip_invoke:
return self.execute(context)
return context.window_manager.invoke_props_dialog(self)
class CopyClass(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.copy_class"
bl_label = "Copy Class"
bl_options = {"REGISTER", "UNDO"}
obj: bpy.props.StringProperty()
def _execute(self, context):
objects = [bpy.data.objects.get(self.obj)] if self.obj else context.selected_objects
for obj in objects:
core.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=obj)
blenderbim.bim.handler.refresh_ui_data()
@@ -1,138 +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
from blenderbim.bim.prop import StrProperty, Attribute
from blenderbim.bim.module.spatial.data import SpatialDecompositionData
from bpy.types import PropertyGroup
from bpy.props import (
PointerProperty,
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
CollectionProperty,
)
import blenderbim.tool as tool
import ifcopenshell
import ifcopenshell.util.element
def get_subelement_class(self, context):
if not SpatialDecompositionData.is_loaded:
SpatialDecompositionData.load()
return SpatialDecompositionData.data["subelement_class"]
def update_elevation(self, context):
if ifc_definition_id := self.ifc_definition_id:
entity = tool.Ifc.get().by_id(ifc_definition_id)
obj = tool.Ifc.get_object(entity)
if not obj:
return
obj.location.z = self.elevation
def update_name(self, context):
if ifc_definition_id := self.ifc_definition_id:
tool.Spatial.edit_container_name(tool.Ifc.get().by_id(ifc_definition_id), self.name)
def update_active_container_index(self, context):
SpatialDecompositionData.data["subelement_class"] = SpatialDecompositionData.subelement_class()
tool.Spatial.load_contained_elements()
def update_should_include_children(self, context):
tool.Spatial.load_contained_elements()
def update_container_obj(self, context):
if self.container_obj is None or not (obj := context.active_object):
return
if not (element := tool.Ifc.get_entity(self.container_obj)):
self.container_obj = None
return
if tool.Spatial.can_contain(element, obj):
return
if (
(container := ifcopenshell.util.element.get_container(element))
and (container_obj := tool.Ifc.get_object(container))
and tool.Spatial.can_contain(container, obj)
):
self.container_obj = container_obj
return
self.container_obj = None
def poll_container_obj(self, obj):
return obj is None or tool.Ifc.get_entity(obj)
class BIMObjectSpatialProperties(PropertyGroup):
is_editing: BoolProperty(name="Is Editing")
container_obj: PointerProperty(
type=bpy.types.Object, name="Container", update=update_container_obj, poll=poll_container_obj
)
class BIMContainer(PropertyGroup):
name: StringProperty(name="Name", update=update_name)
ifc_class: StringProperty(name="IFC Class")
description: StringProperty(name="Description")
long_name: StringProperty(name="Long Name")
elevation: FloatProperty(name="Elevation", subtype="DISTANCE", update=update_elevation)
level_index: IntProperty(name="Level Index")
has_children: BoolProperty(name="Has Children")
is_expanded: BoolProperty(name="Is Expanded")
ifc_definition_id: IntProperty(name="IFC Definition ID")
class Element(PropertyGroup):
name: StringProperty(name="Name")
is_class: BoolProperty(name="Is Class", default=False)
is_type: BoolProperty(name="Is Type", default=False)
ifc_definition_id: IntProperty(name="IFC Definition ID")
total: IntProperty(name="Total")
class BIMSpatialDecompositionProperties(PropertyGroup):
containers: CollectionProperty(name="Containers", type=BIMContainer)
contracted_containers: StringProperty(name="Contracted containers", default="[]")
expanded_containers: StringProperty(name="Expanded containers", default="[]")
active_container_index: IntProperty(name="Active Container Index", update=update_active_container_index)
elements: CollectionProperty(name="Elements", type=Element)
active_element_index: IntProperty(name="Active Element Index")
total_elements: IntProperty(name="Total Elements")
subelement_class: bpy.props.EnumProperty(items=get_subelement_class, name="Subelement Class")
default_container: IntProperty(name="Default Container", default=0)
should_include_children: BoolProperty(
name="Should Include Children", default=True, update=update_should_include_children
)
@property
def active_container(self):
if self.containers and self.active_container_index < len(self.containers):
return self.containers[self.active_container_index]
@property
def active_element(self):
if self.elements and self.active_element_index < len(self.elements):
return self.elements[self.active_element_index]
@@ -1,571 +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 bmesh
import ifcopenshell.util.element
import ifcopenshell.util.schema
import ifcopenshell.util.representation
import ifcopenshell.util.type
import ifcopenshell.util.unit
import ifcopenshell.api
import blenderbim.tool as tool
import blenderbim.core.geometry
import blenderbim.core.type as core
import blenderbim.core.root
from blenderbim.bim.ifc import IfcStore
class AssignType(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.assign_type"
bl_label = "Assign Type"
bl_options = {"REGISTER", "UNDO"}
relating_type: bpy.props.IntProperty()
related_object: bpy.props.StringProperty()
def _execute(self, context):
type = tool.Ifc.get().by_id(self.relating_type or int(context.active_object.BIMTypeProperties.relating_type))
related_objects = (
[bpy.data.objects.get(self.related_object)]
if self.related_object
else context.selected_objects or [context.active_object]
)
model_props = context.scene.BIMModelProperties
for obj in related_objects:
element = tool.Ifc.get_entity(obj)
core.assign_type(tool.Ifc, tool.Type, element=element, type=type)
if model_props.occurrence_name_style == "TYPE":
obj.name = tool.Model.generate_occurrence_name(type, element.is_a())
class UnassignType(bpy.types.Operator):
bl_idname = "bim.unassign_type"
bl_label = "Unassign Type"
bl_options = {"REGISTER", "UNDO"}
related_object: bpy.props.StringProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
def exclude_callback(attribute):
return attribute.is_a("IfcProfileDef") and attribute.ProfileName
self.file = IfcStore.get_file()
objs = [bpy.data.objects.get(self.related_object)] if self.related_object else context.selected_objects
for obj in objs:
element = tool.Ifc.get_entity(obj)
if not element or element.is_a("IfcElementType"):
continue
ifcopenshell.api.run("type.unassign_type", self.file, related_objects=[element])
active_representation = tool.Geometry.get_active_representation(obj)
active_context = active_representation.ContextOfItems
new_active_representation = None
if element.Representation:
representations = []
for representation in element.Representation.Representations:
resolved_representation = ifcopenshell.util.representation.resolve_representation(representation)
if representation == resolved_representation:
representations.append(representation)
else:
# We must unmap representations.
copied_representation = ifcopenshell.util.element.copy_deep(
tool.Ifc.get(),
resolved_representation,
exclude=["IfcGeometricRepresentationContext"],
exclude_callback=exclude_callback,
)
representations.append(copied_representation)
if representation.ContextOfItems == active_context:
new_active_representation = copied_representation
element.Representation.Representations = representations
if new_active_representation:
blenderbim.core.geometry.switch_representation(
tool.Ifc,
tool.Geometry,
obj=obj,
representation=new_active_representation,
should_reload=False,
is_global=False,
should_sync_changes_first=False,
)
return {"FINISHED"}
class EnableEditingType(bpy.types.Operator):
bl_idname = "bim.enable_editing_type"
bl_label = "Enable Editing Type"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
context.active_object.BIMTypeProperties.is_editing_type = True
context.active_object.BIMTypeProperties.relating_type_object = None
return {"FINISHED"}
class DisableEditingType(bpy.types.Operator):
bl_idname = "bim.disable_editing_type"
bl_label = "Disable Editing Type"
bl_options = {"REGISTER", "UNDO"}
obj: bpy.props.StringProperty()
def execute(self, context):
obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object
obj.BIMTypeProperties.is_editing_type = False
return {"FINISHED"}
class SelectType(bpy.types.Operator):
bl_idname = "bim.select_type"
bl_label = "Select Type"
bl_options = {"REGISTER", "UNDO"}
relating_type: bpy.props.IntProperty()
def execute(self, context):
if self.relating_type: # if operator button sends a relating_type, the iterator only selects this one type
element = tool.Ifc.get().by_id(self.relating_type)
obj = tool.Ifc.get_object(element)
selected_objs = [obj]
else: # else, the iterator selects all the types of all the selected objects
selected_objs = context.selected_objects
active_obj = context.active_object
selected_objs.append(active_obj) # update selected_objs so the active_obj is at the end of the list
last_relating_type_obj = None
for obj in selected_objs:
element = tool.Ifc.get_entity(obj)
relating_type = ifcopenshell.util.element.get_type(element)
if relating_type:
relating_type_obj = tool.Ifc.get_object(relating_type)
if relating_type_obj:
if relating_type_obj.hide_get():
relating_type_obj.hide_set(False)
relating_type_obj.select_set(True)
last_relating_type_obj = relating_type_obj
if not element.is_a("IfcTypeObject"):
obj.select_set(False)
context.view_layer.objects.active = last_relating_type_obj # makes the active_obj's type the active object
return {"FINISHED"}
def find_collection_in_ifcproject(self, context, collection_name):
ifc_project_collection = None
for child in context.view_layer.layer_collection.children:
if "IfcProject" in child.name:
ifc_project_collection = child
break
if ifc_project_collection:
collection_in_view_layer = ifc_project_collection.children.get(collection_name)
return collection_in_view_layer
class SelectSimilarType(bpy.types.Operator):
bl_idname = "bim.select_similar_type"
bl_label = "Select Similar Type"
bl_options = {"REGISTER", "UNDO"}
related_object: bpy.props.StringProperty()
def execute(self, context):
self.file = IfcStore.get_file()
objects = bpy.context.selected_objects
# store relating types to avoid selecting same elements multiple times
relating_types = set()
for related_object in objects:
relating_type = ifcopenshell.util.element.get_type(tool.Ifc.get_entity(related_object))
if not relating_type:
related_object.select_set(False)
continue
relating_types.add(relating_type)
for relating_type in relating_types:
related_objects = ifcopenshell.util.element.get_types(relating_type)
for element in related_objects:
obj = tool.Ifc.get_object(element)
if obj and obj in context.visible_objects:
obj.select_set(True)
return {"FINISHED"}
class SelectTypeObjects(bpy.types.Operator):
bl_idname = "bim.select_type_objects"
bl_label = "Select Type Objects"
bl_options = {"REGISTER", "UNDO"}
relating_type: bpy.props.StringProperty()
def execute(self, context):
self.file = IfcStore.get_file()
relating_type = bpy.data.objects.get(self.relating_type) if self.relating_type else context.active_object
at_least_one_selectable_typed_object = False
for element in ifcopenshell.util.element.get_types(tool.Ifc.get_entity(relating_type)):
obj = tool.Ifc.get_object(element)
if obj and obj in context.selectable_objects:
obj.select_set(True)
at_least_one_selectable_typed_object = True
if at_least_one_selectable_typed_object:
context.active_object.select_set(False)
context.view_layer.objects.active = context.selected_objects[0]
else:
self.report({"INFO"}, "Typed objects can't be selected : They may be hidden or in an excluded collection.")
return {"FINISHED"}
class AddType(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_type"
bl_label = "Add Type"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = context.scene.BIMModelProperties
ifc_class = props.type_class
predefined_type = props.type_predefined_type
name = props.type_name
template = props.type_template
ifc_file = tool.Ifc.get()
body = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW")
if not body:
props.type_class = props.type_class
self.report({"ERROR"}, "No Model/Body/MODEL_VIEW context found.")
return {"FINISHED"}
if template == "MESH":
location = context.scene.cursor.location
if context.active_object and context.selected_objects and context.active_object.data:
obj = context.active_object
element = tool.Ifc.get_entity(obj)
if element:
mesh = obj.data.copy()
mesh.BIMMeshProperties.ifc_definition_id = 0
obj = bpy.data.objects.new(element.Name or name, mesh)
else:
mesh = bpy.data.meshes.new(name)
bm = bmesh.new()
bmesh.ops.create_cube(bm, size=1)
bm.to_mesh(mesh)
bm.free()
obj = bpy.data.objects.new(name, mesh)
obj.matrix_world.translation = location
blenderbim.core.root.assign_class(
tool.Ifc,
tool.Collector,
tool.Root,
obj=obj,
ifc_class=ifc_class,
predefined_type=predefined_type,
should_add_representation=True,
context=body,
ifc_representation_class=None,
)
elif template in ("LAYERSET_AXIS2", "LAYERSET_AXIS3"):
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
obj = bpy.data.objects.new(name, None)
element = blenderbim.core.root.assign_class(
tool.Ifc,
tool.Collector,
tool.Root,
obj=obj,
ifc_class=ifc_class,
predefined_type=predefined_type,
should_add_representation=True,
context=body,
ifc_representation_class=None,
)
materials = ifc_file.by_type("IfcMaterial")
if materials:
material = materials[0] # Arbitrarily pick a material
else:
material = ifcopenshell.api.run("material.add_material", tool.Ifc.get(), name="Unknown")
rel = ifcopenshell.api.run(
"material.assign_material", ifc_file, products=[element], type="IfcMaterialLayerSet"
)
layer_set = rel.RelatingMaterial
layer = ifcopenshell.api.run("material.add_layer", ifc_file, layer_set=layer_set, material=material)
thickness = 0.1 # Arbitrary metric thickness for now
layer.LayerThickness = thickness / unit_scale
pset = ifcopenshell.api.run("pset.add_pset", ifc_file, product=element, name="EPset_Parametric")
if template == "LAYERSET_AXIS2":
axis = "AXIS2"
elif template == "LAYERSET_AXIS3":
axis = "AXIS3"
ifcopenshell.api.run("pset.edit_pset", ifc_file, pset=pset, properties={"LayerSetDirection": axis})
elif template == "PROFILESET" or template.startswith("FLOW_SEGMENT_"):
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
obj = bpy.data.objects.new(name, None)
element = blenderbim.core.root.assign_class(
tool.Ifc,
tool.Collector,
tool.Root,
obj=obj,
ifc_class=ifc_class,
predefined_type=predefined_type,
should_add_representation=True,
context=body,
ifc_representation_class=None,
)
materials = ifc_file.by_type("IfcMaterial")
if materials:
material = materials[0] # Arbitrarily pick a material
else:
material = ifcopenshell.api.run("material.add_material", tool.Ifc.get(), name="Unknown")
if template == "PROFILESET":
named_profiles = [p for p in ifc_file.by_type("IfcProfileDef") if p.ProfileName]
if named_profiles:
profile = named_profiles[0]
else:
size = 0.5 / unit_scale
profile = ifc_file.create_entity(
"IfcRectangleProfileDef", ProfileName="New Profile", ProfileType="AREA", XDim=size, YDim=size
)
else:
# NOTE: defaults dims are in meters / mm
# for now default names are hardcoded to mm
if template == "FLOW_SEGMENT_RECTANGULAR":
default_x_dim = 0.4
default_y_dim = 0.2
profile_name = f"{ifc_class}-{default_x_dim*1000}x{default_y_dim*1000}"
profile = ifc_file.create_entity(
"IfcRectangleProfileDef",
ProfileName=profile_name,
ProfileType="AREA",
XDim=default_x_dim / unit_scale,
YDim=default_y_dim / unit_scale,
)
elif template == "FLOW_SEGMENT_CIRCULAR":
default_diameter = 0.1
profile_name = f"{ifc_class}-{default_diameter*1000}"
profile = ifc_file.create_entity(
"IfcCircleProfileDef",
ProfileName=profile_name,
ProfileType="AREA",
Radius=(default_diameter / 2) / unit_scale,
)
elif template == "FLOW_SEGMENT_CIRCULAR_HOLLOW":
default_diameter = 0.15
default_thickness = 0.005
profile_name = f"{ifc_class}-{default_diameter*1000}x{default_thickness*1000}"
profile = ifc_file.create_entity(
"IfcCircleHollowProfileDef",
ProfileName=profile_name,
ProfileType="AREA",
Radius=(default_diameter / 2) / unit_scale,
WallThickness=default_thickness,
)
rel = ifcopenshell.api.run(
"material.assign_material", ifc_file, products=[element], type="IfcMaterialProfileSet"
)
profile_set = rel.RelatingMaterial
material_profile = ifcopenshell.api.run(
"material.add_profile", ifc_file, profile_set=profile_set, material=material
)
ifcopenshell.api.run(
"material.assign_profile", ifc_file, material_profile=material_profile, profile=profile
)
elif template == "EMPTY":
obj = bpy.data.objects.new(name, None)
blenderbim.core.root.assign_class(
tool.Ifc,
tool.Collector,
tool.Root,
obj=obj,
ifc_class=ifc_class,
predefined_type=predefined_type,
should_add_representation=True,
context=body,
ifc_representation_class=None,
)
elif template == "WINDOW":
mesh = bpy.data.meshes.new(name)
obj = bpy.data.objects.new(name, mesh)
element = blenderbim.core.root.assign_class(
tool.Ifc,
tool.Collector,
tool.Root,
obj=obj,
predefined_type=predefined_type if tool.Ifc.get_schema() != "IFC2X3" else None,
ifc_class="IfcWindowType" if tool.Ifc.get_schema() != "IFC2X3" else "IfcWindowStyle",
should_add_representation=False,
)
tool.Blender.select_and_activate_single_object(context, obj)
bpy.ops.bim.add_window(obj=obj.name)
elif template == "DOOR":
mesh = bpy.data.meshes.new(name)
obj = bpy.data.objects.new(name, mesh)
element = blenderbim.core.root.assign_class(
tool.Ifc,
tool.Collector,
tool.Root,
obj=obj,
predefined_type=predefined_type if tool.Ifc.get_schema() != "IFC2X3" else None,
ifc_class="IfcDoorType" if tool.Ifc.get_schema() != "IFC2X3" else "IfcDoorStyle",
should_add_representation=False,
)
tool.Blender.select_and_activate_single_object(context, obj)
bpy.ops.bim.add_door(obj=obj.name)
elif template == "STAIR":
mesh = bpy.data.meshes.new(name)
obj = bpy.data.objects.new(name, mesh)
element = blenderbim.core.root.assign_class(
tool.Ifc,
tool.Collector,
tool.Root,
obj=obj,
predefined_type=predefined_type,
ifc_class=ifc_class,
should_add_representation=False,
)
tool.Blender.select_and_activate_single_object(context, obj)
bpy.ops.bim.add_stair()
elif template == "RAILING":
mesh = bpy.data.meshes.new(name)
obj = bpy.data.objects.new(name, mesh)
element = blenderbim.core.root.assign_class(
tool.Ifc,
tool.Collector,
tool.Root,
obj=obj,
predefined_type=predefined_type,
ifc_class="IfcRailingType",
should_add_representation=True,
context=body,
)
tool.Blender.select_and_activate_single_object(context, obj)
bpy.ops.bim.add_railing()
elif template == "ROOF":
mesh = bpy.data.meshes.new(name)
obj = bpy.data.objects.new(name, mesh)
element = blenderbim.core.root.assign_class(
tool.Ifc,
tool.Collector,
tool.Root,
obj=obj,
predefined_type=predefined_type,
ifc_class="IfcRoofType",
should_add_representation=True,
context=body,
)
tool.Blender.select_and_activate_single_object(context, obj)
bpy.ops.bim.add_roof()
bpy.ops.bim.load_type_thumbnails(ifc_class=ifc_class)
props.type_class = props.type_class
return {"FINISHED"}
class RemoveType(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_type"
bl_label = "Remove Type"
bl_options = {"REGISTER", "UNDO"}
element: bpy.props.IntProperty()
def _execute(self, context):
element = tool.Ifc.get().by_id(self.element)
obj = tool.Ifc.get_object(element)
tool.Geometry.delete_ifc_object(obj)
class RenameType(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.rename_type"
bl_label = "Rename Type"
bl_options = {"REGISTER", "UNDO"}
element: bpy.props.IntProperty()
name: bpy.props.StringProperty(name="Name")
def _execute(self, context):
element = tool.Ifc.get().by_id(self.element)
obj = tool.Ifc.get_object(element)
element.Name = self.name
if obj:
tool.Root.set_object_name(obj, element)
def invoke(self, context, event):
element = tool.Ifc.get().by_id(self.element)
self.name = element.Name or "Unnamed"
return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
self.layout.prop(self, "name")
class AutoRenameOccurrences(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.auto_rename_occurrences"
bl_label = "Auto Rename Occurrences"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
obj = context.active_object
element_type = tool.Ifc.get_entity(obj)
if element_type and element_type.is_a("IfcTypeObject"):
for occurrence in ifcopenshell.util.element.get_types(element_type):
obj = tool.Ifc.get_object(occurrence)
occurrence.Name = tool.Model.generate_occurrence_name(element_type, occurrence.is_a())
if obj:
tool.Root.set_object_name(obj, occurrence)
class DuplicateType(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.duplicate_type"
bl_label = "Duplicate Type"
bl_options = {"REGISTER", "UNDO"}
element: bpy.props.IntProperty()
def _execute(self, context):
element = tool.Ifc.get().by_id(self.element)
obj = tool.Ifc.get_object(element)
if not obj:
return {"FINISHED"}
new_obj = obj.copy()
if obj.data:
new_obj.data = obj.data.copy()
new = blenderbim.core.root.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=new_obj)
new.Name += " Copy"
bpy.ops.bim.load_type_thumbnails(ifc_class=new.is_a())
if obj in context.selectable_objects:
tool.Blender.select_and_activate_single_object(context, new_obj)
else:
self.report({"INFO"}, "Type object can't be selected : It may be hidden or in an excluded collection.")
context.scene.BIMModelProperties.ifc_class = new.is_a()
context.scene.BIMModelProperties.relating_type_id = str(new_obj.BIMObjectProperties.ifc_definition_id)
return {"FINISHED"}
class PurgeUnusedTypes(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.purge_unused_types"
bl_label = "Purge Unused Types"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
purged_types = core.purge_unused_types(tool.Ifc, tool.Type, tool.Geometry)
self.report({"INFO"}, f"{purged_types} types were purged.")
-103
View File
@@ -1,103 +0,0 @@
def create_repo(ifcgit, ifc):
path_ifc = ifc.get_path()
path_dir = ifcgit.get_path_dir(path_ifc)
ifcgit.init_repo(path_dir)
def add_file(ifcgit, ifc):
path_ifc = ifc.get_path()
repo = ifcgit.repo_from_path(path_ifc)
ifcgit.add_file_to_repo(repo, path_ifc)
def clone_repo(ifcgit, remote_url, local_folder, operator):
repo = ifcgit.clone_repo(remote_url, local_folder)
if not repo:
operator.report({"ERROR"}, "Clone failed")
return
operator.report({"INFO"}, "Repository cloned")
ifcgit.load_anyifc(repo)
def discard_uncommitted(ifcgit, ifc):
path_ifc = ifc.get_path()
# NOTE this is calling the git binary in a subprocess
ifcgit.git_checkout(path_ifc)
ifcgit.load_project(path_ifc)
def commit_changes(ifcgit, ifc, repo):
"""Commit and create new branches as required"""
path_ifc = ifc.get_path()
if repo.head.is_detached:
ifcgit.git_commit(path_ifc)
ifcgit.create_new_branch()
else:
ifcgit.checkout_new_branch(path_ifc)
ifcgit.git_commit(path_ifc)
def add_tag(ifcgit, repo):
ifcgit.add_tag(repo)
def delete_tag(ifcgit, repo, tag_name):
ifcgit.delete_tag(repo, tag_name)
def add_remote(ifcgit, repo):
ifcgit.add_remote(repo)
def delete_remote(ifcgit, repo):
ifcgit.delete_remote(repo)
def push(ifcgit, repo, remote_name, operator):
error_message = ifcgit.push(repo, remote_name, repo.active_branch.name)
if error_message:
operator.report({"ERROR"}, error_message)
def refresh_revision_list(ifcgit, repo, ifc):
if repo.heads:
ifcgit.refresh_revision_list(ifc.get_path())
def colourise_revision(ifcgit):
step_ids = ifcgit.get_revisions_step_ids()
if not step_ids:
return
modified_shape_object_step_ids = ifcgit.get_modified_shape_object_step_ids(step_ids)
final_step_ids = ifcgit.update_step_ids(step_ids, modified_shape_object_step_ids)
ifcgit.colourise(final_step_ids)
def colourise_uncommitted(ifcgit, ifc, repo):
path_ifc = ifc.get_path()
step_ids = ifcgit.ifc_diff_ids(repo, None, "HEAD", path_ifc)
ifcgit.colourise(step_ids)
def switch_revision(ifcgit, ifc):
# FIXME bad things happen when switching to a revision that predates current project
path_ifc = ifc.get_path()
ifcgit.switch_to_revision_item()
ifcgit.load_project(path_ifc)
ifcgit.refresh_revision_list(path_ifc)
def merge_branch(ifcgit, ifc, operator):
path_ifc = ifc.get_path()
ifcgit.config_ifcmerge()
ifcgit.execute_merge(path_ifc, operator)
def entity_log(ifcgit, ifc, step_id, operator):
path_ifc = ifc.get_path()
log_text = ifcgit.entity_log(path_ifc, step_id)
# ERROR is only way to display a multi-line message
operator.report({"ERROR"}, log_text)
@@ -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
-149
View File
@@ -1,149 +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 blenderbim.core.tool
import blenderbim.tool as tool
import ifcopenshell.util.element
from typing import Union
class Collector(blenderbim.core.tool.Collector):
@classmethod
def assign(cls, obj: bpy.types.Object, should_clean_users_collection=True) -> None:
"""Links an object to an appropriate Blender collection."""
if should_clean_users_collection:
for users_collection in obj.users_collection:
if obj.BIMObjectProperties.collection == users_collection:
continue
# Users are free to user extra collections for their own
# purposes except for the reserved keyword "Ifc" and
# "Collection" (which is the default collection that comes with
# a Blender session)
if "Ifc" in users_collection.name or users_collection.name == "Collection":
print('removing', users_collection, 'from', obj)
users_collection.objects.unlink(obj)
element = tool.Ifc.get_entity(obj)
if element.is_a("IfcGridAxis"):
element = (element.PartOfU or element.PartOfV or element.PartOfW)[0]
if element.is_a("IfcProject"):
if collection := cls._create_own_collection(obj):
cls.link_to_collection_safe(obj, collection)
cls.link_to_collection_safe(collection, bpy.context.scene.collection)
elif element.is_a("IfcTypeProduct"):
collection = cls._create_project_child_collection("IfcTypeProduct")
cls.link_to_collection_safe(obj, collection)
elif element.is_a("IfcOpeningElement"):
collection = cls._create_project_child_collection("IfcOpeningElement")
cls.link_to_collection_safe(obj, collection)
elif element.is_a("IfcStructuralItem"):
collection = cls._create_project_child_collection("IfcStructuralItem")
cls.link_to_collection_safe(obj, collection)
elif element.is_a("IfcLinearPositioningElement"):
collection = cls._create_project_child_collection("IfcLinearPositioningElement")
collection.hide_viewport = False
cls.link_to_collection_safe(obj, collection)
elif element.is_a("IfcReferent"):
collection = cls._create_project_child_collection("IfcReferent")
collection.hide_viewport = False
cls.link_to_collection_safe(obj, collection)
elif tool.Ifc.get_schema() == "IFC2X3" and element.is_a("IfcSpatialStructureElement"):
if collection := cls._create_own_collection(obj):
cls.link_to_collection_safe(obj, collection)
project_obj = tool.Ifc.get_object(tool.Ifc.get().by_type("IfcProject")[0])
cls.link_to_collection_safe(collection, project_obj.BIMObjectProperties.collection)
elif (
tool.Ifc.get_schema() != "IFC2X3"
and element.is_a("IfcSpatialElement")
and not element.is_a("IfcSpatialZone")
):
if collection := cls._create_own_collection(obj):
cls.link_to_collection_safe(obj, collection)
project_obj = tool.Ifc.get_object(tool.Ifc.get().by_type("IfcProject")[0])
cls.link_to_collection_safe(collection, project_obj.BIMObjectProperties.collection)
elif container := ifcopenshell.util.element.get_container(element):
container_obj = tool.Ifc.get_object(container)
if not (collection := container_obj.BIMObjectProperties.collection):
cls.assign(container_obj)
collection = container_obj.BIMObjectProperties.collection
cls.link_to_collection_safe(obj, collection)
elif element.is_a("IfcAnnotation"):
if element.ObjectType == "DRAWING":
if collection := cls._create_own_collection(obj):
cls.link_to_collection_safe(obj, collection)
project_obj = tool.Ifc.get_object(tool.Ifc.get().by_type("IfcProject")[0])
cls.link_to_collection_safe(collection, project_obj.BIMObjectProperties.collection)
else:
for rel in element.HasAssignments or []:
if rel.is_a("IfcRelAssignsToGroup") and rel.RelatingGroup.ObjectType == "DRAWING":
for related_object in rel.RelatedObjects:
if related_object.is_a("IfcAnnotation") and related_object.ObjectType == "DRAWING":
drawing_obj = tool.Ifc.get_object(related_object)
if drawing_obj:
cls.link_to_collection_safe(obj, drawing_obj.BIMObjectProperties.collection)
else:
collection = cls._create_project_child_collection("Unsorted")
collection.hide_viewport = False
cls.link_to_collection_safe(obj, collection)
@classmethod
def _create_project_child_collection(cls, name: str) -> bpy.types.Collection:
"""get or create new collection inside project"""
collection = bpy.data.collections.get(name)
if not collection:
collection = bpy.data.collections.new(name)
project_obj = tool.Ifc.get_object(tool.Ifc.get().by_type("IfcProject")[0])
project_obj.BIMObjectProperties.collection.children.link(collection)
collection.hide_viewport = True
return collection
@classmethod
def _create_own_collection(cls, obj: bpy.types.Object) -> bpy.types.Collection:
"""get or create own collection for the element"""
if obj.BIMObjectProperties.collection:
obj.BIMObjectProperties.collection.name = obj.name
return
collection = bpy.data.collections.new(obj.name)
obj.BIMObjectProperties.collection = collection
collection.BIMCollectionProperties.obj = obj
return collection
@classmethod
def link_to_collection_safe(
cls, obj_or_col: Union[bpy.types.Object, bpy.types.Collection], collection: bpy.types.Collection
) -> None:
"""Link `obj_or_col` (an object or a collection) to the `collection`
if `obj_or_col` is not part of that collection already.
Method is needed to avoid RuntimeErrors like below that occur if you link object/collection
to the collection directly and they are already part of that collection.
RuntimeError: Error: Object 'xxx' already in collection 'xxx'.
"""
# TODO: Maybe just catching RuntimeError is faster?
if isinstance(obj_or_col, bpy.types.Object):
if collection.objects.find(obj_or_col.name) != -1:
return
collection.objects.link(obj_or_col)
return
if collection.children.find(obj_or_col.name) != -1:
return
collection.children.link(obj_or_col)
-57
View File
@@ -1,57 +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 blenderbim.bim.helper
import blenderbim.tool as tool
import blenderbim.core.tool
class Context(blenderbim.core.tool.Context):
@classmethod
def set_context(cls, context):
bpy.context.scene.BIMContextProperties.active_context_id = context.id()
@classmethod
def import_attributes(cls):
props = bpy.context.scene.BIMContextProperties
props.context_attributes.clear()
context = cls.get_context()
def callback(name, prop, data):
if context.is_a("IfcGeometricRepresentationSubContext"):
if name == "Precision":
props.context_attributes.remove(props.context_attributes.find("Precision"))
return True
elif name == "CoordinateSpaceDimension":
props.context_attributes.remove(props.context_attributes.find("CoordinateSpaceDimension"))
return True
blenderbim.bim.helper.import_attributes(context.is_a(), props.context_attributes, context.get_info(), callback)
@classmethod
def clear_context(cls):
bpy.context.scene.BIMContextProperties.active_context_id = 0
@classmethod
def get_context(cls):
return tool.Ifc.get().by_id(bpy.context.scene.BIMContextProperties.active_context_id)
@classmethod
def export_attributes(cls):
return blenderbim.bim.helper.export_attributes(bpy.context.scene.BIMContextProperties.context_attributes)
-90
View File
@@ -1,90 +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 os
import bpy
import ifcopenshell.express
import blenderbim.core.tool
import blenderbim.tool as tool
from blenderbim.bim.ifc import IfcStore
class Debug(blenderbim.core.tool.Debug):
@classmethod
def add_schema_identifier(cls, schema):
IfcStore.schema_identifiers.append(schema.schema_name)
@classmethod
def load_express(cls, filename):
schema = ifcopenshell.express.parse(filename)
ifcopenshell.register_schema(schema)
return schema
@classmethod
def purge_hdf5_cache(cls):
cache_dir = os.path.join(bpy.context.scene.BIMProperties.data_dir, "cache")
filelist = [f for f in os.listdir(cache_dir) if f.endswith(".h5")]
for f in filelist:
os.remove(os.path.join(cache_dir, f))
@classmethod
def debug_geometry(cls, verts=[], edges=[], name="Debug"):
mesh = bpy.data.meshes.new("Debug")
mesh.from_pydata(verts, edges, [])
obj = bpy.data.objects.new(name, mesh)
bpy.context.scene.collection.objects.link(obj)
return obj
@classmethod
def remove_unused_elements(cls, elements):
ifc_file = tool.Ifc.get()
for element in elements:
ifcopenshell.util.element.remove_deep2(ifc_file, element)
@classmethod
def print_unused_elements_stats(cls, requested_ifc_class="", ignore_classes=tuple()):
ifc_file = tool.Ifc.get()
# get list of ifc classes used in model
classes = set()
requested_ifc_classes = set()
for el in ifc_file:
if any(el.is_a(i) for i in ignore_classes):
continue
classes.add(el.is_a())
if requested_ifc_class and el.is_a(requested_ifc_class):
requested_ifc_classes.add(el.is_a())
# count unused elements for each class
unused = dict()
for c in classes:
uses = [i for i in ifc_file.by_type(c) if ifc_file.get_total_inverses(i) == 0]
if not uses:
continue
unused[c] = len(uses)
# print classes and their unsued elements in ascending order
if unused:
print("Unused elements by classes:")
for ifc_class in sorted(unused.keys(), key=lambda x: unused[x]):
class_string = ifc_class
if ifc_class in requested_ifc_classes:
class_string = "---> " + class_string
print(f"{class_string: <50} {unused[ifc_class]: >5}")
return sum(unused.values())
-90
View File
@@ -1,90 +0,0 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 @Andrej730
#
# 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 ifcopenshell
import ifcopenshell.geom
import ifcopenshell.util.element
import ifcopenshell.util.unit
import ifcopenshell.util.placement
import ifcopenshell.util.representation
import blenderbim.core.tool
import blenderbim.tool as tool
import PIL.ImageDraw
from blenderbim.bim.module.model.decorator import ProfileDecorator
from typing import Union
class Profile(blenderbim.core.tool.Profile):
@classmethod
def draw_image_for_ifc_profile(
cls, draw: PIL.ImageDraw.ImageDraw, profile: ifcopenshell.entity_instance, size: float
) -> None:
"""generates image based on `profile` using `PIL.ImageDraw`"""
settings = ifcopenshell.geom.settings()
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.CURVES_SURFACES_AND_SOLIDS)
shape = ifcopenshell.geom.create_shape(settings, profile)
verts = shape.verts
edges = shape.edges
grouped_verts = [[verts[i], verts[i + 1]] for i in range(0, len(verts), 3)]
grouped_edges = [[edges[i], edges[i + 1]] for i in range(0, len(edges), 2)]
max_x = max([v[0] for v in grouped_verts])
min_x = min([v[0] for v in grouped_verts])
max_y = max([v[1] for v in grouped_verts])
min_y = min([v[1] for v in grouped_verts])
dim_x = max_x - min_x
dim_y = max_y - min_y
max_dim = max([dim_x, dim_y])
scale = 100 / max_dim
for vert in grouped_verts:
vert[0] = round(scale * (vert[0] - min_x)) + ((size / 2) - scale * (dim_x / 2))
vert[1] = round(scale * (vert[1] - min_y)) + ((size / 2) - scale * (dim_y / 2))
for e in grouped_edges:
draw.line((tuple(grouped_verts[e[0]]), tuple(grouped_verts[e[1]])), fill="white", width=2)
@classmethod
def is_editing_profile(cls) -> bool:
return bool(ProfileDecorator.installed)
@classmethod
def get_profile(cls, element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
representations = element.Representation
for representation in representations.Representations:
if not representation.is_a("IfcShapeRepresentation"):
continue
for representation_item in representation.Items:
if representation_item.is_a("IfcExtrudedAreaSolid"):
profile = representation_item.SweptArea
if profile:
return profile
return None
@classmethod
def get_model_profiles(cls) -> list[ifcopenshell.entity_instance]:
return tool.Ifc.get().by_type("IfcProfileDef")
@classmethod
def duplicate_profile(cls, profile: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
new_profile = ifcopenshell.util.element.copy_deep(tool.Ifc.get(), profile)
# In UI unnamed profiles are not available, so we don't handle them.
new_profile.ProfileName = profile.ProfileName + "_copy"
return new_profile
-432
View File
@@ -1,432 +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 time
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)
env["BLENDERBIM_VERSION"] = tool.Blender.get_blenderbim_version()
ws_process = subprocess.Popen(
[sys.executable, ws_path, "--p", str(port), "--host", "127.0.0.1"],
cwd=webui_path,
env=env,
)
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.kill()
ws_process = None
cls.set_is_running(False)
print("Websocket server killed successfully")
@classmethod
def has_started(cls, port):
max_time = 5
start = time.time()
while True:
if time.time() - start > max_time:
return False
webui_path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "webui")
pid_file = os.path.join(webui_path, "running_pid.json")
try:
with open(pid_file, "r") as f:
data = json.load(f)
if port in data.values():
return True
except:
pass
time.sleep(0.1)
@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"])
elif operator["sourcePage"] == "drawings":
cls.handle_drawings_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 handle_drawings_operator(cls, operator_data: dict) -> None:
if operator_data["type"] == "getDrawings":
drawings_data = []
sheets_data = []
ifc_file_dir = os.path.dirname(bpy.context.scene.BIMProperties.ifc_file)
sheets = [d for d in tool.Ifc.get().by_type("IfcDocumentInformation") if d.Scope == "SHEET"]
for sheet in sorted(sheets, key=lambda s: getattr(s, "Identification", getattr(s, "DocumentId", None))):
for reference in tool.Drawing.get_document_references(sheet):
reference_description = tool.Drawing.get_reference_description(reference)
reference_location = tool.Drawing.get_reference_location(reference)
reference_name = os.path.basename(reference_location)
reference_path = os.path.join(ifc_file_dir, reference_location)
if reference_description == "SHEET":
sheets_data.append({"name": reference_name, "path": reference_path})
if reference_description == "DRAWING":
drawings_data.append({"name": reference_name, "path": reference_path})
cls.send_webui_data(
data={"drawings": drawings_data, "sheets": sheets_data}, data_key="drawings_data", event="drawings_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.
-179
View File
@@ -1,179 +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?q=blenderbim&expanded=true>`__,
then follow the usual :doc:`installation
instructions</users/quickstart/installation>`.
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 (``linux-x64``)
- 64-bit MacOS Intel (``macos-x64``)
- 64-bit MacOS Silicon (``macos-arm64``)
- 64-bit Windows (``windows-x64``)
- Blender 4.2 with Python 3.11
Due to significant changes in the Blender extensions system, Blender versions
<4.2 are not supported.
Developer builds may exist for different 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/>`_ and the `VFX Platform
<https://vfxplatform.com/>`_ standard.
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 ``py312``, ``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 :ref:`devs/installation: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 :ref:`devs/installation: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
symbolic links, 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
-------------------------
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 logic)
tool/ (Blender specific shared functionality)
bim/ (Blender specific UI)
libs/ (other assets)
wheels/ (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>`__
in the ``dist`` target.
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.
-214
View File
@@ -1,214 +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/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/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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

@@ -1,140 +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>`__
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.
Where is the add-on installed?
------------------------------
Upon installation, the BlenderBIM Add-on is stored in 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/
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/
On Linux, if you are deploying the add-on system-wide (this may also depend on
your Linux distribution):
::
/usr/share/blender/X.XX/
On Mac, if you are installing the add-on as a user:
::
/Users/{YOUR_USER}/Library/Application Support/Blender/X.XX/
On Mac, if you are deploying the add-on system-wide:
::
/Library/Application Support/Blender/X.XX/
On Windows:
::
C:\Users\{YOUR_USER}\AppData\Roaming\Blender Foundation\X.XX\
Inside the Blender configuration folder, the BlenderBIM Add-on is stored in two
different locations. The extension itself is stored in
``extensions/blender_org/blenderbim`` whereas the Python packages are installed
into ``extensions/.local/lib/pythonX.XX/site-packages/``.
@@ -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,86 +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.2** installed from https://blender.org/ and have
:ref:`updated to the latest version <users/quickstart/installation:Updating>`.
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<users/quickstart/installation:Where is the add-on
installed?>`. 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 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.
3. **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``.
Saving and loading blend files
------------------------------
The BlenderBIM Add-on transform Blender into a native IFC authoring platform.
This means that you can open and save IFC files directly without using
Blender's ``.blend`` format.
All data about your model is saved in your IFC. No data is stored in the
``.blend`` format. This means that if you save or open a ``.blend`` file, you
are **not** saving and loading your model. At best, you are saving and loading
Blender geometry that represents what the model might've looked at at some
point. At worst, you might be looking at a completely wrong model.
If you continue to open and save ``.blend`` files, you will run the risk of
editing something that doesn't actually exist in your IFC model. This will
create unpredictable, and sometimes unrecoverable errors.
To avoid this issue, only open and save IFCs.
@@ -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

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