🌶️ RootBlock paradigm

Eyeshot 2023 includes a Block, called RootBlock, that represents the scene root. This means that every single piece of geometry is always inside a Block definition. There is no longer a collection of entities associated with the environment, the Workspace.Entities collection is now a shortcut that refers always to a Block.Entities collection, normally of the RootBlock if you don't work with the assembly navigation features.


The BlockKeyedCollection, if and only if assigned to a Workspace, always has a root block defined. The root block is not typed, has no properties different than other blocks, it simply must be identified to initialize the scene when a new BlockKeyedCollection is assigned to a workspace. For it, you have to use the BlockKeyedCollection.SetRootBlock(string key) method:

BlockKeyedCollection blocks = new BlockKeyedCollection();
string name = "MyRootBlock";
blocks.Add(new Block(name));
design1.Blocks = blocks;

Once the BlockKeyedCollection is assigned to a workspace, the root block can't be removed, but you can rename it simply by changing its name property or replace it:

model.RootBlock.Name = "newName";

The name of the RootBlock is stored in the BlockKeyedCollection.RootBlockName. If this string is null or empty, the collection doesn't have a root block specified. To get an instance, there is the Workspace.RootBlock shortcut.

Block with EntityList

The Block.Entities collection is now an EntityList, no longer a simple List<Entity>. Properties and methods of the EntityList work now at block level so it's possible to operate only in a specified context and not on the whole scene. To work on the whole scene you should always refer to the RootBlock.

For example:

block.Entities.Regen(); //regenerates only the entities of the block
design1.RootBlock.Entities.Regen(); //regenerates all the entities of the root block that are also all the entities of the design.

Now when an entity is added to a Block already assigned to a Workspace, it's automatically regenerated. It's highly recommended to fill the block entities before adding it to the Workspace.Blocks collection to prevent performance slow down during the geometry loading. For editing/reorganization of already loaded geometry, it's possible to temporarily suspend the automatic regeneration with BlockKeyedCollection.TakeOffLine(), to resume it call BlockKeyedCollection.BringOnline().

The following features, which are strictly related to the control, are moved from the EntityList to the Workspace.

UpdateBoundingBox: the scene bounding box is now updated by Workspace.UpdateBoundingBox(), because it needs to manage also the OverrideSceneExtents option. This method updates also the Turbo representation. Block.Entities.UpdateBoundingBox() works only at block level, so each block has now its own bounding box.

Assembly Navigation: see the related article.

Visual Refinement Deviation: it is now always computed based on the RootBlock extents. It's possible to use a custom value as explained in this article.


For the file formats that support the root block, the default behavior of the various AddTo methods is to replace the environment root block with the one loaded from the file. To change this behavior you must use the AddTo method that accepts the replaceRootBlock flag as a parameter.

Generally, in writer classes, we use the root block entities as main entities to be exported, but it's still possible to specify the desired list of entities by using the constructor with the collections:

Brep box = Brep.CreateBox(10, 10, 10);
WriteFileParams writeFileParams = new WriteFileParams(new Entity[]{box});
WriteFile writeFile = new WriteFile(writeFileParams, "box.eye");

Adding the file contents to an existing 3D scene

A small example of how to insert the content of a file (*.eye or *.igs, *.stp, *.stl, etc.) to the existing 3D scene follows. In the case that the file contains a root block, its name may collide with the current one, so we need to change it.

ReadFileAsyncWithBlocks rfawb = rfa as ReadFileAsyncWithBlocks;
if (rfawb == null || rfawb.Blocks.RootBlockName == null) { rfa.FillAllCollectionsData(model1); design1.Entities.AddRange(rfa.Entities); } else // the file contains a root block with a name that may collide with current one { const string newName = "dummy"; rfawb.Blocks["RootBlock"].Name = newName; rfawb.FillAllCollectionsData(model1); Entity ent = new BlockReference(newName); design1.Entities.Add(ent); }

You can read more on this topic here.

Was this article helpful?
3 out of 4 found this helpful



Please sign in to leave a comment.

Articles in this section

See more